Estoy ejecutando docker-container en Amazon EC2. Actualmente he agregado credenciales de AWS a Dockerfile. ¿Podría decirme cuál es la mejor manera de hacer esto?
Estoy ejecutando docker-container en Amazon EC2. Actualmente he agregado credenciales de AWS a Dockerfile. ¿Podría decirme cuál es la mejor manera de hacer esto?
Respuestas:
La mejor forma es utilizar el rol de IAM y no ocuparse en absoluto de las credenciales. (ver http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )
Las credenciales se pueden recuperar de http://169.254.169.254.....
Dado que se trata de una dirección IP privada, solo se puede acceder a ella desde instancias EC2.
Todas las bibliotecas de cliente de AWS modernas "saben" cómo obtener, actualizar y usar credenciales desde allí. Entonces, en la mayoría de los casos, ni siquiera necesita saberlo. Simplemente ejecute ec2 con el rol de IAM correcto y listo.
Como opción, puede pasarlos en el tiempo de ejecución como variables de entorno (es decir docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage
)
Puede acceder a estas variables de entorno ejecutando printenv en la terminal.
AWS_SECRET_ACCESS_KEY
, no AWS_SECRET_KEY
, de todos modos tu respuesta fue muy útil. Gracias.
Mucho ha cambiado en Docker desde que se hizo esta pregunta, así que aquí hay un intento de obtener una respuesta actualizada.
Primero, específicamente con las credenciales de AWS en contenedores que ya se ejecutan dentro de la nube, usar roles de IAM como sugiere Vor es una muy buena opción. Si puede hacer eso, agregue uno más más uno a su respuesta y omita el resto de esto.
Una vez que empiezas a ejecutar cosas fuera de la nube, o tienes un tipo diferente de secreto, hay dos lugares clave que recomiendo no almacenar secretos:
Variables de entorno: cuando se definen en un contenedor, todos los procesos dentro del contenedor tienen acceso a ellas, son visibles a través de / proc, las aplicaciones pueden volcar su entorno a stdout donde se almacena en los registros y, lo más importante, aparecen en texto claro cuando inspecciona el contenedor.
En la propia imagen: las imágenes a menudo se envían a registros donde muchos usuarios tienen acceso de extracción, a veces sin que se requieran credenciales para extraer la imagen. Incluso si elimina el secreto de una capa, la imagen se puede desmontar con utilidades comunes de Linux como tar
y el secreto se puede encontrar desde el paso donde se agregó por primera vez a la imagen.
Entonces, ¿qué otras opciones existen para los secretos en los contenedores de Docker?
Opción A: si necesita este secreto solo durante la compilación de su imagen, no puede usar el secreto antes de que comience la compilación y aún no tiene acceso a BuildKit, entonces una compilación de varias etapas es la mejor de las malas opciones. Agregaría el secreto a las etapas iniciales de la compilación, lo usaría allí y luego copiaría la salida de esa etapa sin el secreto a su etapa de lanzamiento, y solo enviaría esa etapa de lanzamiento a los servidores de registro. Este secreto todavía está en la memoria caché de imágenes en el servidor de compilación, por lo que tiendo a usarlo solo como último recurso.
Opción B: también durante el tiempo de compilación, si puede usar BuildKit que se lanzó en 18.09, actualmente hay características experimentales para permitir la inyección de secretos como un montaje de volumen para una sola línea RUN. Ese montaje no se escribe en las capas de imagen, por lo que puede acceder al secreto durante la compilación sin preocuparse de que se envíe a un servidor de registro público. El Dockerfile resultante se ve así:
# 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://... ...
Y lo construyes con un comando en 18.09 o más reciente como:
DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .
Opción C:En tiempo de ejecución en un solo nodo, sin el modo Swarm u otra orquestación, puede montar las credenciales como un volumen de solo lectura. El acceso a esta credencial requiere el mismo acceso que tendría fuera de la ventana acoplable al mismo archivo de credenciales, por lo que no es mejor ni peor que el escenario sin la ventana acoplable. Lo más importante es que el contenido de este archivo no debe ser visible cuando inspecciona el contenedor, ve los registros o envía la imagen a un servidor de registro, ya que el volumen está fuera de ese en todos los escenarios. Esto requiere que copie sus credenciales en el host de la ventana acoplable, aparte de la implementación del contenedor. (Tenga en cuenta que cualquier persona con la capacidad de ejecutar contenedores en ese host puede ver su credencial, ya que el acceso a la API de Docker es root en el host y root puede ver los archivos de cualquier usuario. Si no confía en los usuarios con root en el host ,
Para a docker run
, esto se ve así:
docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image
O para un archivo de redacción, tendría:
version: '3'
services:
app:
image: your_image
volumes:
- $HOME/.aws/credentials:/home/app/.aws/credentials:ro
Opción D:Con herramientas de orquestación como Swarm Mode y Kubernetes, ahora tenemos compatibilidad con secretos que es mejor que un volumen. Con el modo Swarm, el archivo se cifra en el sistema de archivos del administrador (aunque la clave de descifrado a menudo también está allí, lo que permite que el administrador se reinicie sin que un administrador ingrese una clave de descifrado). Más importante aún, el secreto solo se envía a los trabajadores que necesitan el secreto (ejecutando un contenedor con ese secreto), solo se almacena en la memoria del trabajador, nunca en el disco, y se inyecta como un archivo en el contenedor con un tmpfs montar. Los usuarios en el host fuera del enjambre no pueden montar ese secreto directamente en su propio contenedor, sin embargo, con acceso abierto a la API de la ventana acoplable, podrían extraer el secreto de un contenedor en ejecución en el nodo, por lo que nuevamente, limite quién tiene este acceso al API. De componer, esta inyección secreta se ve así:
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
Activa el modo de enjambre con docker swarm init
para un solo nodo, luego sigue las instrucciones para agregar nodos adicionales. Puede crear el secreto externamente con docker secret create aws_creds $HOME/.aws/credentials
. E implementas el archivo de redacción con docker stack deploy -c docker-compose.yml stack_name
.
A menudo versiono mis secretos usando un script de: https://github.com/sudo-bmitch/docker-config-update
Opción E: existen otras herramientas para administrar secretos, y mi favorita es Vault porque brinda la capacidad de crear secretos por tiempo limitado que expiran automáticamente. Luego, cada aplicación obtiene su propio conjunto de tokens para solicitar secretos, y esos tokens les dan la capacidad de solicitar esos secretos por tiempo limitado mientras puedan llegar al servidor de la bóveda. Eso reduce el riesgo si alguna vez se saca un secreto de su red, ya que no funcionará o caducará rápidamente. La funcionalidad específica de AWS for Vault está documentada en https://www.vaultproject.io/docs/secrets/aws/index.html
Otro enfoque consiste en pasar las claves de la máquina host al contenedor de la ventana acoplable. Puede agregar las siguientes líneas al docker-compose
archivo.
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}
Otro enfoque más es crear un volumen temporal de solo lectura en docker-compose.yaml. AWS CLI y SDK (como boto3 o AWS SDK para Java, etc.) están buscando un default
perfil en el ~/.aws/credentials
archivo.
Si desea utilizar otros perfiles, solo necesita exportar la variable AWS_PROFILE antes de ejecutar el 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
En este ejemplo utilicé el usuario root en la ventana acoplable. Si está utilizando otro usuario, simplemente cambie /root/.aws
al directorio de inicio del usuario
:ro
- significa volumen de la ventana acoplable de solo lectura
Es muy útil cuando tiene varios perfiles en ~/.aws/credentials
archivo y también está utilizando MFA. También es útil cuando desea probar localmente docker-container antes de implementarlo en ECS en el que tiene roles de IAM, pero localmente no los tiene.
"%UserProfile%\.aws"
. Así que supongo que tienes que cambiar: - ~/.aws/:/root/.aws:ro
a- %UserProfile%\.aws:/root/.aws:ro
- host:container
sintaxis, si el archivo / carpeta no existe en el host que se crea (como raíz) y el awscli no le agradecerá que le proporcione un archivo de cero bytes. Debe usar el "formulario largo" que especifica el tipo de enlace, la ruta del host y la ruta del contenedor en líneas separadas, esto falla si el archivo no existe, que es lo que desea en su docker-compose.dev. yml pero no en su docker-compose.yml (prod / AWS deploy).
Podrías crear ~/aws_env_creds
conteniendo
touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds
agregue el valor inferior (reemplace la clave suya)
AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C
"esc" para guardar el archivo.
Ejecuta y prueba el contenedor
my_service:
build: .
image: my_image
env_file:
- ~/aws_env_creds