

# IAM 자습서: CloudFormation 템플릿을 사용하여 SAML 페더레이션 IAM 역할 생성
<a name="tutorial_saml-federated-role"></a>

AWS 계정에 기존 SAML ID 제공업체(idP)가 구성되어 있는 경우, 해당 IdP를 신뢰하는 페더레이션 IAM 역할을 생성할 수 있습니다. 이 자습서에서는 CloudFormation 템플릿을 사용하여 외부 IdP를 통해 인증된 사용자가 수임할 수 있는 SAML 페더레이션 IAM 역할을 생성하는 방법을 보여줍니다.

템플릿은 SAML IdP가 역할을 수임하도록 허용하는 신뢰 정책을 사용하여 페더레이션 IAM 역할을 생성합니다. 외부 IdP에서 인증된 사용자는 이 역할을 수임하여 역할에 연결된 권한을 기준으로 AWS 리소스에 액세스할 수 있습니다.

배포된 리소스는 다음 항목으로 이루어져 있습니다.
+ 기존 SAML IdP를 신뢰하는 페더레이션 IAM 역할.
+ 구성 가능한 관리형 정책 - 역할에 연결하여 특정 권한을 부여할 수 있습니다.
+ 선택적 권한 경계 및 세션 지속 시간 설정.

## 사전 조건
<a name="tutorial_saml-federated-role-prereqs"></a>

이 자습서에서는 다음을 이미 완료했다고 가정합니다.
+ AWS 계정에 구성된 기존 SAML IdP. 아직 없는 경우 [IAM 자습서: CloudFormation 템플릿을 사용하여 SAML ID 제공업체(idP) 생성](tutorial_saml-idp.md) 자습서를 사용하여 생성할 수 있습니다.
+ 스택을 생성할 때 파라미터로 지정해야 하는 SAML IdP의 ARN입니다.
+ 이 자습서에서 IdP의 SAML 메타데이터 XML 파일의 형식을 지정하는 데 사용되는 Python 명령을 실행할 수 있도록 로컬 시스템에 설치된 Python 3.6 이상 버전.

## CloudFormation을 사용하여 SAML 페더레이션 역할 생성
<a name="tutorial_saml-federated-role-create"></a>

SAML 페더레이션 역할을 생성하려면 CloudFormation 템플릿을 생성하고 이를 사용하여 역할이 포함된 스택을 생성합니다.

### 템플릿 생성
<a name="tutorial_saml-federated-role-file"></a>

우선 CloudFormation 템플릿을 만듭니다.

1. [템플릿](#tutorial_saml-federated-role-template) 섹션에서 **JSON** 또는 **YAML** 탭의 복사 아이콘을 클릭하여 템플릿 콘텐츠를 복사합니다.

1. 템플릿 콘텐츠를 새 파일에 붙여 넣습니다.

1. 파일을 로컬에 저장합니다.

### 스택 생성
<a name="tutorial_saml-federated-role-stack"></a>

다음으로, 저장한 템플릿을 사용하여 CloudFormation 스택을 프로비저닝합니다.

1. CloudFormation 콘솔([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/))을 엽니다.

1. **스택** 페이지의 **스택 생성**에서 **새 리소스 사용(표준)**을 선택합니다.

1. 템플릿을 지정합니다.

   1. **사전 조건**에서 **기존 템플릿 선택**을 선택합니다.

   1. **템플릿 지정**에서 **템플릿 파일 업로드**를 선택합니다.

   1. **파일 선택**을 선택하고 템플릿 파일로 이동한 후 해당 파일을 선택합니다.

   1. **다음**을 선택합니다.

1. 다음과 같은 스택 세부 정보를 지정합니다.

   1. 스택 이름을 입력합니다.

   1. **SAMLProviderARN**의 경우 기존 SAML IdP의 ARN을 입력합니다. 이는 `arn:aws:iam::123456789012:saml-provider/YourProviderName` 형식이어야 합니다.

      예시: `arn:aws:iam::123456789012:saml-provider/CompanyIdP`
**참고**  
[IAM 자습서: CloudFormation 템플릿을 사용하여 SAML ID 제공업체(idP) 생성](tutorial_saml-idp.md) 자습서를 사용하여 SAML IdP를 생성한 경우, 해당 CloudFormation 스택의 출력 탭에서 제공업체 ARN을 찾을 수 있습니다.

   1. **RoleName**의 경우 이 값을 비워 두어 스택 이름을 기반으로 이름을 자동 생성하거나, IAM 역할의 사용자 지정 이름을 입력할 수 있습니다.

      예: `SAML-Developer-Access` 또는 `SAML-ReadOnly-Role`

   1. 다른 파라미터의 경우 기본값을 적용하거나, 요구 사항에 따라 직접 입력합니다.
      + **RoleSessionDuration** - 최대 세션 지속 시간(초)(3,600\$143,200, 기본값 7,200)

        예: `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`

   1. **다음**을 선택합니다.

1. 스택 옵션을 구성합니다.

   1. **스택 실패 옵션**에서 **새로 생성된 모든 리소스 삭제**를 선택합니다.
**참고**  
이 옵션을 선택하면 스택 생성에 실패하더라도 삭제 정책에서 보존하도록 지정하는 리소스에 대해서는 요금이 청구되지 않습니다.

   1. 모든 기타 기본값을 적용합니다.

   1. **기능**에서 CloudFormation이 계정에 IAM 리소스를 생성할 수 있음을 승인하는 확인란을 선택합니다.

   1. **다음**을 선택합니다.

1. 스택 세부 정보를 검토하고 **제출**을 선택합니다.

CloudFormation이 스택을 생성합니다. 스택 생성이 완료되면 스택 리소스를 사용할 준비가 된 것입니다. 스택 세부 정보 페이지의 **리소스** 탭을 사용하여 계정에 프로비저닝된 리소스를 볼 수 있습니다.

스택은 **출력** 탭에서 볼 수 있는 다음과 같은 값을 출력합니다.
+ **RoleARN**: 생성된 IAM 역할의 ARN(예: `arn:aws:iam::123456789012:role/SAML-Developer-Access` 또는 자동 생성된 이름을 사용하는 경우 `arn:aws:iam::123456789012:role/stack-name-a1b2c3d4`).

역할 수임을 위해 적절한 SAML 속성을 전송할 수 있도록 IdP를 구성할 경우 이러한 역할 ARN이 필요합니다.

## SAML 페더레이션 역할 테스트
<a name="tutorial_saml-federated-role-using"></a>

SAML 페더레이션 역할이 생성되면 해당 역할의 구성을 확인하고 페더레이션 설정을 테스트할 수 있습니다.

1. IAM 콘솔([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/))을 엽니다.

1. 탐색 창에서 **역할**을 선택합니다.

1. 새로 생성된 페더레이션 역할을 찾아 선택합니다.

   사용자 지정 역할 이름을 제공한 경우, 해당 이름을 찾습니다. RoleName 파라미터를 비워 둔 경우, 역할은 스택 이름과 고유 식별자를 기반으로 자동 생성된 이름을 갖게 됩니다.

1. **신뢰 관계** 탭을 선택하여 신뢰 정책을 검토할 수 있습니다.

   신뢰 정책에는 SAML IdP를 신뢰하여 이 역할을 수임할 수 있도록 하며, SAML 대상(`SAML:aud`)이 `https://signin.aws.amazon.com/saml`과 일치해야 한다는 조건이 포함된다는 내용이 표시되어야 합니다.

1. **권한** 탭에서 연결된 정책을 검토합니다.

   생성하는 동안 역할에 연결된 모든 관리형 정책을 볼 수 있습니다.

1. 역할 요약 페이지에 표시된 **역할 ARN**을 기록합니다.

   사용자가 이 역할을 수임할 수 있도록 외부 IdP를 구성하려면 이 ARN이 필요합니다.

이제 SAML 페더레이션 역할을 사용할 준비가 되었습니다. SAML 어설션에 이 역할의 ARN을 포함하도록 외부 IdP를 구성하면 인증된 사용자가 이 역할을 수임하여 AWS 리소스에 액세스할 수 있습니다.

## 정리: 리소스 삭제
<a name="tutorial_saml-federated-role-delete"></a>

마지막 단계로, 스택을 삭제하고 해당 스택에 포함된 리소스를 삭제합니다.

1. CloudFormation 콘솔을 엽니다.

1. **스택** 페이지에서 템플릿을 통해 생성한 스택을 선택하고 **삭제**를 선택한 다음, **삭제**를 확인합니다.

   CloudFormation은 스택 및 해당 스택에 포함된 모든 리소스의 삭제를 시작합니다.

## CloudFormation 템플릿 세부 정보
<a name="tutorial_saml-federated-role-template-details"></a>

### 리소스
<a name="tutorial_saml-federated-role-template-resources"></a>

이 자습서에서 CloudFormation 템플릿은 계정에 다음과 같은 리소스를 생성합니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html): SAML IdP를 통해 인증된 사용자가 수임할 수 있는 페더레이션 IAM 역할입니다.

### 구성
<a name="tutorial_saml-federated-role-configuration"></a>

템플릿에는 다음과 같은 구성 가능한 파라미터가 포함되어 있습니다.
+ **RoleName** - IAM 역할의 이름(자동 생성된 이름의 경우 비워둠)
+ **SAMLProviderARN** - SAML IdP의 ARN(필수)
+ **RoleSessionDuration** - 최대 세션 지속 시간(초)(3,600\$143,200, 기본값 7,200)
+ **RolePermissionsBoundary** - 권한 경계 정책의 선택적 ARN
+ **RolePath** - IAM 역할의 경로(기본값은 /)
+ **ManagedPolicy1-5** - 연결할 최대 5개의 관리형 정책의 선택적 ARN

## CloudFormation 템플릿
<a name="tutorial_saml-federated-role-template"></a>

아래의 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'
```

------