(Dieses Bild wurde mit Unterstützung von Stable Diffusion erstellt.)
In Kundenprojekten begegnen mir immer wieder Amazon-RDS-Datenbanken, die in einem VPC-Subnetz mit Default-Route ins Internet betrieben werden.
Schutzmaßnahmen sind dabei oft durchaus vorhanden: eine deaktivierte Option "publicly accessible" in RDS, eingehende Security-Group-Regeln, die nur die freigegebenen EC2- oder Lambda-Ressourcen zulassen, sowie Stateful-Firewall-Regeln, die Bedrohungen und Exploits über SQL-Signaturen erkennen. Vorfälle wie der Datenleck der Target Corporation 2013 zeigen aber: Es reicht heute nicht mehr, nur eingehenden Internet-Traffic zu blockieren und gleichzeitig sämtlichen ausgehenden Traffic zuzulassen, wenn man das Risiko der Datenexfiltration ernsthaft minimieren will. Command-and-Control-Malware (auch als C&C- oder C2-Malware bekannt) kann den ausgehenden Traffic über gängige Ports wie HTTP:80 und HTTPS:443 für Beaconing missbrauchen.
Dieser Artikel beschreibt, wie Sie eine Amazon RDS aus einem Public Subnet mit ins Internet routender Route Table in ein Isolated Subnet verschieben – ohne über Snapshot-Restore eine neue DB-Instanz anlegen zu müssen.
In jeder VPC sind drei Arten von Subnetzen möglich: ein Public Subnet mit angeschlossenem Internet Gateway, das ein- und ausgehenden Internet-Traffic erlaubt; ein Private Subnet mit Network Address Translation (NAT) oder Internet-Egress-only-Gateway, das nur ausgehenden Internet-Traffic zulässt; sowie ein Isolated Subnet, das ausschließlich Traffic innerhalb der VPC erlaubt und keine Routen zu Zielen außerhalb der VPC besitzt.
Wer die Datenbank in einem Isolated Subnet betreibt, verkleinert die Angriffsfläche und damit auch das Risiko der Datenexfiltration: Ein Angreifer wie eine C&C-Malware findet schlicht weniger Wege, um Daten herauszuschleusen.
Wichtig dabei: Netzwerkisolation ist eine zentrale, aber nicht die einzige Sicherheitsmaßnahme – und kein Allheilmittel gegen Datenexfiltration. Eine Kette ist nur so stark wie ihr schwächstes Glied. Jede zusätzliche Schutzschicht zählt.
Testumgebung mit Multi-AZ Amazon RDS einrichten
Um die Schritte zum Verschieben der RDS-Instanz aus einem Public Subnet in ein Isolated Subnet nachvollziehen zu können, brauchen Sie eine Testumgebung: eine Amazon RDS in den Public Subnets einer VPC, die zugleich Public und Isolated Subnets enthält.
Wenn Sie bereits Amazon-RDS-Instanzen in Public Subnets betreiben und Ihre VPC über Isolated Subnets verfügt, können Sie den Schritt zur VPC-Erstellung überspringen.
Wir legen die AWS-Ressourcen mit CDK an. Falls Sie noch nicht mit CDK gearbeitet haben, finden Sie unter https://docs.aws.amazon.com/cdk/v2/guide/hello_world.htm eine Einführung.
CDK-Stack zum Erstellen einer VPC
Im ersten Schritt erstellen wir mit dem unten stehenden CDK-Stack eine VPC mit jeweils einem Public und einem Isolated Subnet pro Availability Zone, verteilt über zwei Availability Zones.
Wir exportieren die nötigen VPC-Parameter wie die VPC-ID, damit wir sie im nächsten Schritt im Stack zur RDS-Erstellung importieren können.
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
const app = new cdk.App();
const vpcStack = new cdk.Stack(app, "vpc-stack");
const vpc = new cdk.aws_ec2.Vpc(vpcStack, `test-vpc`, {
ipAddresses: cdk.aws_ec2.IpAddresses.cidr("10.0.0.0/20"),
vpcName: `test-vpc`,
enableDnsHostnames: true,
enableDnsSupport: true,
maxAzs: 2,
subnetConfiguration: [\
{\
name: "public",\
subnetType: cdk.aws_ec2.SubnetType.PUBLIC,\
cidrMask: 27\
},\
{\
name: "isolated",\
subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED,\
cidrMask: 27\
},\
]
});
new cdk.CfnOutput(
vpcStack, 'testVpcVpcID', {
value: vpc.vpcId,
description: 'Test Vpc ID',
exportName: 'test-vpc-VpcID',
});
new cdk.CfnOutput(
vpcStack, 'testVpcAz', {
value: vpc.availabilityZones.join(","),
description: 'Vpc AZs',
exportName: 'test-Vpc-AZs',
});
new cdk.CfnOutput(
vpcStack, 'testVpcPublicSubnets', {
value: vpc.selectSubnets({
subnetType: cdk.aws_ec2.SubnetType.PUBLIC
}).subnetIds.join(","),
description: 'Vpc Public Subnet IDs',
exportName: 'test-Vpc-PublicSubnetIds',
});
new cdk.CfnOutput(
vpcStack, 'testVpcIsolatedSubnets', {
value: vpc.selectSubnets({
subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED
}).subnetIds.join(","),
description: 'Vpc Isolated Subnet IDs',
exportName: 'test-Vpc-IsolatedSubnetIds',
});
Wenn cdk deploy vpc-stack erfolgreich durchläuft, sollten Sie etwa folgende Ausgaben sehen:
✅ vpc-stack
✨ Deployment time: 76.83s
Outputs:
vpc-stack.testVpcAz = us-east-1a,us-east-1b
vpc-stack.testVpcIsolatedSubnets = subnet-03e58f5428463ad26,subnet-06721c9fdaac5f333
vpc-stack.testVpcVpcID = vpc-090949477d23289ce
vpc-stack.testeVpcPublicSubnets = subnet-0271290b1164913ad,subnet-079b9aaba653c430b
Notieren Sie sich die VPC-ID, die Public-Subnet-IDs und die Isolated-Subnet-IDs.
In diesem Beispiel arbeiten wir beim Anlegen der Amazon RDS mit folgenden Parametern:
- VPC-ID:
vpc-090949477d23289ce - Public-Subnet-IDs:
subnet-0271290b1164913ad,subnet-079b9aaba653c430b - Isolated-Subnet-IDs:
subnet-06721c9fdaac5f333,subnet-03e58f5428463ad26
CDK-Stack zum Erstellen der Amazon RDS
Als Nächstes provisionieren wir eine Amazon-Postgres-RDS im Public Subnet der VPC:
Kurztipp zu CDK:
cdk.Fn.importValue()ist ein late-bound attribute. Daher müssen wir die CloudFormation-String-Split-Funktioncdk.Fn.Split()verwenden statt eines TypeScript-String-Splits wiecdk.Fn.importValue(‘test-Vpc-AZs’).split(","), der Fehler wie diesen auslösen würde:Some input subnets in :[subnet-0271290b1164913ad,subnet-079b9aaba653c430b] are invalid.
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
const app = new cdk.App();
const rdsStack = new cdk.Stack(app, "rds-stack");
const vpcLookup = cdk.aws_ec2.Vpc.fromVpcAttributes(
rdsStack, `${rdsStack.stackName}-vpc-lookup`,
<cdk.aws_ec2.VpcAttributes>{
vpcId: cdk.Fn.importValue('test-vpc-VpcID'),
availabilityZones: cdk.Fn.split(",",cdk.Fn.importValue('test-Vpc-AZs')),
publicSubnetIds: cdk.Fn.split(",",cdk.Fn.importValue('test-Vpc-PublicSubnetIds')),
isolatedSubnetIds: cdk.Fn.split(",",cdk.Fn.importValue('test-Vpc-IsolatedSubnetIds'))
});
const subnetType: cdk.aws_ec2.SubnetSelection = { subnetType: cdk.aws_ec2.SubnetType.PUBLIC };
const subnetGroup = new cdk.aws_rds.SubnetGroup(
rdsStack, `${rdsStack.stackName}-rds-subnetgroup`,
<cdk.aws_rds.SubnetGroupProps>{
subnetGroupName: `${rdsStack.stackName}-rds-subnetgroup`,
vpc: vpcLookup,
vpcSubnets: {
subnets: vpcLookup.selectSubnets(subnetType).subnets
},
description: "RDS subnetgroup"
});
const rdsInstance = new cdk.aws_rds.DatabaseInstance(
rdsStack, `${rdsStack.stackName}-rdsInstance`,
<cdk.aws_rds.DatabaseInstanceProps>{
engine: cdk.aws_rds.DatabaseInstanceEngine.postgres({
version: cdk.aws_rds.PostgresEngineVersion.VER_15_3
}),
vpcLookup,
subnetGroup: subnetGroup,
publiclyAccessible: false,
multiAz: true,
credentials: cdk.aws_rds.Credentials.fromSecret(
new cdk.aws_rds.DatabaseSecret( rdsStack, `${rdsStack.stackName}-database-secret`,
<cdk.aws_rds.DatabaseSecretProps>{
username: "dbMaster",
secretName: `dbMaster-credential`,
}
)
),
instanceIdentifier: `${rdsStack.stackName}-rds`,
instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.BURSTABLE4_GRAVITON, cdk.aws_ec2.InstanceSize.MICRO),
storageType: cdk.aws_rds.StorageType.GP3,
});
new cdk.CfnOutput(
rdsStack, `${rdsStack.stackName}-rds-name`, {
value: rdsInstance.instanceIdentifier,
description: 'RDS instance identifier'
});
new cdk.CfnOutput(
rdsStack, `${rdsStack.stackName}-subnetgroup-name`, {
value: subnetGroup.subnetGroupName,
description: "RDS Subnet Group Name"
});
Wenn die RDS in einer bereits vorhandenen VPC angelegt werden soll, passen Sie vpcLookup entsprechend an, etwa so:
const vpcLookup = cdk.aws_ec2.Vpc.fromVpcAttributes(rdsStack, `${rdsStack.stackName}-vpc-lookup`, {
vpcId: "vpc-090949477d23289ce",
availabilityZones: ["us-east-1a", "us-east-1b"],
publicSubnetIds: ["subnet-0271290b1164913ad", "subnet-079b9aaba653c430b"],
isolatedSubnetIds: ["subnet-03e58f5428463ad26", "subnet-06721c9fdaac5f333"],
});
Wenn cdk deploy rds-stack erfolgreich durchläuft, sollten Sie etwa folgende Ausgaben sehen:
✅ rds-stack
✨ Deployment time: 20.95s
Outputs:
rds-stack.rdsstackrdsname = rds-stack-rds
Was haben wir damit erstellt?
Wir haben eine VPC mit zwei Availability Zones angelegt. Jede Zone enthält ein Public und ein Isolated Subnet.
Außerdem haben wir eine Multi-AZ-Amazon-RDS in den Public Subnets beider Availability Zones provisioniert.

Multi-AZ-RDS in Public Subnets
Amazon RDS aus den Public Subnets in die Isolated Subnets verschieben
Unsere RDS Subnet Group besteht aus mehreren Subnetzen, je eines pro Availability Zone – etwa die Primary-Instanz in AZ-1 und die Standby-Instanz in AZ-2.
Um das Subnetz einer Instanz zu wechseln, müssen wir die Instanz, die dieses Subnetz nutzt, allerdings zuerst entfernen. Andernfalls schlägt die Subnetz-Änderung fehl, solange dort eine RDS-Instanz läuft:
An error occurred (InvalidParameterValue) when calling the ModifyDBSubnetGroup operation: Some of the subnets to be deleted are currently in use: subnet-0271290b1164913ad
Überblick der Schritte, um die Amazon RDS vom Public Subnet ins Isolated Subnet zu verschieben:
- Standby-Instanz stoppen, damit das Public Subnet frei wird. Die RDS Subnet Group kann dieses Public Subnet dann durch das Isolated Subnet ersetzen, bevor die Standby-Instanz im Isolated Subnet neu deployt wird.
- Standby zur Primary heraufstufen und denselben Vorgang für die nun zur Standby degradierte Instanz wiederholen.
- State des CDK aktualisieren.
Schritt 1: Standby-Instanz verschieben
Bevor es losgeht, erfassen wir einige zentrale Parameter:
Subnetz von Primary- und Standby-RDS-Instanz notieren
Mit folgendem AWS-CLI-Befehl ermitteln Sie die primäre und die sekundäre Availability Zone:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone}" --output table
------------------------------
| DescribeDBInstances |
+-------------+--------------+
| Primary | Standby |
+-------------+--------------+
| us-east-1a | us-east-1b |
+-------------+--------------+
Mappen Sie die Availability Zone mit folgendem CLI-Befehl auf die Subnetze in der RDS Subnet Group:
% aws rds describe-db-subnet-groups --db-subnet-group rds-stack-rds-subnetgroup --query "DBSubnetGroups[*].Subnets[*].{AvailabilityZone:SubnetAvailabilityZone.Name,SubnetIdentifier:SubnetIdentifier}" --output table
--------------------------------------------------
| DescribeDBSubnetGroups |
+-------------------+----------------------------+
| AvailabilityZone | SubnetIdentifier |
+-------------------+----------------------------+
| us-east-1b | subnet-079b9aaba653c430b |
| us-east-1a | subnet-0271290b1164913ad |
+-------------------+----------------------------+
Aus diesen beiden Ausgaben ergibt sich:
- Die primäre RDS-Instanz liegt in
subnet-0271290b1164913ad. - Die Standby-RDS-Instanz liegt in
subnet-079b9aaba653c430b.
Standby-Instanz stoppen und Subnetz wechseln
Modifizieren Sie die RDS-Instanz mit dem CLI-Befehl modify-db-instance:
% aws rds modify-db-instance --db-instance-identifier rds-stack-rds --no-multi-az --apply-immediately --query "DBInstance.MultiAZ"
true
Um zu prüfen, ob die RDS-Instanz nun Single-AZ ist, führen Sie describe-db-instances erneut aus:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone}" --output table
---------------------------
| DescribeDBInstances |
+-------------+-----------+
| Primary | Standby |
+-------------+-----------+
| us-east-1a | None |
+-------------+-----------+
Aktualisieren Sie die RDS Subnet Group, um das Public Subnet der entfernten Standby durch ein Isolated Subnet derselben Availability Zone zu ersetzen.
% aws rds modify-db-subnet-group --db-subnet-group-name rds-stack-rds-subnetgroup --subnet-ids "subnet-0271290b1164913ad" "subnet-06721c9fdaac5f333"
{
"DBSubnetGroup": {
"DBSubnetGroupName": "rds-stack-rds-subnetgroup",
"DBSubnetGroupDescription": "RDS subnetgroup",
"VpcId": "vpc-090949477d23289ce",
"SubnetGroupStatus": "Complete",
"Subnets": [\
{\
"SubnetIdentifier": "subnet-0271290b1164913ad",\
"SubnetAvailabilityZone": {\
"Name": "us-east-1a"\
},\
"SubnetOutpost": {},\
"SubnetStatus": "Active"\
},\
{\
"SubnetIdentifier": "subnet-06721c9fdaac5f333",\
"SubnetAvailabilityZone": {\
"Name": "us-east-1b"\
},\
"SubnetOutpost": {},\
"SubnetStatus": "Active"\
}\
],
"DBSubnetGroupArn": "arn:aws:rds:us-east-1:825202810339:subgrp:rds-stack-rds-subnetgroup",
"SupportedNetworkTypes": [\
"IPV4"\
]
}
}
Bestätigen Sie die RDS Subnet Group mit describe-db-subnet-groups:
% aws rds describe-db-subnet-groups --db-subnet-group rds-stack-rds-subnetgroup --query "DBSubnetGroups[*].Subnets[*].{AvailabilityZone:SubnetAvailabilityZone.Name,SubnetIdentifier:SubnetIdentifier}" --output table
--------------------------------------------------
| DescribeDBSubnetGroups |
+-------------------+----------------------------+
| AvailabilityZone | SubnetIdentifier |
+-------------------+----------------------------+
| us-east-1a | subnet-0271290b1164913ad |
| us-east-1b | subnet-06721c9fdaac5f333 |
+-------------------+----------------------------+
Aktivieren Sie das Multi-AZ-Deployment mit modify-db-instance wieder:
% aws rds modify-db-instance --db-instance-identifier rds-stack-rds --multi-az --apply-immediately --query "DBInstance.MultiAZ"
false
Die Änderung kann etwas dauern; den Fortschritt verfolgen Sie über DBInstanceStatus:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone}" --output table
----------------------------------------
| DescribeDBInstances |
+------------+-----------+-------------+
| Primary | Standby | Status |
+------------+-----------+-------------+
| us-east-1a| None | modifying |
+------------+-----------+-------------+
Bestätigen Sie die erstellte Standby-Instanz mit describe-db-instances:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone}" --output table
-------------------------------------------
| DescribeDBInstances |
+------------+--------------+-------------+
| Primary | Standby | Status |
+------------+--------------+-------------+
| us-east-1a| us-east-1b | available |
+------------+--------------+-------------+
Was haben wir jetzt?
Wir haben die Standby-Instanz in der sekundären Availability Zone vom Public Subnet ins Isolated Subnet verschoben.

Multi-AZ-RDS mit Primary im Public Subnet und Standby im Isolated Subnet
Schritt 2: Standby heraufstufen und alte Primary verschieben
Notieren Sie sich den RDS-Endpoint, damit Sie überprüfen können, dass die Endpoint-Adresse nach dem Failover unverändert bleibt – nur so ist die Verfügbarkeit gewährleistet:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address}" --output table
-----------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+-------------+-------------+-------------+
| Endpoint | Primary | Standby | Status |
+---------------------------------------------------------+-------------+-------------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | us-east-1a | us-east-1b | available |
+---------------------------------------------------------+-------------+-------------+-------------+
Hinweis: Führen Sie den Reboot der Instanz nur in Wartungsfenstern oder zu lastarmen Zeiten durch, da die Instanzen während des Reboots nicht verfügbar sind.
Starten Sie die RDS-Instanz mit dem Parameter --force-failover neu:
aws rds reboot-db-instance --db-instance-identifier rds-stack-rds --force-failover
Bestätigen Sie das Failover mit describe-db-instances:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address,MultiAZ:MultiAZ}" --output table
----------------------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| Endpoint | MultiAZ | Primary | Standby | Status |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | True | us-east-1b | us-east-1a | available |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
Neue Standby (alte Primary) im Public Subnet entfernen
Da die neue Primary nun im Isolated Subnet liegt, können Sie die soeben degradierte Standby-Instanz entfernen:
% aws rds modify-db-instance --db-instance-identifier rds-stack-rds --no-multi-az --apply-immediately --query "DBInstance.MultiAZ"
true
Die RDS-Instanz steht nun im Status modifying:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address,MultiAZ:MultiAZ}" --output table
----------------------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| Endpoint | MultiAZ | Primary | Standby | Status |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | True | us-east-1b | us-east-1a | modifying |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
Sobald die RDS-Instanz wieder den Status available hat, ist das Standby-Subnetz für den nächsten Schritt freigegeben:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address,MultiAZ:MultiAZ,Pending:PendingModifiedValues}" --output table
-------------------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+----------+-------------+----------+-------------+
| Endpoint | MultiAZ | Primary | Standby | Status |
+---------------------------------------------------------+----------+-------------+----------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | False | us-east-1b | None | available |
+---------------------------------------------------------+----------+-------------+----------+-------------+
Passen Sie nun die RDS Subnet Group an und ersetzen Sie das Public Subnet durch das Isolated Subnet:
% aws rds modify-db-subnet-group --db-subnet-group-name rds-stack-rds-subnetgroup --subnet-ids "subnet-03e58f5428463ad26" "subnet-06721c9fdaac5f333"
{
"DBSubnetGroup": {
"DBSubnetGroupName": "rds-stack-rds-subnetgroup",
"DBSubnetGroupDescription": "RDS subnetgroup",
"VpcId": "vpc-090949477d23289ce",
"SubnetGroupStatus": "Complete",
"Subnets": [\
{\
"SubnetIdentifier": "subnet-06721c9fdaac5f333",\
"SubnetAvailabilityZone": {\
"Name": "us-east-1b"\
},\
"SubnetOutpost": {},\
"SubnetStatus": "Active"\
},\
{\
"SubnetIdentifier": "subnet-03e58f5428463ad26",\
"SubnetAvailabilityZone": {\
"Name": "us-east-1a"\
},\
"SubnetOutpost": {},\
"SubnetStatus": "Active"\
}\
],
"DBSubnetGroupArn": "arn:aws:rds:us-east-1:825202810339:subgrp:rds-stack-rds-subnetgroup",
"SupportedNetworkTypes": [\
"IPV4"\
]
}
}
Deployen Sie die Multi-AZ-RDS erneut:
% aws rds modify-db-instance --db-instance-identifier rds-stack-rds --multi-az --apply-immediately
Die RDS-Instanz wechselt in den Status modifying; der MultiAZ-Wert ist als ausstehende Änderung markiert:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address,MultiAZ:MultiAZ,NewValue:PendingModifiedValues}" --output table
-------------------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+----------+-------------+----------+-------------+
| Endpoint | MultiAZ | Primary | Standby | Status |
+---------------------------------------------------------+----------+-------------+----------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | False | us-east-1b | None | modifying |
+---------------------------------------------------------+----------+-------------+----------+-------------+
|| NewValue ||
|+------------------------------------------------------------+--------------------------------------------+|
|| MultiAZ | True ||
|+------------------------------------------------------------+--------------------------------------------+|
Sobald die RDS-Instanz wieder available ist, wird die neue Standby im Isolated Subnet bereitgestellt:
% aws rds describe-db-instances --db-instance-identifier rds-stack-rds --query "DBInstances[*].{Status:DBInstanceStatus,Primary:AvailabilityZone,Standby:SecondaryAvailabilityZone,Endpoint:Endpoint.Address,MultiAZ:MultiAZ,NewValue:PendingModifiedValues}" --output table
----------------------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| Endpoint | MultiAZ | Primary | Standby | Status |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
| rds-stack-rds.cmkhfj0htgnu.us-east-1.rds.amazonaws.com | True | us-east-1b | us-east-1a | available |
+---------------------------------------------------------+----------+-------------+-------------+-------------+
Was haben wir jetzt?
Wir haben die Standby-Instanz in der sekundären Availability Zone vom Public Subnet ins Isolated Subnet verschoben.

Multi-AZ-RDS in den Isolated Subnets
Schritt 3: CDK-Stack aktualisieren
Da die Architektur nun real angepasst wurde, sollten Sie auch das CDK-Template entsprechend nachziehen. Setzen Sie im CDK-Stack subnetType auf PRIVATE_ISOLATED:
const subnetType: cdk.aws_ec2.SubnetSelection = { subnetType: cdk.aws_ec2.SubnetType.PRIVATE_ISOLATED };
Wenn Sie nach dem Update prüfen möchten, ob CDK-Template und tatsächlicher Stack synchron sind, führen Sie nach der Änderung cdk deploy rds-stack aus. Da die echte Subnet Group bereits aktualisiert ist, ergeben sich keine materialisierten Änderungen. cdk deploy rds-stack sollte erfolgreich durchlaufen:
rds-stack
rds-stack: deploying... [2/2]
✅ rds-stack (no changes)
✨ Deployment time: 2.25s
Outputs:
rds-stack.rdsstackrdsname = rds-stack-rds
rds-stack.rdsstacksubnetgroupname = rds-stack-rds-subnetgroup
Wer der CDK-State-Synchronisation skeptisch gegenübersteht, kann den Stack testweise mit
const subnetType: cdk.aws_ec2.SubnetSelection = { subnetType: cdk.aws_ec2.SubnetType.PUBLIC };deployen.
cdk deploy rds-stacksollte denselben Fehler zu belegten Subnetzen zurückgeben:UPDATE_FAILED | AWS::RDS::DBSubnetGroup | rdsstackrdssubnetgroup Resource handler returned message: "Some of the subnets to be deleted are currently in use: subnet-03e58f5428463ad26, subnet-06721c9fdaac5f333
Eine Amazon RDS in einer isolierten Umgebung ohne Internet-Egress-Routing zu betreiben, bringt eine Reihe entscheidender Vorteile für Datensicherheit, Datenschutz und operative Integrität mit sich:
- Schutz vor Datenexfiltration: Ohne Internet-Egress-Routing sinkt das Risiko der Datenexfiltration deutlich. Sensible Daten bleiben in der kontrollierten Umgebung, sodass versehentliche oder gezielte Datenabflüsse unwahrscheinlicher werden. Das ist besonders wichtig, um Datenschutzvorgaben einzuhalten und schützenswerte Informationen abzusichern.
- Erhalt der operativen Integrität: Der Betrieb der Datenbank in einer isolierten Umgebung sichert deren operative Integrität. Ungewollter Internetzugang – etwa durch Fehlkonfigurationen oder Schwachstellen – kann zu unerwartetem Verhalten, Datenkorruption oder unautorisierten Datenänderungen führen.
- Compliance und regulatorische Anforderungen: Viele Branchen unterliegen strengen Compliance-Vorgaben, die rigorose Kontrollen über Datenverarbeitung und -speicherung verlangen. Die Netzwerkisolation der Datenbank stützt Compliance-Maßnahmen, etwa zur Erfüllung von ISO27001:2013 A.13.1.3.
- Reduzierung der Angriffsfläche: Eine isolierte Umgebung verkleinert die Angriffsfläche der Datenbank und macht sie widerstandsfähiger gegen unterschiedliche Angriffsarten. Ohne direkte Internetverbindung haben Angreifer weniger Möglichkeiten, Schwachstellen auszunutzen, Schadcode einzuschleusen oder Aufklärung zu betreiben.
- Fokus auf interne Bedrohungen: Externe Bedrohungen sind ein Thema – interne können jedoch genauso großen Schaden anrichten. Die Isolation der Datenbank beschränkt den Zugriff auf autorisiertes Personal und senkt damit das Risiko von Insider-Bedrohungen, versehentlicher Datenpreisgabe oder Datenmanipulation.