Tutorial de IAM: use una plantilla de AWS CloudFormation para crear un proveedor de identidades (IdP) de SAML y un rol de IAM federado de SAML - AWS Identity and Access Management

Tutorial de IAM: use una plantilla de AWS CloudFormation para crear un proveedor de identidades (IdP) de SAML y un rol de IAM federado de SAML

Para familiarizarse con la federación de SAML y sus capacidades, utilizará una plantilla de AWS CloudFormation para configurar un proveedor de identidades (IdP) y el rol de IAM federado de SAML asociado. En este tutorial, se muestra cómo crear ambos recursos en una sola pila.

La plantilla crea un IdP de SAML que se puede utilizar para el acceso federado a los recursos de AWS, junto con un rol de IAM que confía en el proveedor de SAML. Los usuarios autenticados por su IdP externo pueden asumir este rol para acceder a los recursos de AWS.

Los recursos desplegados constan de los siguientes elementos:

  • Un IdP de SAML configurado con el documento de metadatos de su IdP.

  • Un rol de IAM federado que confía en el IdP de SAML y que pueden asumir los usuarios autenticados.

  • Políticas administradas configurables que se pueden adjuntar al rol para conceder permisos específicos.

Requisitos previos

En este tutorial se presupone que los elementos siguientes ya existen:

  • Python 3.6 o una versión posterior instalada en su máquina local para ejecutar el comando de Python utilizado en este tutorial a fin de formatear el archivo XML de metadatos SAML de su IdP.

  • Un documento de metadatos de SAML de su IdP externo guardado como un archivo XML.

Crear un IdP y un rol de SAML mediante AWS CloudFormation

Para crear el IdP y el rol federado de SAML, debe crear una plantilla de CloudFormation y utilizarla para crear una pila que contenga ambos recursos.

Crear la plantilla

Primero, cree la plantilla de CloudFormation.

  1. En la sección Plantilla, haga clic en el icono de copia de la pestaña JSON o YAML para copiar el contenido de la plantilla.

  2. Pegue el contenido de la plantilla en un archivo nuevo.

  3. Guarde el archivo localmente.

Creación de la pila

A continuación, utilice la plantilla que creó para aprovisionar una pila de CloudFormation.

  1. Abra la consola de AWS CloudFormation en https://console.aws.amazon.com/cloudformation.

  2. En la página Pilas, para Crear pila elija Con nuevos recursos (estándar).

  3. En Especificar plantilla:

    1. En Requisito previo, elija Seleccionar una plantilla existente.

    2. En Especificar plantilla, elija Cargar un archivo de plantilla.

    3. Seleccione Elegir archivo para navegar hasta el archivo y seleccionarlo.

    4. Elija Siguiente.

  4. Especifique los siguientes detalles de la pila:

    1. Introduzca un nombre de pila.

    2. En el caso de IdentityProviderName, puede dejar este campo vacío para generar automáticamente un nombre basado en el nombre de la pila o introducir un nombre personalizado para su IdP de SAML.

      Ejemplo: CompanyIdP o EnterpriseSSO

    3. En el caso de IdentityProviderSAMLMetadataDocument, debe formatear el archivo XML de metadatos de SAML en una sola línea antes de pegarlo en este campo. Esto es necesario porque la consola de CloudFormation requiere que el contenido XML se formatee como una sola línea cuando se pasa por los parámetros de la consola.

      Use el siguiente comando de Python para cambiar el formato del archivo XML:

      python3 -c "import sys, re; content=open(sys.argv[1]).read(); print(re.sub(r'>\s+<', '><', content.replace('\n', '').replace('\r', '').strip()))" saml-metadata.xml
      nota

      El documento de metadatos de SAML del IdP debe estar formateado en una sola línea para introducir los parámetros en la consola. El comando Python elimina los saltos de línea y los espacios en blanco adicionales para crear el formato requerido y, al mismo tiempo, mantener todo el contenido y la estructura originales.

      Copie el resultado del comando Python y péguelo en el campo IdentityProviderSAMLMetadataDocument.

      Ejemplo de documento de metadatos de SAML formateado (abreviado):

      <?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://portal.sso.example.com/saml/assertion/CompanyIdP"><md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV...</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://portal.sso.example.com/saml/logout/CompanyIdP"/><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://portal.sso.example.com/saml/assertion/CompanyIdP"/></md:IDPSSODescriptor></md:EntityDescriptor>
    4. Para RoleName, puede dejar este campo vacío para generar automáticamente un nombre basado en el nombre de la pila o introducir un nombre personalizado para el rol de IAM federado.

      Ejemplo: SAML-Developer-Access o SAML-ReadOnly-Role

    5. Para otros parámetros, acepte los valores predeterminados o introduzca los propios en función de sus requisitos:

      • IdentityProviderAddPrivateKey: clave privada opcional para descifrar las aserciones de SAML

      • IdentityProviderAssertionEncryptionMode: modo de cifrado para las aserciones de SAML

        Valores de ejemplo: Allowed, Required, o déjelos en blanco si no se cifra

      • RoleSessionDuration: duración máxima de la sesión en segundos (3600-43 200, el valor predeterminado es 7200)

        Ejemplo: 14400 (4 horas)

      • RolePermissionsBoundary: ARN opcional de una política de límite de permisos

        Ejemplo: arn:aws:iam::123456789012:policy/DeveloperBoundary

      • RolePath: ruta para el rol de IAM (el valor predeterminado es /)

        Ejemplo: /saml-roles/

      • RoleManagedPolicy1-5: se pueden adjuntar ARN opcionales de hasta 5 políticas administradas

        Ejemplo de RoleManagedPolicy1: arn:aws:iam::aws:policy/ReadOnlyAccess

        Ejemplo de RoleManagedPolicy2: arn:aws:iam::123456789012:policy/CustomPolicy

    6. Elija Siguiente.

  5. Configure las opciones la pila:

    1. En las opciones de error de pila, seleccione Eliminar todos los recursos recién creados.

      nota

      Si elige esta opción, evita que se le facturen los recursos cuya política de eliminación especifique que se conservarán incluso si se produce un error durante la creación de la pila.

    2. Acepte todos los demás valores predeterminados.

    3. En Capacidades, seleccione la casilla para aceptar que CloudFormation puede crear recursos de IAM en su cuenta.

    4. Elija Siguiente.

  6. Revise los detalles de la pila y elija Enviar.

AWS CloudFormation crea el stack. Una vez completada la creación de la pila, los recursos de la pila están listos para usarse. Puede usar la pestaña Recursos de la página de detalles de la pila para ver los recursos que se aprovisionaron en su cuenta.

La pila generará los siguientes valores, que puede ver en la pestaña Resultados:

  • RoleARN: el ARN del rol de IAM creado (por ejemplo, arn:aws:iam::123456789012:role/SAML-Developer-Access o arn:aws:iam::123456789012:role/stack-name-a1b2c3d4 si se utiliza un nombre generado automáticamente).

  • IdentityProviderARN: el ARN del IDP de SAML creado (por ejemplo, arn:aws:iam::123456789012:saml-provider/CompanyIdP ).

Necesitará estos dos ARN al configurar su IDP para enviar los atributos de SAML adecuados para la asunción del rol.

Probar la federación de SAML

Una vez que se hayan creado el IdP y el rol federado de SAML, puede probar la configuración de la federación.

  1. Abra la consola de IAM en https://console.aws.amazon.com/iam/.

  2. En el panel de navegación, elija Proveedores de identidades.

    Ahora debería poder ver el IdP de SAML recién creado en la lista.

  3. Seleccione el nombre del IdP para ver sus detalles.

    En la página de detalles del IdP, puede ver el documento de metadatos de SAML y otros detalles de configuración.

  4. Seleccione Roles en el panel de navegación.

  5. Busque y seleccione el rol federado que acaba de crear.

    En la página de detalles del rol, puede ver la política de confianza que permite que el IdP de SAML asuma este rol.

  6. Seleccione la pestaña Relaciones de confianza para revisar la política de confianza.

    La política de confianza debe mostrar que se confía en el IdP de SAML para asumir este rol con la condición de que la audiencia de SAML (SAML:aud) coincida con https://signin.aws.amazon.com/saml.

Limpieza: elimine recursos

Como último paso, eliminará la pila y los recursos que contiene.

  1. Abra la consola de AWS CloudFormation.

  2. En la página Pilas, seleccione la pila creada a partir de la plantilla, seleccione Eliminar y, a continuación, confirme Eliminar.

    CloudFormation inicia la eliminación de la pila y de todos los recursos que incluye.

Detalles de la plantilla de CloudFormation

Recursos

La plantilla de AWS CloudFormation para este tutorial crea los siguientes recursos en su cuenta:

  • AWS::IAM::SAMLProvider: un IdP de SAML que establece confianza entre AWS y su IdP externo.

  • AWS::IAM::Role: un rol de IAM federado que pueden asumir los usuarios autenticados a través del IdP de SAML.

Configuración

La plantilla incluye los siguientes parámetros configurables:

  • IdentityProviderName: nombre del IdP de SAML (déjelo en blanco para que el nombre se genere automáticamente)

  • IdentityProviderSAMLMetadataDocument: documento de metadatos de SAML de su IdP (obligatorio)

  • IdentityProviderAddPrivateKey: clave privada opcional para descifrar las aserciones de SAML

  • IdentityProviderAssertionEncryptionMode: modo de cifrado para las aserciones de SAML

  • RoleName: nombre del rol de IAM (déjelo en blanco para que el nombre se genere automáticamente)

  • RolePath: ruta para el rol de IAM (el valor predeterminado es /)

  • RolePermissionsBoundary: ARN opcional de una política de límite de permisos

  • RoleSessionDuration: duración máxima de la sesión en segundos (3600-43 200, el valor predeterminado es 7200)

  • RoleManagedPolicy1-5: se pueden adjuntar ARN opcionales de hasta 5 políticas administradas

Plantilla de CloudFormation

Guarde el siguiente código JSON o YAML como un archivo independiente para usarlo como plantilla de CloudFormation en este tutorial.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "[AWSDocs] IAM: tutorial_saml-idp-and-federated-role", "Parameters": { "IdentityProviderName": { "Type": "String", "Description": "Name of the SAML Identity Provider (leave empty for auto-generated name like '{StackName}-{UniqueId}')", "Default": "", "AllowedPattern": "^$|^[a-zA-Z0-9._-]+$", "ConstraintDescription": "Must be empty or contain only alphanumeric characters, periods, underscores, and hyphens" }, "IdentityProviderSAMLMetadataDocument": { "Type": "String", "Description": "SAML metadata document from identity provider" }, "IdentityProviderAddPrivateKey": { "Type": "String", "Description": "Optional private key for decrypting SAML assertions. The private key must be a .pem file that uses AES-GCM or AES-CBC encryption algorithm to decrypt SAML assertions.", "Default": "" }, "IdentityProviderAssertionEncryptionMode": { "Type": "String", "Description": "Optional, sets encryption mode for SAML assertions", "Default": "", "AllowedValues": ["", "Allowed", "Required"] }, "RoleName": { "Type": "String", "Description": "Name of the IAM Role (leave empty for auto-generated name like '{StackName}-{UniqueId}')", "Default": "", "AllowedPattern": "^$|^[\\w+=,.@-]{1,64}$", "ConstraintDescription": "Must be empty or 1-64 characters and can contain alphanumeric characters and +=,.@-" }, "RolePath": { "Type": "String", "Description": "Path for the IAM Role", "AllowedPattern": "(^\\/$)|(^\\/.*\\/$)", "Default": "/" }, "RolePermissionsBoundary": { "Type": "String", "Description": "Optional ARN of the permissions boundary policy (leave empty for none)", "Default": "" }, "RoleSessionDuration": { "Description": "The maximum session duration (in seconds) that you want to set for the specified role (3600-43200)", "Type": "Number", "MinValue": 3600, "MaxValue": 43200, "Default": 7200 }, "RoleManagedPolicy1": { "Type": "String", "Description": "Optional managed policy ARN 1", "Default": "" }, "RoleManagedPolicy2": { "Type": "String", "Description": "Optional managed policy ARN 2", "Default": "" }, "RoleManagedPolicy3": { "Type": "String", "Description": "Optional managed policy ARN 3", "Default": "" }, "RoleManagedPolicy4": { "Type": "String", "Description": "Optional managed policy ARN 4", "Default": "" }, "RoleManagedPolicy5": { "Type": "String", "Description": "Optional managed policy ARN 5", "Default": "" } }, "Conditions": { "HasCustomProviderName": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderName"}, ""]}]}, "HasCustomRoleName": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleName"}, ""]}]}, "HasPermissionsBoundary": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RolePermissionsBoundary"}, ""]}]}, "HasPolicy1": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleManagedPolicy1"}, ""]}]}, "HasPolicy2": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleManagedPolicy2"}, ""]}]}, "HasPolicy3": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleManagedPolicy3"}, ""]}]}, "HasPolicy4": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleManagedPolicy4"}, ""]}]}, "HasPolicy5": {"Fn::Not": [{"Fn::Equals": [{"Ref": "RoleManagedPolicy5"}, ""]}]}, "HasPrivateKey": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderAddPrivateKey"}, ""]}]}, "HasAssertionEncryptionMode": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderAssertionEncryptionMode"}, ""]}]} }, "Resources": { "SAMLProvider": { "Type": "AWS::IAM::SAMLProvider", "Properties": { "Name": {"Fn::If": ["HasCustomProviderName", {"Ref": "IdentityProviderName"}, {"Ref": "AWS::NoValue"}]}, "SamlMetadataDocument": {"Ref": "IdentityProviderSAMLMetadataDocument"}, "AddPrivateKey": {"Fn::If": ["HasPrivateKey", {"Ref": "IdentityProviderAddPrivateKey"}, {"Ref": "AWS::NoValue"}]}, "AssertionEncryptionMode": {"Fn::If": ["HasAssertionEncryptionMode", {"Ref": "IdentityProviderAssertionEncryptionMode"}, {"Ref": "AWS::NoValue"}]} } }, "SAMLFederatedRole": { "Type": "AWS::IAM::Role", "Properties": { "RoleName": {"Fn::If": ["HasCustomRoleName", {"Ref": "RoleName"}, {"Ref": "AWS::NoValue"}]}, "Path": {"Ref": "RolePath"}, "Description": "SAML federated IAM role for SSO access with specified permissions", "MaxSessionDuration": {"Ref": "RoleSessionDuration"}, "PermissionsBoundary": {"Fn::If": ["HasPermissionsBoundary", {"Ref": "RolePermissionsBoundary"}, {"Ref": "AWS::NoValue"}]}, "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": {"Ref": "SAMLProvider"} }, "Action": [ "sts:AssumeRole", "sts:SetSourceIdentity", "sts:TagSession" ], "Condition": { "StringEquals": { "SAML:aud": "https://signin.aws.amazon.com/saml" } } } ] }, "ManagedPolicyArns": { "Fn::Split": [ ",", { "Fn::Join": [ ",", [ {"Fn::If": ["HasPolicy1", {"Ref": "RoleManagedPolicy1"}, {"Ref": "AWS::NoValue"}]}, {"Fn::If": ["HasPolicy2", {"Ref": "RoleManagedPolicy2"}, {"Ref": "AWS::NoValue"}]}, {"Fn::If": ["HasPolicy3", {"Ref": "RoleManagedPolicy3"}, {"Ref": "AWS::NoValue"}]}, {"Fn::If": ["HasPolicy4", {"Ref": "RoleManagedPolicy4"}, {"Ref": "AWS::NoValue"}]}, {"Fn::If": ["HasPolicy5", {"Ref": "RoleManagedPolicy5"}, {"Ref": "AWS::NoValue"}]} ] ] } ] } } } }, "Outputs": { "RoleARN": { "Description": "ARN of the created IAM Role", "Value": {"Fn::GetAtt": ["SAMLFederatedRole", "Arn"]}, "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-RoleARN"} } }, "IdentityProviderARN": { "Description": "ARN of the created SAML Identity Provider", "Value": {"Ref": "SAMLProvider"}, "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-IdentityProviderARN"} } } } }
YAML
AWSTemplateFormatVersion: '2010-09-09' Description: '[AWSDocs] IAM: tutorial_saml-idp-and-federated-role' Parameters: IdentityProviderName: Type: String Description: Name of the SAML Identity Provider (leave empty for auto-generated name like '{StackName}-{UniqueId}') Default: "" AllowedPattern: '^$|^[a-zA-Z0-9._-]+$' ConstraintDescription: Must be empty or contain only alphanumeric characters, periods, underscores, and hyphens IdentityProviderSAMLMetadataDocument: Type: String Description: SAML metadata document from identity provider IdentityProviderAddPrivateKey: Type: String Description: Optional private key for decrypting SAML assertions. The private key must be a .pem file that uses AES-GCM or AES-CBC encryption algorithm to decrypt SAML assertions. Default: "" IdentityProviderAssertionEncryptionMode: Type: String Description: Optional, sets encryption mode for SAML assertions Default: "" AllowedValues: - "" - "Allowed" - "Required" RoleName: Type: String Description: Name of the IAM Role (leave empty for auto-generated name like '{StackName}-{UniqueId}') Default: "" AllowedPattern: '^$|^[\w+=,.@-]{1,64}$' ConstraintDescription: "Must be empty or 1-64 characters and can contain alphanumeric characters and +=,.@-" RolePath: Type: String Description: Path for the IAM Role AllowedPattern: (^\/$)|(^\/.*\/$) Default: "/" RolePermissionsBoundary: Type: String Description: Optional ARN of the permissions boundary policy (leave empty for none) Default: "" RoleSessionDuration: Description: The maximum session duration (in seconds) that you want to set for the specified role (3600-43200) Type: Number MinValue: 3600 MaxValue: 43200 Default: 7200 RoleManagedPolicy1: Type: String Description: Optional managed policy ARN 1 Default: "" RoleManagedPolicy2: Type: String Description: Optional managed policy ARN 2 Default: "" RoleManagedPolicy3: Type: String Description: Optional managed policy ARN 3 Default: "" RoleManagedPolicy4: Type: String Description: Optional managed policy ARN 4 Default: "" RoleManagedPolicy5: Type: String Description: Optional managed policy ARN 5 Default: "" Conditions: HasCustomProviderName: !Not [!Equals [!Ref IdentityProviderName, ""]] HasCustomRoleName: !Not [!Equals [!Ref RoleName, ""]] HasPermissionsBoundary: !Not [!Equals [!Ref RolePermissionsBoundary, ""]] HasPolicy1: !Not [!Equals [!Ref RoleManagedPolicy1, ""]] HasPolicy2: !Not [!Equals [!Ref RoleManagedPolicy2, ""]] HasPolicy3: !Not [!Equals [!Ref RoleManagedPolicy3, ""]] HasPolicy4: !Not [!Equals [!Ref RoleManagedPolicy4, ""]] HasPolicy5: !Not [!Equals [!Ref RoleManagedPolicy5, ""]] HasPrivateKey: !Not [!Equals [!Ref IdentityProviderAddPrivateKey, ""]] HasAssertionEncryptionMode: !Not [!Equals [!Ref IdentityProviderAssertionEncryptionMode, ""]] Resources: SAMLProvider: Type: AWS::IAM::SAMLProvider Properties: Name: !If - HasCustomProviderName - !Ref IdentityProviderName - !Ref AWS::NoValue SamlMetadataDocument: !Ref IdentityProviderSAMLMetadataDocument AddPrivateKey: !If - HasPrivateKey - !Ref IdentityProviderAddPrivateKey - !Ref AWS::NoValue AssertionEncryptionMode: !If - HasAssertionEncryptionMode - !Ref IdentityProviderAssertionEncryptionMode - !Ref AWS::NoValue SAMLFederatedRole: Type: AWS::IAM::Role Properties: RoleName: !If - HasCustomRoleName - !Ref RoleName - !Ref AWS::NoValue Path: !Ref RolePath Description: "SAML federated IAM role for SSO access with specified permissions" MaxSessionDuration: !Ref RoleSessionDuration PermissionsBoundary: !If - HasPermissionsBoundary - !Ref RolePermissionsBoundary - !Ref AWS::NoValue AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Federated: !Ref SAMLProvider Action: - 'sts:AssumeRole' - 'sts:SetSourceIdentity' - 'sts:TagSession' Condition: StringEquals: 'SAML:aud': 'https://signin.aws.amazon.com/saml' ManagedPolicyArns: !Split - ',' - !Join - ',' - - !If [HasPolicy1, !Ref RoleManagedPolicy1, !Ref "AWS::NoValue"] - !If [HasPolicy2, !Ref RoleManagedPolicy2, !Ref "AWS::NoValue"] - !If [HasPolicy3, !Ref RoleManagedPolicy3, !Ref "AWS::NoValue"] - !If [HasPolicy4, !Ref RoleManagedPolicy4, !Ref "AWS::NoValue"] - !If [HasPolicy5, !Ref RoleManagedPolicy5, !Ref "AWS::NoValue"] Outputs: RoleARN: Description: ARN of the created IAM Role Value: !GetAtt SAMLFederatedRole.Arn Export: Name: !Sub '${AWS::StackName}-RoleARN' IdentityProviderARN: Description: ARN of the created SAML Identity Provider Value: !Ref SAMLProvider Export: Name: !Sub '${AWS::StackName}-IdentityProviderARN'