

# IAM 자습서
<a name="tutorials"></a>

다음 튜토리얼에서는 AWS Identity and Access Management(IAM)에 대한 일반적인 작업을 처음부터 끝까지 수행하는 절차를 보여줍니다. 이러한 절차는 가상 회사 이름 및 사용자 이름 등을 사용하여 랩 유형의 환경에 맞게 고안되었습니다. 그 목적은 일반적인 지침을 제공하는 것입니다. 조직의 고유한 요구 사항에 맞는지 주의 깊은 검토 및 조정 없이 프로덕션 환경에 바로 사용할 수 있도록 고안된 것이 아닙니다.

**Topics**
+ [역할을 사용하여 AWS 계정 간 액세스 권한 위임](tutorial_cross-account-with-roles.md)
+ [고객 관리형 정책 생성](tutorial_managed-policies.md)
+ [속성 기반 액세스 제어(ABAC) 사용](tutorial_attribute-based-access-control.md)
+ [사용자가 자신의 자격 증명 및 MFA 설정을 관리할 수 있도록 허가](tutorial_users-self-manage-mfa-and-creds.md)
+ [CloudFormation을 사용하여 SAML IdP 생성](tutorial_saml-idp.md)
+ [CloudFormation을 사용하여 SAML 페더레이션 역할 생성](tutorial_saml-federated-role.md)
+ [CloudFormation을 사용하여 SAML IdP 및 페더레이션 역할 생성](tutorial_saml-idp-and-federated-role.md)

# 튜토리얼: IAM 역할을 사용한 AWS 계정 간 액세스 권한 위임
<a name="tutorial_cross-account-with-roles"></a>

**중요**  
 IAM [모범 사례](best-practices.md)는 장기 보안 인증 정보가 있는 IAM 사용자를 사용하는 대신, 인간 사용자가 자격 증명 공급자와의 페더레이션을 사용하여 임시 보안 인증으로 AWS에 액세스하도록 하는 것입니다. 페더레이션 사용자가 지원하지 않는 [특정 사용 사례](gs-identities-iam-users.md)에는 IAM 사용자만 사용하는 것이 좋습니다.

이 자습서에서는 역할을 사용하여 **Destination**과 **Originating**이라는 서로 다른 AWS 계정의 리소스에 대한 액세스 권한을 위임하는 방법을 설명합니다. 한 계정의 리소스는 다른 계정의 사용자와 공유합니다. 이러한 방식으로 크로스 계정 액세스를 설정하면 각 계정에 개별 IAM 사용자를 생성할 필요가 없습니다. 또한 사용자는 다른 AWS 계정의 리소스에 액세스하기 위해 한 계정에서 로그아웃하고 다른 계정에 로그인할 필요가 없습니다. 역할을 구성한 후에는 AWS Management Console, AWS CLI 및 API에서 역할을 사용하는 방법에 대해서도 알아봅니다.

이 자습서에서 **Destination** 계정은 다양한 애플리케이션과 팀이 액세스하는 애플리케이션 데이터를 관리합니다. 각 계정에서 Amazon S3 버킷에 애플리케이션 정보를 저장합니다. **Developers**와 **Analysts**라는 두 가지 IAM 사용자 역할이 있는 **Originating** 계정에서 IAM 사용자를 관리합니다. Developers와 Analysts는 **Originating** 계정을 사용하여 여러 마이크로서비스가 공유하는 데이터를 생성합니다. 두 역할 모두 Originating 계정에서 작업하고 이 계정의 리소스에 액세스할 수 있는 권한이 있습니다. 개발자는 종종 **Destination** 계정의 공유 데이터를 업데이트해야 합니다. 개발자는 이 데이터를 `amzn-s3-demo-bucket-shared-container`라는 Amazon S3 버킷에 저장합니다.

이 자습서의 마지막에서는 다음 항목을 갖게 됩니다.
+ **Destination** 계정의 특정 역할을 수임할 수 있는 **Originating** 계정(신뢰할 수 있는 계정)의 사용자.
+ 특정 Amazon S3 버킷에 액세스할 수 있는 **Destination** 계정(신뢰하는 계정)의 역할.
+ **Destination** 계정의 `amzn-s3-demo-bucket-shared-container` 버킷.

개발자들은 AWS Management Console에서 이 역할을 사용하여 **Destination** 계정의 `amzn-s3-demo-bucket-shared-container` 버킷에 액세스할 수 있습니다. 또한 역할을 통해 제공되는 임시 자격 증명으로 API 호출을 인증함으로써 버킷에 액세스하는 것도 가능합니다. 하지만 분석가가 이 역할을 사용하려는 비슷한 시도는 실패합니다.

이 워크플로우는 세 가지 기본 단계로 이루어집니다.

**[Destination 계정에 역할 생성](#tutorial_cross-account-with-roles-1)**  
먼저 AWS Management Console을 사용하여 **Destination** 계정(ID 번호 999999999999)과 **Originating** 계정(ID 번호 111111111111) 사이에 신뢰를 설정합니다. *UpdateData*라는 IAM 역할을 생성하여 시작합니다. 역할을 생성할 때 **Originating** 계정을 신뢰할 수 있는 엔터티로 정의하고 신뢰할 수 있는 사용자가 `amzn-s3-demo-bucket-shared-container` 버킷을 업데이트하는 것을 허용하는 권한 정책을 지정합니다.

**[역할에 대한 액세스 권한 부여](#tutorial_cross-account-with-roles-2)**  
이 섹션에서는 분석가들이 `UpdateData` 역할에 액세스하는 것을 거부하도록 역할 정책을 수정합니다. 분석가들은 이 시나리오에서 PowerUser 액세스 권한을 갖기 때문에 역할을 사용하지 못하도록 명시적으로 *거부*해야 합니다.

**[역할을 전환하여 액세스 테스트](#tutorial_cross-account-with-roles-3)**  
마지막으로, 개발자로서 `UpdateData` 역할을 사용하여 **Destination** 계정의 `amzn-s3-demo-bucket-shared-container` 버킷을 업데이트합니다. 이제 AWS 콘솔, AWS CLI 및 API를 통해 역할에 액세스할 수 있게 되었습니다.

## 고려 사항
<a name="tutorial_cross-account-with-roles-considerations"></a>

IAM 역할을 사용하여 AWS 계정 전반의 리소스 액세스를 위임하기 전에 다음 사항을 고려해야 합니다.
+ AWS 계정 루트 사용자로 로그인하면 역할을 바꿀 수 없습니다.
+ IAM 역할 및 리소스 기반 정책은 단일 파티션 내에서만 계정 간에 액세스 권한을 위임합니다. 예를 들어 표준 `aws` 파티션의 미국 서부(캘리포니아 북부)에 계정이 있다고 가정합니다. `aws-cn` 파티션의 중국(베이징)에도 계정이 있습니다. 중국(베이징)의 계정에서 Amazon S3 리소스 기반 정책을 사용하여 표준 `aws` 계정의 사용자에 대한 액세스를 허용할 수 없습니다.
+ AWS IAM Identity Center을 사용하면 SAML(Security Assertion Markup Language)을 사용한 외부 AWS 계정(사용자 AWS Organizations 외부의 계정)의 Single Sign-On(SSO)을 촉진할 수 있습니다. 자세한 내용은 [ Integrate external AWS 계정 into AWS IAM Identity Center for central access management with independent billing using SAML 2.0](https://community.aws/content/2dIMI8N7w7tGxbE0KQMrkSBfae4/aws-iam-identity-center-integration-with-external-aws-accounts-for-independent-billing?lang=en)을 참조하세요.
+ Amazon EC2 인스턴스 또는 AWS Lambda 함수와 같은 AWS 리소스에 역할을 연결할 수 있습니다. 자세한 내용은 [AWS 서비스에 대한 권한을 위임할 역할 생성](id_roles_create_for-service.md)을 참조하세요.
+ 애플리케이션이 다른 AWS 계정의 역할을 수임하도록 하려면 크로스 계정 역할 수임에 AWS SDK를 사용할 수 있습니다. 자세한 내용은 *AWS SDK 및 도구 참조 안내서*의 [위임 및 액세스](https://docs.aws.amazon.com//sdkref/latest/guide/access.html)를 참조하세요.
+ AWS Management Console을 사용한 역할 전환은 `ExternalId`가 필요하지 않은 계정에서만 작동합니다. 예를 들어, 계정에 대한 액세스 권한을 타사에 부여하고 권한 정책의 `Condition` 요소에 `ExternalId`가 필요하다고 가정합니다. 이 경우 타사는 AWS API 또는 명령줄 도구를 사용해야만 계정에 액세스할 수 있습니다. `ExternalId`에 대한 값을 제공해야 하기 때문에 타사는 콘솔을 사용할 수 없습니다. 이 시나리오에 대한 자세한 정보는 [타사가 소유한 AWS 계정에 액세스](id_roles_common-scenarios_third-party.md) 및 AWS 보안 블로그의 [AWS Management Console에 대한 크로스 계정 액세스를 가능하게 하는 방법](https://aws.amazon.com/blogs/security/how-to-enable-cross-account-access-to-the-aws-management-console)을 참조하세요.

## 사전 조건
<a name="tutorial_cross-account-with-roles-prereqs"></a>

이 자습서에서는 다음을 이미 완료했다고 가정합니다.
+ 사용할 수 있는 **2개**의 개별 AWS 계정(**Originating** 계정을 대표하는 1개와 **Destination** 계정을 대표하는 1개).
+ **Originating** 계정에서 다음과 같이 생성 및 구성된 사용자 및 역할.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)
+ **Destination** 계정에는 사용자를 생성할 필요가 없습니다.
+ **Destination** 계정에서 생성된 Amazon S3 버킷. 이 자습서에서는 이를 `amzn-s3-demo-bucket-shared-container`(이)라고 부릅니다. 하지만 S3 버킷 이름은 전역에서 고유해야 하므로 다른 이름의 버킷을 사용해야 합니다.

## Destination 계정에 역할 생성
<a name="tutorial_cross-account-with-roles-1"></a>

한 AWS 계정의 사용자가 다른 AWS 계정의 리소스에 액세스하도록 허용할 수 있습니다. 이 자습서에서는 해당 리소스에 액세스할 수 있는 사용자와 해당 역할로 전환하는 사용자에게 부여할 권한을 정의하는 역할을 생성하여 액세스를 허용합니다.

자습서의 이 단계에서는 **Destination** 계정에서 역할을 생성하고 **Originating** 계정을 신뢰할 수 있는 엔터티로 지정합니다. 또한 역할 권한을 `amzn-s3-demo-bucket-shared-container` 버킷에 대한 읽기 및 쓰기 액세스 권한으로 제한합니다. 따라서 역할을 사용할 수 있는 권한을 받은 사용자는 누구나 `shared-container` 버킷에 대해 읽기나 쓰기가 가능합니다.

역할을 생성하기 전에 **Originating** AWS 계정의 *계정 ID*가 필요합니다. 각 AWS 계정은 할당된 고유 계정 ID 식별자를 갖습니다.

**Originating AWS 계정 ID를 가져오는 방법**

1. **Originating** 계정 관리자로 AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)에서 IAM 콘솔을 엽니다.

1. IAM 콘솔에서 상단 오른쪽 모서리에 있는 탐색 표시줄에서 사용자 이름을 선택합니다. 일반적인 형식은 ***username*@*account\$1ID\$1number\$1or\$1alias***입니다.

   이 시나리오에서는 **Originating** 계정에 계정 ID 111111111111을 사용할 수 있습니다. 그러나 테스트 환경에서 시나리오를 재구성하는 경우에는 유효한 계정 ID를 사용해야 합니다.

**Originating 계정이 사용할 수 있는 역할을 Destination 계정에 생성하는 방법**

1. **Destination** 계정 관리자로 에AWS Management Console 로그인한 후 IAM 콘솔을 엽니다.

1. 역할을 만들기 전에 먼저 해당 역할에 필요한 권한을 정의하는 관리형 정책을 준비합니다. 차후 단계에서 이 정책을 해당 역할에 연결합니다.

   `amzn-s3-demo-bucket-shared-container` 버킷에 대한 읽기 및 쓰기 액세스 권한을 설정하려고 합니다. AWS에 이미 몇 가지 Amazon S3 관리형 정책이 있지만, 단일 Amazon S3 버킷에 대한 읽기 및 쓰기 액세스가 가능한 정책은 없습니다. 대신에 사용자가 직접 정책을 생성할 수 있습니다.

   탐색 창에서 **정책**을 선택한 후 **정책 생성**을 선택합니다.

1. **JSON** 탭을 선택하고 다음 JSON 정책 문서에서 텍스트를 복사합니다. 이 텍스트를 **JSON** 텍스트 상자에 붙여 넣어 리소스 ARN(`arn:aws:s3:::shared-container`)을 실제 Amazon S3 버킷에 대한 ARN으로 바꿉니다.

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "s3:ListAllMyBuckets",
         "Resource": "*"
       },
       {
         "Effect": "Allow",
         "Action": [
           "s3:ListBucket",
           "s3:GetBucketLocation"
          ],
         "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-shared-container"
       },
       {
         "Effect": "Allow",
         "Action": [
           "s3:GetObject",
           "s3:PutObject",
           "s3:DeleteObject"
         ],
         "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-shared-container/*"
       }
     ]
   }
   ```

------

   `ListAllMyBuckets` 작업은 요청의 인증된 발신자가 소유한 모든 버킷을 나열할 수 있는 권한을 부여합니다. `ListBucket`은 사용자가 `amzn-s3-demo-bucket-shared-container` 버킷에 저장되어 있는 객체를 볼 수 있는 권한입니다. `GetObject`, `PutObject` 및 `DeleteObject`는 사용자가 `amzn-s3-demo-bucket-shared-container` 버킷에 저장되어 있는 콘텐츠를 각각 보거나, 업데이트하거나, 삭제할 수 있는 권한입니다.
**참고**  
언제든지 **시각적** 편집기 옵션과 **JSON** 편집기 옵션 간에 전환할 수 있습니다. 그러나 변경을 적용하거나 **시각적** 편집기에서 **다음**을 선택한 경우 IAM은 시각적 편집기에 최적화되도록 정책을 재구성할 수 있습니다. 자세한 내용은 [정책 재구성](troubleshoot_policies.md#troubleshoot_viseditor-restructure) 섹션을 참조하세요.

1. **검토 및 생성** 페이지에서 정책 이름에 **read-write-app-bucket**을 입력합니다. 정책이 부여한 권한을 검토한 다음 **정책 생성**을 선택하여 작업을 저장합니다.

   새로운 정책이 관리형 정책 목록에 나타납니다.

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

1. **AWS 계정** 역할 유형을 선택합니다.

1. **계정 ID**에 **Originating** 계정 ID를 입력합니다.

   이 자습서에서는 **Originating** 계정의 예제 ID **111111111111**을 사용합니다. 하지만 실제로는 유효한 계정 ID를 사용해야 합니다. **111111111111**과 같이 잘못된 계정 ID를 사용할 경우, IAM에서 새로운 역할을 생성할 수 없습니다.

   이 연습에서는 외부 ID를 요구하거나, 사용자가 역할을 위임하기 위해 멀티 팩터 인증(MFA)을 요구할 필요가 없습니다. 이러한 옵션을 선택하지 않은 상태로 두십시오. 자세한 내용은 [IAM의 AWS 다중 인증](id_credentials_mfa.md) 섹션을 참조하세요.

1. **다음: 권한**을 선택하여 역할과 연결된 권한을 설정합니다.

1. 이전에 생성한 정책 옆의 확인란을 선택하세요.
**도움말**  
**Filter(필터)**에서 **Customer managed(고객 관리형)**을 선택하여 생성한 정책만 포함하도록 목록을 필터링합다. 이렇게 하면 AWS에서 생성한 정책이 표시되지 않아서 필요한 정책을 쉽게 찾을 수 있습니다.

   그리고 **다음**을 선택합니다.

1. (선택 사항) 태그를 키-값 페어로 연결하여 메타데이터를 역할에 추가합니다. IAM에서의 태그 사용에 대한 자세한 내용은 [AWS Identity and Access Management 리소스용 태그](id_tags.md) 섹션을 참조하세요.

1. (선택 사항)**설명**에 새 역할에 대한 설명을 입력합니다.

1. 역할을 검토한 후 **역할 만들기**를 선택합니다.

    

   역할 목록에 `UpdateData` 역할이 표시됩니다.

이제 역할의 Amazon 리소스 이름(ARN), 즉 역할에 대한 고유 식별자를 얻어야 합니다. Originating 계정의 Developer 역할을 수정할 때 권한을 부여하거나 거부하려면 Destination 계정의 역할 ARN을 지정해야 합니다.

**UpdateData의 ARN을 가져오는 방법**

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

1. 역할 목록에서 `UpdateData` 역할을 선택합니다.

1. 세부 정보 창의 **요약** 섹션에서 **역할 ARN** 값을 복사합니다.

   Destination 계정 ID는 999999999999입니다. 따라서 역할 ARN은 `arn:aws:iam::999999999999:role/UpdateData`입니다. Destination 계정의 실제 AWS 계정 ID를 제공해야 합니다.

이제 **Destination** 계정과 **Originating** 계정 간에 신뢰가 설정되었습니다. **Destination** 계정에서 **Originating** 계정을 신뢰할 수 있는 보안 주체로 식별하는 역할을 생성하여 이 작업을 수행했습니다. 그 밖에도 `UpdateData` 역할 전환 사용자의 권한까지 정의했습니다.

다음으로 Developer 역할의 권한을 수정합니다.

## 역할에 대한 액세스 권한 부여
<a name="tutorial_cross-account-with-roles-2"></a>

이 시점에는 Analysts와 Developers 모두 **Originating** 계정의 데이터를 관리할 수 있는 권한을 갖고 있습니다. 역할 전환에 필요한 권한을 추가하려면 다음의 몇 단계를 거쳐야 합니다.

**UpdateData 역할로 전환할 수 있도록 Developers 역할을 수정하는 방법**

1. **Originating** 계정에 관리자로 로그인한 다음 IAM 콘솔을 엽니다.

1. **역할**을 선택한 후 **Developers**를 선택합니다.

1. **권한(Permissions)** 탭을 선택하고 **권한 추가(Add permissions)**, **인라인 정책 생성(Create inline policy)**을 차례로 선택합니다.

1. **JSON** 탭을 선택합니다.

1. 아래 정책문을 추가하여 Destination 계정의 `UpdateData` 역할에 대한 `AssumeRole` 작업을 허용합니다. 이때 `Resource` 요소의 *DESTINATION-ACCOUNT-ID*를 Destination 계정의 실제 AWS 계정 ID로 변경해야 합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": {
           "Effect": "Allow",
           "Action": "sts:AssumeRole",
           "Resource": "arn:aws:iam::111122223333:role/UpdateData"
       }
   }
   ```

------

   `Allow`는 Destination 계정에서 `UpdateData` 역할에 대한 Developers 그룹의 액세스를 명시적으로 허용하는 값입니다. 개발자라면 누구나 이 역할에 액세스할 수 있습니다.

1. **정책 검토**를 선택합니다.

1. **이름**에 **allow-assume-S3-role-in-destination**과 같은 사용자 이름을 입력합니다.

1. **정책 생성**을 선택합니다.

대부분 환경에서 다음과 같은 절차는 필요하지 않을 수 있습니다. 하지만 PowerUserAccess 권한을 사용하는 경우에는 역할 전환을 할 수 있는 그룹이 있을 수도 있습니다. 다음 절차는 Analysts 그룹이 역할을 수임할 수 없도록 Analysts 그룹에 `"Deny"` 권한을 추가하는 방법을 보여줍니다. 이 절차가 필요 없는 환경인 경우 추가하지 않는 것이 좋습니다. `"Deny"` 권한은 전체 권한 구조를 관리하고 이해하기가 더 복잡하게 만듭니다. `"Deny"` 권한은 더 좋은 방법이 없을 때만 사용하십시오.

**`UpdateData` 역할 수임 권한을 거부하도록 Analysts 역할을 수정하는 방법**

1. **역할**을 선택한 다음 **Analysts**를 선택합니다.

1. **권한(Permissions)** 탭을 선택하고 **권한 추가(Add permissions)**, **인라인 정책 생성(Create inline policy)**을 차례로 선택합니다.

1. **JSON** 탭을 선택합니다.

1. 다음 정책을 추가하여 `AssumeRole` 역할의 `UpdateData` 작업을 거부합니다. 이때 `Resource` 요소의 *DESTINATION-ACCOUNT-ID*를 Destination 계정의 실제 AWS 계정 ID로 변경해야 합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": {
           "Effect": "Deny",
           "Action": "sts:AssumeRole",
           "Resource": "arn:aws:iam::111122223333:role/UpdateData"
       }
   }
   ```

------

   `Deny`는 Destination 계정에서 `UpdateData` 역할에 대한 Analysts 그룹의 액세스를 명시적으로 거부하는 값입니다. 이 역할에 액세스하려는 모든 분석가는 액세스 거부 메시지를 받습니다.

1. **정책 검토**를 선택합니다.

1. **deny-assume-S3-role-in-destination**과 같은 **이름**을 입력합니다.

1. **정책 생성**을 선택합니다.

Developers 역할은 이제 Destination 계정에서 `UpdateData` 역할을 사용할 수 있는 권한이 생겼습니다. Analysts 역할은 `UpdateData` 역할을 사용하지 못합니다.

다음으로 개발자인 David가 Destination 계정의 `amzn-s3-demo-bucket-shared-container` 버킷에 액세스하는 방법을 알아봅니다. David는 AWS Management Console, AWS CLI 또는 AWS API에서 버킷에 액세스할 수 있습니다.

## 역할을 전환하여 액세스 테스트
<a name="tutorial_cross-account-with-roles-3"></a>

이 자습서의 첫 두 단계를 완료하면 **Destination** 계정의 리소스에 대한 액세스 권한을 부여하는 역할이 생깁니다. 또한 **Originating** 계정에 역할 하나와 해당 역할을 사용할 수 있는 사용자도 생깁니다. 이 단계에서는 AWS Management Console, AWS CLI 및 AWS API에서 해당 역할로 전환을 테스트하는 방법을 설명합니다.

IAM 역할 작업 시 발생할 수 있는 공통적 문제에 대한 도움을 받으려면 [IAM 역할 문제 해결](troubleshoot_roles.md) 섹션을 참조하세요.

### 역할 전환(콘솔)
<a name="switch-tutorial_cross-account-with-roles"></a>

David가 AWS Management Console에서 **Destination** 계정의 데이터를 업데이트해야 할 경우 **역할 전환**을 사용하면 됩니다. David가 계정 ID나 별칭 및 역할 이름을 지정하면 David의 권한이 해당 역할에 허용되는 권한으로 즉시 전환됩니다. 그런 다음 David는 콘솔을 사용하여 `amzn-s3-demo-bucket-shared-container` 버킷으로 작업할 수 있지만 **Destination**의 다른 리소스로는 작업할 수 없습니다. David가 이 역할을 사용하는 동안에는 **Originating** 계정에서 파워 유저 권한도 사용할 수 없습니다. 한 번에 하나의 권한 집합만 적용할 수 있기 때문입니다.

IAM는 David가 **Switch Role(역할 전환)** 페이지를 시작하는 데 사용할 수 있는 두 가지 방법을 제공합니다.
+ David가 관리자로부터 미리 정의된 Switch Role 구성을 가리키는 링크를 받습니다. 이 링크는 **역할 생성** 마법사의 마지막 페이지 또는 크로스 계정 역할의 **Role Summary(역할 요약)** 페이지에서 관리자에게 제공됩니다. 이 링크를 선택하면 David는 **계정 ID(Account ID)** 및 **역할 이름(Role name)** 필드에 이미 정보가 채워진 **역할 전환(Switch Role)** 페이지로 이동됩니다. David는 **역할 전환**을 선택하기만 하면 됩니다.
+ 관리자가 이메일로 링크를 보내는 대신 **계정 ID** 번호 및 **역할 이름** 값을 보냅니다. 역할을 전환하려면 David가 값을 수동으로 입력해야 합니다. 다음 절차에 이 내용이 잘 설명되어 있습니다.

**역할 수임**

1. David가 **Originating** 계정의 일반 사용자로 AWS Management Console에 로그인합니다.

1. 관리자가 이메일로 보낸 링크를 선택합니다. 계정 ID나 별칭 및 역할 이름 정보가 이미 채워진 **역할 전환(Switch Role)** 페이지가 David에게 표시됩니다.

   —또는—

   David는 탐색 모음에서 자신의 이름(아이덴티티(Identity) 메뉴)을 선택한 후 **역할 전환(Switch Roles)**을 선택합니다.

   David가 이 방법으로 처음 Switch Role(역할 전환) 페이지 액세스를 시도하는 것이라면 첫 실행 **Switch Role(역할 전환)** 페이지가 표시됩니다. 이 페이지에는 역할 전환을 통해 사용자가 여러 AWS 계정의 리소스를 관리하는 방법에 대한 추가 정보가 제공됩니다. 이 절차의 나머지 부분을 완료하려면 David가 이 페이지에서 **Switch Role(역할 전환)**을 선택해야 합니다.

1. 다음으로, 해당 역할에 액세스하기 위해 David는 수동으로 Destination 계정 ID 번호(`999999999999`)와 역할 이름(`UpdateData`)을 입력해야 합니다.

   또한 David는 IAM에서 현재 활성 상태인 역할 및 관련 권한을 모니터링하려고 합니다. 이 정보를 추적하려면 **표시 이름(Display Name)** 텍스트 상자에 `Destination`을 입력하고 빨간색 옵션을 선택한 다음 **역할 전환(Switch Role)**을 선택합니다.

1. 이제 David는 Amazon S3 콘솔을 사용하여 Amazon S3 버킷으로 작업하거나 `UpdateData` 역할에 권한이 있는 다른 모든 리소스로 작업할 수 있습니다.

1. 완료되면 David는 원래 권한으로 돌아갈 수 있습니다. 이를 위해 탐색 모음에서 **Destination **역할 표시 이름을 선택한 다음 **Back to David @ 111111111111**을 선택합니다.

1. 다음에 David가 역할을 전환하려고 탐색 모음에서 **자격 증명** 메뉴를 선택하면 지난 번에 사용한 Destination 항목이 표시되는 것을 볼 수 있습니다. 계정 ID와 역할 이름을 다시 입력할 필요 없이 해당 항목을 선택하기만 하면 즉시 역할이 전환됩니다.

### 역할 전환(AWS CLI)
<a name="switch-cli-tutorial_cross-account-with-roles"></a>

 David가 명령줄에서 **Destination** 환경으로 작업해야 할 경우 [AWS CLI](https://aws.amazon.com/cli/)을 사용하면 됩니다. David는 `aws sts assume-role` 명령을 실행하고 역할 ARN을 전달하여 해당 역할에 대한 임시 보안 자격 증명을 얻습니다. 그런 다음 후속 AWS CLI 명령이 해당 역할의 권한을 사용하여 작동하도록 환경 변수에서 해당 자격 증명을 구성합니다. 한 번에 한 가지 권한 세트만 적용될 수 있기 때문에 David가 해당 역할을 사용하는 동안에는 **Originating** 계정의 파워 유저 권한을 사용할 수 없습니다.

모든 액세스 키와 토큰은 예시일 뿐이며 표시된 대로 사용할 수 없습니다. 라이브 환경의 적절한 값으로 바꾸세요.

**역할 수임**

1. David가 명령 프롬프트 창을 열고 다음 명령을 실행하여 AWS CLI 클라이언트가 작동하는지 확인합니다.

   ```
   aws help
   ```
**참고**  
David의 기본 환경에는 `David` 명령으로 만든 기본 프로필의 `aws configure` 사용자 자격 증명이 사용됩니다. 자세한 내용은 *AWS Command Line Interface 사용 설명서*의 [AWS Command Line Interface 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-quick-configuration)을 참조하세요.

1. David가 **Destination** 계정의 `UpdateData` 역할로 전환하기 위해 다음 명령을 실행하여 역할 전환 프로세스를 시작합니다. David는 해당 역할을 만든 관리자에게서 역할 ARN을 받았습니다. 이 명령을 실행하려면 세션 이름도 제공해야 합니다. 원하는 아무 텍스트나 선택할 수 있습니다.

   ```
   aws sts assume-role --role-arn "arn:aws:iam::999999999999:role/UpdateData" --role-session-name "David-ProdUpdate"
   ```

   다음 내용이 출력됩니다.

   ```
   {
       "Credentials": {
           "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
           "SessionToken": "AQoDYXdzEGcaEXAMPLE2gsYULo+Im5ZEXAMPLEeYjs1M2FUIgIJx9tQqNMBEXAMPLE
   CvSRyh0FW7jEXAMPLEW+vE/7s1HRpXviG7b+qYf4nD00EXAMPLEmj4wxS04L/uZEXAMPLECihzFB5lTYLto9dyBgSDy
   EXAMPLE9/g7QRUhZp4bqbEXAMPLENwGPyOj59pFA4lNKCIkVgkREXAMPLEjlzxQ7y52gekeVEXAMPLEDiB9ST3Uuysg
   sKdEXAMPLE1TVastU1A0SKFEXAMPLEiywCC/Cs8EXAMPLEpZgOs+6hz4AP4KEXAMPLERbASP+4eZScEXAMPLEsnf87e
   NhyDHq6ikBQ==",
           "Expiration": "2014-12-11T23:08:07Z",
           "AccessKeyId": "AKIAIOSFODNN7EXAMPLE"
       }
   }
   ```

1. 출력의 Credentials 섹션에 David에게 필요한 세 가지 항목이 표시됩니다.
   + `AccessKeyId`
   + `SecretAccessKey`
   + `SessionToken`

   David는 후속 호출 시 이러한 파라미터를 사용하도록 AWS CLI 환경을 구성해야 합니다. 자격 증명을 구성하는 다양한 방법에 대한 자세한 정보는 [AWS Command Line Interface 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#config-settings-and-precedence)을 참조하십시오. `aws configure` 명령은 세션 토큰 캡처를 지원하지 않기 때문에 사용할 수 없습니다.ㅂ 하지만 구성 파일에 정보를 수동으로 입력할 수 있습니다. 이는 비교적 만료 시간이 짧은 임시 자격 증명이기 때문에 현재 명령줄 세션의 환경에 추가하는 것이 가장 쉽습니다.

1. 세 값을 환경에 추가하기 위해 David는 이전 단계의 출력을 잘라내어 다음 명령에 붙여 넣습니다. 세션 토큰 출력의 줄 바꿈 문제를 해결하기 위해 간단한 텍스트 편집기에서 텍스트 출력을 잘라내어 붙여 넣을 수 있습니다. 여기서는 명확성을 위해 줄을 바꾸어 표시했지만 긴 문자열 하나로 추가해야 합니다.

   다음 예시는 Windows 환경에 표시된 명령을 나타내며, 여기서 "set"은 환경 변수를 생성하라는 명령입니다. Linux 또는 macOS 컴퓨터에서는 "export" 명령을 대신 사용할 수 있습니다. 예시의 나머지 부분은 세 환경에서 모두 유효합니다.

   Windows Powershell용 도구를 사용하는 방법에 대한 자세한 내용은 [IAM 역할로 전환(Tools for Windows PowerShell)](id_roles_use_switch-role-twp.md)을 참조하세요.

   ```
   set AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
   set AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
   set AWS_SESSION_TOKEN=AQoDYXdzEGcaEXAMPLE2gsYULo+Im5ZEXAMPLEeYjs1M2FUIgIJx9tQqNMBEXAMPLECvS
   Ryh0FW7jEXAMPLEW+vE/7s1HRpXviG7b+qYf4nD00EXAMPLEmj4wxS04L/uZEXAMPLECihzFB5lTYLto9dyBgSDyEXA
   MPLEKEY9/g7QRUhZp4bqbEXAMPLENwGPyOj59pFA4lNKCIkVgkREXAMPLEjlzxQ7y52gekeVEXAMPLEDiB9ST3UusKd
   EXAMPLE1TVastU1A0SKFEXAMPLEiywCC/Cs8EXAMPLEpZgOs+6hz4AP4KEXAMPLERbASP+4eZScEXAMPLENhykxiHen
   DHq6ikBQ==
   ```

   이 시점에서 모든 후속 명령은 해당 자격 증명으로 식별되는 역할의 권한에 따라 실행됩니다. David의 경우 `UpdateData` 역할입니다.
**중요**  
AWS CLI에서 유지되는 파일에 자주 사용되는 구성 설정과 보안 인증을 저장할 수 있습니다. 자세한 내용은 *AWS Command Line Interface 사용 설명서*의 [기존 구성 및 보안 인증 파일 사용](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-quickstart.html#getting-started-quickstart-existing)을 참조하세요.

1. 명령을 실행하여 Destination 계정의 리소스에 액세스합니다. 이 예시에서 David는 단순히 다음 명령을 사용하여 S3 버킷의 콘텐츠를 나열합니다.

   ```
   aws s3 ls s3://shared-container
   ```

   Amazon S3 버킷 이름은 범용 고유 이름이기 때문에 해당 버킷을 소유하는 계정 ID를 지정할 필요가 없습니다. 다른 AWS 서비스의 리소스에 액세스하려면 해당 서비스의 AWS CLI 설명서에서 해당 리소스를 참조하는 데 필요한 명령과 구문을 참조하세요.

### AssumeRole(AWS API)사용
<a name="api-tutorial_cross-account-with-roles"></a>

David가 코드에서 **Destination** 계정을 업데이트해야 하는 경우 `AssumeRole`을 호출하여 `UpdateData` 역할을 수임합니다. 이 호출은 **Destination** 계정에서 David가 `amzn-s3-demo-bucket-shared-container` 버킷에 액세스하기 위해 사용할 수 있는 임시 보안 인증 정보를 반환합니다. David는 해당 자격 증명을 사용하여 `amzn-s3-demo-bucket-shared-container` 버킷을 업데이트하는 API 호출을 실행할 수 있습니다. 그러나 David는 **Originating** 계정의 파워 유저 권한이 있더라도 **Destination** 계정의 다른 리소스에 액세스하는 API 호출을 실행할 수 없습니다.

**역할 수임**

1. David가 애플리케이션의 일부로 `AssumeRole`을 호출합니다. `UpdateData` ARN인 `arn:aws:iam::999999999999:role/UpdateData`을 지정해야 합니다.

   `AssumeRole` 호출의 응답에는 `AccessKeyId` 및 `SecretAccessKey`가 있는 임시 자격 증명이 포함됩니다. 또한 자격 증명이 만료되고 새 자격 증명을 요청해야 하는 시점을 나타내는 `Expiration` 시간이 포함됩니다. AWS SDK로 역할 함께 묶기를 설정하면 많은 보안 인증 정보 공급자가 만료 전에 보안 인증 정보를 자동으로 새로 고칩니다.

1. David가 임시 자격 증명을 사용하여 `s3:PutObject` 버킷을 업데이트하는 `amzn-s3-demo-bucket-shared-container` 호출을 실행합니다. 이때 자격 증명을 `AuthParams` 파라미터로 API 호출에 전달합니다. 임시 역할 보안 인증 정보에는 `amzn-s3-demo-bucket-shared-container` 버킷에 대한 읽기 및 쓰기 권한만 있기 때문에 Destination 계정의 다른 모든 작업은 거부됩니다.

코드 샘플(Python 사용)은 [IAM 역할로 전환(AWS API)](id_roles_use_switch-role-api.md) 단원을 참조하십시오.

## 추가 리소스
<a name="tutorial_cross-account-with-roles-related"></a>

다음 리소스는 이 자습서의 주제에 대해 자세히 알아보는 데 도움이 됩니다.
+ IAM 사용자에 대한 자세한 내용은 [IAM 자격 증명](id.md) 섹션을 참조하세요.
+ Amazon S3 버킷에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [Create a Bucket(버킷 생성)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/CreatingABucket.html)을 참조하세요.
+  해당 신뢰 영역(신뢰할 수 있는 조직 또는 계정) 외의 계정 내 보안 주체가 역할을 수임하는 권한이 있는지 자세히 알고 싶다면, [IAM Access Analyzer란 무엇일까요?](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html)를 참조하세요.

## 요약
<a name="tutorial_cross-account-with-roles-summary"></a>

크로스 계정 API 액세스 자습서를 완료했습니다. 다른 계정과 신뢰 관계를 설정하기 위한 역할을 만들고 신뢰할 수 있는 주체가 수행할 수 있는 작업을 정의했습니다. 그런 다음 해당 역할에 액세스할 수 있는 IAM 사용자를 제어하도록 역할 정책을 수정했습니다. 그 결과 **Originating** 계정의 개발자가 임시 보안 인증 정보를 사용하여 **Destination** 계정에서 `amzn-s3-demo-bucket-shared-container` 버킷을 업데이트할 수 있습니다.

# IAM 튜토리얼: 첫 번째 고객 관리형 정책 만들기 및 연결
<a name="tutorial_managed-policies"></a>

이 튜토리얼에서는 AWS Management Console을 사용하여 [고객 관리형 정책](access_policies_managed-vs-inline.md#customer-managed-policies)을 만든 다음 이 정책을 AWS 계정의 IAM 사용자에게 연결합니다. 여기서 생성하는 정책은 IAM 테스트 사용자가 읽기 전용 권한으로 AWS Management Console에 직접 로그인할 수 있도록 허용합니다.

이 워크플로우는 세 가지 기본 단계로 이루어집니다.

**[1단계: 정책 생성](#step1-create-policy)**  
기본적으로 IAM 사용자에게는 아무런 권한이 없습니다. 관리자가 허용하지 않는 한, 이들 사용자가 AWS 관리 콘솔에 액세스하거나 그 안에서 데이터를 관리할 수 없습니다. 이 단계에서는 연결된 사용자가 콘솔에 로그인할 수 있도록 허용하는 고객 관리형 정책을 생성합니다.

**[2단계: 정책 연결](#step2-attach-policy)**  
정책을 사용자에 연결할 경우 이 사용자는 해당 정책과 관련된 액세스 권한을 모두 상속받습니다. 이 단계에서는 새 정책을 테스트 사용자에 연결합니다.

**[3단계: 사용자 액세스 테스트](#step3-test-access)**  
정책을 연결하고 나면 해당 사용자로 로그인하여 정책을 테스트할 수 있습니다.

## 사전 조건
<a name="tutorial-managed-policies-prereqs"></a>

이 자습서의 단계를 수행하려면 다음이 준비되어 있어야 합니다.
+ 관리 권한을 가진 IAM 사용자로 로그인할 수 있는 AWS 계정.
+ 다음과 같이 할당된 권한 또는 그룹 멤버십이 없는 테스트 IAM 사용자.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_managed-policies.html)

## 1단계: 정책 생성
<a name="step1-create-policy"></a>

이 단계에서는 연결된 사용자가 IAM 데이터에 대한 읽기 전용 권한으로 AWS Management Console에 로그인할 수 있도록 허용하는 고객 관리형 정책을 생성합니다.

**테스트 사용자에 대한 정책을 생성하려면**

1. 관리자 권한이 있는 사용자로 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)의 IAM 콘솔에 로그인합니다.

1. 탐색 창에서 **정책**을 선택합니다.

1. 콘텐츠 창에서 **정책 생성**을 선택합니다.

1. **JSON** 옵션을 선택하고 다음 JSON 정책 문서에서 텍스트를 복사합니다. 이 텍스트를 **JSON** 텍스트 상자에 붙여 넣습니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [ {
           "Effect": "Allow",
           "Action": [
               "iam:GenerateCredentialReport",
               "iam:Get*",
               "iam:List*"
           ],
           "Resource": "*"
       } ]
   }
   ```

------

1.  [정책 검증](access_policies_policy-validator.md) 중에 생성되는 모든 보안 경고, 오류 또는 일반 경고를 해결하고 **다음**을 선택합니다.
**참고**  
언제든지 **시각적** 편집기 옵션과 **JSON** 편집기 옵션을 서로 전환할 수 있습니다. 그러나 변경을 수행하거나 **시각적** 편집기 탭에서 **정책 검토**를 선택한 경우 IAM은 시각적 편집기에 최적화되도록 정책을 재구성할 수 있습니다. 자세한 내용은 [정책 재구성](troubleshoot_policies.md#troubleshoot_viseditor-restructure) 섹션을 참조하세요.

1. **검토 및 생성** 페이지에서 정책 이름에 **UsersReadOnlyAccessToIAMConsole**을 입력합니다. 정책이 부여한 권한을 검토한 다음 **정책 생성**을 선택하여 작업을 저장합니다.

   새로운 정책이 관리형 정책 목록에 나타나며 연결 준비가 완료됩니다.

## 2단계: 정책 연결
<a name="step2-attach-policy"></a>

다음에는 방금 생성한 테스트 IAM 사용자에 정책을 연결합니다.

**테스트 사용자에 정책을 연결하려면**

1. IAM 콘솔의 탐색 창에서 **정책(Policies)**을 선택합니다.

1. 정책 목록의 맨 위에 있는 검색 상자에서 해당 정책이 표시될 때까지 **UsersReadOnlyAccesstoIAMConsole** 입력을 시작합니다. 그런 다음 목록에서 **UsersReadOnlyAccessToIAMConsole** 옆에 있는 라디오 버튼을 선택합니다.

1. **작업(Actions)** 버튼을 선택한 후 **연결(Attach)**을 선택합니다.

1. IAM 엔터티에서 **사용자**를 필터링할 옵션을 선택합니다.

1. 검색 상자에서 해당 사용자가 목록에 표시될 때까지 **PolicyUser** 입력을 시작합니다. 그런 다음 목록에서 해당 사용자 옆의 확인란을 선택합니다.

1. **정책 연결**을 선택합니다.

이제 IAM 테스트 사용자에 정책을 연결했습니다. 즉, 이 사용자가 IAM 콘솔에 읽기 전용으로 액세스할 수 있습니다.

## 3단계: 사용자 액세스 테스트
<a name="step3-test-access"></a>

이 자습서에서는 사용자가 어떤 경험을 하게 되는지 볼 수 있도록 테스트 사용자로 로그인하여 액세스를 테스트할 것을 권장합니다.

**테스트 사용자로 로그인하여 액세스 권한을 테스트하려면**

1. IAM 콘솔([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/))에 `PolicyUser` 테스트 사용자로 로그인합니다.

1. 콘솔에서 각 페이지를 탐색하고 새 사용자 또는 그룹을 생성해 봅니다. `PolicyUser`는 데이터를 표시할 수는 있지만 IAM 데이터를 생성하거나 수정할 수는 없습니다.

## 관련 리소스
<a name="tutorial-managed-policies-addl-resources"></a>

관련 내용은 다음 리소스를 참조하십시오.
+ [관리형 정책과 인라인 정책](access_policies_managed-vs-inline.md)
+ [AWS Management Console에 대한 IAM 사용자 액세스 제어](console_controlling-access.md)

## 요약
<a name="tutorial-managed-policies-summary"></a>

이제 고객 관리형 정책을 생성 및 연결하는 데 필요한 모든 단계를 성공적으로 완료했습니다. 테스트 계정으로 IAM 콘솔에 로그인하여 사용자의 환경을 확인할 수 있습니다.

# IAM 튜토리얼: 태그를 기반으로 AWS 리소스에 액세스할 수 있는 권한 정의
<a name="tutorial_attribute-based-access-control"></a>

속성 기반 액세스 제어(ABAC)는 속성에 근거하여 권한을 정의하는 권한 부여 전략입니다. AWS에서는 이러한 속성을 태그**라고 합니다. IAM 엔터티(사용자 또는 역할)와 AWS 리소스에 태그를 연결할 수 있습니다. 태그 조건 키를 사용하여 해당 태그를 기반으로 보안 주체에 권한을 부여하는 정책을 정의할 수 있습니다. 태그를 사용하여 AWS 리소스에 대한 액세스를 제어하면 AWS 정책에 대한 변경 사항이 줄어들면서 팀과 리소스가 성장할 수 있습니다. ABAC 정책은 각 개별 리소스를 나열해야 하는 기존 AWS 정책보다 유연합니다. ABAC에 대한 자세한 내용 및 기존 정책과 비교할 때의 이점은 [ABAC 권한 부여를 통한 속성 기반 권한 정의](introduction_attribute-based-access-control.md) 단원을 참조하십시오.

**참고**  
각 세션 태그에는 단일 값을 전달해야 합니다. AWS Security Token Service에서는 다중 값 세션 태그를 지원하지 않습니다.

**Topics**
+ [자습서 개요](#tutorial_attribute-based-access-control-overview)
+ [사전 조건](#tutorial_abac_prereqs)
+ [1단계: 테스트 사용자 생성](#tutorial_abac_step1)
+ [2단계: ABAC 정책 생성](#tutorial_abac_step2)
+ [3단계: 역할 생성](#tutorial_abac_step3)
+ [4단계: 비밀 생성 테스트](#tutorial_abac_step4)
+ [5단계: 비밀 보기 테스트](#tutorial_abac_step5)
+ [6단계: 테스트 확장성](#tutorial_abac_step6)
+ [7단계: 비밀 업데이트 및 삭제 테스트](#tutorial_abac_step7)
+ [요약](#tutorial-abac-summary)
+ [관련 리소스](#tutorial_abac_related)
+ [IAM 튜토리얼: ABAC에 SAML 세션 태그 사용](tutorial_abac-saml.md)

## 자습서 개요
<a name="tutorial_attribute-based-access-control-overview"></a>

이 튜토리얼에서는 보안 주체 태그가 있는 IAM 역할이 일치하는 태그가 있는 리소스에 액세스할 수 있도록 허용하는 정책을 생성하고 테스트하는 방법을 보여줍니다. 보안 주체가 AWS에 요청하면 보안 주체와 리소스 태그가 일치하는지 여부에 따라 권한이 부여됩니다. 이 전략을 통해 개인이 자신의 작업에 필요한 AWS 리소스만 보거나 편집할 수 있습니다.

**시나리오**  
Example Corporation이라는 대기업의 수석 개발자이자 숙련된 IAM 관리자가 있다고 가정해 보겠습니다. 이 관리자는 IAM 사용자, 역할 및 정책을 생성하고 관리하는 데 익숙합니다. 개발 엔지니어와 품질 보증 팀 멤버가 필요한 리소스에 액세스할 수 있도록 해야 하며 기업의 성장에 따라 확장 가능한 전략도 준비해야 합니다.

AWS 리소스 태그와 IAM 역할 보안 주체 태그를 사용하여 이를 지원하는 서비스에 대한 ABAC 전략을 구현하도록 선택합니다(AWS Secrets Manager로 시작). 태그를 기반으로 권한 부여를 지원하는 서비스에 대한 자세한 내용은 [AWS IAM으로 작업하는 서비스](reference_aws-services-that-work-with-iam.md) 단원을 참조하십시오. 각 서비스의 작업 및 리소스와 함께 정책에서 사용할 수 있는 태그 지정 조건 키에 대한 자세한 내용은 [AWS 서비스에 사용되는 작업, 리소스 및 조건 키](reference_policies_actions-resources-contextkeys.html)를 참조하세요. [세션 태그](id_session-tags.md)를 AWS에 전달하도록 SAML 기반 또는 웹 자격 증명 공급자를 구성할 수 있습니다. 직원이 AWS에 연동되면 해당 속성이 AWS의 결과 보안 주체에 적용됩니다. 그런 다음 ABAC를 사용하여 이러한 속성에 따라 권한을 허용하거나 거부할 수 있습니다. SAML 페더레이션 자격 증명과 함께 세션 태그를 사용하는 것이 이 자습서와 어떻게 다른지 알아보려면 [IAM 튜토리얼: ABAC에 SAML 세션 태그 사용](tutorial_abac-saml.md) 단원을 참조하십시오.

엔지니어링 및 품질 보증 팀 멤버는 **Pegasus** 또는 **Unicorn** 프로젝트에 참여하고 있습니다. 다음 세 글자로 된 프로젝트 및 팀 태그 값을 선택합니다.
+ **Pegasus** 프로젝트에 대해 `access-project` = `peg`
+ **Unicorn** 프로젝트에 대해 `access-project` = `uni`
+ 엔지니어링 팀에 대해 `access-team` = `eng`
+ 품질 보증 팀에 대해 `access-team` = `qas`

또한 사용자 지정 AWS 결제 보고서를 활성화할 때 `cost-center` 비용 할당 태그가 필요하도록 선택할 수 있습니다. 자세한 내용은 *AWS 결제 및 비용 관리 사용 설명서*의 [비용 할당 태그 사용](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html)을 참조하세요.

**주요 의사 결정 요약**
+ 직원은 IAM 사용자 자격 증명으로 로그인한 다음 팀 및 프로젝트의 IAM 역할을 맡습니다. 회사에 자체 자격 증명 시스템이 있는 경우 직원이 IAM 사용자 없이 역할을 맡을 수 있도록 연동을 설정할 수 있습니다. 자세한 내용은 [IAM 튜토리얼: ABAC에 SAML 세션 태그 사용](tutorial_abac-saml.md) 섹션을 참조하세요.
+ 동일한 정책이 모든 역할에 연결됩니다. 작업은 태그에 따라 허용되거나 거부됩니다.
+ 직원은 자신의 역할에 적용되는 리소스에 동일한 태그를 연결하는 경우에만 새 리소스를 생성할 수 있습니다. 이렇게 하면 직원이 리소스를 생성한 후 해당 리소스를 볼 수 있습니다. 관리자는 더 이상 새 리소스의 ARN으로 정책을 업데이트할 필요가 없습니다.
+ 직원은 프로젝트와 관계없이 자신의 팀이 소유한 리소스를 읽을 수 있습니다.
+ 직원은 자신의 팀과 프로젝트가 소유한 리소스를 업데이트하고 삭제할 수 있습니다.
+ IAM 관리자는 새 프로젝트에 대한 새 역할을 추가할 수 있습니다. 해당 역할에 대한 액세스를 허용하도록 새 IAM 사용자를 생성하고 태그를 지정할 수 있습니다. 관리자는 새 프로젝트 또는 팀 멤버를 지원하기 위해 정책을 편집할 필요가 없습니다.

이 자습서에서는 각 리소스에 태그를 지정하고 프로젝트 역할에 태그를 지정하고 역할에 정책을 추가하여 앞에서 설명한 동작을 허용합니다. 결과 정책은 동일한 프로젝트 및 팀 태그로 태그가 지정된 리소스에 대한 역할 `Create`, `Read`, `Update` 및 `Delete` 액세스를 허용합니다. 또한 이 정책은 동일한 팀으로 태그가 지정된 리소스에 대해 프로젝트 간 `Read` 액세스를 허용합니다.

![\[다이어그램은 역할이 자체 프로젝트 밖에서는 읽기 전용 액세스로 제한되지만 자체 프로젝트에서는 리소스를 생성하고, 읽고, 업데이트하고, 삭제할 수 있는 권한이 있는 두 프로젝트를 보여줍니다.\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/images/tutorial-abac-cross-project.png)


## 사전 조건
<a name="tutorial_abac_prereqs"></a>

이 자습서의 단계를 수행하려면 다음이 준비되어 있어야 합니다.
+ 관리 권한을 가진 사용자로 로그인할 수 있는 AWS 계정.
+ 3단계에서 역할을 생성하는 데 사용한 12자리 계정 ID입니다.

  AWS Management Console을 사용하여 AWS 계정 ID 번호를 찾으려면 오른쪽 상단에 있는 탐색 모음에서 **지원**을 선택한 후 **지원 센터**를 선택합니다. 계정 번호(ID)가 왼쪽 탐색 창에 나타납니다.  
![\[계정 번호가 표시된 지원 센터 페이지.\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/images/account-id-support-center.console.png)
+ AWS Management Console에서 IAM 사용자, 역할 및 정책을 생성 및 편집해 본 경험. 그러나 IAM 관리 프로세스를 기억해야 하는 경우를 위해 이 튜토리얼에서는 단계별 지침을 볼 수 있는 링크를 제공합니다.

## 1단계: 테스트 사용자 생성
<a name="tutorial_abac_step1"></a>

테스트를 위해 동일한 태그를 사용하여 역할을 맡을 권한이 있는 IAM 사용자 4명을 생성합니다. 이렇게 하면 팀에 사용자를 더 쉽게 추가할 수 있습니다. 사용자에게 태그를 지정하면 올바른 역할을 맡을 수 있는 액세스 권한이 자동으로 부여됩니다. 사용자가 하나의 프로젝트와 팀에서만 작업하는 경우 역할의 신뢰 정책에 사용자를 추가할 필요가 없습니다.

1. 다음과 같이 `access-assume-role`이라는 고객 관리형 정책을 생성합니다. JSON 정책 생성에 대한 자세한 내용은 [IAM 정책 생성](access_policies_create-console.md#access_policies_create-start) 단원을 참조하십시오.

**ABAC 정책: 사용자 및 역할 태그가 일치하는 경우에만 모든 ABAC 역할 수임**  
다음 정책은 사용자가 `access-` 이름 접두사가 있는 계정의 모든 역할을 맡을 수 있도록 허용합니다. 역할에는 사용자와 동일한 프로젝트, 팀 및 비용 센터 태그가 지정되어 있어야 합니다.

   이 정책을 사용하려면 *기울임꼴 자리 표시자 텍스트*를 계정 정보로 바꿉니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "TutorialAssumeRole",
               "Effect": "Allow",
               "Action": "sts:AssumeRole",
               "Resource": "arn:aws:iam::111122223333:role/access-*",
               "Condition": {
                   "StringEquals": {
                       "iam:ResourceTag/access-project": "${aws:PrincipalTag/access-project}",
                       "iam:ResourceTag/access-team": "${aws:PrincipalTag/access-team}",
                       "iam:ResourceTag/cost-center": "${aws:PrincipalTag/cost-center}"
                   }
               }
           }
       ]
   }
   ```

------

   이 자습서를 많은 사용자로 확장하기 위해 정책을 그룹에 연결하고 각 사용자를 그룹에 추가할 수 있습니다. 자세한 내용은 [IAM 그룹 생성](id_groups_create.md) 및 [IAM 그룹의 사용자 편집](id_groups_manage_add-remove-users.md)(을)를 참조하세요.

1. 다음 IAM 사용자를 생성하고, `access-assume-role` 권한 정책을 연결합니다. **AWS Management Console에 대한 사용자 액세스 제공**을 선택하고 다음 태그를 추가해야 합니다.

       
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)

## 2단계: ABAC 정책 생성
<a name="tutorial_abac_step2"></a>

다음과 같이 **access-same-project-team**이라는 정책을 생성합니다. 이후 단계에서 이 정책을 역할에 추가합니다. JSON 정책 생성에 대한 자세한 내용은 [IAM 정책 생성](access_policies_create-console.md#access_policies_create-start) 단원을 참조하십시오.

이 자습서에 적용할 수 있는 추가 정책은 다음 페이지를 참조하십시오.
+ [IAM 보안 주체에 대한 액세스 제어](access_iam-tags.md#access_iam-tags_control-principals)
+ [Amazon EC2: 프로그래밍 방식으로 콘솔에서 사용자가 태그를 지정한 EC2 인스턴스를 시작 또는 중지할 수 있도록 허용](reference_policies_examples_ec2_tag-owner.md)
+ [EC2: 일치하는 보안 주체 및 리소스 태그를 기반으로 인스턴스 시작 또는 중지](reference_policies_examples_ec2-start-stop-match-tags.md)
+ [EC2: 태그를 기반으로 인스턴스 시작 또는 중지](reference_policies_examples_ec2-start-stop-tags.md)
+ [IAM: 특정 태그가 있는 역할 수임](reference_policies_examples_iam-assume-tagged-role.md)

**ABAC 정책: 보안 주체 및 리소스 태그가 일치하는 경우에만 Secrets Manager 리소스 액세스**  
다음 정책은 보안 주체와 동일한 키-값 페어로 리소스에 태그가 지정된 경우에만 보안 주체가 리소스를 생성, 읽기, 편집 및 삭제할 수 있도록 허용합니다. 보안 주체가 리소스를 생성할 때 보안 주체의 태그와 일치하는 값을 가진 `access-project`, `access-team` 및 `cost-center` 태그를 추가해야 합니다. 이 정책에서는 선택 사항인 `Name` 또는 `OwnedBy` 태그를 추가할 수도 있습니다.

------
#### [ JSON ]

****  

```
{
 "Version":"2012-10-17",		 	 	 
 "Statement": [
     {
         "Sid": "AllActionsSecretsManagerSameProjectSameTeam",
         "Effect": "Allow",
         "Action": "secretsmanager:*",
         "Resource": "*",
         "Condition": {
             "StringEquals": {
                 "aws:ResourceTag/access-project": "${aws:PrincipalTag/access-project}",
                 "aws:ResourceTag/access-team": "${aws:PrincipalTag/access-team}",
                 "aws:ResourceTag/cost-center": "${aws:PrincipalTag/cost-center}"
             },
             "ForAllValues:StringEquals": {
                 "aws:TagKeys": [
                     "access-project",
                     "access-team",
                     "cost-center",
                     "Name",
                     "OwnedBy"
                 ]
             },
             "StringEqualsIfExists": {
                 "aws:RequestTag/access-project": "${aws:PrincipalTag/access-project}",
                 "aws:RequestTag/access-team": "${aws:PrincipalTag/access-team}",
                 "aws:RequestTag/cost-center": "${aws:PrincipalTag/cost-center}"
             }
         }
     },
     {
         "Sid": "AllResourcesSecretsManagerNoTags",
         "Effect": "Allow",
         "Action": [
             "secretsmanager:GetRandomPassword",
             "secretsmanager:ListSecrets"
         ],
         "Resource": "*"
     },
     {
         "Sid": "ReadSecretsManagerSameTeam",
         "Effect": "Allow",
         "Action": [
             "secretsmanager:Describe*",
             "secretsmanager:Get*",
             "secretsmanager:List*"
         ],
         "Resource": "*",
         "Condition": {
             "StringEquals": {
                 "aws:ResourceTag/access-team": "${aws:PrincipalTag/access-team}"
             }
         }
     },
     {
         "Sid": "DenyUntagSecretsManagerReservedTags",
         "Effect": "Deny",
         "Action": "secretsmanager:UntagResource",
         "Resource": "*",
         "Condition": {
             "ForAnyValue:StringLike": {
                 "aws:TagKeys": "access-*"
             }
         }
     },
     {
         "Sid": "DenyPermissionsManagement",
         "Effect": "Deny",
         "Action": "secretsmanager:*Policy",
         "Resource": "*"
     }
 ]
}
```

------

**이 정책이 하는 일은 무엇입니까?**
+ `AllActionsSecretsManagerSameProjectSameTeam` 문은 리소스 태그가 보안 주체 태그와 일치하는 경우에만 모든 관련 리소스에 대해 이 서비스의 모든 작업을 허용합니다. 정책에 `"Action": "secretsmanager:*"`를 추가하면 Secrets Manager가 커질수록 정책도 커집니다. Secrets Manager에서 새 API 작업을 추가하는 경우 문에 해당 작업을 추가할 필요가 없습니다. 이 문은 세 가지 조건 블록을 사용하여 ABAC를 구현합니다. 세 블록 모두 true를 반환하는 경우에만 요청이 허용됩니다.
  + 지정된 태그 키가 리소스에 있고 해당 값이 보안 주체의 태그와 일치하는 경우 이 문의 첫 번째 조건 블록은 true를 반환합니다. 이 블록은 일치하지 않는 태그 또는 리소스 태그 지정을 지원하지 않는 작업에 대해 false를 반환합니다. 이 블록에서 허용되지 않는 작업에 대한 자세한 내용은 [AWS Secrets Manager에 대한 작업, 리소스 및 조건 키](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awssecretsmanager.html)를 참조하십시오 . 이 페이지에서는 [**비밀** 리소스 유형](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awssecretsmanager.html#awssecretsmanager-resources-for-iam-policies)에 대해 수행된 작업이 `secretsmanager:ResourceTag/tag-key` 조건 키를 지원한다는 것을 보여 줍니다. 일부 [Secrets Manager 작업](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awssecretsmanager.html#awssecretsmanager-actions-as-permissions)에서는 `GetRandomPassword` 및 `ListSecrets`를 포함하여 해당 해당 리소스 유형을 지원하지 않습니다. 이러한 작업을 허용하려면 추가 문을 생성해야 합니다.
  + 두 번째 조건 블록은 요청에 전달된 모든 태그 키가 지정된 목록에 포함된 경우 true를 반환합니다. 이 작업은 `StringEquals` 조건 연산자와 함께 `ForAllValues`를 사용하여 수행됩니다. 키 또는 키 세트의 일부가 전달되지 않으면 조건이 true를 반환합니다. 이 경우 요청에서 태그 전달을 허용하지 않는 `Get*` 작업을 사용할 수 있습니다. 요청자가 목록에 없는 태그 키를 포함하는 경우 조건은 false를 반환합니다. 요청에 전달되는 모든 태그 키가 이 목록의 멤버와 일치해야 합니다. 자세한 내용은 [다중 값 컨텍스트 키에 대한 연산자 설정](reference_policies_condition-single-vs-multi-valued-context-keys.md#reference_policies_condition-multi-valued-context-keys) 섹션을 참조하세요.
  + 세 번째 조건 블록은 요청이 태그 전달을 지원하고, 세 개의 태그가 모두 존재하고, 보안 주체 태그 값과 일치하는 경우 true를 반환합니다. 요청이 태그 전달을 지원하지 않는 경우에도 이 블록은 true를 반환합니다. 그 이유는 조건 연산자의 [`...IfExists`](reference_policies_elements_condition_operators.md#Conditions_IfExists) 때문입니다. 지원하는 작업 중에 전달된 태그가 없거나 태그 키 및 값이 일치하지 않으면 블록이 false를 반환합니다.
+ `AllResourcesSecretsManagerNoTags` 문은 첫 번째 문에서 허용되지 않는 `GetRandomPassword` 및 `ListSecrets` 작업을 허용합니다.
+ `ReadSecretsManagerSameTeam` 문은 보안 주체가 리소스와 동일한 액세스 팀 태그로 태그가 지정된 경우 읽기 전용 작업을 허용합니다. 이는 프로젝트 또는 비용 센터 태그와 관계없이 허용됩니다.
+ `DenyUntagSecretsManagerReservedTags` 문은 Secrets Manager에서 “access-”로 시작하는 키가 있는 태그를 제거하라는 요청을 거부합니다. 이러한 태그는 리소스에 대한 액세스를 제어하는 데 사용되므로 태그를 제거하면 권한이 제거될 수 있습니다.
+ `DenyPermissionsManagement` 문은 Secrets Manager 리소스 기반 정책을 생성, 편집 또는 삭제할 수 있는 권한을 거부합니다. 이러한 정책을 사용하여 비밀의 권한을 변경할 수 있습니다.

**중요**  
이 정책은 전략을 사용하여 서비스에 대한 모든 작업을 허용하지만 권한 변경 작업을 명시적으로 거부합니다. 작업을 거부하면 보안 주체가 해당 작업을 수행할 수 있도록 허용하는 다른 정책을 재정의합니다. 이로 인해 의도하지 않은 결과가 발생할 수 있습니다. 명시적 거부는 해당 작업을 허용해야 하는 상황이 없는 경우에만 사용하는 것이 가장 좋습니다. 그렇지 않은 경우 개별 작업 목록을 허용하고 원치 않는 작업이 기본적으로 거부됩니다.

## 3단계: 역할 생성
<a name="tutorial_abac_step3"></a>

다음 IAM 역할을 생성하고 이전 단계에서 생성한 **access-same-project-team** 정책을 연결합니다. IAM 역할 생성에 대한 자세한 내용은 [IAM 사용자에게 권한을 부여할 역할 생성](id_roles_create_for-user.md) 섹션을 참조하세요. IAM 사용자 및 역할 대신 연동을 사용하도록 선택한 경우 [IAM 튜토리얼: ABAC에 SAML 세션 태그 사용](tutorial_abac-saml.md) 섹션을 참조하세요.


| 직무 | 역할 이름 | 역할 태그 | 역할 설명 | 
| --- | --- | --- | --- | 
|  프로젝트 Pegasus 엔지니어링  |  access-peg-engineering  |  access-project = `peg` access-team = `eng` cost-center = `987654`   | 엔지니어는 모든 엔지니어링 리소스를 읽고 Pegasus 엔지니어링 리소스를 생성 및 관리할 수 있습니다. | 
|  프로젝트 Pegasus 품질 보증  |  access-peg-quality-assurance  |  access-project = `peg` access-team = `qas` cost-center = `987654`  |  QA 팀은 모든 QA 리소스를 읽고 모든 Pegasus QA 리소스를 생성 및 관리할 수 있습니다.  | 
|  프로젝트 Unicorn 엔지니어링  |  access-uni-engineering  |  access-project= `uni` access-team = `eng` cost-center = `123456`  | 엔지니어는 모든 엔지니어링 리소스를 읽고 Unicorn 엔지니어링 리소스를 생성 및 관리할 수 있습니다. | 
|  프로젝트 Unicorn 품질 보증  |  access-uni-quality-assurance  |  access-project = `uni` access-team = `qas` cost-center = `123456`   |  QA 팀은 모든 QA 리소스를 읽고 모든 Unicorn QA 리소스를 생성 및 관리할 수 있습니다.  | 

## 4단계: 비밀 생성 테스트
<a name="tutorial_abac_step4"></a>

역할에 연결된 권한 정책을 통해 직원이 비밀을 생성할 수 있습니다. 이 작업은 비밀에 프로젝트, 팀 및 비용 센터 태그가 지정된 경우에만 허용됩니다. Secrets Manager에서 사용자로 로그인하고, 올바른 역할을 맡고, 활동을 테스트하여 권한이 예상대로 작동하는지 확인합니다.

**필수 태그를 사용하거나 사용하지 않고 비밀 생성을 테스트하려면**

1. 기본 브라우저 창에서 관리자 사용자로 로그인한 상태로 유지되므로 IAM에서 사용자, 역할 및 정책을 검토할 수 있습니다. 테스트를 위해 브라우저 익명 창 또는 별도의 브라우저를 사용하십시오. 이제 `access-Arnav-peg-eng` IAM 사용자로 로그인하고 [https://console.aws.amazon.com/secretsmanager/](https://console.aws.amazon.com/secretsmanager/)에서 Secrets Manager 콘솔을 엽니다.

1. `access-uni-engineering` 역할로의 전환을 시도합니다.

   `access-Arnav-peg-eng` 사용자와 `access-uni-engineering` 역할의 `access-project` 및 `cost-center` 태그 값이 일치하지 않기 때문에 이 작업은 실패합니다.

   AWS Management Console에서의 역할 전환에 대한 자세한 내용은 [사용자에서 IAM 역할로 전환(콘솔)](id_roles_use_switch-role-console.md)의 내용을 참조하세요.

1. `access-peg-engineering` 역할로 전환합니다.

1. 다음 정보를 사용하여 새 비밀을 저장합니다. 비밀을 저장하는 방법에 대한 자세한 내용을 알아보려면 *AWS Secrets Manager 사용 설명서*의 [Creating a Basic Secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html)(기본 보안 암호 생성)을 참조하세요.
**중요**  
Secrets Manager에 Secrets Manager에 사용되는 추가 AWS 서비스에 대한 권한이 없다는 알림이 표시됩니다. 예를 들어, Amazon RDS 데이터베이스에 대한 자격 증명을 생성하려면 RDS 인스턴스, RDS 클러스터 및 Amazon Redshift 클러스터를 설명할 수 있는 권한이 있어야 합니다. 이 자습서에서 이러한 특정 AWS 서비스를 사용하지 않으므로 이러한 알림은 무시해도 좋습니다.

   1. **비밀 유형 선택** 섹션에서 **다른 유형의 비밀**을 선택합니다. 두 텍스트 상자에 `test-access-key` 및 `test-access-secret`를 입력합니다.

   1. **비밀 이름** 필드에 `test-access-peg-eng`를 입력합니다.

   1. 다음 표에서 다양한 태그 조합을 추가하고 예상되는 동작을 확인합니다.

   1. **Store(저장)**를 선택하여 비밀을 생성합니다. 스토리지에 장애가 발생하면 이전 Secrets Manager 콘솔 페이지로 돌아가서 아래 표에 있는 다음 태그 세트를 사용합니다. 마지막 태그 세트가 허용되고 비밀이 성공적으로 생성됩니다.

   다음 표에는 `test-access-peg-eng` 역할의 ABAC 태그 조합이 나와 있습니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)

1. 로그아웃하고 다음 역할 및 태그 값 각각에 대해 이 절차의 처음 세 단계를 반복합니다. 이 절차의 네 번째 단계에서는 선택한 누락된 태그, 선택적 태그, 허용되지 않는 태그 및 잘못된 태그 값 세트를 테스트합니다. 그런 다음 필수 태그를 사용하여 다음 태그와 이름으로 비밀을 생성합니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)

## 5단계: 비밀 보기 테스트
<a name="tutorial_abac_step5"></a>

각 역할에 연결된 정책을 통해 직원은 프로젝트와 관계없이 팀 이름으로 태그가 지정된 모든 비밀을 볼 수 있습니다. Secrets Manager에서 역할을 테스트하여 권한이 예상대로 작동하는지 확인합니다.

**필수 태그를 사용하거나 사용하지 않고 비밀 보기를 테스트하려면**

1. 다음 IAM 사용자 중 한 명으로 로그인합니다.
   + `access-Arnav-peg-eng`
   + `access-Mary-peg-qas`
   + `access-Saanvi-uni-eng`
   + `access-Carlos-uni-qas`

1. 일치하는 역할로 전환합니다.
   + `access-peg-engineering`
   + `access-peg-quality-assurance`
   + `access-uni-engineering`
   + `access-uni-quality-assurance`

   AWS Management Console에서의 역할 전환에 대한 자세한 내용은 [사용자에서 IAM 역할로 전환(콘솔)](id_roles_use_switch-role-console.md) 단원을 참조하십시오.

1. 왼쪽의 탐색 창에서 메뉴 아이콘을 선택하여 메뉴를 확장한 다음 **비밀**을 선택합니다.

1. 현재 역할과 관계없이 표에 네 가지 비밀이 모두 표시됩니다. 이는 `access-same-project-team`이라는 정책이 모든 리소스에 대해 `secretsmanager:ListSecrets` 작업을 허용하기 때문입니다.

1. 비밀 중 하나의 이름을 선택합니다.

1. 비밀에 대한 세부 정보 페이지에서 역할의 태그에 따라 페이지 콘텐츠를 볼 수 있는지 여부가 결정됩니다. 역할의 이름을 비밀의 이름과 비교합니다. 동일한 팀 이름을 공유하는 경우 `access-team` 태그가 일치합니다. 일치하지 않으면 액세스가 거부됩니다.

   다음 표는 각 역할의 ABAC 비밀 보기 동작을 보여줍니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)

1. 페이지 상단의 이동 경로에서 **비밀**을 선택하여 비밀 목록으로 돌아갑니다. 다른 역할을 사용하여 이 절차의 단계를 반복하여 각 암호를 볼 수 있는지 여부를 테스트합니다.

## 6단계: 테스트 확장성
<a name="tutorial_abac_step6"></a>

RBAC(역할 기반 액세스 제어)를 통해 ABAC(속성 기반 액세스 제어)를 사용하는 중요한 이유는 확장성입니다. 회사에서 새 프로젝트, 팀 또는 인력을 AWS에 추가할 때 ABAC 기반 정책을 업데이트할 필요가 없습니다. 예를 들어, Example Company가 코드명이 **Centaur**인 새로운 프로젝트에 자금을 조달하고 있다고 가정합니다. Saanvi Sarkar라는 엔지니어는 **Unicorn** 프로젝트에서 계속 작업하면서 **Centaur**의 수석 엔지니어도 겸할 예정입니다. Saanvi는 **Peg** 프로젝트의 작업도 검토할 것입니다. 또한 Nikhil Jayashankar를 포함하여 **Centaur** 프로젝트에서만 작업하기 위해 몇 명의 엔지니어가 새로 고용되었습니다.

**새 프로젝트를 AWS에 추가하려면**

1. IAM 관리자로 로그인하여 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)에서 IAM 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **역할(Roles)**을 선택한 후 `access-cen-engineering`이라는 IAM 역할을 추가합니다. 역할에 **access-same-project-team** 권한 정책을 연결하고 다음 역할 태그 추가:
   + `access-project` = `cen`
   + `access-team` = `eng`
   + `cost-center` = `101010`

1. 왼쪽에 있는 탐색 창에서 **Users(사용자)**를 선택합니다.

1. `access-Nikhil-cen-eng`라는 새 사용자를 추가하고, `access-assume-role`이라는 정책을 연결하고, 다음 사용자 태그를 추가합니다.
   + `access-project` = `cen`
   + `access-team` = `eng`
   + `cost-center` = `101010`

1. [4단계: 비밀 생성 테스트](#tutorial_abac_step4) 및 [5단계: 비밀 보기 테스트](#tutorial_abac_step5)의 절차를 사용합니다. 다른 브라우저 창에서 Nikhil이 **Centaur** 엔지니어링 비밀만 만들 수 있는지와 모든 엔지니어링 비밀을 볼 수 있는지를 테스트합니다.

1. 관리자로 로그인한 기본 브라우저 창에서 사용자 `access-Saanvi-uni-eng`를 선택합니다.

1. **권한** 탭에서 **access-assume-role** 권한 정책을 제거합니다.

1. `access-assume-specific-roles`라는 다음 인라인 정책을 추가합니다. 인라인 정책을 사용자에게 추가하는 방법에 대한 자세한 내용은 [사용자 또는 역할의 인라인 정책을 포함하려면(콘솔)](access_policies_manage-attach-detach.md#embed-inline-policy-console) 단원을 참조하십시오.

**ABAC 정책: 특정 역할만 수임**  
이 정책을 통해 Saanvi는 **Pegasus** 또는 **Centaur** 프로젝트의 엔지니어링 역할을 맡을 수 있습니다. IAM에서는 다중 값 태그를 지원하지 않으므로 이 사용자 지정 정책을 생성해야 합니다. Saanvi의 사용자에게 `access-project` = `peg` 및 `access-project` = `cen` 태그를 지정할 수 없습니다. 또한 AWS 권한 부여 모델은 두 값과 모두 일치할 수 없습니다. 자세한 내용은 [IAM 및 AWS STS의 태그 지정 규칙](id_tags.md#id_tags_rules) 섹션을 참조하세요. 대신 Saanvi가 맡을 수 있는 두 역할을 수동으로 지정해야 합니다.

   이 정책을 사용하려면 *기울임꼴 자리 표시자 텍스트*를 계정 정보로 바꿉니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "TutorialAssumeSpecificRoles",
               "Effect": "Allow",
               "Action": "sts:AssumeRole",
               "Resource": [
                   "arn:aws:iam::111122223333:role/access-peg-engineering",
                   "arn:aws:iam::111122223333:role/access-cen-engineering"
               ]
           }
       ]
   }
   ```

------

1. [4단계: 비밀 생성 테스트](#tutorial_abac_step4) 및 [5단계: 비밀 보기 테스트](#tutorial_abac_step5)의 절차를 사용합니다. 다른 브라우저 창에서 Saanvi가 두 역할을 모두 맡을 수 있는지 확인합니다. 역할의 태그에 따라 프로젝트, 팀 및 비용 센터에 대해서만 비밀을 생성할 수 있는지 확인합니다. 또한 Saanvi가 방금 생성한 비밀을 포함하여 엔지니어링 팀이 소유한 비밀에 대한 세부 정보를 볼 수 있는지 확인합니다.

## 7단계: 비밀 업데이트 및 삭제 테스트
<a name="tutorial_abac_step7"></a>

역할에 연결된 `access-same-project-team` 정책을 통해 직원은 프로젝트, 팀 및 비용 센터로 태그가 지정된 모든 비밀을 업데이트하고 삭제할 수 있습니다. Secrets Manager에서 역할을 테스트하여 권한이 예상대로 작동하는지 확인합니다.

**필수 태그를 사용하거나 사용하지 않고 비밀 업데이트 및 삭제를 테스트하려면**

1. 다음 IAM 사용자 중 한 명으로 로그인합니다.
   + `access-Arnav-peg-eng`
   + `access-Mary-peg-qas`
   + `access-Saanvi-uni-eng`
   + `access-Carlos-uni-qas`
   + `access-Nikhil-cen-eng`

1. 일치하는 역할로 전환합니다.
   + `access-peg-engineering`
   + `access-peg-quality-assurance`
   + `access-uni-engineering`
   + `access-peg-quality-assurance`
   + `access-cen-engineering`

   AWS Management Console에서의 역할 전환에 대한 자세한 내용은 [사용자에서 IAM 역할로 전환(콘솔)](id_roles_use_switch-role-console.md) 단원을 참조하십시오.

1. 각 역할에 대해 비밀 설명을 업데이트하고 다음 비밀을 삭제해봅니다. 자세한 내용은 *AWS Secrets Manager 사용 설명서*의 [보안 암호 수정](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_update-secret.html)과 [Deleting and Restoring a Secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_delete-restore-secret.html)(보안 암호 삭제 및 복원)을 참조하세요.

   다음 표는 각 역할의 ABAC 비밀 업데이트 및 삭제 동작을 보여줍니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)

## 요약
<a name="tutorial-abac-summary"></a>

이제 속성 기반 액세스 제어(ABAC)에 태그를 사용하는 데 필요한 모든 단계를 성공적으로 완료했습니다. 태그 지정 전략을 정의하는 방법을 배웠습니다. 보안 주체와 리소스에 해당 전략을 적용했습니다. Secrets Manager에 대한 전략을 적용하는 정책을 생성하고 적용했습니다. 또한 새 프로젝트 및 팀 멤버를 추가할 때 ABAC가 쉽게 확장된다는 사실을 알게 되었습니다. 따라서 테스트 역할을 사용하여 IAM 콘솔에 로그인하고 AWS에서 ABAC에 대한 태그를 사용하는 방법을 경험할 수 있습니다.

**참고**  
특정 조건에서만 작업을 허용하는 정책을 추가했습니다. 더 광범위한 권한을 가진 사용자 또는 역할에 다른 정책을 적용하는 경우, 작업에서 태그 지정이 필요하도록 제한을 받지 않을 수 있습니다. 예를 들어 `AdministratorAccess` AWS 관리형 정책을 사용하여 사용자에게 전체 관리 권한을 부여하는 경우, 이러한 정책은 해당 액세스를 제한하지 않습니다. 여러 정책이 적용될 때 권한이 결정되는 방법에 대한 자세한 내용은 [AWS 적용 코드 로직이 액세스 허용 또는 거부 요청을 평가하는 방법](reference_policies_evaluation-logic_policy-eval-denyallow.md) 단원을 참조하십시오.

## 관련 리소스
<a name="tutorial_abac_related"></a>

관련 내용은 다음 리소스를 참조하십시오.
+ [ABAC 권한 부여를 통한 속성 기반 권한 정의](introduction_attribute-based-access-control.md)
+ [AWS 글로벌 조건 컨텍스트 키](reference_policies_condition-keys.md)
+ [IAM 사용자에게 권한을 부여할 역할 생성](id_roles_create_for-user.md)
+ [AWS Identity and Access Management 리소스용 태그](id_tags.md)
+ [태그를 사용한 AWS 리소스 액세스 제어](access_tags.md)
+ [사용자에서 IAM 역할로 전환(콘솔)](id_roles_use_switch-role-console.md)
+ [IAM 튜토리얼: ABAC에 SAML 세션 태그 사용](tutorial_abac-saml.md)

계정의 태그를 모니터링하는 방법을 알아보려면 [서버리스 워크플로 및 Amazon CloudWatch Events를 사용하여 AWS에서 리소스 태그 변경 모니터링](https://aws.amazon.com/blogs/mt/monitor-tag-changes-on-aws-resources-with-serverless-workflows-and-amazon-cloudwatch-events/)을 참조하세요.

# IAM 튜토리얼: ABAC에 SAML 세션 태그 사용
<a name="tutorial_abac-saml"></a>

속성 기반 액세스 제어(ABAC)는 속성에 근거하여 권한을 정의하는 권한 부여 전략입니다. AWS에서는 이러한 속성을 태그라고 합니다. IAM 엔터티(사용자 또는 역할)와 AWS 리소스에 태그를 연결할 수 있습니다. 엔터티를 사용하여 AWS에 요청하면 해당 엔터티가 보안 주체가 되고 해당 보안 주체에 태그가 포함됩니다.

역할을 맡거나 사용자를 연동할 때 [세션 태그](id_session-tags.md)를 전달할 수도 있습니다. 그런 다음 태그 조건 키를 사용하여 해당 태그를 기반으로 보안 주체에 권한을 부여하는 정책을 정의할 수 있습니다. 태그를 사용하여 AWS 리소스에 대한 액세스를 제어하면 AWS 정책에 대한 변경 사항이 줄어들면서 팀과 리소스가 성장할 수 있습니다. ABAC 정책은 각 개별 리소스를 나열해야 하는 기존 AWS 정책보다 유연합니다. ABAC에 대한 자세한 내용 및 기존 정책과 비교할 때의 이점은 [ABAC 권한 부여를 통한 속성 기반 권한 정의](introduction_attribute-based-access-control.md) 단원을 참조하십시오.

회사에서 SAML 기반 자격 증명 공급자(IdP)를 사용하여 회사 사용자 자격 증명을 관리하는 경우 AWS에서 SAML 속성을 사용하여 세밀한 액세스 제어를 수행할 수 있습니다. 속성에는 비용 센터 식별자, 사용자 이메일 주소, 부서 분류 및 프로젝트 할당이 포함될 수 있습니다. 이러한 속성을 세션 태그로 전달하면 이러한 세션 태그를 기반으로 AWS에 대한 액세스를 제어할 수 있습니다.

세션 보안 주체에 SAML 속성을 전달하여 [ABAC 자습서](tutorial_attribute-based-access-control.md)를 완료하려면 이 주제에 포함된 변경 사항을 사용하여 [IAM 튜토리얼: 태그를 기반으로 AWS 리소스에 액세스할 수 있는 권한 정의](tutorial_attribute-based-access-control.md)의 작업을 완료합니다.

## 사전 조건
<a name="tutorial_abac-saml-prerequisites"></a>

ABAC에 대해 SAML 세션 태그를 사용하는 단계를 수행하려면 다음 사항이 이미 있어야 합니다.
+ 특정 속성을 가진 테스트 사용자를 생성할 수 있는 SAML 기반 IdP에 대한 액세스 
+ 관리 권한이 있는 사용자로 로그인하는 기능.
+ AWS Management Console에서 IAM 사용자, 역할 및 정책을 생성 및 편집해 본 경험. 그러나 IAM 관리 프로세스를 기억해야 하는 경우를 위해 ABAC 튜토리얼에서는 단계별 지침을 볼 수 있는 링크를 제공합니다.
+ IAM에서 SAML 기반 IdP를 설정해 본 경험. 자세한 내용과 자세한 IAM 설명서에 대한 링크를 보려면 [AssumeRoleWithSAML을 사용하여 세션 태그 전달](id_session-tags.md#id_session-tags_adding-assume-role-saml) 섹션을 참조하세요.

## 1단계: 테스트 사용자 생성
<a name="tutorial_abac-saml-step1"></a>

[1단계: 테스트 사용자 생성](tutorial_attribute-based-access-control.md#tutorial_abac_step1)의 지침을 건너뜁니다. 자격 증명은 공급자에 정의되어 있으므로 직원에 대한 IAM 사용자를 추가할 필요는 없습니다.

## 2단계: ABAC 정책 생성
<a name="tutorial_abac-saml-step2"></a>

[2단계: ABAC 정책 생성](tutorial_attribute-based-access-control.md#tutorial_abac_step2)의 지침에 따라 IAM에서 지정된 관리형 정책을 생성합니다.

## 3단계: SAML 역할 생성 및 구성
<a name="tutorial_abac-saml-step3"></a>

SAML용 ABAC 자습서를 사용하는 경우 역할을 생성하고, SAML IdP를 구성하고, AWS Management Console 액세스를 활성화하기 위한 추가 단계를 수행해야 합니다. 자세한 내용은 [3단계: 역할 생성](tutorial_attribute-based-access-control.md#tutorial_abac_step3) 섹션을 참조하세요.

### 3A단계: SAML 역할 생성
<a name="tutorial_abac-saml-step3a"></a>

SAML 자격 증명 공급자 및 1단계에서 생성한 `test-session-tags` 사용자를 신뢰하는 단일 역할을 생성합니다. ABAC 자습서에서는 역할 태그가 서로 다른 별도의 역할을 사용합니다. SAML IdP에서 세션 태그를 전달하기 때문에 역할은 하나만 필요합니다. SAML 기반 역할을 생성하는 방법은 [SAML 2.0 페더레이션을 위한 역할 생성(콘솔)](id_roles_create_for-idp_saml.md) 단원을 참조하십시오.

역할 이름을 `access-session-tags`로 지정합니다. 역할에 `access-same-project-team` 권한 정책을 연결합니다. 다음 정책을 사용하도록 역할 신뢰 정책을 편집합니다. 역할의 신뢰 관계를 편집하는 방법에 대한 자세한 지침은 [역할 트러스트 정책 업데이트](id_roles_update-role-trust-policy.md) 단원을 참조하십시오.

다음 역할 신뢰 정책은 SAML 자격 증명 공급자 및 `test-session-tags` 사용자가 역할을 맡을 수 있도록 허용합니다. 역할을 맡을 때는 세 개의 지정된 세션 태그를 전달해야 합니다. 이 `sts:TagSession` 작업은 세션 태그 전달을 허용하는 데 필요합니다.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowSamlIdentityAssumeRole",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRoleWithSAML",
                "sts:TagSession"
            ],
            "Principal": {"Federated":"arn:aws:iam::123456789012:saml-provider/ExampleCorpProvider"},
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/cost-center": "*",
                    "aws:RequestTag/access-project": "*",
                    "aws:RequestTag/access-team": [
                        "eng",
                        "qas"
                    ]
                },
                "StringEquals": {"SAML:aud": "https://signin.aws.amazon.com/saml"}
            }
        }
    ]
}
```

------

이 `AllowSamlIdentityAssumeRole` 문을 사용하면 엔지니어링 및 품질 보증 팀의 멤버가 Example Corporation IdP에서 AWS로 연동될 때 이 역할을 맡을 수 있습니다. `ExampleCorpProvider` SAML 공급자는 IAM에 정의되어 있습니다. 관리자가 세 개의 필수 세션 태그를 전달하도록 SAML 어설션을 이미 설정했습니다. 어설션에서 추가 태그를 전달할 수 있지만 이 세 가지 태그는 반드시 있어야 합니다. 자격 증명의 속성은 `cost-center` 및 `access-project` 태그에 대한 값을 가질 수 있습니다. 그러나 자격 증명이 엔지니어링 또는 품질 보증 팀에 속한다는 것을 나타내려면 `access-team` 속성 값이 `eng` 또는 `qas`와 일치해야 합니다.

### 3B단계: SAML IdP 구성
<a name="tutorial_abac-saml-step3b"></a>

`cost-center`, `access-project` 및 `access-team` 속성을 세션 태그로 전달하도록 SAML IdP를 구성합니다. 자세한 내용은 [AssumeRoleWithSAML을 사용하여 세션 태그 전달](id_session-tags.md#id_session-tags_adding-assume-role-saml) 섹션을 참조하세요.

이러한 속성을 세션 태그로 전달하려면 SAML 어설션에 다음 요소를 포함합니다.

```
<Attribute Name="https://aws.amazon.com/SAML/Attributes/PrincipalTag:cost-center">
  <AttributeValue>987654</AttributeValue>
</Attribute>
<Attribute Name="https://aws.amazon.com/SAML/Attributes/PrincipalTag:access-project">
  <AttributeValue>peg</AttributeValue>
</Attribute>
<Attribute Name="https://aws.amazon.com/SAML/Attributes/PrincipalTag:access-team">
  <AttributeValue>eng</AttributeValue>
</Attribute>
```

### 3C 단계: 콘솔 액세스 활성화
<a name="tutorial_abac-saml-step3b"></a>

페더레이션 SAML 사용자에 대해 콘솔 액세스를 활성화합니다. 자세한 내용은 [SAML 2.0 페더레이션 위탁자의 AWS Management Console 액세스 활성화](id_roles_providers_enable-console-saml.md) 섹션을 참조하세요.

## 4단계: 비밀 생성 테스트
<a name="tutorial_abac-saml-step4"></a>

`access-session-tags` 역할을 사용하여 AWS Management Console에 연동합니다. 자세한 내용은 [SAML 2.0 페더레이션 위탁자의 AWS Management Console 액세스 활성화](id_roles_providers_enable-console-saml.md) 섹션을 참조하세요. 그런 다음 [4단계: 비밀 생성 테스트](tutorial_attribute-based-access-control.md#tutorial_abac_step4)의 지침에 따라 비밀을 생성합니다. 다양한 SAML 자격 증명을 속성과 함께 사용하여 ABAC 자습서에 표시된 태그와 일치시킵니다. 자세한 내용은 [4단계: 비밀 생성 테스트](tutorial_attribute-based-access-control.md#tutorial_abac_step4) 섹션을 참조하세요.

## 5단계: 비밀 보기 테스트
<a name="tutorial_abac-saml-step5"></a>

[5단계: 비밀 보기 테스트](tutorial_attribute-based-access-control.md#tutorial_abac_step5) 단원의 지침에 따라 이전 단계에서 생성한 비밀을 확인합니다. 다양한 SAML 자격 증명을 속성과 함께 사용하여 ABAC 자습서에 표시된 태그와 일치시킵니다.

## 6단계: 테스트 확장성
<a name="tutorial_abac-saml-step6"></a>

[6단계: 테스트 확장성](tutorial_attribute-based-access-control.md#tutorial_abac_step6) 단원의 지침에 따라 확장성을 테스트합니다. 다음 속성을 사용하여 SAML 기반 IdP에 새 자격 증명을 추가하면 됩니다.
+ `cost-center = 101010`
+ `access-project = cen`
+ `access-team = eng`

## 7단계: 비밀 업데이트 및 삭제 테스트
<a name="tutorial_abac-saml-step7"></a>

[7단계: 비밀 업데이트 및 삭제 테스트](tutorial_attribute-based-access-control.md#tutorial_abac_step7) 단원의 지침에 따라 비밀을 업데이트 및 삭제합니다. 다양한 SAML 자격 증명을 속성과 함께 사용하여 ABAC 자습서에 표시된 태그와 일치시킵니다.

**중요**  
요금이 청구되지 않도록 생성한 모든 비밀을 삭제합니다. Secrets Manager의 요금에 대한 자세한 내용은 [AWS Secrets Manager 요금](https://aws.amazon.com/secrets-manager/pricing/)을 참조하세요.

## 요약
<a name="tutorial-abac-saml-summary"></a>

이제 권한 관리를 위해 SAML 세션 태그 및 리소스 태그를 사용하는 데 필요한 모든 단계를 성공적으로 완료했습니다.

**참고**  
특정 조건에서만 작업을 허용하는 정책을 추가했습니다. 더 광범위한 권한을 가진 사용자 또는 역할에 다른 정책을 적용하는 경우, 작업에서 태그 지정이 필요하도록 제한을 받지 않을 수 있습니다. 예를 들어 `AdministratorAccess` AWS 관리형 정책을 사용하여 사용자에게 전체 관리 권한을 부여하는 경우, 이러한 정책은 해당 액세스를 제한하지 않습니다. 여러 정책이 적용될 때 권한이 결정되는 방법에 대한 자세한 내용은 [AWS 적용 코드 로직이 액세스 허용 또는 거부 요청을 평가하는 방법](reference_policies_evaluation-logic_policy-eval-denyallow.md) 단원을 참조하십시오.

# IAM 자습서: 사용자가 자신의 자격 증명 및 MFA 설정을 관리하도록 허용
<a name="tutorial_users-self-manage-mfa-and-creds"></a>

사용자가 **보안 인증** 페이지에서 자신의 다중 인증(MFA) 디바이스와 보안 인증을 스스로 관리하도록 허가할 수 있습니다. AWS Management Console을 사용해 보안 인증(액세스 키, 암호, 서명 인증서 및 SSH 퍼블릭 키)을 구성하거나 필요하지 않은 보안 인증을 삭제 또는 비활성화하거나 사용자에 대해 MFA 디바이스를 활성화할 수 있습니다. 이 작업은 소수의 사용자에게는 유용하지만 사용자 수가 증가하면 곧 작업에 너무 많은 시간이 소요될 수 있습니다. 이 자습서에서는 관리자에게 부담을 주지 않으면서 이러한 모범 사례를 활성화하는 방법을 보여 줍니다.

이 자습서에서는 사용자가 MFA를 사용하여 로그인하는 **경우에만** AWS 서비스에 액세스할 수 있도록 허용하는 방법을 보여 줍니다. MFA 디바이스에 로그인하지 않으면 사용자가 다른 서비스에 액세스할 수 없습니다.

이 워크플로우는 세 가지 기본 단계로 이루어집니다.

**[1단계: MFA 로그인을 강제할 정책 생성](#tutorial_mfa_step1)**  
소량의 IAM 작업을 ***제외하고*** 모든 작업을 금지하는 고객 관리형 정책을 생성합니다. 이러한 예외는 사용자가 **보안 인증** 페이지에서 자신의 보안 인증을 변경하고 MFA 디바이스를 관리할 수 있도록 허용합니다. 해당 페이지에 액세스하는 방법에 대한 자세한 내용은 [IAM 사용자가 자신의 암호를 변경하는 방법(콘솔)](id_credentials_passwords_user-change-own.md#ManagingUserPwdSelf-Console) 단원을 참조하세요.

**[2단계: 테스트 사용자 그룹에 정책 연결](#tutorial_mfa_step2)**  
멤버가 MFA로 로그인한 경우 해당 멤버에게 모든 Amazon EC2 작업의 전체 액세스 권한을 부여한 사용자 그룹을 생성합니다. 이러한 사용자 그룹을 생성하려면 `AmazonEC2FullAccess`라는 AWS 관리형 정책과 1단계에서 생성한 고객 관리형 정책을 모두 연결합니다.

**[3단계: 사용자 액세스 테스트](#tutorial_mfa_step3)**  
테스트 사용자로 로그인하여 사용자가 MFA 디바이스를 *생성할 때까지* Amazon EC2에 대한 액세스가 차단되는지 확인합니다. 그런 다음 사용자는 해당 디바이스를 사용하여 로그인할 수 있습니다.

## 사전 조건
<a name="tutorial_mfa_prereqs"></a>

이 자습서의 단계를 수행하려면 다음이 준비되어 있어야 합니다.
+ 관리 권한을 가진 IAM 사용자로 로그인할 수 있는 AWS 계정.
+ 1단계에서 정책에 입력한 계정 ID 번호.

  계정 ID 번호를 찾으려면 페이지 상단의 탐색 표시줄에서 **지원**을 선택한 후 **지원 센터**를 선택합니다. 이 페이지의 **지원** 메뉴에서 계정 ID를 찾을 수 있습니다.
+ [가상(소프트웨어 기반) MFA 디바이스](id_credentials_mfa_enable_virtual.md), [FIDO 보안 키](id_credentials_mfa_enable_fido.md) 또는 [하드웨어 기반 MFA 디바이스](id_credentials_mfa_enable_physical.md).
+ 다음과 같은 사용자 그룹의 멤버인 테스트 IAM 사용자:


| 사용자 이름 | 사용자 이름 지침 | 사용자 그룹 이름 | 사용자를 멤버로 추가 | 사용자 그룹 지침 | 
| --- | --- | --- | --- | --- | 
| MFAUser | 콘솔 액세스 활성화 – 선택사항 옵션만 선택하고 암호를 지정합니다. | EC2MFA | MFAUser | 이 사용자 그룹에 정책을 연결하거나 권한을 부여하지 마세요. | 

## 1단계: MFA 로그인을 강제할 정책 생성
<a name="tutorial_mfa_step1"></a>

IAM 사용자가 자신의 자격 증명과 MFA 디바이스를 관리하는 데 필요한 권한을 제외한 모든 권한을 거부하는 IAM 고객 관리형 정책을 생성하는 것부터 시작합니다.

1. 관리자 자격 증명을 가진 사용자로 AWS 관리 콘솔에 로그인합니다. IAM 모범 사례를 준수하려면 AWS 계정 루트 사용자 자격 증명을 사용하여 로그인하지 마세요.
**중요**  
 IAM [모범 사례](best-practices.md)는 장기 보안 인증 정보가 있는 IAM 사용자를 사용하는 대신, 인간 사용자가 자격 증명 공급자와의 페더레이션을 사용하여 임시 보안 인증으로 AWS에 액세스하도록 하는 것입니다. 페더레이션 사용자가 지원하지 않는 [특정 사용 사례](gs-identities-iam-users.md)에는 IAM 사용자만 사용하는 것이 좋습니다.

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

   

1. 탐색 창에서 **정책**을 선택한 후 **정책 생성**을 선택합니다.

1. **JSON** 탭을 선택하고 다음 JSON 정책 문서에서 텍스트를 복사합니다. [AWS: MFA 인증 IAM 사용자가 보안 인증 페이지에서 자신의 보안 인증을 관리할 수 있도록 허용](reference_policies_examples_aws_my-sec-creds-self-manage.md) 

1. 이 텍스트를 **JSON** 텍스트 상자에 붙여넣습니다. 정책 검증 동안 생성된 모든 보안 경고, 오류 또는 일반 경고를 해결하고 **다음**을 선택합니다.
**참고**  
언제든지 **시각적** 편집기 옵션과 **JSON** 옵션을 서로 전환할 수 있습니다. 그러나 위의 정책에는 시각적 편집기에서 사용할 수 없는 `NotAction` 요소가 포함되어 있습니다. **시각적 편집기** 탭에 이 정책에 대한 알림 메시지가 표시됩니다. 이 정책으로 작업을 계속하려면 **JSON**으로 돌아가세요.  
이 정책 예시에서는 사용자가 처음으로 AWS Management Console에 로그인하는 동안 암호 재설정을 허용하지 않습니다. 새 사용자가 로그인하고 암호를 재설정할 때까지 새 사용자에게 권한을 부여하지 않는 것이 좋습니다.

1. **검토 및 생성** 페이지에서 정책 이름에 **Force\$1MFA**을 입력합니다. 정책 설명에 **This policy allows users to manage their own passwords and MFA devices but nothing else unless they authenticate with MFA.**를 입력합니다. **태그** 영역에서 원한다면 고객 관리형 정책에 대한 태그 키-값 페어를 추가할 수 있습니다. 정책이 부여한 권한을 검토한 다음 **정책 생성**을 선택하여 작업을 저장합니다.

   새로운 정책이 관리형 정책 목록에 나타나며 연결 준비가 완료됩니다.

## 2단계: 테스트 사용자 그룹에 정책 연결
<a name="tutorial_mfa_step2"></a>

그런 다음 MFA 보호 권한을 부여하는 데 사용할 테스트 IAM 사용자 그룹에 두 개의 정책을 연결합니다.

1. 탐색 창에서 **사용자 그룹(User groups)**을 선택합니다.

1. 검색 상자에 **`EC2MFA`**를 입력하고 목록에서 그룹 이름(확인란 아님)을 선택하세요.

1. **권한** 탭을 선택하고 **권한 추가**, **정책 연결**을 차례로 선택합니다.

1. **EC2MFA 그룹에 권한 정책 연결(Attach permission policies to EC2MFA group)** 페이지의 검색 상자에 **EC2Full**을 입력합니다. 그런 다음 목록에서 **AmazonEC2FullAccess** 옆의 확인란을 선택하세요. 변경 내용을 저장하지 마세요.

1. 검색 상자에 **Force**를 입력한 다음, 목록에서 **Force\$1MFA** 옆에 있는 확인란을 선택하세요.

1. **정책 연결**을 선택합니다.

## 3단계: 사용자 액세스 테스트
<a name="tutorial_mfa_step3"></a>

자습서의 이 부분에서는 테스트 사용자로 로그인하여 정책이 의도한 대로 작동하는지 검증합니다.

1. 이전 섹션에서 할당한 암호를 사용해 **MFAUser**로 AWS 계정에 로그인합니다. URL은 `https://<alias or account ID number>.signin.aws.amazon.com/console`을 사용합니다.

1. **EC2**를 선택해 Amazon EC2 콘솔을 열고 사용자에게 어떤 권한도 없는지 확인합니다.

1. 오른쪽 상단의 탐색 모음에서 `MFAUser` 사용자 이름을 선택한 다음 **Security credentials**(보안 자격 증명)를 선택합니다.  
![\[AWS Management Console 보안 인증 정보 링크.\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/images/security-credentials-user.shared.console.png)

1. 이제 MFA 디바이스를 추가합니다. **Multi-Factor Authentication (MFA)** 섹션에서 **MFA 디바이스 할당**을 선택합니다.
**참고**  
`iam:DeleteVirtualMFADevice` 수행 권한이 없다는 오류가 표시될 수 있습니다. 이는 이전에 다른 누군가가 가상 MFA 디바이스를 사용자에게 할당하기 시작했다가 프로세스를 취소한 경우 발생할 수 있습니다. 계속 진행하려면 사용자 또는 다른 관리자가 사용자의 기존 할당되지 않은 가상 MFA 디바이스를 삭제해야 합니다. 자세한 내용은 [iam:DeleteVirtualMFADevice를 수행할 권한이 없음](troubleshoot.md#troubleshoot_general_access-denied-delete-mfa) 단원을 참조하세요.

1. 이 자습서의 경우 휴대폰의 Google Authenticator 앱과 같은 가상(소프트웨어 기반) MFA 디바이스를 사용합니다. **Authenticator app**(인증 앱)을 선택하고 **Next**(다음)를 클릭합니다.

   IAM은 QR 코드 그래픽을 포함하여 가상 MFA 디바이스의 구성 정보를 생성 및 표시합니다. 그래픽은 QR 코드를 지원하지 않는 디바이스 상에서 수동 입력할 수 있는 보안 구성 키를 표시한 것입니다.

1. 가상 MFA 앱을 엽니다. (가상 MFA 디바이스의 호스팅에 사용되는 앱 목록은 [가상 MFA 애플리케이션](https://aws.amazon.com/iam/details/mfa/#Virtual_MFA_Applications)을 참조하십시오) 가상 MFA 앱이 다수의 계정(다수의 가상 MFA 디바이스)을 지원하는 경우 옵션을 선택하여 새로운 계정(새로운 가상 MFA 디바이스)을 생성합니다.

1. MFA 앱의 QR 코드 지원 여부를 결정한 후 다음 중 한 가지를 실행합니다.
   + 마법사에서 **Show QR code(QR 코드 표시)**를 선택합니다. 그런 다음 앱을 사용하여 QR 코드를 스캔합니다. 예를 들어 카메라 모양의 아이콘을 선택하거나 **코드 스캔(Scan code)**과 비슷한 옵션을 선택한 다음, 디바이스의 카메라를 사용하여 코드를 스캔합니다.
   + **Set up device**(디바이스 설정) 마법사에서 **Show secret key**(보안 키 표시)를 선택한 다음 MFA 앱에 보안 키를 입력합니다.

   모든 작업을 마치면 가상 MFA 디바이스가 일회용 암호 생성을 시작합니다.

1. **Set up device**(디바이스 설정) 마법사의 **Enter the code from your authenticator app.**(Authenticator 앱에서 코드 입력) 상자에 현재 가상 MFA 디바이스에 표시된 일회용 암호를 입력합니다. **Register MFA**(Register MFA)를 선택합니다.
**중요**  
코드를 생성한 후 즉시 요청을 제출하세요. 코드를 생성하고 너무 오래 시간이 지난 후 요청을 제출하면 MFA 디바이스가 사용자와 연결은 되지만 MFA 디바이스가 동기화되지 않습니다. 이는 시간 기반 일회용 암호(TOTP)가 잠시 후에 만료되기 때문입니다. 이 경우, [디바이스를 재동기화](id_credentials_mfa_sync.md)할 수 있습니다.

   이제 AWS에서 가상 MFA 디바이스를 사용할 준비를 마쳤습니다.

1. 콘솔에서 로그아웃한 다음, **MFAUser**로 다시 로그인합니다. 이번에는 AWS가 휴대전화로 받은 MFA 코드를 입력하도록 요청합니다. 코드를 받아 상자에 입력한 후 **전송**을 선택합니다.

1. **EC2**를 선택하여 Amazon EC2 콘솔을 다시 엽니다. 이번에는 모든 정보를 볼 수 있으며 원하는 작업은 모두 수행할 수 있습니다. 이 사용자로 다른 콘솔로 이동하면 액세스 거부 메시지가 표시됩니다. 그 이유는 이 튜토리얼의 정책에서 Amazon EC2에 대해서만 액세스 권한을 부여하기 때문입니다.

## 관련 리소스
<a name="tutorial_mfa_related"></a>

추가 정보는 다음 주제를 참조하세요.
+ [IAM의 AWS 다중 인증](id_credentials_mfa.md)
+ [MFA 지원 로그인](console_sign-in-mfa.md)

# IAM 자습서: CloudFormation 템플릿을 사용하여 SAML ID 제공업체(idP) 생성
<a name="tutorial_saml-idp"></a>

AWS 계정에 대한 SAML 페더레이션을 설정하려면 SAML ID 제공업체(idP)를 생성해야 합니다. 이 자습서에서는 CloudFormation 템플릿을 사용하여 AWS와 외부 IdP 간에 신뢰를 설정하는 SAML IdP를 생성하는 방법을 보여줍니다.

이 템플릿은 IdP의 메타데이터 문서로 구성된 SAML IdP를 생성합니다. 그러면 페더레이션 IAM 역할이 이 IdP를 참조하여 외부 IdP의 인증된 사용자가 AWS 리소스에 액세스할 수 있도록 허용합니다.

배포된 리소스는 IdP의 메타데이터 문서와 선택적 암호화 설정으로 구성된 SAML IdP로 이루어져 있습니다.

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

이 자습서에서는 다음을 이미 완료했다고 가정합니다.
+ 이 자습서에서 IdP의 SAML 메타데이터 XML 파일의 형식을 지정하는 데 사용되는 Python 명령을 실행할 수 있도록 로컬 시스템에 설치된 Python 3.6 이상 버전.
+ XML 파일로 저장된 외부 IdP의 SAML 메타데이터 문서.

## CloudFormation을 사용하여 SAML IdP 생성
<a name="tutorial_saml-idp-create"></a>

SAML IdP를 생성하려면 CloudFormation 템플릿을 생성하고 이를 사용하여 IdP 리소스가 포함된 스택을 생성합니다.

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

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

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

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

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

### 스택 생성
<a name="tutorial_saml-idp-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. **IdentityProviderName**의 경우 이 값을 비워 두어 스택 이름을 기반으로 이름을 자동 생성하거나, SAML IdP의 사용자 지정 이름을 입력할 수 있습니다. 사용자 지정 이름에는 영숫자, 마침표, 밑줄, 하이픈만 포함할 수 있습니다.

   1. **IdentityProviderSAMLMetadataDocument**의 경우 이 필드에 붙여 넣기 전에 SAML 메타데이터 XML 파일의 형식을 한 줄로 지정해야 합니다. 이렇게 해야 하는 이유는 CloudFormation 콘솔에서 콘솔 파라미터를 전달할 때 XML 콘텐츠의 형식을 한 줄로 지정해야 하기 때문입니다.

      아래의 Python 명령을 사용하여 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
      ```
**참고**  
IdP의 SAML 메타데이터 문서는 콘솔 파라미터 입력을 위해 한 줄로 형식을 지정해야 합니다. Python 명령은 줄 바꿈과 추가 공백을 제거하여 모든 원본 콘텐츠와 구조를 그대로 유지하면서 필요한 형식을 생성합니다.

      Python 명령에서 출력을 복사한 후 이를 **IdentityProviderSAMLMetadataDocument** 필드에 붙여 넣습니다.

      형식이 지정된 SAML 메타데이터 문서의 예시(간략화함):

      ```
      <?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>
      ```

   1. 다른 파라미터의 경우 기본값을 적용하거나, 요구 사항에 따라 직접 입력합니다.
      + **IdentityProviderAddPrivateKey** - SAML 어설션의 암호 해독을 위한 선택적 프라이빗 키
      + **IdentityProviderAssertionEncryptionMode** - 선택 사항, SAML 어설션에 대한 암호화 모드 설정(허용됨, 필수 또는 비어 있음)

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

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

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

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

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

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

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

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

스택은 **출력** 탭에서 볼 수 있는 다음과 같은 값을 출력합니다.
+ **ProviderARN**: 생성된 SAML IdP의 ARN(예: `arn:aws:iam::123456789012:saml-provider/CompanyIdP`). 이 제공업체를 신뢰하는 역할을 생성할 경우 이 ARN이 필요합니다.
+ **ProviderName**: 생성된 SAML IdP의 이름(예: 사용자 지정 이름을 지정한 경우 `CompanyIdP`, 또는 기본 이름을 사용한 경우 `my-saml-stack-saml-provider`).

이러한 출력도 내보내므로, `Fn::ImportValue` 함수를 사용하여 이를 다른 CloudFormation 스택에서 가져올 수 있습니다.

## SAML IdP 확인
<a name="tutorial_saml-idp-using"></a>

SAML IdP가 생성되면 구성을 확인하고 페더레이션 역할과 함께 사용할 ARN을 기록할 수 있습니다.

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

1. 탐색 창에서 [**자격 증명 공급자(Identity providers)**]를 선택합니다.

   새로 생성된 SAML IdP가 목록에 표시됩니다.

1. 세부 정보를 보려면 IdP 이름을 선택합니다.

   IdP 세부 정보 페이지에서 SAML 메타데이터 문서 및 기타 구성 세부 정보를 볼 수 있습니다.

1. 세부 정보 페이지에 표시된 **공급자 ARN**을 기록해 둡니다.

   이 IdP를 신뢰하는 페더레이션 IAM 역할을 생성할 경우 이 ARN이 필요합니다.

1. 메타데이터 문서를 검토하여 외부 IdP에서 제공한 것과 일치하는지 확인합니다.

이제 SAML IdP를 페더레이션 IAM 역할에서 사용할 준비가 되었습니다. 이 IdP를 신뢰하는 역할을 생성하면 외부 IdP의 인증된 사용자가 이러한 역할을 수임하고 AWS 리소스에 액세스할 수 있습니다.

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

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

1. CloudFormation 콘솔을 엽니다.

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

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

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

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

이 자습서에서 CloudFormation 템플릿은 계정에 다음과 같은 리소스를 생성합니다.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-samlprovider.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-samlprovider.html): AWS와 외부 IdP 간에 신뢰를 설정하는 SAML IdP입니다.

### 구성
<a name="tutorial_saml-idp-template-config"></a>

템플릿에는 다음과 같은 구성 가능한 파라미터가 포함되어 있습니다.
+ **IdentityProviderName** - SAML IdP의 이름(자동 생성된 이름의 경우 비워둠)

  예: `CompanyIdP` 또는 `EnterpriseSSO`
+ **IdentityProviderSAMLMetadataDocument** - 외부 IdP의 SAML 메타데이터 문서(한 줄 형식)
+ **IdentityProviderAddPrivateKey** - SAML 어설션의 암호 해독을 위한 선택적 프라이빗 키
+ **IdentityProviderAssertionEncryptionMode** - 선택 사항, SAML 어설션에 대한 암호화 모드 설정

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

아래의 JSON 또는 YAML 코드를 별도의 파일로 저장하여 이 자습서의 CloudFormation 템플릿으로 사용하세요.

------
#### [ JSON ]

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "[AWSDocs] IAM: tutorial_saml-idp",
  "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"]
    }
  },
  "Conditions": {
    "HasPrivateKey": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderAddPrivateKey"}, ""]}]},
    "HasEncryptionMode": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderAssertionEncryptionMode"}, ""]}]},
    "HasCustomName": {"Fn::Not": [{"Fn::Equals": [{"Ref": "IdentityProviderName"}, ""]}]}
  },
  "Resources": {
    "SAMLProvider": {
      "Type": "AWS::IAM::SAMLProvider",
      "Properties": {
        "Name": {"Fn::If": ["HasCustomName", {"Ref": "IdentityProviderName"}, {"Ref": "AWS::NoValue"}]},
        "SamlMetadataDocument": {"Ref": "IdentityProviderSAMLMetadataDocument"},
        "Tags": [
          {
            "Key": "Name",
            "Value": {"Fn::If": ["HasCustomName", {"Ref": "IdentityProviderName"}, {"Fn::Sub": "${AWS::StackName}-saml-provider"}]}
          }
        ],
        "AddPrivateKey": {"Fn::If": ["HasPrivateKey", {"Ref": "IdentityProviderAddPrivateKey"}, {"Ref": "AWS::NoValue"}]},
        "AssertionEncryptionMode": {"Fn::If": ["HasEncryptionMode", {"Ref": "IdentityProviderAssertionEncryptionMode"}, {"Ref": "AWS::NoValue"}]}
      }
    }
  },
  "Outputs": {
    "ProviderARN": {
      "Description": "ARN of the created SAML Identity Provider",
      "Value": {"Ref": "SAMLProvider"},
      "Export": {
        "Name": {"Fn::Sub": "${AWS::StackName}-ProviderARN"}
      }
    },
    "ProviderName": {
      "Description": "Name of the SAML Identity Provider",
      "Value": {"Fn::If": ["HasCustomName", {"Ref": "IdentityProviderName"}, {"Fn::Sub": "${AWS::StackName}-saml-provider"}]},
      "Export": {
        "Name": {"Fn::Sub": "${AWS::StackName}-ProviderName"}
      }
    }
  }
}
```

------
#### [ YAML ]

```
AWSTemplateFormatVersion: '2010-09-09'
Description: '[AWSDocs] IAM: tutorial_saml-idp'

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"

Conditions:
  HasPrivateKey: !Not [!Equals [!Ref IdentityProviderAddPrivateKey, ""]]
  HasEncryptionMode: !Not [!Equals [!Ref IdentityProviderAssertionEncryptionMode, ""]]
  HasCustomName: !Not [!Equals [!Ref IdentityProviderName, ""]]

Resources:
  SAMLProvider:
    Type: 'AWS::IAM::SAMLProvider'
    Properties:
      Name: !If
        - HasCustomName
        - !Ref IdentityProviderName
        - !Ref AWS::NoValue
      SamlMetadataDocument: !Ref IdentityProviderSAMLMetadataDocument
      Tags:
        - Key: Name
          Value: !If
            - HasCustomName
            - !Ref IdentityProviderName
            - !Sub '${AWS::StackName}-saml-provider'
      AddPrivateKey: !If
        - HasPrivateKey
        - !Ref IdentityProviderAddPrivateKey
        - !Ref AWS::NoValue
      AssertionEncryptionMode: !If
        - HasEncryptionMode
        - !Ref IdentityProviderAssertionEncryptionMode
        - !Ref AWS::NoValue

Outputs:
  ProviderARN:
    Description: 'ARN of the created SAML Identity Provider'
    Value: !Ref SAMLProvider
    Export:
      Name: !Sub '${AWS::StackName}-ProviderARN'
  
  ProviderName:
    Description: 'Name of the SAML Identity Provider'
    Value: !If
      - HasCustomName
      - !Ref IdentityProviderName
      - !Sub '${AWS::StackName}-saml-provider'
    Export:
      Name: !Sub '${AWS::StackName}-ProviderName'
```

------

# 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'
```

------

# IAM 자습서: CloudFormation 템플릿을 사용하여 SAML ID 제공업체(idP) 및 SAML 페더레이션 IAM 역할 생성
<a name="tutorial_saml-idp-and-federated-role"></a>

SAML 페더레이션 및 해당 기능에 익숙해질 수 있도록 CloudFormation 템플릿을 사용하여 SAML ID 제공업체(idP) 및 관련 페더레이션 IAM 역할을 설정합니다. 이 자습서에서는 단일 스택에서 2가지 리소스를 모두 생성하는 방법을 보여줍니다.

템플릿은 SAML 제공업체를 신뢰하는 IAM 역할과 함께, AWS 리소스에 대한 페더레이션 액세스에 사용할 수 있는 SAML IdP를 생성합니다. 외부 IdP에서 인증된 사용자는 이 역할을 수임하여 AWS 리소스에 액세스할 수 있습니다.

배포된 리소스는 다음 항목으로 이루어져 있습니다.
+ SAML IdP - IdP의 메타데이터 문서로 구성됩니다.
+ 페더레이션 IAM 역할 - SAML IdP를 신뢰하며, 인증된 사용자가 수임할 수 있습니다.
+ 구성 가능한 관리형 정책 - 역할에 연결하여 특정 권한을 부여할 수 있습니다.

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

이 자습서에서는 다음을 이미 완료했다고 가정합니다.
+ 이 자습서에서 IdP의 SAML 메타데이터 XML 파일의 형식을 지정하는 데 사용되는 Python 명령을 실행할 수 있도록 로컬 시스템에 설치된 Python 3.6 이상 버전.
+ XML 파일로 저장된 외부 IdP의 SAML 메타데이터 문서.

## CloudFormation을 사용하여 SAML IdP 및 역할 생성
<a name="tutorial_saml-idp-and-federated-role-create"></a>

SAML IdP 및 페더레이션 역할을 생성하려면 CloudFormation 템플릿을 생성하고 이를 사용하여 2가지 리소스가 모두 포함된 스택을 생성합니다.

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

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

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

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

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

### 스택 생성
<a name="tutorial_saml-idp-and-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. **IdentityProviderName**의 경우 이 값을 비워 두어 스택 이름을 기반으로 이름을 자동 생성하거나, SAML IdP의 사용자 지정 이름을 입력할 수 있습니다.

      예: `CompanyIdP` 또는 `EnterpriseSSO`

   1. **IdentityProviderSAMLMetadataDocument**의 경우 이 필드에 붙여 넣기 전에 SAML 메타데이터 XML 파일의 형식을 한 줄로 지정해야 합니다. 이렇게 해야 하는 이유는 CloudFormation 콘솔에서 콘솔 파라미터를 전달할 때 XML 콘텐츠의 형식을 한 줄로 지정해야 하기 때문입니다.

      아래의 Python 명령을 사용하여 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
      ```
**참고**  
IdP의 SAML 메타데이터 문서는 콘솔 파라미터 입력을 위해 한 줄로 형식을 지정해야 합니다. Python 명령은 줄 바꿈과 추가 공백을 제거하여 모든 원본 콘텐츠와 구조를 그대로 유지하면서 필요한 형식을 생성합니다.

      Python 명령에서 출력을 복사한 후 이를 **IdentityProviderSAMLMetadataDocument** 필드에 붙여 넣습니다.

      형식이 지정된 SAML 메타데이터 문서의 예시(간략화함):

      ```
      <?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>
      ```

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

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

   1. 다른 파라미터의 경우 기본값을 적용하거나, 요구 사항에 따라 직접 입력합니다.
      + **IdentityProviderAddPrivateKey** - SAML 어설션의 암호 해독을 위한 선택적 프라이빗 키
      + **IdentityProviderAssertionEncryptionMode** - SAML 어설션의 암호화 모드

        예시 값: `Allowed`, `Required`, 또는 암호화가 없는 경우 비워 둠
      + **RoleSessionDuration** - 최대 세션 지속 시간(초)(3,600\$143,200, 기본값 7,200)

        예: `14400`(4시간)
      + **RolePermissionsBoundary** - 권한 경계 정책의 선택적 ARN

        예시: `arn:aws:iam::123456789012:policy/DeveloperBoundary`
      + **RolePath** - IAM 역할의 경로(기본값은 /)

        예시: `/saml-roles/`
      + **RoleManagedPolicy1-5** - 연결할 최대 5개의 관리형 정책의 선택적 ARN

        RoleManagedPolicy1의 예: `arn:aws:iam::aws:policy/ReadOnlyAccess`

        RoleManagedPolicy2의 예: `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`).
+ **IdentityProviderARN**: 생성된 SAML IdP의 ARN(예: `arn:aws:iam::123456789012:saml-provider/CompanyIdP`).

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

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

SAML IdP 및 페더레이션 역할이 생성되면 페더레이션 설정을 테스트할 수 있습니다.

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

1. 탐색 창에서 [**자격 증명 공급자(Identity providers)**]를 선택합니다.

   새로 생성된 SAML IdP가 목록에 표시됩니다.

1. 세부 정보를 보려면 IdP 이름을 선택합니다.

   IdP 세부 정보 페이지에서 SAML 메타데이터 문서 및 기타 구성 세부 정보를 볼 수 있습니다.

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

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

   역할 세부 정보 페이지에서 SAML IdP가 이 역할을 수임하도록 허용하는 신뢰 정책을 볼 수 있습니다.

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

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

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

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

1. CloudFormation 콘솔을 엽니다.

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

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

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

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

이 자습서에서 CloudFormation 템플릿은 계정에 다음과 같은 리소스를 생성합니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-samlprovider.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-samlprovider.html): AWS와 외부 IdP 간에 신뢰를 설정하는 SAML IdP입니다.
+ [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-idp-and-federated-role-configuration"></a>

템플릿에는 다음과 같은 구성 가능한 파라미터가 포함되어 있습니다.
+ **IdentityProviderName** - SAML IdP의 이름(자동 생성된 이름의 경우 비워둠)
+ **IdentityProviderSAMLMetadataDocument** - IdP의 SAML 메타데이터 문서(필수)
+ **IdentityProviderAddPrivateKey** - SAML 어설션의 암호 해독을 위한 선택적 프라이빗 키
+ **IdentityProviderAssertionEncryptionMode** - SAML 어설션의 암호화 모드
+ **RoleName** - IAM 역할의 이름(자동 생성된 이름의 경우 비워둠)
+ **RolePath** - IAM 역할의 경로(기본값은 /)
+ **RolePermissionsBoundary** - 권한 경계 정책의 선택적 ARN
+ **RoleSessionDuration** - 최대 세션 지속 시간(초)(3,600\$143,200, 기본값 7,200)
+ **RoleManagedPolicy1-5** - 연결할 최대 5개의 관리형 정책의 선택적 ARN

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

아래의 JSON 또는 YAML 코드를 별도의 파일로 저장하여 이 자습서의 CloudFormation 템플릿으로 사용하세요.

------
#### [ 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'
```

------