bash - east - ¿Es seguro almacenar scripts de shell EC2 User-Data en un depósito privado de S3?
ec2 dashboard (2)
Tengo un ASG de EC2 en AWS y estoy interesado en almacenar el script de shell que se utiliza para instanciar cualquier instancia dada en un cubo de S3 y descargarlo y ejecutarlo en el momento de la creación de instancias, pero todo se siente un poco desvencijado aunque estoy usando una IAM Instance Role
, la transferencia a través de HTTPS y el cifrado de la secuencia de comandos mientras está en reposo en el depósito de S3 utilizando utilizando el KMS
S3 Server Side Encryption
( porque el método KMS
estaba generando un error ''Desconocido'' ).
La puesta en marcha
- Creé un
IAM Instance Role
que se asigna a cualquier instancia en mi ASG en la instanciación, lo que da como resultado que mis credenciales de AWS se incorporen a la instancia como variablesENV
- Subí y cifré mi script
Instance-Init.sh
a S3, lo que dio como resultado un punto final privado como el siguiente: https://s3.amazonaws.com/super-secret-bucket/Instance-Init.sh
En el campo de User-Data
Ingresé lo siguiente en el campo User Data
del User Data
al crear la Launch Configuration
. Quiero que use mi ASG:
#!/bin/bash
apt-get update
apt-get -y install python-pip
apt-get -y install awscli
cd /home/ubuntu
aws s3 cp s3://super-secret-bucket/Instance-Init.sh . --region us-east-1
chmod +x Instance-Init.sh
. Instance-Init.sh
shred -u -z -n 27 Instance-Init.sh
Lo anterior hace lo siguiente:
- Listas de paquetes de actualizaciones
- Instala Python (requerido para ejecutar
aws-cli
) - Instala
aws-cli
- Cambios en el directorio de usuario
/home/ubuntu
- Utiliza el
aws-cli
para descargar el archivoInstance-Init.sh
deS3
. Debido alIAM Role
asignado a mi instancia, mis credenciales de AWS son descubiertas automáticamente poraws-cli
. ElIAM Role
también otorga a mi instancia los permisos necesarios para descifrar el archivo. - Lo hace ejecutable
- Ejecuta el script
- Borra el script después de que se haya completado.
El script Instance-Init.sh
La secuencia de comandos en sí misma hará cosas como configurar env
vars y la ventana docker run
los contenedores que necesito implementar en mi instancia. Un poco así:
#!/bin/bash
export MONGO_USER=''MyMongoUserName''
export MONGO_PASS=''Top-Secret-Dont-Tell-Anyone''
docker login -u <username> -p <password> -e <email>
docker run - e MONGO_USER=${MONGO_USER} -e MONGO_PASS=${MONGO_PASS} --name MyContainerName quay.io/myQuayNameSpace/MyAppName:latest
Muy útil
Esto crea una forma muy útil de actualizar User-Data
scripts de User-Data
sin la necesidad de crear una nueva Launch Config
cada vez que necesite hacer un cambio menor. Y hace un gran trabajo de obtener env
vars de su base de código y en un espacio estrecho y controlable (el propio script Instance-Init.sh
).
Pero todo se siente un poco inseguro. La idea de poner mis credenciales de base de datos maestras en un archivo en S3 es inquietante por decir lo menos.
Las preguntas
- ¿Es esto una práctica común o estoy soñando con una mala idea aquí?
- ¿El hecho de que el archivo se descargue y almacene (aunque brevemente) en la nueva instancia constituye una vulnerabilidad?
- ¿Existe un método mejor para eliminar el archivo de una manera más segura?
- ¿Importa incluso si el archivo se elimina después de ejecutarse? Teniendo en cuenta que los secretos se transfieren a las variables
env
, casi parece redundante eliminar el archivoInstance-Init.sh
. - ¿Hay algo que me estoy perdiendo en mis días nacientes de operaciones?
Gracias por cualquier ayuda por adelantado.
Lo que estás describiendo es casi exactamente lo que estamos usando para crear una instancia de los contenedores de Docker de nuestro registro (ahora usamos v2 auto-hospedado / privado, registro de docker respaldado por s3 en lugar de Quay) en producción. FWIW, tuve la misma sensación de "esto se siente desvencijado" que describió cuando recorrió este camino por primera vez, pero después de casi un año de hacerlo, y en comparación con la alternativa de almacenar estos datos de configuración confidenciales en un repositorio o incorporados a la imagen: estoy seguro de que es una de las mejores maneras de manejar estos datos. Ahora, dicho esto, actualmente estamos considerando usar el nuevo software Vault de Hashicorp para implementar secretos de configuración para reemplazar este contenedor de script de shell secreto encriptado "compartido" (digamos que cinco veces más rápido). Estamos pensando que Vault será el equivalente de externalizar criptografía a la comunidad de código abierto (donde pertenece), pero para el almacenamiento de configuración.
En pocas palabras, no hemos encontrado muchos problemas con una situación muy similar que hemos estado usando durante aproximadamente un año, pero ahora estamos considerando el uso de un proyecto de código abierto externo (Vault de Hashicorp) para reemplazar nuestro método de cosecha propia. ¡Buena suerte!
Una alternativa a Vault es usar credstash , que aprovecha AWS KMS y DynamoDB para lograr un objetivo similar.
De hecho, uso credstash para importar dinámicamente datos de configuración confidenciales al iniciar el contenedor a través de un simple script de punto de entrada: de esta manera, los datos confidenciales no se exponen a través de la inspección de la ventana acoplable o en los registros de la ventana acoplable, etc.
Aquí hay un ejemplo de secuencia de comandos de punto de entrada (para una aplicación de Python): la belleza aquí es que todavía puede pasar las credenciales a través de variables de entorno para entornos que no sean AWS / dev.
#!/bin/bash
set -e
# Activate virtual environment
. /app/venv/bin/activate
# Pull sensitive credentials from AWS credstash if CREDENTIAL_STORE is set with a little help from jq
# AWS_DEFAULT_REGION must also be set
# Note values are Base64 encoded in this example
if [[ -n $CREDENTIAL_STORE ]]; then
items=$(credstash -t $CREDENTIAL_STORE getall -f json | jq ''to_entries | .[]'' -r)
keys=$(echo $items | jq .key -r)
for key in $keys
do
export $key=$(echo $items | jq ''select(.key=="''$key''") | .value'' -r | base64 --decode)
done
fi
exec $@