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?
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?
Réponses:
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.
AWS_SECRET_ACCESS_KEY
, non AWS_SECRET_KEY
, de toute façon votre réponse a été très utile. Merci.
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:
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.
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 tar
et 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 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 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
Une autre approche consiste à transmettre les clés de la machine hôte au conteneur Docker. 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}
AWS_DEFAULT_REGION
docs.aws.amazon.com/cli/latest/userguide/…
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
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 default
profil dans le ~/.aws/credentials
fichier.
Si vous souhaitez utiliser d'autres profils, il vous suffit également d'exporter la variable AWS_PROFILE avant d'exécuter la 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 docker. Si vous utilisez un autre utilisateur, passez simplement /root/.aws
au 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/credentials
fichier 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.
"%UserProfile%\.aws"
. Je suppose donc que vous devez changer: - ~/.aws/:/root/.aws:ro
pour- %UserProfile%\.aws:/root/.aws:ro
- host:container
syntaxe, 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).
Vous pouvez créer ~/aws_env_creds
contenant
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