Quelle est la meilleure façon de transmettre les informations d'identification AWS au conteneur Docker?

104

J'utilise docker-container sur Amazon EC2. Actuellement, j'ai ajouté des informations d'identification AWS à Dockerfile. Pourriez-vous s'il vous plaît me faire part de la meilleure façon de procéder?

chopade suraj
la source
2
Et si j'exécute un conteneur Docker sur mon ordinateur portable qui est censé fonctionner également comme par magie dans ECS lorsque je le pousse là-bas? Je vais deviner que j'utilise le drapeau --volume ... quelqu'un doit déjà avoir répondu ...
Randy L

Réponses:

107

Le meilleur moyen est d'utiliser le rôle IAM et de ne pas traiter du tout les informations d'identification. (voir http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

Les informations d'identification peuvent être récupérées à partir de http://169.254.169.254..... Puisqu'il s'agit d'une adresse IP privée, elle ne peut être accessible qu'à partir des instances EC2.

Toutes les bibliothèques clientes AWS modernes «savent» comment récupérer, actualiser et utiliser les informations d'identification à partir de là. Donc, dans la plupart des cas, vous n'avez même pas besoin de le savoir. Exécutez simplement ec2 avec le rôle IAM correct et vous êtes prêt à partir.

En option, vous pouvez les transmettre au moment de l'exécution en tant que variables d'environnement (ie docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

Vous pouvez accéder à ces variables d'environnement en exécutant printenv sur le terminal.

Vor
la source
35
Existe-t-il un bon moyen de le faire lors du développement / test local qui ne compromet pas la sécurité en production? J'aimerais m'assurer qu'une image fonctionne sans la déployer complètement.
honktronic
3
une alternative que j'ai publiée avec des variables d'environnement fonctionne très bien dans un environnement dev / local.
Vor
5
Je me demande si c'est une faute de frappe, mais je dois entrer AWS_SECRET_ACCESS_KEY, non AWS_SECRET_KEY, de toute façon votre réponse a été très utile. Merci.
Akavall
14
Pour le dire simplement (pour ceux qui arrivent à cette réponse de la même manière que moi); Un conteneur docker s'exécutant sur EC2 héritera du même rôle que l'instance hôte. (J'avais besoin d'un "ELI5" comme celui-ci lorsque les commandes de l'AWS CLI dans mes conteneurs fonctionnaient mystérieusement malgré qu'aucune information d'identification ne leur soit transmise!)
Adam Westbrook
8
Un moyen facile d'obtenir les valeurs de clé de votre profil local à affecter à la variable d'environnement à des fins de développement (comme suggéré dans cameroneckelberry.co/words/… ): "aws --profile default configure get aws_access_key_id"
Altair7852
92

Beaucoup de choses ont changé dans Docker depuis que cette question a été posée, voici donc une tentative de réponse mise à jour.

Tout d'abord, en particulier avec les informations d'identification AWS sur les conteneurs déjà exécutés à l'intérieur du cloud, l'utilisation des rôles IAM comme le suggère Vor est une très bonne option. Si vous pouvez le faire, ajoutez un plus un plus à sa réponse et ignorez le reste.


Une fois que vous commencez à exécuter des choses en dehors du cloud ou que vous avez un type de secret différent, il y a deux endroits clés que je déconseille de stocker des secrets:

  1. Variables d'environnement: lorsqu'elles sont définies sur un conteneur, chaque processus à l'intérieur du conteneur y a accès, elles sont visibles via / proc, les applications peuvent vider leur environnement sur stdout où il est stocké dans les journaux, et surtout, ils apparaissent dans texte clair lorsque vous inspectez le conteneur.

  2. Dans l'image elle-même: les images sont souvent poussées vers des registres où de nombreux utilisateurs ont un accès par extraction, parfois sans aucune information d'identification requise pour extraire l'image. Même si vous supprimez le secret d'une couche, l'image peut être désassemblée avec des utilitaires Linux courants tels que taret le secret peut être trouvé à partir de l'étape où il a été ajouté pour la première fois à l'image.


Alors, quelles autres options existe-t-il pour les secrets dans les conteneurs Docker?

Option A: Si vous avez besoin de ce secret uniquement pendant la construction de votre image, ne pouvez pas utiliser le secret avant le début de la construction et n'avez pas encore accès à BuildKit, alors une construction en plusieurs étapes est la meilleure des mauvaises options. Vous ajouteriez le secret aux étapes initiales de la construction, l'utiliseriez là, puis copiez la sortie de cette étape sans le secret dans votre étape de publication, et ne transmettriez que cette étape de publication aux serveurs de registre. Ce secret est toujours dans le cache d'image sur le serveur de construction, donc j'ai tendance à ne l'utiliser qu'en dernier recours.

Option B: également pendant la construction, si vous pouvez utiliser BuildKit qui a été publié en 18.09, il existe actuellement des fonctionnalités expérimentales pour permettre l'injection de secrets en tant que montage de volume pour une seule ligne RUN. Ce montage n'est pas écrit sur les couches d'image, vous pouvez donc accéder au secret pendant la construction sans vous soucier qu'il sera poussé vers un serveur de registre public. Le Dockerfile résultant ressemble à ceci:

# 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://... ...

Et vous le construisez avec une commande en 18.09 ou plus récente comme:

DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .

Option C:Lors de l'exécution sur un seul nœud, sans mode Swarm ou autre orchestration, vous pouvez monter les informations d'identification en tant que volume en lecture seule. L'accès à ces informations d'identification nécessite le même accès que vous auriez en dehors de docker au même fichier d'informations d'identification, donc ce n'est ni meilleur ni pire que le scénario sans docker. Plus important encore, le contenu de ce fichier ne doit pas être visible lorsque vous inspectez le conteneur, affichez les journaux ou poussez l'image vers un serveur de registre, car le volume est en dehors de cela dans tous les scénarios. Cela nécessite que vous copiez vos informations d'identification sur l'hôte docker, indépendamment du déploiement du conteneur. (Notez que toute personne ayant la possibilité d'exécuter des conteneurs sur cet hôte peut afficher vos informations d'identification puisque l'accès à l'API Docker est root sur l'hôte et que root peut afficher les fichiers de n'importe quel utilisateur. Si vous ne faites pas confiance aux utilisateurs avec root sur l'hôte ,

Pour un docker run, cela ressemble à:

docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image

Ou pour un fichier de composition, vous auriez:

version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro

Option D:Avec des outils d'orchestration tels que le mode Swarm et Kubernetes, nous avons désormais une prise en charge des secrets mieux qu'un volume. Avec le mode Swarm, le fichier est chiffré sur le système de fichiers du gestionnaire (bien que la clé de déchiffrement soit souvent là aussi, permettant au gestionnaire d'être redémarré sans qu'un administrateur n'entre une clé de déchiffrement). Plus important encore, le secret n'est envoyé qu'aux workers qui ont besoin du secret (exécutant un conteneur avec ce secret), il n'est stocké qu'en mémoire sur le worker, jamais sur le disque, et il est injecté sous forme de fichier dans le conteneur avec un tmpfs monter. Les utilisateurs sur l'hôte en dehors de swarm ne peuvent pas monter ce secret directement dans leur propre conteneur, cependant, avec un accès ouvert à l'API docker, ils pourraient extraire le secret d'un conteneur en cours d'exécution sur le nœud, donc encore une fois, limiter qui a cet accès au API. De compose, cette injection secrète ressemble à:

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

Vous activez le mode Swarm avec docker swarm initpour un seul nœud, puis suivez les instructions pour ajouter des nœuds supplémentaires. Vous pouvez créer le secret en externe avec docker secret create aws_creds $HOME/.aws/credentials. Et vous déployez le fichier de composition avec docker stack deploy -c docker-compose.yml stack_name.

Je version souvent mes secrets en utilisant un script de: https://github.com/sudo-bmitch/docker-config-update

Option E: D'autres outils existent pour gérer les secrets, et mon préféré est Vault car il donne la possibilité de créer des secrets limités dans le temps qui expirent automatiquement. Chaque application obtient alors son propre ensemble de jetons pour demander des secrets, et ces jetons leur donnent la possibilité de demander ces secrets limités dans le temps tant qu'ils peuvent atteindre le serveur du coffre-fort. Cela réduit le risque si un secret est retiré de votre réseau car il ne fonctionnera pas ou expirera rapidement. La fonctionnalité spécifique à AWS for Vault est documentée à l' adresse https://www.vaultproject.io/docs/secrets/aws/index.html

BMitch
la source
21

Une autre approche consiste à transmettre les clés de la machine hôte au conteneur Docker. Vous pouvez ajouter les lignes suivantes au docker-composefichier.

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}
prafi
la source
3
La variable d'environnement de région correcte est AWS_REGION. Voir stackoverflow.com/questions/44151982/…
John Camerin
3
Veuillez consulter le document officiel qui mentionne AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi
7
Lorsque j'ai utilisé AWS_DEFAULT_REGION, j'ai reçu une exception selon laquelle une région par défaut n'a pas pu être trouvée. Ma recherche a conduit à docs.aws.amazon.com/sdk-for-java/v1/developer-guide/… qui spécifie la variable d'environnement AWS_REGION, et cela a fonctionné pour moi.
John Camerin
Si vous utilisez des informations d'identification temporaires, vous devrez peut-être égalementAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Davos, le
14

Une autre approche consiste à créer un volume temporaire en lecture seule dans docker-compose.yaml. AWS CLI et SDK (comme boto3 ou AWS SDK pour Java, etc.) recherchent le defaultprofil dans le ~/.aws/credentialsfichier.

Si vous souhaitez utiliser d'autres profils, il vous suffit également d'exporter la variable AWS_PROFILE avant d'exécuter la docker-composecommande

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

Dans cet exemple, j'ai utilisé l'utilisateur root sur le docker. Si vous utilisez un autre utilisateur, passez simplement /root/.awsau répertoire de base de l'utilisateur

:ro - représente le volume du docker en lecture seule

C'est très utile lorsque vous avez plusieurs profils dans le ~/.aws/credentialsfichier et que vous utilisez également MFA. Également utile lorsque vous souhaitez tester localement le conteneur docker avant de le déployer sur ECS sur lequel vous avez des rôles IAM, mais pas localement.

Artur Siepietowski
la source
Sur Windows, le catalogue .aws se trouve "%UserProfile%\.aws". Je suppose donc que vous devez changer: - ~/.aws/:/root/.aws:ropour- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski
1
Cela ne fonctionnera qu'avec des processus de construction uniques et non en plusieurs étapes.
wlarcheveque
@wlarcheveque Voulez-vous élaborer?
ErikE
Soyez TRÈS prudent en utilisant la - host:containersyntaxe, si le fichier / dossier n'existe pas sur l'hôte, il est créé (en tant que root) et awscli ne vous remerciera pas de lui avoir fourni un fichier de zéro octet. Vous devez utiliser la "forme longue" qui spécifie le type est bind, le chemin de l'hôte et le chemin du conteneur sur des lignes séparées, cela échoue si le fichier n'existe pas, ce que vous voulez dans votre docker-compose.dev. yml mais pas dans votre docker-compose.yml (prod / AWS deploy).
dragon788
0

Vous pouvez créer ~/aws_env_credscontenant

touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds

ajouter ci-dessous la valeur (remplacer la clé de la vôtre)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

"esc" pour enregistrer le fichier.

Exécuter et tester le conteneur

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
Manimaran Samuthirapandi
la source