virginia ec2 east aws bash shell amazon-ec2 amazon-s3 user-data

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 KMS utilizando el 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 variables ENV
  • 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 archivo Instance-Init.sh de S3 . Debido al IAM Role asignado a mi instancia, mis credenciales de AWS son descubiertas automáticamente por aws-cli . El IAM 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

  1. ¿Es esto una práctica común o estoy soñando con una mala idea aquí?
  2. ¿El hecho de que el archivo se descargue y almacene (aunque brevemente) en la nueva instancia constituye una vulnerabilidad?
  3. ¿Existe un método mejor para eliminar el archivo de una manera más segura?
  4. ¿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 archivo Instance-Init.sh .
  5. ¿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 $@