IAM 教程:使用 AWS CloudFormation 模板创建 SAML 联合 IAM 角色 - AWS Identity and Access Management

IAM 教程:使用 AWS CloudFormation 模板创建 SAML 联合 IAM 角色

当 AWS 账户中配置了现有 SAML 身份提供者 (IdP) 时,可创建信任该 IdP 的联合 IAM 角色。本教程展示如何使用 AWS CloudFormation 模板,创建通过外部 IdP 进行身份验证的用户可代入的 SAML 联合 IAM 角色。

该模板使用允许 SAML IdP 代入该角色的信任策略创建联合 IAM 角色。经外部 IdP 进行身份验证的用户可以代入此角色,根据附加至该角色的权限访问 AWS 资源。

所部署的资源包括以下部分:

  • 信任现有 SAML IdP 的联合 IAM 角色。

  • 可配置的托管策略,可以附加到该角色以授予特定权限。

  • 可选的权限边界和会话持续时间设置。

先决条件

本教程假定您已准备好以下各项:

  • AWS 账户中配置的现有 SAML IdP。如果还没有,可以使用 IAM 教程:使用 AWS CloudFormation 模板创建 SAML 身份提供者 (IdP) 教程创建一个。

  • SAML IdP 的 ARN,需要在创建堆栈时将其指定为参数。

  • 本地计算机上安装了 Python 3.6 或更高版本,可运行本教程中用于对 IdP 的 SAML 元数据 XML 文件进行格式化的 Python 命令。

使用 AWS CloudFormation 创建 SAML 联合角色

要创建 SAML 联合角色,您需要创建 CloudFormation 模板,并使用此模板创建包含该角色的堆栈。

创建 模板

首先,创建 CloudFormation 模板。

  1. 模板 部分中,单击 JSONYAML 选项卡上的复制图标,以复制模板内容。

  2. 将模板内容粘贴到新文件中。

  3. 将该文件保存在本地。

创建堆栈

接下来,使用已保存的模板来预置 CloudFormation 堆栈。

  1. 通过以下网址打开 AWS CloudFormation 控制台:https://console.aws.amazon.com/cloudformation

  2. 堆栈页面,从创建堆栈菜单中选择(采用新资源(标准))

  3. 指定模板:

    1. 先决条件下,选择选择现有模板

    2. 指定模板下,选择上传模板文件

    3. 选择选择文件,导航到模板文件并将其选中。

    4. 选择下一步

  4. 指定以下堆栈详细信息:

    1. 输入堆栈名称。

    2. 对于 SAMLProviderARN,请输入现有 SAML IdP 的 ARN。其格式应为 arn:aws:iam::123456789012:saml-provider/YourProviderName

      示例:arn:aws:iam::123456789012:saml-provider/CompanyIdP

      注意

      如果使用 IAM 教程:使用 AWS CloudFormation 模板创建 SAML 身份提供者 (IdP) 教程创建了 SAML IdP,则可以在该 CloudFormation 堆栈的“输出”选项卡中找到提供者 ARN。

    3. 对于 RoleName,可将其留空以根据堆栈名称自动生成名称,也可以为 IAM 角色输入自定义名称。

      示例:SAML-Developer-AccessSAML-ReadOnly-Role

    4. 对于其他参数,请接受默认值或根据需要输入自己的值:

      • RoleSessionDuration - 最大会话持续时间,以秒为单位(3600-43200,默认为 7200)

        示例:14400(4 小时)

      • RolePermissionsBoundary - 权限边界策略的可选 ARN

        示例:arn:aws:iam::123456789012:policy/DeveloperBoundary

      • RolePath - IAM 角色的路径(默认为 /)

        示例:/saml-roles/

      • ManagedPolicy1-5 - 最多 5 个待附加托管策略的可选 ARN

        ManagedPolicy1 示例:arn:aws:iam::aws:policy/ReadOnlyAccess

        ManagedPolicy2 示例:arn:aws:iam::123456789012:policy/CustomPolicy

    5. 选择下一步

  5. 配置堆栈选项:

    1. 堆栈故障选项下,选择删除所有新创建的资源

      注意

      如果选择此选项,即使堆栈创建失败,您可能也不会因为删除策略规定保留资源而向资源付费。

    2. 接受其他所有默认值。

    3. 功能下勾选复选框,确认 CloudFormation 可能在您的账户中创建 IAM 资源。

    4. 选择下一步

  6. 查看堆栈详细信息并选择提交

AWS CloudFormation 将创建堆栈。一旦堆栈创建完成之后,堆栈资源就即可投入使用。可使用堆栈详细信息页面上的资源选项卡来查看账户中预置的资源。

堆栈将输出以下值,可参见输出选项卡:

  • RoleARN:已创建的 IAM 角色的 ARN(例如,arn:aws:iam::123456789012:role/SAML-Developer-Accessarn:aws:iam::123456789012:role/stack-name-a1b2c3d4,如果使用自动生成的名称)。

在配置 IdP 以发送相应 SAML 属性进行角色代入时,需要此角色 ARN。

测试 SAML 联合角色

一旦创建 SAML 联合角色后,可验证其配置并测试联合身份验证设置。

  1. 通过以下网址打开 IAM 控制台:https://console.aws.amazon.com/iam/

  2. 在导航窗格中,选择角色

  3. 找到并选择新创建的联合角色。

    如果提供了自定义角色名称,请查找该名称。如果将 RoleName 参数留空,则该角色将拥有一个基于堆栈名称和唯一标识符的自动生成名称。

  4. 选择信任关系选项卡,查看信任策略。

    信任策略应表明在 SAML 受众 (SAML:aud) 匹配 https://signin.aws.amazon.com/saml 的条件下,信任您的 SAML IdP 代入此角色。

  5. 选择权限选项卡,查看附加的策略。

    您可以看到在创建过程中附加至该角色的任何托管策略。

  6. 记下角色摘要页面上显示的角色 ARN

    您需要此 ARN 来配置外部 IdP,以允许用户代入此角色。

您的 SAML 联合角色已准备好投入使用。将外部 IdP 配置为在 SAML 断言中包含此角色的 ARN,经过身份验证的用户将能够代入此角色来访问 AWS 资源。

清理:删除资源

最后一步,您将删除该堆栈及其包含的资源。

  1. 打开 AWS CloudFormation 控制台。

  2. 堆栈页面上,选择根据该模板创建的堆栈,选择删除,然后确认删除

    CloudFormation 启动删除堆栈及其包含的所有资源。

CloudFormation 模板详细信息

资源

本教程的 AWS CloudFormation 模板将在您的账户中创建以下资源:

  • AWS::IAM::Role:一个可以由通过 SAML IdP 进行身份验证的用户代入的联合 IAM 角色。

配置

模板包含如下可配置参数:

  • RoleName - IAM 角色的名称(自动生成的名称请留空)

  • SAMLProviderARN - SAML IdP 的 ARN(必需)

  • RoleSessionDuration - 最大会话持续时间,以秒为单位(3600-43200,默认为 7200)

  • RolePermissionsBoundary - 权限边界策略的可选 ARN

  • RolePath - IAM 角色的路径(默认为 /)

  • ManagedPolicy1-5 - 最多 5 个待附加托管策略的可选 ARN

CloudFormation 模板

将以下 JSON 或 YAML 代码另存为单独文件,以用作本教程的 CloudFormation 模板。

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "[AWSDocs] IAM: tutorial_saml-federated-role", "Parameters": { "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 +=,.@-" }, "SAMLProviderARN": { "Type": "String", "Description": "ARN of the SAML Identity Provider", "AllowedPattern": "^arn:aws:iam::\\d{12}:saml-provider/[a-zA-Z0-9._-]+$", "ConstraintDescription": "Must be a valid SAML provider ARN" }, "RoleSessionDuration": { "Type": "Number", "Description": "The maximum session duration (in seconds) that you want to set for the specified role (3600-43200)", "MinValue": 3600, "MaxValue": 43200, "Default": 7200 }, "RolePermissionsBoundary": { "Type": "String", "Description": "Optional ARN of the permissions boundary policy (leave empty for none)", "Default": "" }, "RolePath": { "Type": "String", "Description": "Path for the IAM role (must start and end with /)", "Default": "/", "AllowedPattern": "^\/.*\/$|^\/$", "ConstraintDescription": "Role path must start and end with forward slash (/)" }, "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": { "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"}, ""]}]} }, "Resources": { "SAMLFederatedRole": { "Type": "AWS::IAM::Role", "Properties": { "RoleName": {"Fn::If": ["HasCustomRoleName", {"Ref": "RoleName"}, {"Ref": "AWS::NoValue"}]}, "Description": "IAM role with SAML provider trust", "MaxSessionDuration": {"Ref": "RoleSessionDuration"}, "PermissionsBoundary": {"Fn::If": ["HasPermissionsBoundary", {"Ref": "RolePermissionsBoundary"}, {"Ref": "AWS::NoValue"}]}, "Path": {"Ref": "RolePath"}, "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": {"Ref": "SAMLProviderARN"} }, "Action": "sts:AssumeRoleWithSAML", "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"} } } } }
YAML
AWSTemplateFormatVersion: '2010-09-09' Description: '[AWSDocs] IAM: tutorial_saml-federated-role' Parameters: 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 +=,.@-' SAMLProviderARN: Type: String Description: 'ARN of the SAML Identity Provider' AllowedPattern: '^arn:aws:iam::\d{12}:saml-provider/[a-zA-Z0-9._-]+$' ConstraintDescription: 'Must be a valid SAML provider ARN' RoleSessionDuration: Type: Number Description: 'The maximum session duration (in seconds) that you want to set for the specified role (3600-43200)' MinValue: 3600 MaxValue: 43200 Default: 7200 RolePermissionsBoundary: Type: String Description: Optional ARN of the permissions boundary policy (leave empty for none) Default: "" RolePath: Type: String Description: 'Path for the IAM role (must start and end with /)' Default: "/" AllowedPattern: '^\/.*\/$|^\/$' ConstraintDescription: 'Role path must start and end with forward slash (/)' 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: 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, ""]] Resources: SAMLFederatedRole: Type: 'AWS::IAM::Role' Properties: RoleName: !If - HasCustomRoleName - !Ref RoleName - !Ref AWS::NoValue Description: 'IAM role with SAML provider trust' MaxSessionDuration: !Ref RoleSessionDuration PermissionsBoundary: !If - HasPermissionsBoundary - !Ref RolePermissionsBoundary - !Ref AWS::NoValue Path: !Ref RolePath AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Federated: !Ref SAMLProviderARN Action: 'sts:AssumeRoleWithSAML' 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'