Qual è il modo migliore per passare le credenziali AWS al container Docker?


102

Sto eseguendo docker-container su Amazon EC2. Attualmente ho aggiunto le credenziali AWS a Dockerfile. Potresti farmi sapere il modo migliore per farlo?


2
Che ne dici se sto eseguendo un container Docker sul mio laptop che dovrebbe funzionare anche magicamente in ECS quando lo spingo lì? Immagino di usare il flag --volume ... qualcuno deve aver già risposto ...
Randy L

Risposte:


105

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.


35
C'è un buon modo per farlo durante lo sviluppo / test locale che non comprometta la sicurezza in produzione? Mi piacerebbe assicurarmi che un'immagine funzioni senza distribuirla completamente.
honktronic

3
un'alternativa che ho pubblicato con le variabili d'ambiente funziona bene nell'ambiente dev / local.
Vor

5
Mi chiedo se sia un errore di battitura, ma devo entrare AWS_SECRET_ACCESS_KEY, no AWS_SECRET_KEY, comunque la tua risposta è stata molto utile. Grazie.
Akavall

14
Per dirla semplicemente (per coloro che arrivano a questa risposta nello stesso modo in cui ho fatto io); Un container Docker in esecuzione su EC2 erediterà lo stesso ruolo dell'istanza host. (Avevo bisogno di un "ELI5" come questo quando i comandi dell'AWS CLI nei miei container funzionavano misteriosamente nonostante non venissero trasmesse loro credenziali!)
Adam Westbrook

8
Un modo semplice per ottenere i valori chiave dal tuo profilo locale da assegnare alla variabile di ambiente per scopi di sviluppo (come suggerito in cameroneckelberry.co/words/… ): "aws --profile default configure get aws_access_key_id"
Altair7852

89

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:

  1. 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.

  2. 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 tare 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 initper 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


20

Un altro approccio consiste nel passare le chiavi dalla macchina host al container Docker. Puoi aggiungere le seguenti righe al docker-composefile.

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}

3
La variabile di ambiente della regione corretta è AWS_REGION. Vedi stackoverflow.com/questions/44151982/…
John Camerin

3
Si prega di controllare il documento ufficiale che menziona AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi

7
Quando ho utilizzato AWS_DEFAULT_REGION, ho ricevuto un'eccezione per cui non è stato possibile trovare una regione predefinita. La mia ricerca ha portato a docs.aws.amazon.com/sdk-for-java/v1/developer-guide/… che specifica la variabile d'ambiente AWS_REGION e che ha funzionato per me.
John Camerin

Se stai utilizzando credenziali temporanee, potresti anche aver bisogno diAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Davos

13

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 defaultprofilo nel ~/.aws/credentialsfile.

Se desideri utilizzare altri profili, devi solo esportare la variabile AWS_PROFILE prima di eseguire il docker-composecomando

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/.awspassa alla home directory dell'utente

:ro - sta per volume docker di sola lettura

È molto utile quando hai più profili nel ~/.aws/credentialsfile 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.


Sul catalogo di Windows .aws si trova "%UserProfile%\.aws". Quindi presumo che tu debba cambiare: - ~/.aws/:/root/.aws:roa- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski

1
Funzionerà solo con processi di compilazione singoli e non multistadio.
wlarcheveque

@wlarcheveque Ti interessa elaborare?
ErikE

Stai MOLTO attento usando la - host:containersintassi, 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).
dragon788

0

Potresti creare ~/aws_env_credscontenitori

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.