Desarrollo para AWS: Roles IAM, claves, credenciales y despliegue
Publicado originalmente en Santander Global T&O.
Also available in english.
¿Cómo tenemos que usar los roles en aplicaciones desarrolladas de forma nativa para ser desplegadas en AWS (Amazon Web Services)? En este artículo, hablaremos del desarrollo en AWS, de los roles, de usuarios, claves, y otros aspectos relacionados con la seguridad en AWS.
Será una introducción muy básica a algunos conceptos sobre el funcionamiento interno de los permisos de AWS, y otros no tan básicos, pero siempre fáciles de entender e implementar.
En Santander, apostamos por una estrategia de nube híbrida usando Azure y AWS como nubes públicas y OHE que es nuestra nube privada. ¿Quieres saber cómo desarrollamos nuestra estrategia cloud?
Los conceptos aquí descritos son específicos de AWS pero también se pueden aplicar en otros proveedores de nube como Azure o Google Cloud.
1. Conceptos básicos IAM (Identity and Access Management)
Para empezar, hablaremos de AWS IAM, usuarios, roles y permisos. Este es uno de los aspectos básicos a la hora de desarrollar aplicaciones, y crearlas de forma segura. Además, también es una de las cosas más difíciles de entender para los recién llegados.
AWS IAM es el servicio donde se gestionan los usuarios, grupos, permisos, etc. No mentiría si dijera que es el servicio más importante de AWS…
AWS tiene muchos servicios como computación (EC2), almacenamiento de objetos (S3), mensajería (SQS/SNS), bases de datos (RDS), sólo por nombrar algunos. Cuando queremos utilizar o conectarnos a estos servicios, necesitamos un usuario en AWS. Este usuario tiene una serie de políticas asociadas, por ejemplo:
{
"Version": "2012-10-17,"
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "*"
}
]
}
La política anterior nos permite ejecutar todas las acciones de S3 (s3:*
) en cualquier recurso (*
); por ejemplo, podríamos crear un bucket de S3 (un contenedor de objetos donde se pueden subir datos), pero no podríamos crear una instancia de EC2 (una máquina virtual). Con las políticas podemos restringir lo que un usuario puede y no puede hacer en AWS.
Además, ¿podemos crear un bucket S3 desde un script, sin usar la consola web? No hay problema; puedes instalar la CLI de AWS (o usar otras herramientas como CloudFormation, Terraform o Pulumi) y generar una clave de acceso (un par de un ID de clave de acceso, y una clave de acceso secreta) y luego podrías ejecutar:
AWS_ACCESS_KEY_ID=ABCD
AWS_SECRET_ACCESS_KEY=EF1234
aws s3 mb s3://mybucket
En este caso, la CLI de AWS utilizará las variables de entorno AWS_ACCESS_KEY_ID
y AWS_SECRET_ACCESS_KEY
. También puedes almacenar estas claves manualmente en el archivo ~/.aws/credentials
o ejecutando aws configure
. Como puedes ver, el CLI (y cualquier otro script o programa que utilice las librerías de AWS) intentará encontrar estas claves de múltiples maneras. Puedes hacer lo mismo usando el CLI que usando la Consola Web, sólo estás limitado por los permisos de tu usuario. Fácil, ¿verdad?
2. El problema con las claves
Bueno, fácil y no tan fácil… ¿Qué pasaría si un desarrollador sube sus credenciales a un repo público de Git por error (no sería el primero ni el último que lo hace…)? Hay gente malvada que busca continuamente este tipo de datos. Si un hacker encuentra tus claves, sería capaz de crear buckets, subir archivos, compartir el contenido, etc… Eso probablemente aumentaría tu factura de AWS, o incluso peor, accedería a tus datos y pediría un rescate; ha habido casos en los que los hackers crearon instancias para minar bitcoins.
Para evitar esto, y ahorrarnos el problema de generar claves, rotarlas, distribuirlas, etc. AWS tiene el concepto de rol. Un rol es un conjunto de políticas que se pueden asignar a otros recursos de AWS, para que estos recursos puedan realizar acciones sin necesidad de credenciales.
Por ejemplo, podemos crear un rol para una aplicación que suba datos a S3; para ello, podemos crear un rol con una política que sólo permita el acceso a un bucket de S3 específico y nada más.
Podemos desplegar esta aplicación de ejemplo en una máquina virtual (una instancia de EC2), o incluso mejor, un contenedor desplegado en ECS Fargate. Pero, ¿cómo puede la aplicación acceder al bucket? Pues asignaríamos el rol al servicio/tarea de ECS.
3. Fuentes de credenciales
Cuando una aplicación inicializa la librería de AWS para subir datos al bucket de S3, busca las credenciales utilizando esta lista:
- Credenciales establecidas directamente en el código
- Variables de entorno (
AWS_ACCESS_KEY_ID
yAWS_SECRET_ACCESS_KEY
) - Archivo de configuración (
~/.aws/credentials
) - Credenciales temporales de la instancia/contenedor
Las 3 primeras opciones se explican por sí mismas. Pero, ¿qué son esas credenciales temporales de instancia/contenedor? Pues bien, cuando ejecutamos una aplicación utilizando, por ejemplo, una instancia de EC2 o un contenedor, podemos configurarlos para que utilicen un rol de IAM.
EC2 y los contenedores contienen un servicio de metadatos de forma automática (bueno, no exactamente, pero esto es así en general); este servicio de metadatos nos proporcionan información sobre el entorno de AWS: la dirección IP pública y privada, la AMI que estamos utilizando, la región, la zona de disponibilidad, etc.
Y… lo más importante para nosotros en este momento, un conjunto de credenciales temporales con los permisos asignados al rol que hemos adjuntado. ¡Boooom! Estas credenciales temporales se rotan automáticamente, por lo que no tenemos que preocuparnos si las perdemos, ya que serán inválidas después de un corto período de tiempo. Como hemos dicho antes, esta es una de las opciones que utilizan automáticamente las librerías de AWS, si no se encuentra ninguna otra fuente de credenciales.
Esta forma de asignar permisos a los objetos mediante roles se utiliza en todos los servicios de AWS, por ejemplo, en Lambda, para acceder a otros recursos de AWS necesarios para el código; en ECS para lanzar contenedores, ya que necesita acceder a otros recursos de AWS (por ejemplo, ECR, o para crear interfaces de red); etc.
4. De lo local a la nube
El uso de roles es la principal diferencia cuando desplegamos las aplicaciones en AWS que a cuando desarrollamos en local. Pero si sabemos que las librerías de AWS intentan encontrar automáticamente la fuente de credenciales más adecuada, podemos olvidarnos de ello. Por ejemplo, el siguiente fragmento de Python:
# https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#using-boto3
import boto3
# Let's use Amazon S3
s3 = boto.resource('s3')
# Print out bucket names
for bucket in s3.buckets.all():
print(bucket.name)
Se ejecutaría en el ordenador del desarrollador si ha configurado sus propias credenciales personales en el archivo ~/.aws/credentials
, pero también al desplegar en un contenedor en AWS usando roles. El mismo código. Sin modificaciones, claves de acceso en el código, roles en el código y sin configuración. Mágico.
5. Conclusión
Los desarrolladores a menudo requieren que el DevOps configure un conjunto de claves en las instancias, ya que esta es la forma en que están acostumbrados a trabajar localmente. Pero esto no es necesario, y es un problema de seguridad. Si nosotros, como expertos en AWS, o tratando de serlo, enseñamos a los desarrolladores, DevOps, y otros equipos a centrarse en la seguridad y la usabilidad, todos seremos más felices, y nuestra aplicación será más segura, resistente, etc. Eso es lo que queremos conseguir, porque eso hará que los usuarios finales también estén contentos.
Santander Global T&O es una compañía global del Grupo Santander con más de 2.000 empleados y basada en Madrid, trabajamos para convertir al Santander en una plataforma abierta de servicios financieros.
¿Quieres unirte a este equipazo? Mira las posiciones que tenemos abiertas aquí y Be Tech! with Santander.