web-dev-qa-db-fra.com

Quel est le meilleur moyen de transmettre les informations d'identification AWS au conteneur Docker?

J'exécute docker-container sur Amazon EC2. Actuellement, j'ai ajouté des informations d'identification AWS à Dockerfile. Pourriez-vous s'il vous plaît laissez-moi savoir la meilleure façon de faire cela?

57
suraj chopade

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

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

Toutes les bibliothèques clientes AWS modernes "savent" comment extraire, 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. Il suffit de lancer ec2 avec le rôle correct IAM et vous voilà prêt à partir.

En option, vous pouvez les transmettre au moment de l'exécution en tant que variables d'environnement (c'est-à-dire 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.

67
Vor

Docker a beaucoup changé depuis que cette question a été posée. Voici donc une tentative de réponse actualisée.

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


Une fois que vous commencez à utiliser des éléments en dehors du cloud ou que vous avez un type de secret différent, il existe deux endroits clés que je recommande de ne pas stocker des secrets:

  1. Variables d'environnement: lorsque celles-ci sont définies dans un conteneur, tous les processus du conteneur y ont accès, elles sont visibles via/proc, les applications peuvent vider leur environnement sur la sortie standard où il est stocké dans les journaux, et surtout, texte en clair lorsque vous inspectez le conteneur.

  2. Dans l'image elle-même: les images sont souvent placées dans des registres où de nombreux utilisateurs ont un accès direct, parfois sans les informations d'identification requises pour extraire l'image. Même si vous supprimez le secret d'une couche, l'image peut être désassemblée à l'aide d'utilitaires Linux courants tels que tar et le secret peut être trouvé à partir de l'étape où il a d'abord été ajouté à 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, vous ne pouvez pas l'utiliser avant le début de la construction, et n'avez pas encore accès à BuildKit, alors un multi-stage build est la meilleure des mauvaises options. Vous ajouteriez le secret aux étapes initiales de la construction, l'utiliseriez là-bas, puis copiez la sortie de cette étape sans le secret vers votre étape de publication et ne transmettriez que cette étape aux serveurs de registre. Ce secret est toujours dans le cache des images sur le serveur de génération, donc j'ai tendance à ne l'utiliser qu'en dernier recours.

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

# 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 dans 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. Par conséquent, il 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 Transférez l'image sur un serveur de registre, car le volume est en dehors de cela dans chaque scénario. Pour cela, vous devez copier vos informations d'identification sur l'hôte de menu fixe, séparément du déploiement du conteneur. (Notez que toute personne ayant la capacité d'exécuter des conteneurs sur cet hôte peut voir vos informations d'identification puisque l'accès à l'API du menu fixe est situé sur la racine de l'hôte et que celui-ci peut afficher les fichiers de n'importe quel utilisateur. Si vous ne faites pas confiance aux utilisateurs possédant la racine sur l'hôte , ne leur donnez pas alors un accès à l’API docker.)

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 Swarm Mode et Kubernetes, nous disposons désormais d'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 présente également, ce qui permet de redémarrer le gestionnaire sans qu'un administrateur n'entre une clé de déchiffrement). Plus important encore, le secret est uniquement envoyé aux travailleurs qui en ont besoin (exécuter un conteneur avec ce secret), il est uniquement stocké en mémoire sur le travailleur, jamais sur disque, et il est injecté sous forme de fichier dans le conteneur avec un tmpfs. monter. Les utilisateurs de l'hôte situés en dehors de swarm ne peuvent pas monter ce secret directement dans leur propre conteneur. Toutefois, avec un accès ouvert à l'API de docker, ils peuvent extraire le secret d'un conteneur en cours d'exécution sur le nœud. API. De composition, 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 essaim avec docker swarm init pour 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 permet de créer des secrets à durée limitée qui expirent automatiquement. Chaque application reçoit alors son propre ensemble de jetons pour demander des secrets, et ces jetons leur permettent de demander ces secrets limités dans le temps aussi longtemps qu'ils peuvent atteindre le serveur de coffre-fort. Cela réduit le risque qu'un secret soit retiré de votre réseau car il ne fonctionnerait pas ou expirerait rapidement. La fonctionnalité spécifique à AWS pour Vault est décrite à https: //www.vaultproject.io/docs/secrets/aws/index.html

21
BMitch

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

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}
8
prafi

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 un profil default dans ~/.aws/credentials fichier.

Si vous souhaitez utiliser d'autres profils, vous devez également exporter la variable AWS_PROFILE avant d'exécuter docker-compose commande

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 menu fixe. Si vous utilisez un autre utilisateur, il suffit de changer /root/.aws vers le répertoire personnel de l'utilisateur

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

C'est très utile lorsque vous avez plusieurs profils dans ~/.aws/credentials fichier et 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.

4
artusiep