Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Accesso sicuro a RDS privati con Amazon EC2 Instance Connect Endpoint

By Richard KangJun 29, 20237 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

aws security best practices

Per connettersi a risorse AWS private, ad esempio per lanciare comandi psql su un database Postgres RDS, di solito si ricorre a un bastion host. Ma i bastion host possono essere costosi e difficili da gestire. Le mostro come farlo in modo economico, pratico e sicuro con Amazon EC2 Instance Connect.

Le best practice di sicurezza AWS raccomandano di rendere il database accessibile solo su un intervallo di indirizzi IP privati, così da garantire l'isolamento di rete. In altre parole, è buona prassi ospitare il database, ad esempio un'istanza RDS, in una subnet privata.

Un modo per accedere alle risorse private è proprio tramite bastion host.

I bastion host, però, hanno un costo: spesso restano attivi 24x7 solo per consentire accessi sporadici e portano con sé l'onere di gestire un'istanza dedicata, tra patch di sicurezza periodiche e regole di eccezione nel firewall di rete. Un bastion host gestito male può addirittura ampliare la superficie di attacco del sistema: si pensi al rischio di cybersecurity legato a una chiave SSH a lunga scadenza condivisa in anticipo con un partner per accedere al bastion stesso.

La nuova funzionalità Amazon EC2 Instance Connect Endpoint, annunciata il 13 giugno 2023, offre un meccanismo aggiuntivo per accedere ai workloads in una subnet privata senza dover mantenere un bastion host.

Indice dei contenuti

· Indice dei contenuti

· Panoramica

· Procedura passo passo

· Prerequisiti

· Creare un Security Group per l'EC2 Instance Connect Endpoint

· Creare l'EC2 Instance Connect Endpoint

· Configurare la policy IAM per la connessione

· Container DevOps per connettersi all'RDS privato

· Connettersi all'RDS tramite EC2 Instance Connect Endpoint

· Troubleshooting

· InvalidParameter da aws ec2-instance-connect open-tunnel

· Conclusioni

Panoramica

aws security best practices

Architettura complessiva di EC2 Instance Connect che si collega a un RDS in una subnet privata

  1. Gli utenti si connettono da Internet al servizio EC2 Instance Connect Endpoint usando AWS CLI con aws ec2-instance-connect open-tunnel;
  2. Le connessioni EIC sono soggette ai permessi IAM e, in opzione, al logging;
  3. Le connessioni provenienti dall'EC2 Instance Connect Endpoint devono essere ammesse in ingresso dal Security Group del workload;
  4. L'EC2 Instance Connect Endpoint si collega all'RDS tramite IP privati.

Procedura passo passo

Prerequisiti

  1. Per dimostrare che la connettività funziona senza passare da Internet, verificare che la route table della subnet dell'RDS non contenga una route verso un Internet Gateway.
  2. Annotare il Security Group dell'RDS, ad esempio sg-012345.
  3. Annotare la VPC dell'RDS, ad esempio vpc-012345.

Creeremo l'EC2 Instance Connect Endpoint nella stessa VPC, come illustrato nel diagramma in alto. 4. Annotare le subnet private in cui è ospitato l'RDS, ad esempio subnet-0abc101 e subnet-0abc102.

Creeremo l'EC2 Instance Connect Endpoint in una di queste subnet. 5. Annotare gli IP privati dell'RDS, ad esempio 10.0.128.61

Ci collegheremo da Internet all'EC2 Instance Connect tramite AWS CLI; nella versione 2.12.1 di AWS CLI, open-tunnel accetta solo indirizzi IP per aprire un tunnel.

L'IP privato dell'istanza RDS si trova in "Network interfaces" nel Dashboard EC2, filtrando per "Description=RDSNetworkInterface".

Se i risultati restituiscono più voci, restringere la ricerca filtrando per VPC.

Selezionare la Network Interface di interesse: l'indirizzo IPv4 privato è riportato nel pannello "IP addresses".

ec2 security group

Ricerca dell'IP privato di RDSNetworkInterface

Raccolte le informazioni sulle risorse AWS private a cui vogliamo connetterci tramite l'EC2 Instance Connect Endpoint, creeremo prima un Security Group dedicato e poi l'EC2 Instance Connect Endpoint vero e proprio.

Creare un Security Group per l'EC2 Instance Connect Endpoint

Creeremo un Security Group dedicato per l'EC2 Instance Connect Endpoint, senza regole in ingresso e con un'unica regola in uscita per raggiungere l'RDS, identificato tramite il proprio Security Group.

  • Aprire "Create security group" nella console EC2 a questo link https://console.aws.amazon.com/ec2/v2/home#CreateSecurityGroup.
  • Inserire un "Security group name" e una "Description" significativi.
  • Selezionare la VPC dell'RDS. In questo esempio è vpc-012345.
  • Lasciare vuote le "Inbound rules".
  • In "Outbound rules", configurare una regola in uscita con i seguenti parametri:

a. Type: Custom TCP

b. Port range: porta di connettività dell'RDS, ad esempio 5432 per Postgresql

c. Destination: selezionare il Security Group dell'RDS. In questo esempio è sg-012345.

d. Description: Outbound connection from EC2 Instance Connect Endpoint to RDS

  • Selezionare "Create Security Group" in basso a destra.
  • Verrà creato un Security Group dedicato, ad esempio sg-0abcde.

"ec2-instance-connect"

Creazione di un nuovo Security Group per l'EC2 Instance Connect Endpoint

Creare l'EC2 Instance Connect Endpoint

  1. Aprire la pagina Create endpoint nella VPC a questo link https://console.aws.amazon.com/vpc/home#CreateVpcEndpoint
  2. Inserire un nome significativo per l'Endpoint
  3. In Service Category selezionare "EC2 Instance Connect Endpoint"
  4. Nella lista VPC selezionare la VPC dell'RDS. In questo esempio: vpc-012345
  5. In "Security groups" selezionare il Security Group creato per l'EC2 Instance Connect Endpoint. In questo esempio: sg-0abcde
  6. Selezionare una delle subnet che ospitano l'RDS. In questo esempio: subnet-0abc101 o subnet-0abc102
  7. Selezionare "Create endpoint"

"aws

Creare l'EC2 Instance Connect Endpoint utilizzando il relativo Security Group

Configurare la policy IAM per la connessione

Creato l'EC2 Instance Connect Endpoint e impostata la connettività tramite Security Group, passiamo a creare l'utente IAM con il minimo privilegio necessario per utilizzare la connessione.

  1. Aprire Create Policy nella console IAM a questo link https://console.aws.amazon.com/iamv2/home#/policies/create?step=addPermissions
  2. Passare al JSON Policy Editor e incollare la policy seguente. Sostituire la Resource dell'EC2 Instance Connect Endpoint con l'ARN corrispondente e le variabili tra parentesi angolari con i valori del proprio ambiente:
{
"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 per connettersi all'RDS privato

Ora che abbiamo l'EC2 Instance Connect e una policy a privilegi minimi associata all'utente IAM, possiamo testare la connessione.

Ci collegheremo con un client Postgres a partire da una container image Postgres, seguendo l'approccio Container DevOps.

Un approccio Container DevOps consente di ottenere affidabilità, ripetibilità e sicurezza:

  • Affidabilità: la container image racchiude versione degli strumenti, dipendenze e configurazioni, garantendo coerenza.
  • Ripetibilità: la stessa container image viene utilizzata nella pipeline CICD e l'eventuale errore può essere riprodotto fedelmente nell'ambiente di debug DevOps.
  • Sicurezza: la container image viene sottoposta a security scanning e gli script di automazione vengono analizzati con SCAT prima di essere distribuiti al team DevOps e usati nell'automazione CICD.

Connettersi all'RDS tramite EC2 Instance Connect Endpoint

  1. Utilizzare il profilo AWS dell'utente IAM associato alla policy creata in precedenza
  2. Avviare un client Postgres da Docker per collegarsi all'RDS privato con il comando docker run -it — rm — network=bridge postgres psql -h host.docker.internal -U <db user>
  3. Inserire la password del db user
  4. Se tutto funziona correttamente, comparirà il prompt postgres
% docker run -it --rm --network=bridge postgres psql -h host.docker.internal -U postgres
Password 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 da aws ec2-instance-connect open-tunnel

Eseguendo aws ec2-instance-connect open-tunnel ho riscontrato il seguente errore:

% aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id <EIC ID> --private-ip-address <RDS Endpoint DNS> --local-port 5432 --remote-port 5432
Listening 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.

L'errore dipende dall'implementazione del WebSocket di AWS CLI, che richiede un IP privato. Risolvere l'Endpoint dell'RDS al suo IP interno e passarlo come parametro --private-ip-address di aws ec2-instance-connect open-tunnel.

EC2 Instance Connect è un modo decisamente più efficace per collegarsi a risorse private come RDS. Trattandosi di un servizio gestito, alza il livello di sicurezza, riduce i costi e abbatte gli oneri di gestione.

E, soprattutto, è davvero semplice da usare!