Sto eseguendo docker-container su Amazon EC2. Attualmente ho aggiunto le credenziali AWS a Dockerfile. Potresti farmi sapere il modo migliore per farlo?
Sto eseguendo docker-container su Amazon EC2. Attualmente ho aggiunto le credenziali AWS a Dockerfile. Potresti farmi sapere il modo migliore per farlo?
Risposte:
Il modo migliore è utilizzare il ruolo IAM e non gestire affatto le credenziali. (vedi http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )
È possibile recuperare le credenziali da http://169.254.169.254.....
Poiché si tratta di un indirizzo IP privato, potrebbe essere accessibile solo dalle istanze EC2.
Tutte le moderne librerie client AWS "sanno" come recuperare, aggiornare e utilizzare le credenziali da lì. Quindi nella maggior parte dei casi non hai nemmeno bisogno di saperlo. Esegui ec2 con il ruolo IAM corretto e sei a posto.
Come opzione puoi passarli al runtime come variabili d'ambiente (cioè docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage
)
È possibile accedere a queste variabili di ambiente eseguendo printenv sul terminale.
AWS_SECRET_ACCESS_KEY
, no AWS_SECRET_KEY
, comunque la tua risposta è stata molto utile. Grazie.
Molto è cambiato in Docker da quando è stata posta questa domanda, quindi ecco un tentativo di una risposta aggiornata.
Innanzitutto, in particolare con le credenziali AWS sui container già in esecuzione all'interno del cloud, l'utilizzo dei ruoli IAM come suggerisce Vor è un'ottima opzione. Se puoi farlo, aggiungi un altro più uno alla sua risposta e salta il resto.
Una volta che inizi a eseguire le cose al di fuori del cloud o hai un diverso tipo di segreto, ci sono due punti chiave che consiglio di non memorizzare i segreti:
Variabili d'ambiente: quando queste sono definite su un contenitore, ogni processo all'interno del contenitore ha accesso ad esse, sono visibili tramite / proc, le app possono scaricare il loro ambiente su stdout dove viene memorizzato nei log e, soprattutto, compaiono in testo in chiaro quando si ispeziona il contenitore.
Nell'immagine stessa: le immagini spesso vengono inviate a registri in cui molti utenti hanno accesso pull, a volte senza alcuna credenziale richiesta per estrarre l'immagine. Anche se elimini il segreto da un livello, l'immagine può essere smontata con utilità Linux comuni come tar
e il segreto può essere trovato dal passaggio in cui è stato aggiunto per la prima volta all'immagine.
Quindi quali altre opzioni ci sono per i segreti nei container Docker?
Opzione A: Se hai bisogno di questo segreto solo durante la compilazione della tua immagine, non puoi usare il segreto prima dell'inizio della compilazione e non hai ancora accesso a BuildKit, allora una build in più fasi è la migliore delle cattive opzioni. Dovresti aggiungere il segreto alle fasi iniziali della build, usarlo lì e quindi copiare l'output di quella fase senza il segreto nella tua fase di rilascio e inviare quella fase di rilascio solo ai server del registro. Questo segreto è ancora nella cache delle immagini sul server di compilazione, quindi tendo a usarlo solo come ultima risorsa.
Opzione B: anche durante la fase di compilazione, se è possibile utilizzare BuildKit che è stato rilasciato nel 18.09, sono attualmente disponibili funzionalità sperimentali per consentire l'iniezione di segreti come montaggio del volume per una singola riga RUN. Quel montaggio non viene scritto sui livelli dell'immagine, quindi puoi accedere al segreto durante la compilazione senza preoccuparti che venga inviato a un server del registro pubblico. Il Dockerfile risultante ha il seguente aspetto:
# syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...
E lo costruisci con un comando in 18.09 o più recente come:
DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .
Opzione C:In fase di esecuzione su un singolo nodo, senza Swarm Mode o altra orchestrazione, è possibile montare le credenziali come volume di sola lettura. L'accesso a questa credenziale richiede lo stesso accesso che avresti all'esterno della finestra mobile allo stesso file delle credenziali, quindi non è migliore o peggiore dello scenario senza finestra mobile. Ancora più importante, il contenuto di questo file non dovrebbe essere visibile quando si ispeziona il contenitore, si visualizzano i registri o si invia l'immagine a un server del registro, poiché il volume è al di fuori di quello in ogni scenario. Ciò richiede la copia delle credenziali sull'host Docker, separatamente dalla distribuzione del contenitore. (Nota, chiunque abbia la possibilità di eseguire contenitori su quell'host può visualizzare le tue credenziali poiché l'accesso all'API Docker è root sull'host e root può visualizzare i file di qualsiasi utente. Se non ti fidi degli utenti con root sull'host ,
Per a docker run
, questo assomiglia a:
docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image
O per un file di composizione, avresti:
version: '3'
services:
app:
image: your_image
volumes:
- $HOME/.aws/credentials:/home/app/.aws/credentials:ro
Opzione D:Con strumenti di orchestrazione come Swarm Mode e Kubernetes, ora abbiamo un supporto segreto che è meglio di un volume. Con la modalità Swarm, il file viene crittografato sul file system del gestore (sebbene spesso sia presente anche la chiave di decrittografia, consentendo il riavvio del gestore senza che un amministratore immetta una chiave di decrittografia). Ancora più importante, il segreto viene inviato solo ai lavoratori che necessitano del segreto (eseguendo un contenitore con quel segreto), viene archiviato solo in memoria sul lavoratore, mai su disco, e viene iniettato come file nel contenitore con un tmpfs montare. Gli utenti sull'host al di fuori di swarm non possono montare quel segreto direttamente nel proprio contenitore, tuttavia, con accesso aperto all'API docker, potrebbero estrarre il segreto da un contenitore in esecuzione sul nodo, quindi, di nuovo, limitare chi ha questo accesso al API. Dalla composizione, questa iniezione segreta assomiglia a:
version: '3.7'
secrets:
aws_creds:
external: true
services:
app:
image: your_image
secrets:
- source: aws_creds
target: /home/user/.aws/credentials
uid: '1000'
gid: '1000'
mode: 0700
Attivi la modalità sciame con docker swarm init
per un singolo nodo, quindi segui le indicazioni per aggiungere ulteriori nodi. Puoi creare il segreto esternamente con docker secret create aws_creds $HOME/.aws/credentials
. E distribuisci il file di composizione con docker stack deploy -c docker-compose.yml stack_name
.
Spesso eseguo la versione dei miei segreti usando uno script da: https://github.com/sudo-bmitch/docker-config-update
Opzione E: esistono altri strumenti per gestire i segreti e il mio preferito è Vault perché dà la possibilità di creare segreti a tempo limitato che scadono automaticamente. Ogni applicazione riceve quindi il proprio set di token per richiedere segreti e quei token danno loro la possibilità di richiedere quei segreti a tempo limitato per tutto il tempo in cui possono raggiungere il server del vault. Ciò riduce il rischio se un segreto viene mai rimosso dalla rete poiché non funzionerà o scadrà rapidamente. La funzionalità specifica di AWS per Vault è documentata su https://www.vaultproject.io/docs/secrets/aws/index.html
Un altro approccio consiste nel passare le chiavi dalla macchina host al container Docker. Puoi aggiungere le seguenti righe al docker-compose
file.
services:
web:
build: .
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
AWS_DEFAULT_REGION
docs.aws.amazon.com/cli/latest/userguide/…
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Un altro approccio consiste nel creare un volume di sola lettura temporaneo in docker-compose.yaml. AWS CLI e SDK (come boto3 o AWS SDK per Java ecc.) Stanno cercando il default
profilo nel ~/.aws/credentials
file.
Se desideri utilizzare altri profili, devi solo esportare la variabile AWS_PROFILE prima di eseguire il docker-compose
comando
export AWS_PROFILE=some_other_profile_name
version: '3'
services:
service-name:
image: docker-image-name:latest
environment:
- AWS_PROFILE=${AWS_PROFILE}
volumes:
- ~/.aws/:/root/.aws:ro
In questo esempio ho usato l'utente root su docker. Se stai usando un altro utente, /root/.aws
passa alla home directory dell'utente
:ro
- sta per volume docker di sola lettura
È molto utile quando hai più profili nel ~/.aws/credentials
file e stai anche usando MFA. Utile anche quando si desidera testare localmente docker-container prima di distribuirlo su ECS su cui si hanno ruoli IAM, ma localmente no.
"%UserProfile%\.aws"
. Quindi presumo che tu debba cambiare: - ~/.aws/:/root/.aws:ro
a- %UserProfile%\.aws:/root/.aws:ro
- host:container
sintassi, se il file / cartella non esiste sull'host viene creato (come root) e awscli non ti ringrazierà per avergli fornito un file a zero byte. Dovresti usare la "forma lunga" che specifica che il tipo è bind, il percorso host e il percorso del contenitore su righe separate, questo fallisce se il file non esiste, che è quello che vuoi nel tuo docker-compose.dev. yml ma non nel tuo docker-compose.yml (prod / AWS deploy).
Potresti creare ~/aws_env_creds
contenitori
touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds
aggiungi sotto il valore (Sostituisci la tua chiave)
AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C
"esc" per salvare il file.
Esegui e prova il contenitore
my_service:
build: .
image: my_image
env_file:
- ~/aws_env_creds