Capítulo 1. Seguridad Seguridad

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

1.0 Introducción

El coste medio en de una violación de datos en 2021 alcanzó un nuevo máximo de 4,24 millones de USD, según el Informe del Instituto IBM/Ponemon. Cuando eliges ejecutar tus aplicaciones en la nube, confías en AWS para que te proporcione una infraestructura segura que ejecute servicios en la nube, de modo que puedas centrarte en tus propias actividades de innovación y valor añadido.

Pero la seguridad en la nube es una responsabilidad compartida entre tú y AWS. Eres responsable de la configuración de cosas como las políticas de AWS Identity and Access Management (IAM), los grupos de seguridad de Amazon EC2 y los cortafuegos basados en host. En otras palabras, la seguridad de la plataforma de hardware y software que componen la nube de AWS es responsabilidad de AWS. La seguridad del software y de las configuraciones que implementes en tu(s) cuenta(s) de AWS es responsabilidad tuya.

A medida que implementas recursos en la nube en AWS y aplicas la configuración, es fundamental comprender los ajustes de seguridad necesarios para mantener un entorno seguro. Las recetas de este capítulo incluyen buenas prácticas y casos de uso centrados en la seguridad. Como la seguridad forma parte de todo, utilizarás estas recetas junto con otras recetas y capítulos de este libro. Por ejemplo, a lo largo del libro verás cómo se utiliza el Administrador de Sesiones del Gestor de Sistemas de AWS cuando te conectes a tus instancias EC2. Estas recetas básicas de seguridad te darán las herramientas que necesitas para crear soluciones seguras en AWS.

Además del contenido de este capítulo, tienes a tu disposición muchos recursos estupendos para profundizar en los temas de seguridad en AWS. "Los fundamentos de la seguridad en la nube de AWS", presentado en la conferencia de seguridad de AWS re:Inforce 2019, ofrece una gran visión general. Una charla más avanzada, "Cifrado: El mejor de los controles, el peor de los controles", de AWS re:Invent, explora escenarios de cifrado explicados en detalle.

Consejo

AWS publica una guía de buenas prácticas para proteger tu cuenta, y todos los titulares de cuentas AWS deberían familiarizarse con las buenas prácticas, ya que siguen evolucionando.

Advertencia

En este capítulo cubrimos temas importantes de seguridad. No es posible cubrir todos los temas, ya que la lista de servicios y configuraciones (con respecto a la seguridad en AWS) sigue creciendo y evolucionando. AWS mantiene actualizada su página web de Buenas prácticas de seguridad, identidad y conformidad.

Configuración del puesto de trabajo

En necesitarás algunas cosas instaladas para estar preparado para las recetas de este capítulo.

Configuración general

Sigue los "Pasos generales de configuración de la estación de trabajo para las recetas CLI" para validar tu configuración y establecer las variables de entorno necesarias. A continuación, clona el repositorio de código del capítulo:

git clone https://github.com/AWSCookbook/Security

1.1 Crear y asumir un rol IAM para el acceso de desarrollador

Problema

Para asegurarte de que no estás utilizando siempre permisos administrativos, tienes que crear un rol IAM para uso de desarrollo en tu cuenta de AWS.

Solución

Crea un rol utilizando una política IAM que permita asumir el rol más adelante. Adjunta la política IAM gestionada por AWS PowerUserAccess al rol (ver Figura 1-1).

Create role, attach policy, and assume role
Figura 1-1. Crear rol, adjuntar política y asumir rol

Pasos

  1. Crea un archivo llamado assume-role-policy-template.json con el siguiente contenido. Esto permitirá que una entidad de seguridad IAM asuma el rol que crearás a continuación (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "PRINCIPAL_ARN"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    Consejo

    Si estás utilizando un usuario IAM, y eliminas y vuelves a crear el usuario IAM, esta política no seguirá funcionando debido a la forma en que el servicio IAM ayuda a mitigar el riesgo de escalada de privilegios. Para más información, consulta la Nota de la documentación de IAM al respecto.

  2. Recupera el ARN de tu usuario y establécelo como variable:

    PRINCIPAL_ARN=$(aws sts get-caller-identity --query Arn --output text)
  3. Utiliza el comando sed para sustituir PRINCIPAL_ARN en el archivo assume-role-policy-template .json y generar el archivo assume-role-policy.json:

    sed -e "s|PRINCIPAL_ARN|${PRINCIPAL_ARN}|g" \
         assume-role-policy-template.json > assume-role-policy.json
  4. Crea un rol y especifica el archivo de política de rol de asumir:

    ROLE_ARN=$(aws iam create-role --role-name AWSCookbook101Role \
         --assume-role-policy-document file://assume-role-policy.json \
         --output text --query Role.Arn)
  5. Adjunta al rol la política PowerUserAccess gestionada por AWS:

    aws iam attach-role-policy --role-name AWSCookbook101Role \
         --policy-arn arn:aws:iam::aws:policy/PowerUserAccess
    Nota

    AWS proporciona políticas de acceso para funciones de trabajo comunes para tu comodidad. Estas políticas pueden ser un buen punto de partida para que delegues el acceso de los usuarios a tu cuenta para funciones de trabajo específicas; sin embargo, lo mejor es definir una política de mínimos privilegios para tus propios requisitos específicos para cada necesidad de acceso.

Comprobaciones de validación

Asume el papel:

aws sts assume-role --role-arn $ROLE_ARN \
     --role-session-name AWSCookbook101

Deberías ver una salida similar a la siguiente:

{
  "Credentials": {
    "AccessKeyId": "<snip>",
    "SecretAccessKey": "<snip>",
    "SessionToken": "<snip>",
    "Expiration": "2021-09-12T23:34:56+00:00"
  },
  "AssumedRoleUser": {
    "AssumedRoleId": "EXAMPLE:AWSCookbook101",
    "Arn": "arn:aws:sts::11111111111:assumed-role/AWSCookbook101Role/AWSCookbook101"
  }
}
Consejo

La API AssumeRole devuelve un conjunto de credenciales temporales para una sesión de rol desde el Servicio de tokens de seguridad (STS) de AWS a la persona que llama, siempre y cuando lo permitan los permisos de la política AssumeRole para el rol. Todos los roles IAM tienen asociada una política AssumeRole. Puedes utilizarla para configurar las credenciales para la CLI de AWS; establecer la AccessKey, SecretAccessKey y SessionToken como variables de entorno; y también asumir el rol en la consola de AWS utilizando la función Cambiar rol. Cuando tus aplicaciones necesiten hacer llamadas a la API de AWS, el SDK de AWS para el lenguaje de programación que elijas se encargará de ello.

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Utilizar el acceso administrativo para tareas rutinarias de desarrollo no es una buena práctica de seguridad. Conceder permisos innecesarios puede dar lugar a que se realicen acciones no autorizadas. Utilizar la política administrada por AWS PowerUserAccess para fines de desarrollo es una alternativa mejor para empezar que utilizar AdministratorAccess. Más adelante, deberás definir tu propia política gestionada por el cliente concediendo sólo las acciones específicas para tus necesidades. Por ejemplo, si necesitas entrar a menudo para comprobar el estado de tus instancias EC2, puedes crear una política de sólo lectura para este fin y adjuntarla a un rol. Del mismo modo, puedes crear un rol para el acceso a la facturación y utilizarlo sólo para acceder a la consola de facturación de AWS. Cuanto más practiques utilizando el principio del menor privilegio, más natural será que la seguridad forme parte de lo que haces.

En esta receta has utilizado un usuario IAM para realizar los pasos. Si utilizas una cuenta de AWS que aprovecha la federación para el acceso (por ejemplo, una cuenta de AWS sandbox o de desarrollo en tu empresa), debes utilizar credenciales temporales del STS de AWS en lugar de un usuario IAM. Este tipo de acceso utiliza tokens temporales que caducan al cabo de un tiempo, en lugar de credenciales "duraderas" como claves de acceso o contraseñas. Cuando realizaste el AssumeRole en los pasos de validación, llamaste al servicio STS para obtener credenciales temporales. Para ayudarte con las operaciones frecuentes de AssumeRole, la CLI de AWS admite perfiles con nombre que pueden asumir y actualizar automáticamente tus credenciales temporales para tu rol cuando especifiques el parámetro role_arn en el perfil con nombre.

Consejo

Puedes exigir la autenticación multifactor (MFA) como condición dentro de las políticas AssumeRole que crees. Esto permitiría que el rol fuera asumido sólo por una identidad que haya sido autenticada con MFA. Para más información sobre cómo requerir MFA para AssumeRole, consulta el documento de soporte.

Consulta la Receta 9.4 para crear una alerta cuando se produzca un inicio de sesión de root.

Consejo

Puedes conceder acceso entre cuentas a tus recursos de AWS. El recurso que definas en la política de esta receta hará referencia a la cuenta de AWS y a la entidad de seguridad dentro de esa cuenta a la que quieras delegar el acceso. Siempre debes utilizar un ExternalID cuando habilites el acceso entre cuentas. Para más información, consulta el tutorial oficial sobre el acceso entre cuentas.

Desafío

Crea roles IAM adicionales para cada una de las políticas administradas de AWS funciones laborales (por ejemplo, facturación, administrador de bases de datos, redes, etc.)

1.2 Generar una Política IAM de Mínimos Privilegios Basada en Patrones de Acceso

Problema

Te gustaría implementar el acceso de mínimo privilegio para tu usuario y delimitar los permisos para permitir el acceso sólo a los servicios, recursos y acciones que necesites utilizar en tu cuenta de AWS.

Solución

Utiliza el Analizador de Acceso de IAM en la consola de IAM para generar una política de IAM basada en la actividad de CloudTrail en tu cuenta de AWS, como se muestra en la Figura 1-2.

IAM Access Analyzer workflow
Figura 1-2. Flujo de trabajo del Analizador de Acceso IAM

Requisito previo

  • Registro CloudTrail habilitado para tu cuenta a un bucket S3 configurado (ver Receta 9.3)

Pasos

  1. Navega a la consola de IAM y selecciona el rol de IAM o el usuario de IAM para el que deseas generar una política.

  2. En la pestaña Permisos (la pestaña activa por defecto al ver tu director), desplázate hasta la parte inferior, despliega la sección "Generar política basada en eventos de CloudTrail" y haz clic en el botón "Generar política".

    Consejo

    Para obtener una vista rápida de los servicios de AWS a los que se accede desde tu entidad de seguridad, haz clic en la pestaña Asesor de acceso y consulta la lista de servicios y el tiempo de acceso. Aunque el Asesor de Acceso de IAM no es tan potente como el Analizador de Acceso, puede ser útil cuando auditas o solucionas problemas de los principales de IAM en tu cuenta de AWS.

  3. Selecciona el periodo de tiempo de los eventos de CloudTrail que quieres evaluar, selecciona tu rastro de CloudTrail, elige tu Región (o selecciona "Todas las regiones"), y elige "Crear y utilizar un nuevo rol de servicio". El Analizador de Acceso de IAM creará un rol para que el servicio utilice el acceso de lectura a tu rastro que hayas seleccionado. Por último, haz clic en "Generar política". Mira la Figura 1-3 para ver un ejemplo.

    Generate policy in the IAM Access Analyzer configuration
    Figura 1-3. Generar una política en la configuración del Analizador de Acceso IAM
    Nota

    La creación del rol puede tardar hasta 30 segundos. Una vez creado el rol, la generación de la política tardará un tiempo que dependerá de cuánta actividad haya en tu rastro de CloudTrail.

  4. Una vez finalizado el analizador, desplázate hasta la parte inferior de la pestaña de permisos y haz clic en "Ver política generada", como se muestra en la Figura 1-4.

    View generated policy
    Figura 1-4. Visualización de la política generada
  5. Haz clic en Siguiente, y verás una política generada en formato JSON que se basa en la actividad que ha realizado tu administrador principal de IAM. Puedes editar esta política en la interfaz si deseas añadir permisos adicionales. Vuelve a hacer clic en Siguiente, elige un nombre y podrás implementar esta política generada como política de IAM.

    Deberías ver una política IAM generada en la consola IAM similar a ésta:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "access-analyzer:ListPolicyGenerations",
            "cloudtrail:DescribeTrails",
            "cloudtrail:LookupEvents",
            "iam:GetAccountPasswordPolicy",
            "iam:GetAccountSummary",
            "iam:GetServiceLastAccessedDetails",
            "iam:ListAccountAliases",
            "iam:ListGroups",
            "iam:ListMFADevices",
            "iam:ListUsers",
            "s3:ListAllMyBuckets",
            "sts:GetCallerIdentity"
          ],
          "Resource": "*"
        }, ...
    }

Comprobaciones de validación

Crea un nuevo usuario o rol IAM y adjúntale la política IAM recién creada. Realiza una acción concedida por la política para verificar que ésta permite a tu principal de IAM realizar las acciones que necesitas.

Debate

Siempre debes tratar de aplicar las políticas de IAM de mínimo privilegio cuando las apliques a tus usuarios y aplicaciones. A menudo, puede que no sepas exactamente qué permisos puedes necesitar cuando empiezas. Con el Analizador de Acceso de IAM, puedes empezar concediendo a tus usuarios y aplicaciones un alcance mayor en un entorno de desarrollo, activar el registro de CloudTrail(Receta 9.3) y, a continuación, ejecutar el Analizador de Acceso de IAM después de disponer de una ventana de tiempo que proporcione una buena representación de la actividad habitual (elige este periodo de tiempo en la configuración del Analizador de Acceso como hiciste en el paso 3). La política generada contendrá todos los permisos necesarios para permitir que tu aplicación o tus usuarios trabajen como lo hacían durante ese periodo de tiempo que elegiste analizar, ayudando a a aplicar el principio del mínimo privilegio.

Nota

También debes conocer la lista de servicios que admite Access Analyzer.

Desafío

Utiliza el Simulador de Políticas IAM (ver Receta 1.4) en la política generada para verificar que la política contiene el acceso que necesitas.

1.3 Aplicar políticas de contraseña de usuario IAM en tu cuenta AWS

Nota

Gracias especiales a Gaurav Raje por su contribución a esta receta.

Problema

Tu política de seguridad requiere que apliques una política de contraseñas para todos los usuarios de tu cuenta de AWS. La política de contraseñas establece una caducidad de 90 días, y las contraseñas deben estar formadas por un mínimo de 32 caracteres, incluyendo letras minúsculas y mayúsculas, números y símbolos.

Solución

Establece una política de contraseñas para los usuarios de IAM en tu cuenta de AWS. Crea un grupo IAM, un usuario IAM y añade el usuario al grupo para verificar que se aplica la política (ver Figura 1-5).

Using password policies with IAM users
Figura 1-5. Utilizar políticas de contraseñas con usuarios IAM
Nota

Si tu organización dispone de un directorio central de usuarios, te recomendamos que utilices la federación de identidades para acceder a tus cuentas de AWS en mediante AWS Single Sign-On (SSO), en lugar de crear usuarios y grupos IAM individuales. La federación te permite utilizar un proveedor de identidades (IdP) en el que ya mantienes usuarios y grupos. AWS publica una guía que explica las configuraciones de acceso federado disponibles. Puedes seguir la Receta 9.6 para habilitar AWS SSO para tu cuenta aunque no dispongas de un IdP (AWS SSO proporciona un directorio que puedes utilizar por defecto).

Pasos

  1. Establece una política de contraseñas de IAM mediante la CLI de AWS para exigir letras minúsculas y mayúsculas, símbolos y números. La política debe indicar una longitud mínima de 32 caracteres, una antigüedad máxima de la contraseña de 90 días y que se impida su reutilización:

    aws iam update-account-password-policy \
         --minimum-password-length 32 \
         --require-symbols \
         --require-numbers \
         --require-uppercase-characters \
         --require-lowercase-characters \
         --allow-users-to-change-password \
         --max-password-age 90 \
         --password-reuse-prevention true
  2. Crea un grupo IAM:

    aws iam create-group --group-name AWSCookbook103Group

    Deberías ver una salida similar a la siguiente:

    {
      "Group": {
        "Path": "/",
        "GroupName": "AWSCookbook103Group",
        "GroupId": "<snip>",
        "Arn": "arn:aws:iam::111111111111:group/AWSCookbook103Group",
        "CreateDate": "2021-11-06T19:26:01+00:00"
      }
    }
  3. Adjunta la política ReadOnlyAccess al grupo:

    aws iam attach-group-policy --group-name AWSCookbook103Group \
         --policy-arn arn:aws:iam::aws:policy/AWSBillingReadOnlyAccess
    Consejo

    Es mejor adjuntar políticas a los grupos y no directamente a los usuarios. A medida que crece el número de usuarios, es más fácil utilizar grupos IAM para delegar permisos y facilitar la gestión. Esto también ayuda a cumplir normas como la CIS Nivel 1.

  4. Crea un usuario IAM:

    aws iam create-user --user-name awscookbook103user

    Deberías ver una salida similar a la siguiente:

    {
      "User": {
        "Path": "/",
        "UserName": "awscookbook103user",
        "UserId": "<snip>",
        "Arn": "arn:aws:iam::111111111111:user/awscookbook103user",
        "CreateDate": "2021-11-06T21:01:47+00:00"
      }
    }
  5. Utiliza el Gestor de Secretos para generar una contraseña que se ajuste a tu política de contraseñas:

    RANDOM_STRING=$(aws secretsmanager get-random-password \
    --password-length 32 --require-each-included-type \
    --output text \
    --query RandomPassword)
  6. Crea un perfil de inicio de sesión para el usuario que especifique una contraseña:

    aws iam create-login-profile --user-name awscookbook103user \
         --password $RANDOM_STRING

    Deberías ver una salida similar a la siguiente:

    {
      "LoginProfile": {
        "UserName": "awscookbook103user",
        "CreateDate": "2021-11-06T21:11:43+00:00",
        "PasswordResetRequired": false
      }
    }
  7. Añade el usuario al grupo que creaste para el acceso de sólo visualización de la facturación:

    aws iam add-user-to-group --group-name AWSCookbook103Group \
         --user-name awscookbook103user

Comprobaciones de validación

Comprueba que la política de contraseñas que has establecido está ahora activa:

aws iam get-account-password-policy

Deberías ver una salida similar a

{
  "PasswordPolicy": {
    "MinimumPasswordLength": 32,
    "RequireSymbols": true,
    "RequireNumbers": true,
    "RequireUppercaseCharacters": true,
    "RequireLowercaseCharacters": true,
    "AllowUsersToChangePassword": true,
    "ExpirePasswords": true,
    "MaxPasswordAge": 90,
    "PasswordReusePrevention": 1
  }
}

Intenta crear un nuevo usuario utilizando la CLI de AWS con una contraseña que infrinja la política de contraseñas. AWS no te permitirá crear dicho usuario:

aws iam create-user --user-name awscookbook103user2

Utiliza el Gestor de Secretos para generar una contraseña que no se ajuste a tu política de contraseñas:

RANDOM_STRING2=$(aws secretsmanager get-random-password \
--password-length 16 --require-each-included-type \
--output text \
--query RandomPassword)

Crea un perfil de acceso para el usuario que especifique la contraseña:

aws iam create-login-profile --user-name awscookbook103user2 \
--password $RANDOM_STRING2

Este comando debería fallar y deberías ver una salida similar a:

An error occurred (PasswordPolicyViolation) when calling the CreateLoginProfile
operation: Password should have a minimum length of 32

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Para los usuarios que inician sesión con contraseñas, AWS permite a los administradores aplicar políticas de contraseñas a sus cuentas que se ajusten a los requisitos de seguridad de tu organización. De este modo, los administradores pueden garantizar que los usuarios individuales no pongan en peligro la seguridad de la organización eligiendo contraseñas débiles o no cambiando regularmente sus contraseñas.

Consejo

Se recomienda la autenticación multifactor para los usuarios de IAM. Puedes utilizar un dispositivo MFA virtual basado en software o un dispositivo de hardware para un segundo factor en los usuarios de IAM. AWS mantiene una lista actualizada de dispositivos compatibles.

La autenticación multifactor es una forma estupenda de añadir otra capa de seguridad a la seguridad existente basada en contraseñas. Combina "lo que sabes" y "lo que tienes"; así, en los casos en que tu contraseña pudiera quedar expuesta a un tercero malintencionado, éste seguiría necesitando el factor adicional para autenticarse.

Desafío

Descarga el informe de credenciales para analizar los usuarios IAM y la antigüedad de las contraseñas de tu cuenta.

1.4 Probar las Políticas IAM con el Simulador de Políticas IAM

Problema

Tienes una política de IAM que te gustaría poner en práctica, pero primero te gustaría probar su eficacia.

Solución

Adjunta una política IAM a un rol IAM y simula acciones con el Simulador de Políticas IAM, como se muestra en la Figura 1-6.

Simulating IAM policies attached to an IAM role
Figura 1-6. Simulación de políticas IAM asociadas a un rol IAM

Pasos

  1. Crea un archivo llamado assume-role-policy.json con el siguiente contenido (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "ec2.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
  2. Crea un rol IAM utilizando el archivo assume-role-policy.json:

    aws iam create-role --assume-role-policy-document \
         file://assume-role-policy.json --role-name AWSCookbook104IamRole

    Deberías ver una salida similar a la siguiente:

    {
      "Role": {
      "Path": "/",
      "RoleName": "AWSCookbook104IamRole",
      "RoleId": "<<UniqueID>>",
      "Arn": "arn:aws:iam::111111111111:role/AWSCookbook104IamRole",
      "CreateDate": "2021-09-22T23:37:44+00:00",
      "AssumeRolePolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
        ...
  3. Adjunta la política gestionada por IAM para AmazonEC2ReadOnlyAccess al rol IAM:

    aws iam attach-role-policy --role-name AWSCookbook104IamRole \
         --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
Consejo

Puedes encontrar una lista de todas las acciones, recursos y claves de condición para EC2 en este artículo de AWS. Las claves de contexto de condición global de IAM también son útiles para crear políticas de grano fino.

Comprobaciones de validación

Simula el efecto de la política IAM que estás utilizando, probando varios tipos diferentes de acciones en el servicio EC2.

Prueba la acción ec2:CreateInternetGateway:

aws iam simulate-principal-policy \
     --policy-source-arn arn:aws:iam::$AWS_ACCOUNT_ARN:role/AWSCookbook104IamRole \
     --action-names ec2:CreateInternetGateway

Deberías ver una salida similar a la siguiente (fíjate en EvalDecision):

{
  "EvaluationResults": [
  {
    "EvalActionName": "ec2:CreateInternetGateway",
    "EvalResourceName": "*",
    "EvalDecision": "implicitDeny",
    "MatchedStatements": [],
    "MissingContextValues": []
  }
  ]
}
Nota

Como en esta receta sólo has adjuntado al rol la política IAM AmazonEC2ReadOnlyAccess gestionada por AWS, verás una denegación implícita para la acción CreateInternetGateway. Este es el comportamiento esperado. AmazonEC2ReadOnlyAccess no concede ninguna capacidad de "creación" para el servicio EC2.

Prueba la acción ec2:DescribeInstances:

aws iam simulate-principal-policy \
     --policy-source-arn arn:aws:iam::$AWS_ACCOUNT_ARN:role/AWSCookbook104IamRole \
     --action-names ec2:DescribeInstances

Deberías ver una salida similar a la siguiente:

{
  "EvaluationResults": [
  {
    "EvalActionName": "ec2:DescribeInstances",
    "EvalResourceName": "*",
    "EvalDecision": "allowed",
    "MatchedStatements": [
      {
      "SourcePolicyId": "AmazonEC2ReadOnlyAccess",
      "SourcePolicyType": "IAM Policy",
      "StartPosition": {
        "Line": 3,
        "Column": 17
      },
      "EndPosition": {
        "Line": 8,
        "Column": 6
      }
      }
    ],
    "MissingContextValues": []
  }
  ]
}
Nota

La política AmazonEC2ReadOnlyAccess permite operaciones de lectura en el servicio EC2, por lo que la operación DescribeInstances tiene éxito cuando simulas esta acción.

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Las políticas IAM te permiten definir permisos para administrar el acceso en AWS. Las políticas pueden adjuntarse a entidades de seguridad que te permiten conceder (o denegar) permisos a recursos, usuarios, grupos y servicios. Siempre es mejor delimitar tus políticas al conjunto mínimo de permisos necesarios, como buena práctica de seguridad. El Simulador de Políticas IAM puede ser muy útil a la hora de diseñar y gestionar tus propias políticas IAM para el acceso con menos privilegios.

El Simulador de Políticas IAM también expone una interfaz web que puedes utilizar para probar y solucionar problemas de las políticas IAM y comprender su efecto neto con la política que definas. Puedes probar todas las políticas o un subconjunto de políticas que hayas adjuntado a usuarios, grupos y roles.

Consejo

El Simulador de Políticas IAM puede ayudarte a simular el efecto de lo siguiente:

  • Políticas basadas en la identidad

  • Límites de los permisos IAM

  • Políticas de control de servicios (SCP) de las organizaciones de AWS

  • Políticas basadas en los recursos

Después de revisar los resultados del Simulador de Políticas, puedes añadir declaraciones adicionales a tus políticas que resuelvan tu problema (desde el punto de vista de la resolución de problemas) o adjuntar políticas recién creadas a usuarios, grupos y roles con la confianza de que el efecto neto de la política era el que pretendías.

Nota

Para ayudarte a construir fácilmente políticas de IAM desde cero, AWS proporciona el Generador de políticas de AWS.

Desafío

Simula el efecto de un límite de permisos en un principal IAM (ver Receta 1.5).

1.5 Delegar Capacidades Administrativas de IAM Utilizando Límites de Permisos

Problema

Necesitas conceder a los miembros del equipo la capacidad de implementar funciones Lambda y crear roles IAM para ellas. Tienes que limitar los permisos efectivos de los roles IAM creados para que sólo permitan las acciones que necesite la función.

Solución

Crea una política de límite de permisos, crea un rol de IAM para los desarrolladores de Lambda, crea una política de IAM que especifique la política de límite y adjunta la política al rol que has creado. La Figura 1-7 ilustra los permisos efectivos de la política basada en identidad con el límite de permisos.

Effective permissions of identity-based policy with permissions boundary
Figura 1-7. Permisos efectivos de la política basada en la identidad con límite de permisos

Requisito previo

Pasos

  1. Crea un archivo llamado assume-role-policy-template.json con el siguiente contenido (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "PRINCIPAL_ARN"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
  2. Recupera el ARN de tu usuario y establécelo como variable:

    PRINCIPAL_ARN=$(aws sts get-caller-identity --query Arn --output text)
  3. Utiliza el comando sed para sustituir PRINCIPAL_ARN en el archivo assume-role-policy-template .json que proporcionamos en el repositorio y generar el archivo assume-role-policy.json:

    sed -e "s|PRINCIPAL_ARN|${PRINCIPAL_ARN}|g" \
    assume-role-policy-template.json > assume-role-policy.json
    Nota

    A efectos de esta receta, estableces la entidad de seguridad IAM permitida en tu propio usuario (Usuario 1). Para probar el acceso delegado, establecerías la entidad de seguridad IAM en otra cosa.

  4. Crea un rol y especifica el archivo de política de rol de asunción:

    ROLE_ARN=$(aws iam create-role --role-name AWSCookbook105Role \
         --assume-role-policy-document file://assume-role-policy.json \
         --output text --query Role.Arn)
  5. Crea un archivo JSON de límites de permisos llamado boundary-template.json con el siguiente contenido. Esto permite acciones específicas de DynamoDB, S3 y CloudWatch Logs (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "CreateLogGroup",
          "Effect": "Allow",
          "Action": "logs:CreateLogGroup",
          "Resource": "arn:aws:logs:*:AWS_ACCOUNT_ID:*"
        },
        {
          "Sid": "CreateLogStreamandEvents",
          "Effect": "Allow",
          "Action": [
            "logs:CreateLogStream",
            "logs:PutLogEvents"
          ],
          "Resource": "arn:aws:logs:*:AWS_ACCOUNT_ID:*"
        }, 
        {
          "Sid": "DynamoDBPermissions",
          "Effect": "Allow",
          "Action": [
            "dynamodb:PutItem",
            "dynamodb:UpdateItem",
            "dynamodb:DeleteItem"
          ],
          "Resource": "arn:aws:dynamodb:*:AWS_ACCOUNT_ID:table/AWSCookbook*"
        },
        {
          "Sid": "S3Permissions",
          "Effect": "Allow",
          "Action": [
            "s3:GetObject",
            "s3:PutObject"
          ],
          "Resource": "arn:aws:s3:::AWSCookbook*/*"
        }
      ]
    }
  6. Utiliza el comando sed para sustituir AWS_ACCOUNT_ID en el archivo boundary-policy-template.json y generar el archivo boundary-policy.json:

    sed -e "s|AWS_ACCOUNT_ID|${AWS_ACCOUNT_ID}|g" \
         boundary-policy-template.json > boundary-policy.json
  7. Crea la política de límites de permisos utilizando la CLI de AWS:

    aws iam create-policy --policy-name AWSCookbook105PB \
         --policy-document file://boundary-policy.json

    Deberías ver una salida similar a la siguiente:

    {
      "Policy": {
        "PolicyName": "AWSCookbook105PB",
        "PolicyId": "EXAMPLE",
        "Arn": "arn:aws:iam::111111111111:policy/AWSCookbook105PB",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2021-09-24T00:36:53+00:00",
        "UpdateDate": "2021-09-24T00:36:53+00:00"
      }
    }
  8. Crea un archivo de política llamado policy-template.json para el rol (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "DenyPBDelete", 1
          "Effect": "Deny",
          "Action": "iam:DeleteRolePermissionsBoundary",
          "Resource": "*"
        },
        {
          "Sid": "IAMRead", 2
          "Effect": "Allow",
          "Action": [
            "iam:Get*",
            "iam:List*"
          ],
          "Resource": "*"
        },
        {
           "Sid": "IAMPolicies", 3
          "Effect": "Allow",
          "Action": [
            "iam:CreatePolicy",
            "iam:DeletePolicy",
            "iam:CreatePolicyVersion",
            "iam:DeletePolicyVersion",
            "iam:SetDefaultPolicyVersion"
          ],
          "Resource": "arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSCookbook*"
        },
        {
          "Sid": "IAMRolesWithBoundary", 4
          "Effect": "Allow",
          "Action": [
            "iam:CreateRole",
            "iam:DeleteRole",
            "iam:PutRolePolicy",
            "iam:DeleteRolePolicy",
            "iam:AttachRolePolicy",
            "iam:DetachRolePolicy"
          ],
          "Resource": [
            "arn:aws:iam::AWS_ACCOUNT_ID:role/AWSCookbook*"
          ],
          "Condition": {
            "StringEquals": {
              "iam:PermissionsBoundary": "arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSCookbook105PB"
            }
          }
        },
        {
          "Sid": "ServerlessFullAccess", 5
          "Effect": "Allow",
            "Action": [
            "lambda:*",
            "logs:*",
            "dynamodb:*",
            "s3:*"
          ],
          "Resource": "*"
        },
        {
          "Sid": "PassRole", 6
          "Effect": "Allow",
          "Action": "iam:PassRole",
          "Resource": "arn:aws:iam::AWS_ACCOUNT_ID:role/AWSCookbook*",
          "Condition": {
            "StringLikeIfExists": {
              "iam:PassedToService": "lambda.amazonaws.com"
            }
          }
        },
        {
          "Sid": "ProtectPB", 7
          "Effect": "Deny",
          "Action": [
            "iam:CreatePolicyVersion",
            "iam:DeletePolicy",
            "iam:DeletePolicyVersion",
            "iam:SetDefaultPolicyVersion"
          ],
          "Resource": [
            "arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSCookbook105PB",
            "arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSCookbook105Policy"
          ]
        }
      ]
    }

    Esta política IAM personalizada tiene varias declaraciones que funcionan juntas, que definen determinados permisos para la solución de la declaración del problema:

    1

    DenyPBDelete: Niega explícitamente la capacidad de eliminar límites de permisos de los roles.

    2

    IAMRead: Permitir el acceso IAM de sólo lectura a los desarrolladores para garantizar el funcionamiento de la consola IAM.

    3

    IAMPolicies: Permitir la creación de políticas IAM pero forzar un prefijo de convención de nombres AWSCookbook*.

    4

    IAMRolesWithBoundary: Permitir la creación y eliminación de roles IAM sólo si contienen el límite de permisos al que se hace referencia.

    5

    ServerlessFullAccess: Permite a los desarrolladores tener acceso completo a los servicios AWS Lambda, Amazon DynamoDB, registros de Amazon CloudWatch y Amazon S3.

    6

    PassRole: Permitir a los desarrolladores pasar roles IAM a funciones Lambda.

    7

    ProtectPB: Denegar explícitamente la capacidad de modificar el límite de permisos que vincula a los roles que crean.

  9. Utiliza el comando sed para sustituir AWS_ACCOUNT_ID en el archivo policy-template.json y generar el archivo policy.json:

    sed -e "s|AWS_ACCOUNT_ID|${AWS_ACCOUNT_ID}|g" \
         policy-template.json > policy.json
  10. Crea la política de acceso para desarrolladores:

    aws iam create-policy --policy-name AWSCookbook105Policy \
         --policy-document file://policy.json

    Deberías ver una salida similar a la siguiente:

    {
      "Policy": {
        "PolicyName": "AWSCookbook105Policy",
        "PolicyId": "EXAMPLE",
        "Arn": "arn:aws:iam::11111111111:policy/AWSCookbook105Policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2021-09-24T00:37:13+00:00",
        "UpdateDate": "2021-09-24T00:37:13+00:00"
      }
    }
  11. Adjunta la política al rol que creaste en el paso 2:

    aws iam attach-role-policy --policy-arn \
         arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook105Policy \
         --role-name AWSCookbook105Role

Comprobaciones de validación

Asume el rol que has creado y establece la salida a variables locales para la CLI de AWS:

creds=$(aws --output text sts assume-role --role-arn $ROLE_ARN \
     --role-session-name "AWSCookbook105" | \
     grep CREDENTIALS | cut -d " " -f2,4,5)
export AWS_ACCESS_KEY_ID=$(echo $creds | cut -d " " -f2)
export AWS_SECRET_ACCESS_KEY=$(echo $creds | cut -d " " -f4)
export AWS_SESSION_TOKEN=$(echo $creds | cut -d " " -f5)

Intenta crear un rol IAM para una función Lambda, crea una políticade asumir rol para el servicio Lambda(lambda-assume-role-policy.json):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Crea el rol, especificando el límite de permisos, que se ajusta a la norma de denominación de roles especificada en la política:

TEST_ROLE_1=$(aws iam create-role --role-name AWSCookbook105test1 \
     --assume-role-policy-document \
     file://lambda-assume-role-policy.json \
     --permissions-boundary \
     arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook105PB \
     --output text --query Role.Arn)

Adjunta la política gestionada AmazonDynamoDBFullAccess al rol:

aws iam attach-role-policy --role-name AWSCookbook105test1 \
--policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

Adjunta la política gestionada CloudWatchFullAccess al rol:

aws iam attach-role-policy --role-name AWSCookbook105test1 \
--policy-arn arn:aws:iam::aws:policy/CloudWatchFullAccess
Nota

Aunque hayas adjuntado AmazonDynamoDBFullAccess y CloudWatchFullAccess a la función, los permisos efectivos de la función están limitados por las declaraciones del límite de permisos que creaste en el paso 3. Además, aunque tengas definidos s3:GetObject y s3:PutObject en el límite, no los has definido en la política del rol, por lo que la función no podrá realizar estas llamadas hasta que crees una política que permita estas acciones. Cuando adjuntas este rol a una función Lambda, la función Lambda sólo puede realizar las acciones permitidas en la intersección del límite de permisos y la política de rol (ver Figura 1-7).

Ahora puedes crear una función Lambda especificando este rol (AWSCookbook105test1) como rol de ejecución para validar los permisos de DynamoDB y CloudWatch Logs concedidos a la función. También puedes probar los resultados con el Simulador de Políticas de IAM.

Utilizaste un AssumeRole y estableciste variables de entorno para anular el perfil de AWS de tu terminal local para realizar estas comprobaciones de validación. Para asegurarte de que vuelves a tu sesión autenticada original en la línea de comandos, realiza los pasos de limpieza que se indican en la parte superior del archivo README del repositorio.

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Nota

Asegúrate de eliminar las variables de entorno para poder recuperar los permisos necesarios para futuras recetas:

unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN

Debate

En tu afán por implementar un modelo de acceso de mínimo privilegio para usuarios y aplicaciones dentro de AWS, necesitas permitir a los desarrolladores crear roles IAM que sus aplicaciones puedan asumir cuando necesiten interactuar con otros servicios de AWS. Por ejemplo, una función de AWS Lambda que necesite acceder a una tabla de Amazon DynamoDB necesitaría un rol creado para poder realizar operaciones contra la tabla. A medida que tu equipo escale, en lugar de que los miembros de tu equipo acudan a ti cada vez que necesiten que se cree un rol para un fin concreto, puedes habilitarlos (pero controlarlos) con límites de permisos, sin renunciar demasiado al acceso IAM. La condición iam:PermissionsBoundary de la política que concede el iam:CreateRole garantiza que los roles creados deben incluir siempre el límite de permisos adjunto.

Los límites de los permisos actúan como barandilla y limitan la escalada de privilegios. En otras palabras, limitan los permisos efectivos máximos de una entidad de seguridad de IAM creada por un administrador delegado, definiendo lo que pueden hacer las funciones creadas. Como se muestra en la Figura 1-7, funcionan junto con la política de permisos (política IAM) que se adjunta a un principal IAM (usuario o rol IAM). Esto evita la necesidad de conceder un amplio acceso a un rol de administrador, impide la escalada de privilegios y te ayuda a conseguir el acceso con menos privilegios permitiendo a los miembros de tu equipo iterar rápidamente y crear sus propios roles con menos privilegios para sus aplicaciones.

En esta receta, te habrás dado cuenta de que hemos utilizado una convención de nomenclatura de AWSCookbook* en los roles y políticas referenciados en la política de límites de permisos, lo que garantiza que los principales delegados puedan crear roles y políticas dentro de esta convención. Esto significa que los desarrolladores pueden crear recursos, pasar sólo estos roles a los servicios y, además, mantener una convención de nomenclatura estándar. Esta es una práctica ideal cuando se implementan límites de permisos. Puedes desarrollar una convención de nomenclatura para diferentes equipos, aplicaciones y servicios, de modo que todos ellos puedan coexistir dentro de la misma cuenta, aunque se les apliquen diferentes límites en función de sus requisitos, si es necesario.

Como mínimo, tienes que tener en cuenta estas cuatro cosas cuando crees roles que implementen barandillas límite de permisos para delegar permisos de IAM a no administradores:

  1. Permitir la creación de políticas gestionadas por el cliente de IAM: tus usuarios pueden crear cualquier política que deseen; no tienen efecto hasta que se adjuntan a un principal de IAM.

  2. Permitir la creación de roles IAM con la condición de que se adjunte un límite de permisos: obliga a que todos los roles creados por los miembros de tu equipo incluyan el límite de permisos en la creación del rol.

  3. Permite adjuntar políticas, pero sólo a roles que tengan un límite de permisos: no dejes que los usuarios modifiquen roles existentes a los que puedan tener acceso.

  4. Permite iam:PassRole a los servicios de AWS para los que tus usuarios creen roles: puede que tus desarrolladores necesiten crear roles para Amazon EC2 y AWS Lambda, así que dales la posibilidad de pasar sólo los roles que creen a esos servicios que definas.

Consejo

Los límites de permisos son un concepto de IAM potente y avanzado que puede resultar difícil de entender. Te recomendamos que eches un vistazo a la charla de Brigid Johnson en AWS re:Inforce 2018 para ver algunos ejemplos reales de políticas, roles y límites de permisos de IAM explicados de forma práctica.

Desafío

Amplía el límite de permisos para permitir que los roles creados publiquen en una cola SQS y en un tema SNS y ajusta también la política del rol.

1.6 Conectarse a instancias EC2 utilizando el gestor de sesiones SSM de AWS

Problema

Tienes una instancia EC2 de en una subred privada y necesitas conectarte a la instancia sin utilizar SSH a través de Internet.

Solución

Crea un rol IAM, adjunta la política AmazonSSMManagedInstanceCore, crea un perfil de instancia EC2, adjunta el rol IAM que has creado al perfil de instancia, asocia el perfil de instancia EC2 a una instancia EC2 y, por último, ejecuta el comando aws ssm start-session para conectarte a la instancia. En la Figura 1-8 se muestra un flujo lógico de estos pasos.

Using Session Manager to connect to an EC2 instance
Figura 1-8. Uso de Session Manager para conectarse a una instancia EC2

Requisitos previos

Preparación

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Pasos

  1. Crea un archivo llamado assume-role-policy.json con el siguiente contenido (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
      ]
    }
  2. Crea un rol IAM con la declaración del archivo assume-role-policy.json proporcionado utilizando este comando:

    ROLE_ARN=$(aws iam create-role --role-name AWSCookbook106SSMRole \
         --assume-role-policy-document file://assume-role-policy.json \
         --output text --query Role.Arn)
  3. Adjunta la política gestionada AmazonSSMManagedInstanceCore al rol para que éste permita el acceso de a AWS Systems Manager:

    aws iam attach-role-policy --role-name AWSCookbook106SSMRole \
         --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  4. Crea un perfil de instancia:

    aws iam create-instance-profile \
         --instance-profile-name AWSCookbook106InstanceProfile

    Deberías ver una salida similar a la siguiente:

    {
      "InstanceProfile": {
        "Path": "/",
        "InstanceProfileName": "AWSCookbook106InstanceProfile",
        "InstanceProfileId": "(RandomString",
        "Arn": "arn:aws:iam::111111111111:instance-profile/AWSCookbook106InstanceProfile",
        "CreateDate": "2021-11-28T20:26:23+00:00",
        "Roles": []
      }
    }
  5. Añade el rol que has creado al perfil de la instancia:

    aws iam add-role-to-instance-profile \
         --role-name AWSCookbook106SSMRole \
         --instance-profile-name AWSCookbook106InstanceProfile
    Nota

    El perfil de instancia de EC2 contiene un rol que tú creas. La asociación del perfil de instancia con una instancia le permite definir "quién soy", y el rol define "qué se me permite hacer". Ambos son necesarios para que IAM permita que una instancia EC2 se comunique con otros servicios de AWS que utilicen el servicio IAM. Puedes obtener una lista de los perfiles de instancia de tu cuenta ejecutando el comando CLI de AWS aws iam list-instance-profiles.

  6. Consulta a SSM el último ID de AMI de Amazon Linux 2 disponible en tu Región y guárdalo como variable de entorno:

    AMI_ID=$(aws ssm get-parameters --names \
         /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
         --query 'Parameters[0].[Value]' --output text)
  7. Lanza una instancia en una de tus subredes que haga referencia al perfil de instancia que has creado y que además utilice una etiqueta Name que te ayude a identificar la instancia en la consola:

    INSTANCE_ID=$(aws ec2 run-instances --image-id $AMI_ID \
         --count 1 \
         --instance-type t3.nano \
         --iam-instance-profile Name=AWSCookbook106InstanceProfile \
         --subnet-id $SUBNET_1 \
         --security-group-ids $INSTANCE_SG \
         --metadata-options \
    HttpTokens=required,HttpPutResponseHopLimit=64,HttpEndpoint=enabled \
         --tag-specifications \
         'ResourceType=instance,Tags=[{Key=Name,Value=AWSCookbook106}]' \
         'ResourceType=volume,Tags=[{Key=Name,Value=AWSCookbook106}]' \
         --query Instances[0].InstanceId \
         --output text)
    Consejo

    Los metadatos de instancia EC2 son una función que puedes utilizar dentro de tu instancia EC2 para acceder a información sobre tu instancia EC2 a través de un endpoint HTTP desde la propia instancia. Esto es útil para la creación de scripts y la automatización mediante datos de usuario. Siempre debes utilizar la última versión de los metadatos de la instancia. En el paso 7, lo hiciste especificando la bandera --metadata-options y proporcionando la opción HttpTokens=required que fuerza IMDSv2.

Comprobaciones de validación

Asegúrate de que tu instancia EC2 se ha registrado en SSM. Utiliza el siguiente comando para comprobar el estado. Este comando debería devolver el ID de la instancia:

aws ssm describe-instance-information \
     --filters Key=ResourceType,Values=EC2Instance \
     --query "InstanceInformationList[].InstanceId" --output text

Conéctate a la instancia EC2 utilizando el Gestor de Sesiones SSM:

aws ssm start-session --target $INSTANCE_ID

Ahora deberías estar conectado a tu instancia y ver un indicador bash. Desde el indicador bash, ejecuta un comando para validar que estás conectado a tu instancia EC2, solicitando al servicio de metadatos un token IMDSv2 y utilizando el token para consultar los metadatos del perfil de instancia asociado a la instancia:

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/info

Deberías ver una salida similar a la siguiente:

{
  "Code" : "Success",
  "LastUpdated" : "2021-09-23T16:03:25Z",
  "InstanceProfileArn" : "arn:aws:iam::111111111111:instance-profile/AWSCookbook106InstanceProfile",
  "InstanceProfileId" : "AIPAZVTINAMEXAMPLE"
}

Sal de la sesión del Administrador de Sesiones:

exit

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Cuando utilizas AWS SSM Session Manager para conectarte a las instancias EC2, eliminas tu dependencia de Secure Shell (SSH) a través de Internet para acceder a la línea de comandos de tus instancias. Una vez configurado Session Manager para tus instancias, puedes conectarte instantáneamente a una sesión shell bash en Linux o a una sesión PowerShell para sistemas Windows.

Advertencia

SSM puede registrar todos los comandos y su salida durante una sesión. Puedes establecer una preferencia para detener el registro de datos sensibles (por ejemplo, contraseñas) con este comando:

stty -echo; read passwd; stty echo;

Hay más información en un artículo de AWS sobre el registro de la actividad de la sesión.

Session Manager funciona comunicándose con los puntos finales de la API de AWS Systems Manager (SSM) dentro de la región de AWS que estés utilizando a través de HTTPS (puerto TCP 443). El agente de tu instancia se registra en el servicio SSM en el momento del arranque. No se necesitan reglas de grupos de seguridad entrantes para la funcionalidad del Administrador de Sesiones. Recomendamos configurar los Puntos Finales de la VPC para el Gestor de Sesiones para evitar la necesidad de tráfico de Internet y el coste de las pasarelas de Traducción de Direcciones de Red (NAT).

He aquí algunos ejemplos de la mayor seguridad que proporciona Session Manager:

  • No es necesario permitir ningún puerto TCP orientado a Internet en los grupos de seguridad asociados a las instancias.

  • Puedes ejecutar instancias en subredes privadas (o aisladas) sin exponerlas directamente a Internet y seguir accediendo a ellas para tareas de gestión.

  • No es necesario crear, asociar y gestionar claves SSH con las instancias.

  • No es necesario gestionar cuentas de usuario y contraseñas en las instancias.

  • Puedes delegar el acceso para gestionar instancias EC2 utilizando roles IAM.

Nota

Cualquier herramienta como SSM, que proporciona capacidades tan potentes, debe auditarse cuidadosamente. AWS proporciona información sobre el bloqueo de permisos para el usuario SSM, y más información sobre la auditoría de la actividad de la sesión.

Desafío

Visualiza los registros de una sesión y crea una alerta cada vez que se ejecute el comando rm.

1.7 Cifrar volúmenes EBS usando claves KMS

Problema

Necesitas una clave de cifrado para cifrar volúmenes EBS attached to your EC2 instances in a Region, y necesitas rotar la clave automáticamente cada 365 días.

Solución

Crea una clave KMS gestionada por el cliente (CMK), activa la rotación anual de la clave, activa el cifrado por defecto de EC2 para los volúmenes EBS de una Región, y especifica la clave KMS que has creado (mostrada en la Figura 1-9).

Create a customer-managed key, enable rotation, and set default encryption for EC2 using a customer-managed key.
Figura 1-9. Crear una clave gestionada por el cliente, activar la rotación y establecer el cifrado por defecto para EC2 utilizando una clave gestionada por el cliente

Pasos

  1. Crea una clave KMS gestionada por el cliente y almacena el ARN de la clave como variable local:

    KMS_KEY_ID=$(aws kms create-key --description "AWSCookbook107Key" \
         --output text --query KeyMetadata.KeyId)
  2. Crea un alias de clave que te ayude a referirte a ella en otros pasos:

    aws kms create-alias --alias-name alias/AWSCookbook107Key \
         --target-key-id $KMS_KEY_ID
  3. Activa la rotación automática del material de la clave simétrica cada 365 días:

    aws kms enable-key-rotation --key-id $KMS_KEY_ID
  4. Activa el cifrado EBS por defecto para el servicio EC2 dentro de tu Región actual:

    aws ec2 enable-ebs-encryption-by-default

    Deberías ver una salida similar a la siguiente:

    {
         "EbsEncryptionByDefault": true
    }
  5. Actualiza la clave KMS por defecto utilizada para el cifrado EBS por defecto a tu clave gestionada por el cliente que creaste en el paso 1:

    aws ec2 modify-ebs-default-kms-key-id \
         --kms-key-id alias/AWSCookbook107Key

    Deberías ver una salida similar a la siguiente:

    {
      "KmsKeyId": "arn:aws:kms:us-east-1:111111111111:key/1111111-aaaa-bbbb-222222222"
    }

Comprobaciones de validación

Utiliza la CLI de AWS para recuperar el estado de cifrado por defecto de EBS para el servicio EC2:

aws ec2 get-ebs-encryption-by-default

Deberías ver una salida similar a la siguiente:

{
  "EbsEncryptionByDefault": true
}

Recupera el ID de la clave KMS utilizada para la encriptación por defecto:

aws ec2 get-ebs-default-kms-key-id

Deberías ver una salida similar a la siguiente:

{
  "KmsKeyId": "arn:aws:kms:us-east-1:1111111111:key/1111111-aaaa-3333-222222222c64b"
}

Comprueba el estado de rotación automática de la llave que has creado:

aws kms get-key-rotation-status --key-id $KMS_KEY_ID

Deberías ver una salida similar a la siguiente:

{
  "KeyRotationEnabled": true
}

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Cuando te enfrentes al reto de asegurarte de que todos tus volúmenes EBS recién creados están encriptados, la opción ebs-encryption-by-default viene al rescate. Con esta opción activada, cada instancia EC2 que lances tendrá por defecto sus volúmenes EBS cifrados con la clave KMS especificada. Si no especificas una clave KMS, se creará y utilizará una clave KMS por defecto gestionada por AWS aws/ebs. Si necesitas gestionar el ciclo de vida de la clave o tienes algún requisito que especifique que tú o tu organización debéis gestionar la clave, deben utilizarse claves gestionadas por el cliente.

La rotación automática de claves en el servicio KMS simplifica tu enfoque de la rotación de claves y la gestión del ciclo de vida de las claves.

KMS es un servicio flexible que puedes utilizar para aplicar diversas estrategias de encriptación de datos. Admite políticas de claves que puedes utilizar para controlar quién tiene acceso a la clave. Estas políticas de claves se superponen a tu estrategia existente de políticas IAM para una mayor seguridad. Puedes utilizar claves KMS para cifrar muchos tipos diferentes de datos en reposo dentro de tu cuenta de AWS, por ejemplo:

  • Amazon S3

  • Volúmenes EBS de Amazon EC2

  • Bases de datos y clústeres de Amazon RDS

  • Tablas de Amazon DynamoDB

  • Volúmenes de Amazon EFS

  • Archivos compartidos de Amazon FSx

  • Y muchos más

Desafío 1

Cambia la política de claves en la clave KMS para permitir el acceso sólo a tu principal IAM y al servicio EC2.

Desafío 2

Crea un volumen EBS y verifica que está cifrado utilizando el comando aws ec2 describe-volumes.

1.8 Almacenar, cifrar y acceder a contraseñas mediante el Gestor de Secretos

Problema

Necesitas dar a tu instancia EC2 la capacidad de almacenar y recuperar de forma segura una contraseña de base de datos para tu aplicación.

Solución

Crea una contraseña, almacena la contraseña en el Gestor de Secretos, crea una Política IAM con acceso al secreto y concede a un perfil de instancia EC2 acceso al secreto, como se muestra en la Figura 1-10.

Create a secret and retrieve it via EC2 instance
Figura 1-10. Crear un secreto y recuperarlo a través de la instancia EC2

Requisitos previos

  • VPC con subredes aisladas y tablas de rutas asociadas.

  • Instancia EC2 implementada. Necesitarás poder conectarte a ella para realizar pruebas.

Preparación

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Pasos

  1. Crea un secreto utilizando la CLI de AWS:

    RANDOM_STRING=$(aws secretsmanager get-random-password \
         --password-length 32 --require-each-included-type \
         --output text \
         --query RandomPassword)
  2. Guárdalo como un nuevo secreto en el Gestor de Secretos:

    SECRET_ARN=$(aws secretsmanager \
         create-secret --name AWSCookbook108/Secret1 \
         --description "AWSCookbook108 Secret 1" \
         --secret-string $RANDOM_STRING \
         --output text \
         --query ARN)
  3. Crea un archivo llamado secret-access-policy-template.json que haga referencia al secreto que has creado. (archivo proporcionado en el repositorio):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "secretsmanager:GetResourcePolicy",
            "secretsmanager:GetSecretValue",
            "secretsmanager:DescribeSecret",
            "secretsmanager:ListSecretVersionIds"
          ],
          "Resource": [
            "SECRET_ARN"
          ]
        },
        {
          "Effect": "Allow",
          "Action": "secretsmanager:ListSecrets",
          "Resource": "*"
        }
      ]
    }
  4. Utiliza el comando sed para sustituir SECRET_ARN en el archivo secret-access-policy-template .json y generar el archivo secret-access-policy.json:

    sed -e "s|SECRET_ARN|$SECRET_ARN|g" \
         secret-access-policy-template.json > secret-access-policy.json
  5. Crea la política IAM para el acceso secreto:

    aws iam create-policy --policy-name AWSCookbook108SecretAccess \
         --policy-document file://secret-access-policy.json

    Deberías ver una salida similar a la siguiente:

    {
      "Policy": {
        "PolicyName": "AWSCookbook108SecretAccess",
        "PolicyId": "(Random String)",
        "Arn": "arn:aws:iam::1111111111:policy/AWSCookbook108SecretAccess",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2021-11-28T21:25:23+00:00",
        "UpdateDate": "2021-11-28T21:25:23+00:00"
      }
    }
  6. Concede a una instancia EC2 la capacidad de acceder al secreto añadiendo la política IAM que has creado al rol IAM actualmente adjunto al perfil de la instancia EC2:

    aws iam attach-role-policy --policy-arn \
         arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook108SecretAccess \
         --role-name $ROLE_NAME

Comprobaciones de validación

Conéctate a la instancia EC2:

aws ssm start-session --target $INSTANCE_ID

Establece y exporta tu región por defecto:

export AWS_DEFAULT_REGION=us-east-1

Recupera el secreto del Gestor de Secretos del EC2:

aws secretsmanager get-secret-value --secret-id AWSCookbook108/Secret1

Deberías ver una salida similar a la siguiente:

{
  "Name": "AWSCookbook108/Secret1",
  "VersionId": "<string>",
  "SecretString": "<secret value>",
  "VersionStages": [
    "AWSCURRENT"
  ],
  "CreatedDate": 1638221015.646,
  "ARN": "arn:aws:secretsmanager:us-east-1:111111111111:secret:AWSCookbook108/Secret1-<suffix>"
}</suffix>

Sal de la sesión del Administrador de Sesiones:

exit

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Crear, almacenar y gestionar de forma segura el ciclo de vida de los secretos, como las claves API y las contraseñas de bases de datos, es un componente fundamental para una postura de seguridad sólida en la nube. Puedes utilizar el Gestor de Secretos para implantar una estrategia de gestión de secretos que respalde tu estrategia de seguridad. Puedes controlar quién tiene acceso a qué secretos utilizando políticas de IAM para garantizar que los secretos que gestionas sólo son accesibles por los responsables de seguridad necesarios.

Como tu instancia EC2 utiliza un perfil de instancia, no necesitas almacenar ninguna credencial codificada en la instancia para que pueda acceder al secreto. El acceso se concede a través de la política IAM adjunta al perfil de instancia. Cada vez que tú (o tu aplicación) accede al secreto desde la instancia EC2, se obtienen credenciales de sesión temporales del servicio STS para permitir que la llamada a la API get-secret-value recupere el secreto. La CLI de AWS automatiza este proceso de recuperación del token cuando se adjunta un perfil de instancia EC2 a tu instancia. También puedes utilizar el SDK de AWS dentro de tus aplicaciones para conseguir esta funcionalidad.

Algunas ventajas adicionales de utilizar el Gestor de Secretos son las siguientes:

  • Cifrar secretos con claves KMS que tú creas y gestionas

  • Auditar el acceso a los secretos a través de CloudTrail

  • Automatizar la rotación de secretos con Lambda

  • Conceder acceso a otros usuarios, roles y servicios como EC2 y Lambda

  • Replicar secretos a otra Región con fines de alta disponibilidad y recuperación ante desastres

Desafío

Configura una función Lambda para acceder al secreto de forma segura con un rol IAM.

1.9 Bloquear el Acceso Público a un Bucket S3

Problema

El equipo de seguridad de tu organización te ha alertado de que un bucket S3 se ha configurado incorrectamente y necesitas bloquear el acceso público al mismo.

Solución

Aplica la función Acceso Público a Bloques de Amazon S3 a tu bucket, y luego comprueba el estado con el Analizador de Acceso (ver Figura 1-11).

Consejo

AWS proporciona información sobre lo que se considera "público" en un artículo sobre el almacenamiento S3.

Blocking public access to an S3 bucket
Figura 1-11. Bloquear el acceso público a un bucket S3

Requisito previo

  • Cubo S3 con objeto(s) disponible(s) públicamente

Preparación

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Pasos

  1. Crea un Analizador de Accesos para utilizarlo en la validación de accesos:

    ANALYZER_ARN=$(aws accessanalyzer create-analyzer \
         --analyzer-name awscookbook109\
         --type ACCOUNT \
         --output text --query arn)
  2. Realiza un escaneo de tu bucket S3 con el Analizador de Acceso:

    aws accessanalyzer start-resource-scan \
         --analyzer-arn $ANALYZER_ARN \
         --resource-arn arn:aws:s3:::awscookbook109-$RANDOM_STRING
  3. Obtén los resultados del escaneo de Access Analyzer (los resultados del escaneo pueden tardar unos 30 segundos en estar disponibles):

    aws accessanalyzer get-analyzed-resource \
         --analyzer-arn $ANALYZER_ARN \
         --resource-arn arn:aws:s3:::awscookbook109-$RANDOM_STRING

    Deberías ver una salida similar a la siguiente (fíjate en el valor isPublic ):

    {
      "resource": {
      "actions": [
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "analyzedAt": "2021-06-26T17:42:00.861000+00:00",
      "createdAt": "2021-06-26T17:42:00.861000+00:00",
      "isPublic": true,
      "resourceArn": "arn:aws:s3:::awscookbook109-<<string>>",
      "resourceOwnerAccount": "111111111111",
      "resourceType": "AWS::S3::Bucket",
      "sharedVia": [
        "POLICY"
      ],
      "status": "ACTIVE",
      "updatedAt": "2021-06-26T17:42:00.861000+00:00"
      }
    }
  4. Establece el bloqueo de acceso público para tu cubo:

    aws s3api put-public-access-block \
         --bucket awscookbook109-$RANDOM_STRING \
         --public-access-block-configuration \
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
    Nota

    Consulta el artículo de AWS sobre las propiedades de configuración disponibles en PublicAccessBlock.

Comprobaciones de validación

Realiza un escaneo de tu bucket S3:

aws accessanalyzer start-resource-scan \
     --analyzer-arn $ANALYZER_ARN \
     --resource-arn arn:aws:s3:::awscookbook109-$RANDOM_STRING

Obtén los resultados del escaneo del Analizador de Acceso:

aws accessanalyzer get-analyzed-resource \
     --analyzer-arn $ANALYZER_ARN \
     --resource-arn arn:aws:s3:::awscookbook109-$RANDOM_STRING

Deberías ver una salida similar a la siguiente:

{
  "resource": {
  "analyzedAt": "2021-06-26T17:46:24.906000+00:00",
  "isPublic": false,
  "resourceArn": "arn:aws:s3:::awscookbook109-<<string>>",
  "resourceOwnerAccount": "111111111111",
  "resourceType": "AWS::S3::Bucket"
  }
}

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Una de las mejores cosas que puedes hacer para garantizar la seguridad de los datos en tu cuenta de AWS es asegurarte siempre de que aplicas los controles de seguridad adecuados a tus datos. Si marcas un objeto como público en tu cubo de S3, será accesible a cualquier persona en Internet, ya que S3 sirve objetos mediante HTTP. Uno de los errores de configuración de seguridad más comunes que cometen los usuarios en la nube es marcar objeto(s) como público(s) cuando no se pretende o no es necesario. Para protegerte contra la configuración errónea de los objetos de S3, habilitar BlockPublicAccess para tus cubos es una buena medida desde el punto de vista de la seguridad.

Consejo

También puedes establecer la configuración de bloque público a nivel de cuenta, lo que incluiría todos los buckets S3 de tu cuenta:

aws s3control put-public-access-block \
    --public-access-block-configuration \
    BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true \
    --account-id $AWS_ACCOUNT_ID

Puedes servir contenido de S3 a usuarios de Internet a través de HTTP y HTTPS mientras mantienes tu bucket privado. Las redes de entrega de contenido (CDN), como Amazon CloudFront, proporcionan formas más seguras, eficientes y rentables de conseguir alojamiento global de sitios web estáticos y seguir utilizando S3 como tu fuente de objetos. Para ver un ejemplo de configuración de CloudFront que sirve contenido estático desde un bucket de S3, consulta la Receta 1.10.

Desafío

Implementa un endpoint VPC para S3 dentro de tu VPC y crea una política de bucket para restringir el acceso a tu bucket S3 sólo a través de este endpoint.

1.10 Servir contenido web de forma segura desde S3 con CloudFront

Problema

Tienes contenido web no público en S3 y quieres configurar CloudFront para servir el contenido.

Solución

Crea una distribución de CloudFront y establece el origen en tu bucket de S3. A continuación, configura una identidad de acceso al origen (OAI) para requerir a que el bucket sea accesible sólo desde CloudFront (ver Figura 1-12).

CloudFront and S3
Figura 1-12. CloudFront y S3

Requisito previo

  • Bucket S3 con contenido web estático

Preparación

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Pasos

  1. Crea una referencia de CloudFront OAI a en una política de bucket de S3:

    OAI=$(aws cloudfront create-cloud-front-origin-access-identity \
         --cloud-front-origin-access-identity-config \
         CallerReference="awscookbook",Comment="AWSCookbook OAI" \
         --query CloudFrontOriginAccessIdentity.Id --output text)
  2. Utiliza el comando sed para sustituir los valores del archivo distribution-config-template.json por tu OAI de CloudFront y el nombre de tu bucket de S3:

    sed -e "s/CLOUDFRONT_OAI/${OAI}/g" \
         -e "s|S3_BUCKET_NAME|awscookbook110-$RANDOM_STRING|g" \
         distribution-template.json > distribution.json
  3. Crea una distribución CloudFront que utilice el archivo JSON de configuración de la distribución que acabas de crear:

    DISTRIBUTION_ID=$(aws cloudfront create-distribution \
         --distribution-config file://distribution.json \
         --query Distribution.Id --output text)
  4. La distribución tardará unos minutos en crearse; utiliza este comando para comprobar el estado. Espera hasta que el estado sea "Implementado":

    aws cloudfront get-distribution --id $DISTRIBUTION_ID \
        --output text --query Distribution.Status
  5. Configura la política del cubo de S3 para que sólo permita peticiones desde CloudFront utilizando una política de cubo como ésta (hemos proporcionado bucket-policy-template.json en el repositorio):

    {
      "Version": "2012-10-17",
      "Id": "PolicyForCloudFrontPrivateContent",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity CLOUDFRONT_OAI"
          },
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::S3_BUCKET_NAME/*"
        }
      ]
    }
  6. Utiliza el comando sed para sustituir los valores del archivo bucket-policy-template.json por la OAI de CloudFront y el nombre del bucket de S3:

    sed -e "s/CLOUDFRONT_OAI/${OAI}/g" \
         -e "s|S3_BUCKET_NAME|awscookbook110-$RANDOM_STRING|g" \
         bucket-policy-template.json > bucket-policy.json
  7. Aplica la política de cubos al cubo S3 con tu contenido web estático:

    aws s3api put-bucket-policy --bucket awscookbook110-$RANDOM_STRING \
         --policy file://bucket-policy.json
  8. Obtén la dirección DOMAIN_NAME de la distribución que has creado:

    DOMAIN_NAME=$(aws cloudfront get-distribution --id $DISTRIBUTION_ID \
         --query Distribution.DomainName --output text)

Comprobaciones de validación

Intenta acceder directamente al bucket de S3 utilizando HTTPS para verificar que el bucket no sirve contenido directamente:

curl https://awscookbook110-$RANDOM_STRING.s3.$AWS_REGION.amazonaws.com/index.html

Deberías ver una salida similar a la siguiente:

$ curl https://awscookbook110-$RANDOM_STRING.s3.$AWS_REGION.amazonaws.com/index.html
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access
Denied</Message><RequestId>0AKQD0EFJC9ZHPCC</RequestId><HostId>gfld4qKp9A93G8ee7VPBFrXBZV1HE3jiOb3bNB54fP
EPTihit/OyFh7hF2Nu4+Muv6JEc0ebLL4=</HostId></Error>
110-Optimizing-S3-with-CloudFront:$

Utiliza curl para observar que tu archivo index. html se sirve desde el bucket privado de S3 a través de CloudFront:

curl $DOMAIN_NAME

Deberías ver una salida similar a la siguiente:

$ curl $DOMAIN_NAME
AWSCookbook
$

Limpieza

Sigue los pasos de la carpeta de esta receta en el repositorio de código del capítulo.

Debate

Esta configuración te permite mantener el bucket de S3 privado y permite que sólo la distribución de CloudFront pueda acceder a los objetos del bucket. Has creado una identidad de acceso de origen y definido una política de bucket para permitir sólo el acceso de CloudFront a tu contenido de S3. Esto te proporciona una base sólida para mantener seguros tus buckets de S3 con la protección adicional de la CDN global de CloudFront.

Cabe destacar la protección que proporciona una CDN frente a un ataque de denegación de servicio distribuido (DDoS), ya que las solicitudes de los usuarios finales a tu contenido se dirigen a un punto de presencia en la red de CloudFront con la latencia más baja. Esto también te protege de los costes de sufrir un ataque DDoS contra contenido estático alojado en un bucket de S3, ya que suele ser menos costoso servir las peticiones desde CloudFront que desde S3 directamente.

Por defecto, CloudFront viene con un certificado HTTPS en el nombre de host predeterminado para tu distribución que utilizas para asegurar el tráfico. Con CloudFront, puedes asociar tu propio nombre de dominio personalizado, adjuntar un certificado personalizado de Amazon Certificate Manager (ACM), redirigir a HTTPS desde HTTP, forzar HTTPS, personalizar el comportamiento de la caché, invocar funciones Lambda (Lambda @Edge) y mucho más.

Desafío

Añade una restricción geográfica a tu distribución CloudFront .

Get Libro de cocina AWS now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.