IAM 教學課程:使用 CloudFormation 範本建立 SAML 聯合 IAM 角色 - AWS Identity and Access Management

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

IAM 教學課程:使用 CloudFormation 範本建立 SAML 聯合 IAM 角色

當您在 AWS 帳戶中設定現有的 SAML Identity Provider (IdP) 時,您可以建立信任該 IdP 的聯合 IAM 角色。本教學課程說明如何使用 CloudFormation 範本來建立 SAML 聯合 IAM 角色,該角色可由透過外部 IdP 驗證的使用者擔任。

該範本會建立具有信任政策的聯合身分 IAM 角色,允許 SAML IdP 擔任該角色。透過外部 IdP 進行身分驗證的使用者可以擔任此角色,以便根據連接至該角色的許可存取 AWS 資源。

部署的資源包含下列項目:

  • 信任現有 SAML IdP 的聯合身分 IAM 角色。

  • 可連接至角色以授予特定許可的可設定受管政策。

  • 許可界限和工作階段持續時間的選用設定。

先決條件

此教學課程假設您已備妥下列項目:

  • 您 AWS 帳戶中設定的現有 SAML IdP。如果沒有,可以使用 IAM 教學課程:使用 CloudFormation 範本建立 SAML Identity Provider (IdP) 教學課程建立一個。

  • SAML IdP 的 ARN,您需要在建立堆疊時將其指定為參數。

  • 在本機電腦上安裝的 Python 3.6 或更新版本,以便執行本教學課程中用於格式化 IdP SAML 中繼資料 XML 檔案的 Python 命令。

使用 CloudFormation建立 SAML 聯合身分角色

若要建立 SAML 聯合身分角色,需要建立 CloudFormation 範本,並使用它來建立包含該角色的堆疊。

建立範本

首先,建立 CloudFormation 範本。

  1. 範本 區段中,按一下 JSONYAML 索引標籤上的複製圖示,以複製範本內容。

  2. 在新檔案中貼上範本內容。

  3. 在本機儲存檔案。

建立 堆疊。

接下來,使用剛儲存的範本來佈建 CloudFormation 堆疊。

  1. 在 https://https://console.aws.amazon.com/cloudformation 開啟 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 教學課程:使用 CloudFormation 範本建立 SAML Identity Provider (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. 檢閱堆疊詳細資訊,然後選擇提交

CloudFormation 會建立堆疊。堆疊建立完成後,堆疊資源即可使用。您可以使用堆疊詳細資訊頁面上的資源索引標籤,來檢視帳戶中佈建的資源。

堆疊將輸出下列值,您可以在輸出索引標籤上檢視該值:

  • RoleARN:已建立 IAM 角色的 ARN (例如 arn:aws:iam::123456789012:role/SAML-Developer-Access,或者如果使用自動產生的名稱,則為 arn: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 IdP 受信任可擔任此角色,條件是 SAML 對象 (SAML:aud) 與 https://signin.aws.amazon.com/saml 相符。

  5. 選擇許可索引標籤以檢閱連接的政策。

    您可以看到在建立期間連接至角色的所有受管政策。

  6. 記下角色摘要頁面上顯示的角色 ARN

    您需要此 ARN 才能設定外部 IdP,以允許使用者擔任此角色。

SAML 聯合身分角色現已準備就緒,可供使用。將外部 IdP 設定為在 SAML 聲明中包含此角色的 ARN,經過驗證的使用者將能夠擔任此角色來存取 AWS 資源。

清理:刪除資源

最後一個步驟是,刪除堆疊及其包含的資源。

  1. 開啟 CloudFormation 主控台。

  2. 堆疊頁面上,選擇從範本建立的堆疊,然後選擇刪除,接著確認刪除

    CloudFormation 會啟動刪除堆疊及其包含的所有資源。

CloudFormation 範本詳細資訊

Resources

本教學課程的 CloudFormation 範本會在您的帳戶中建立下列資源:

  • AWS::IAM::Role:可由透過 SAML IdP 進行身分驗證之使用者擔任的聯合身分 IAM 角色。

Configuration

範本包含下列可設定的參數:

  • 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'