
Private AWS-Ressourcen wie eine Postgres-RDS per psql ansprechen – das läuft üblicherweise über einen Bastion Host. Bastion Hosts sind aber teuer und aufwendig im Betrieb. In diesem Beitrag zeige ich, wie das günstig, komfortabel und sicher mit Amazon EC2 Instance Connect gelingt.
Die AWS Security Best Practices empfehlen, die Datenbank ausschließlich über einen privaten IP-Adressbereich erreichbar zu machen, um die Netzwerkisolation sicherzustellen. Anders gesagt: Datenbanken wie RDS gehören als Best Practice in ein privates Subnetz.
Eine Möglichkeit, auf private Ressourcen zuzugreifen, ist der Bastion Host.
Bastion Hosts verursachen jedoch zusätzliche Kosten, denn sie laufen oft rund um die Uhr, nur um gelegentliche Zugriffe zu ermöglichen. Hinzu kommt der Aufwand für eine Sonderinstanz: regelmäßige Sicherheits-Patches und Ausnahmeregeln in der Netzwerk-Firewall. Schlecht gepflegte Bastion Hosts vergrößern die Angriffsfläche – etwa durch einen langlebigen SSH-Schlüssel, den Sie vorab mit einem Geschäftspartner geteilt haben, um den Zugriff auf den Bastion Host zu ermöglichen.
Das am 13. Juni 2023 vorgestellte Feature Amazon EC2 Instance Connect Endpoint bietet eine zusätzliche Möglichkeit, auf workloads in einem privaten Subnetz zuzugreifen, ohne einen eigenen Bastion Host betreiben zu müssen.
Inhaltsverzeichnis
· Security Group für den EC2 Instance Connect Endpoint anlegen
· EC2 Instance Connect Endpoint erstellen
· IAM-Policy für die Verbindung konfigurieren
· Container-DevOps-Verbindung zur privaten RDS
· Verbindung zur RDS über den EC2 Instance Connect Endpoint
· InvalidParameter bei aws ec2-instance-connect open-tunnel
Überblick

Die Gesamtarchitektur: EC2 Instance Connect verbindet sich mit einer RDS in einem privaten Subnetz
- Nutzer verbinden sich aus dem Internet über die AWS CLI
aws ec2-instance-connect open-tunnelmit dem EC2 Instance Connect Endpoint Service; - Die EIC-Verbindungen unterliegen IAM-Berechtigungen und lassen sich optional protokollieren;
- Verbindungen vom EC2 Instance Connect Endpoint müssen in der Security Group des workloads als eingehend zugelassen sein;
- Der EC2 Instance Connect Endpoint verbindet sich über private IPs mit der RDS.
Schritt für Schritt
Voraussetzungen
- Damit sich die Konnektivität ohne Internetzugang demonstrieren lässt, darf die Routing-Tabelle Ihres RDS-Subnetzes keine Route zu einem Internet Gateway enthalten.
- Notieren Sie sich die Security Group der RDS, etwa
sg-012345. - Notieren Sie sich die VPC der RDS, etwa
vpc-012345.
Den EC2 Instance Connect Endpoint legen wir in derselben VPC an, wie im Diagramm oben gezeigt. 4. Notieren Sie sich die privaten Subnetze, in denen die RDS gehostet ist, etwa subnet-0abc101 und subnet-0abc102.
Den EC2 Instance Connect Endpoint legen wir in einem dieser Subnetze an. 5. Notieren Sie sich die privaten IPs der RDS, etwa 10.0.128.61
Wir verbinden uns aus dem Internet über die AWS CLI mit EC2 Instance Connect. Stand AWS CLI Version 2.12.1 akzeptiert open-tunnel ausschließlich IP-Adressen für den Tunnelaufbau.
Die private IP der RDS-Instanz finden Sie unter "Network interfaces" im EC2 Dashboard, gefiltert nach " Description=RDSNetworkInterface".
Bei mehreren Treffern grenzen Sie das Ergebnis über die VPC ein.
Wählen Sie das passende Network Interface aus – die private IPv4-Adresse steht im Bereich "IP addresses".

Suche nach der privaten IP des RDSNetworkInterface
Mit den Informationen zu den privaten AWS-Ressourcen, mit denen wir uns über den EC2 Instance Connect Endpoint verbinden möchten, legen wir zuerst eine Security Group für den EC2 Instance Connect Endpoint an und anschließend den Endpoint selbst.
Security Group für den EC2 Instance Connect Endpoint anlegen
Wir erstellen eine eigenständige Security Group für den EC2 Instance Connect Endpoint. Sie hat keine Inbound-Regeln, aber eine Outbound-Regel, die die Verbindung zur RDS über deren Security Group erlaubt.
- Öffnen Sie "Create security group" in der EC2-Konsole über diesen Link https://console.aws.amazon.com/ec2/v2/home#CreateSecurityGroup.
- Vergeben Sie einen aussagekräftigen "Security group name" und eine "Description".
- Wählen Sie die VPC der RDS aus. In diesem Beispiel
vpc-012345 - Lassen Sie die "Inbound rules" leer.
- Konfigurieren Sie unter "Outbound rules" eine Outbound-Regel mit folgenden Werten:
a. Type: Custom TCP
b. Port range: RDS-Verbindungsport, z. B. 5432 für PostgreSQL
c. Destination: Security Group der RDS auswählen. In diesem Beispiel sg-012345
d. Description: Outbound-Verbindung vom EC2 Instance Connect Endpoint zur RDS
- Klicken Sie unten rechts auf "Create Security Group".
- Es wird eine eigenständige Security Group angelegt, etwa
sg-0abcde

Eine neue Security Group für den EC2 Instance Connect Endpoint anlegen
EC2 Instance Connect Endpoint erstellen
- Öffnen Sie die Seite "Create endpoint" in der VPC über diesen Link https://console.aws.amazon.com/vpc/home#CreateVpcEndpoint
- Geben Sie einen aussagekräftigen Endpoint-Namen ein.
- Wählen Sie unter "Service Category" den Eintrag "EC2 Instance Connect Endpoint".
- Wählen Sie in der VPC-Liste die VPC der RDS aus. In diesem Beispiel
vpc-012345 - Wählen Sie unter "Security groups" die zuvor angelegte Security Group für den EC2 Instance Connect Endpoint. In diesem Beispiel
sg-0abcde - Wählen Sie eines der Subnetze, in denen die RDS gehostet ist. In diesem Beispiel entweder
subnet-0abc101odersubnet-0abc102 - Klicken Sie auf "Create endpoint".

EC2 Instance Connect Endpoint anlegen und die zugehörige Security Group verwenden
IAM-Policy für die Verbindung konfigurieren
Nachdem der EC2 Instance Connect Endpoint angelegt und die Konnektivität über die zugewiesenen Security Groups eingerichtet ist, legen wir nun einen IAM-Benutzer mit minimalen Rechten an, der die Verbindung nutzen darf.
- Öffnen Sie "Create Policy" in der IAM-Konsole über diesen Link https://console.aws.amazon.com/iamv2/home#/policies/create?step=addPermissions
- Wechseln Sie zum JSON Policy Editor und tragen Sie die folgende Policy ein. Ersetzen Sie die Resource des EC2 Instance Connect Endpoints durch die passende ARN und die Variablen in spitzen Klammern durch Ihre Umgebungswerte:
{ "Version": "2012-10-17", "Statement": [\ {\ "Effect": "Allow",\ "Action": "ec2-instance-connect:OpenTunnel",\ "Resource": "arn:aws:ec2:<AWS Region>:<AWS Account>:instance-connect-endpoint/eice-<EICE ID>",\ "Condition": {\ "NumericEquals": {\ "ec2-instance-connect:remotePort": "5432"\ },\ "IpAddress": {\ "ec2-instance-connect:privateIpAddress": [\ "<CIDR of subnet-0abc101>",\ "<CIDR of subnet-0abc102>"\ ]\ }\ }\ },\ {\ "Sid": "Describe",\ "Action": [\ "ec2:DescribeInstances",\ "ec2:DescribeInstanceConnectEndpoints"\ ],\ "Effect": "Allow",\ "Resource": "*"\ }\ ]}Container-DevOps-Verbindung zur privaten RDS
Mit dem EC2 Instance Connect und der Least-Privilege-Policy am IAM-Benutzer können wir die Verbindung jetzt testen.
Wir verbinden uns nach dem Container-DevOps-Ansatz mit einem Postgres-Client aus einem Postgres-Container-Image.
Container-DevOps sorgt für Zuverlässigkeit, Reproduzierbarkeit und Sicherheit:
- Zuverlässigkeit durch ein Container-Image, das eine konsistente Version der Tools, Abhängigkeiten und Einstellungen mitbringt.
- Reproduzierbarkeit, weil dasselbe Container-Image in der CICD-Pipeline läuft und sich derselbe Fehler in der DevOps-Debugging-Umgebung nachstellen lässt.
- Sicherheit, indem Container-Images per Security-Scan und Automatisierungsskripte per SCAT geprüft werden, bevor sie im DevOps-Team und in der CICD-Automatisierung zum Einsatz kommen.
Verbindung zur RDS über den EC2 Instance Connect Endpoint
- Verwenden Sie das AWS-Profil des IAM-Benutzers, dem die oben angelegte Policy zugewiesen ist.
- Starten Sie einen Postgres-Client aus Docker, um sich mit der privaten RDS zu verbinden:
docker run -it — rm — network=bridge postgres psql -h host.docker.internal -U <db user> - Geben Sie das Passwort für den
db userein. - Wenn alles passt, erscheint der
postgres-Prompt.
% docker run -it --rm --network=bridge postgres psql -h host.docker.internal -U postgresPassword for user postgres:psql (15.3 (Debian 15.3-1.pgdg120+1), server 14.7)SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)Type "help" for help.
postgres=>Troubleshooting
InvalidParameter bei awsec2-instance-connect open-tunnel
Beim Ausführen von aws ec2-instance-connect open-tunnel trat folgender Fehler auf:
% aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id <EIC ID> --private-ip-address <RDS Endpoint DNS> --local-port 5432 --remote-port 5432Listening for connections on port 5432.
[1] Accepted new tcp connection, opening websocket tunnel.2023-06-20 23:32:09,666 - awscli.customizations.ec2instanceconnect.websocket - ERROR - {"ErrorCode":"InvalidParameter","Message":"The specified PrivateIpAddress is not valid. Specify a valid IPv4 PrivateIpAddress and retry your request."}
AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE: Failed to upgrade HTTP connection to Websocket.Der Fehler tritt auf, weil die WebSocket-Implementierung der AWS CLI eine private IP erwartet. Lösen Sie den RDS-Endpoint zur internen IP auf und übergeben Sie diese als Parameter --private-ip-address an aws ec2-instance-connect open-tunnel.
EC2 Instance Connect ist ein deutlich besserer Weg, sich mit privaten Ressourcen wie RDS zu verbinden. Als Managed Service bringt es mehr Sicherheit, spart Kosten und reduziert den Verwaltungsaufwand.
Und das Beste: Die Bedienung ist denkbar einfach.