IAM 역할로 전환

IAM 역할로 전환 (AWS API) (Switch to an IAM role)

역할(role)은 AWS 리소스에 접근할 때 사용할 권한 집합을 지정해요. 그런 면에서 IAM 사용자와 비슷해요. 프린시펄(사람이나 애플리케이션)이 역할을 **수임(assume)**하면, 필요한 작업을 수행하고 AWS 리소스와 상호작용할 수 있는 임시 권한을 받아요. 역할은 우리 계정이나 다른 AWS 계정에 둘 수 있어요. 역할의 이점과 생성·구성 방법에 대한 자세한 내용은 IAM 역할과 IAM 역할 생성을 참고하세요. 역할을 수임하는 여러 방법은 역할 수임 방법을 참고하세요.

출처: 문서

본문

중요

IAM 사용자의 권한과 수임한 역할의 권한은 합산되지 않아요. 한 번에 하나의 권한 집합만 적용돼요. 역할을 수임하면 이전 사용자·역할 권한을 잠시 내려놓고 역할에 할당된 권한으로 작업해요. 역할에서 나오면 원래 권한이 자동으로 복원돼요.

역할을 수임하려면 애플리케이션이 AWS STS AssumeRole API 작업을 호출하고 사용할 역할의 ARN을 전달해요. 이 작업은 임시 자격 증명으로 새 세션을 만들어요. 이 세션은 그 역할의 아이덴티티 기반 정책과 같은 권한을 가져요.

AssumeRole을 호출할 때 선택적으로 인라인 또는 관리형 세션 정책을 전달할 수 있어요. 세션 정책은 역할이나 페더레이션 사용자 세션의 임시 자격 증명 세션을 프로그래밍 방식으로 만들 때 파라미터로 전달하는 고급 정책이에요. Policy 파라미터로 단일 JSON 인라인 세션 정책 문서를 전달할 수 있어요. PolicyArns 파라미터로 최대 10개의 관리형 세션 정책을 지정할 수 있어요. 결과 세션의 권한은 엔터티의 아이덴티티 기반 정책과 세션 정책의 교집합이에요. 세션 정책은 역할의 임시 자격 증명을 다른 사람에게 줄 필요가 있을 때 유용해요. 그들은 역할의 임시 자격 증명을 후속 AWS API 호출에 사용해 역할을 소유한 계정의 리소스에 접근할 수 있어요. 세션 정책으로 아이덴티티 기반 정책이 허용하는 것보다 더 많은 권한을 부여할 수는 없어요. AWS가 역할의 실효 권한을 어떻게 결정하는지 알아보려면 정책 평가 로직을 참고하세요.

IAM 사용자로 로그인했거나 이미 역할을 사용 중인 외부 인증 사용자(SAML 또는 OIDC)로 AssumeRole을 호출할 수 있어요. 또한 역할을 사용해 두 번째 역할을 수임하는 역할 체이닝도 사용할 수 있어요. AWS 계정 루트 사용자로 로그인한 상태에서는 역할을 수임할 수 없어요.

기본적으로 역할 세션은 1시간 동안 지속돼요. AWS STS AssumeRole* API 작업으로 역할을 수임할 때 DurationSeconds 파라미터의 값을 지정할 수 있어요. 이 값은 900초(15분)부터 역할의 최대 세션 지속 시간 설정까지 범위가 돼요. 역할의 최대 값을 보는 방법은 역할의 최대 세션 지속 시간 업데이트를 참고하세요.

역할 체이닝을 사용하면 세션 지속 시간이 최대 1시간으로 제한돼요. 그런 다음 DurationSeconds 파라미터로 1시간보다 큰 값을 제공하면 작업이 실패해요.

참고

보안을 위해 관리자는 AWS CloudTrail 로그로 누가 AWS에서 어떤 작업을 수행했는지 알 수 있어요. 관리자가 역할을 수임할 때 소스 아이덴티티나 역할 세션 이름을 지정하도록 요구할 수도 있어요. 자세한 내용은 sts:SourceIdentity와 sts:RoleSessionName을 참고하세요.

다음 코드 예시는 사용자를 만들고 역할을 수임하는 방법을 보여줘요.

경고

보안 위험을 피하려면 목적에 맞는 소프트웨어를 개발하거나 실제 데이터를 작업할 때 인증에 IAM 사용자를 사용하지 마세요. 대신 AWS IAM Identity Center 같은 아이덴티티 프로바이더와의 페더레이션을 사용하세요.

  • 권한이 없는 사용자를 만들어요.
  • 계정의 Amazon S3 버킷을 나열할 권한을 부여하는 역할을 만들어요.
  • 사용자가 역할을 수임하도록 정책을 추가해요.
  • 역할을 수임하고 임시 자격 증명으로 S3 버킷을 나열한 뒤 리소스를 정리해요.

.NET (SDK for .NET) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾고, 설정·실행 방법을 배울 수 있어요.

이 예시는 SDK for .NET을 사용해 IAM 래퍼 클래스를 정의하고, 사용자·역할·정책을 만들고, 역할에 권한을 부여하며, 역할 수임을 통한 접근 흐름을 보여줘요.

API 세부 사항은 AWS SDK for .NET API Reference의 AttachRolePolicy, CreateAccessKey, CreatePolicy, CreateRole, CreateUser, DeletePolicy, DeleteUser, DetachRolePolicy, PutUserPolicy, GetUser 토픽을 참고하세요.

C++ (SDK for C++) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

호출자(Python, Bash 등)가 권한 있는 접근에 보안 자격 증명을 사용할 수 있게 하기 위해 IAM 사용자·역할·정책을 만드는 시나리오를 보여줘요. API 세부 사항은 AWS SDK for C++ API Reference의 해당 토픽을 참고하세요.

Go (SDK for Go V2) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

사용자와 역할을 만들고 역할 수임을 통한 S3 버킷 나열 시나리오를 보여줘요. SDK for Go는 AccessDenied 오류를 모델링하지 않으므로 ErrorCode를 직접 확인하는 부분이 있어요. API 세부 사항은 AWS SDK for Go API Reference의 해당 토픽을 참고하세요.

Java (SDK for Java 2.x) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

IAM 요구 사항 시나리오 (IAM)를 보여주며, 사용자·역할·정책 생성과 역할 수임을 통한 접근을 다뤄요. API 세부 사항은 AWS SDK for Java 2.x API Reference의 해당 토픽을 참고하세요.

JavaScript (SDK for JavaScript v3) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

IAM 요구 사항 시나리오 (IAM)를 보여줘요. API 세부 사항은 AWS SDK for JavaScript API Reference의 해당 토픽을 참고하세요.

Kotlin (SDK for Kotlin) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

사용자·역할·정책 생성과 역할 수임 시나리오를 보여줘요. API 세부 사항은 AWS SDK for Kotlin API reference의 해당 토픽을 참고하세요.

PHP (SDK for PHP) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

IAM 사용자·역할·정책 생성과 역할 수임 시나리오를 보여줘요. API 세부 사항은 AWS SDK for PHP API Reference의 해당 토픽을 참고하세요.

Python (SDK for Python, Boto3) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾고, 설정·실행 방법을 배울 수 있어요.

Amazon S3 버킷을 나열할 권한을 부여하는 IAM 사용자와 역할을 만들어요. 사용자는 역할을 수임할 권리만 있어요. 역할을 수임한 뒤 임시 자격 증명으로 계정의 버킷을 나열해요.

import json
import sys
import time
from uuid import uuid4

import boto3
from botocore.exceptions import ClientError


def progress_bar(seconds):
    """Shows a simple progress bar in the command window."""
    for _ in range(seconds):
        time.sleep(1)
        print(".", end="")
        sys.stdout.flush()
    print()


def setup(iam_resource):
    """
    Creates a new user with no permissions.
    Creates an access key pair for the user.
    Creates a role with a policy that lets the user assume the role.
    Creates a policy that allows listing Amazon S3 buckets.
    Attaches the policy to the role.
    Creates an inline policy for the user that lets the user assume the role.

    :param iam_resource: A Boto3 AWS Identity and Access Management (IAM) resource
                         that has permissions to create users, roles, and policies
                         in the account.
    :return: The newly created user, user key, and role.
    """
    try:
        user = iam_resource.create_user(UserName=f"demo-user-{uuid4()}")
        print(f"Created user {user.name}.")
    except ClientError as error:
        print(
            f"Couldn't create a user for the demo. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    try:
        user_key = user.create_access_key_pair()
        print(f"Created access key pair for user.")
    except ClientError as error:
        print(
            f"Couldn't create access keys for user {user.name}. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    print(f"Wait for user to be ready.", end="")
    progress_bar(10)

    try:
        role = iam_resource.create_role(
            RoleName=f"demo-role-{uuid4()}",
            AssumeRolePolicyDocument=json.dumps(
                {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {"AWS": user.arn},
                            "Action": "sts:AssumeRole",
                        }
                    ],
                }
            ),
        )
        print(f"Created role {role.name}.")
    except ClientError as error:
        print(
            f"Couldn't create a role for the demo. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    try:
        policy = iam_resource.create_policy(
            PolicyName=f"demo-policy-{uuid4()}",
            PolicyDocument=json.dumps(
                {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": "s3:ListAllMyBuckets",
                            "Resource": "arn:aws:s3:::*",
                        }
                    ],
                }
            ),
        )
        role.attach_policy(PolicyArn=policy.arn)
        print(f"Created policy {policy.policy_name} and attached it to the role.")
    except ClientError as error:
        print(
            f"Couldn't create a policy and attach it to role {role.name}. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    try:
        user.create_policy(
            PolicyName=f"demo-user-policy-{uuid4()}",
            PolicyDocument=json.dumps(
                {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": "sts:AssumeRole",
                            "Resource": role.arn,
                        }
                    ],
                }
            ),
        )
        print(
            f"Created an inline policy for {user.name} that lets the user assume "
            f"the role."
        )
    except ClientError as error:
        print(
            f"Couldn't create an inline policy for user {user.name}. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    print("Give AWS time to propagate these new resources and connections.", end="")
    progress_bar(10)

    return user, user_key, role


def show_access_denied_without_role(user_key):
    """
    Shows that listing buckets without first assuming the role is not allowed.

    :param user_key: The key of the user created during setup. This user does not
                     have permission to list buckets in the account.
    """
    print(f"Try to list buckets without first assuming the role.")
    s3_denied_resource = boto3.resource(
        "s3", aws_access_key_id=user_key.id, aws_secret_access_key=user_key.secret
    )
    try:
        for bucket in s3_denied_resource.buckets.all():
            print(bucket.name)
        raise RuntimeError("Expected to get AccessDenied error when listing buckets!")
    except ClientError as error:
        if error.response["Error"]["Code"] == "AccessDenied":
            print("Attempt to list buckets with no permissions: AccessDenied.")
        else:
            raise


def list_buckets_from_assumed_role(user_key, assume_role_arn, session_name):
    """
    Assumes a role that grants permission to list the Amazon S3 buckets in the account.
    Uses the temporary credentials from the role to list the buckets that are owned
    by the assumed role's account.

    :param user_key: The access key of a user that has permission to assume the role.
    :param assume_role_arn: The Amazon Resource Name (ARN) of the role that
                            grants access to list the other account's buckets.
    :param session_name: The name of the STS session.
    """
    sts_client = boto3.client(
        "sts", aws_access_key_id=user_key.id, aws_secret_access_key=user_key.secret
    )
    try:
        response = sts_client.assume_role(
            RoleArn=assume_role_arn, RoleSessionName=session_name
        )
        temp_credentials = response["Credentials"]
        print(f"Assumed role {assume_role_arn} and got temporary credentials.")
    except ClientError as error:
        print(
            f"Couldn't assume role {assume_role_arn}. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    # Create an S3 resource that can access the account with the temporary credentials.
    s3_resource = boto3.resource(
        "s3",
        aws_access_key_id=temp_credentials["AccessKeyId"],
        aws_secret_access_key=temp_credentials["SecretAccessKey"],
        aws_session_token=temp_credentials["SessionToken"],
    )
    print(f"Listing buckets for the assumed role's account:")
    try:
        for bucket in s3_resource.buckets.all():
            print(bucket.name)
    except ClientError as error:
        print(
            f"Couldn't list buckets for the account. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise



def teardown(user, role):
    """
    Removes all resources created during setup.

    :param user: The demo user.
    :param role: The demo role.
    """
    try:
        for attached in role.attached_policies.all():
            policy_name = attached.policy_name
            role.detach_policy(PolicyArn=attached.arn)
            attached.delete()
            print(f"Detached and deleted {policy_name}.")
        role.delete()
        print(f"Deleted {role.name}.")
    except ClientError as error:
        print(
            "Couldn't detach policy, delete policy, or delete role. Here's why: "
            f"{error.response['Error']['Message']}"
        )
        raise

    try:
        for user_pol in user.policies.all():
            user_pol.delete()
            print("Deleted inline user policy.")
        for key in user.access_keys.all():
            key.delete()
            print("Deleted user's access key.")
        user.delete()
        print(f"Deleted {user.name}.")
    except ClientError as error:
        print(
            "Couldn't delete user policy or delete user. Here's why: "
            f"{error.response['Error']['Message']}"
        )


def usage_demo():
    """Drives the demonstration."""
    print("-" * 88)
    print(f"Welcome to the IAM create user and assume role demo.")
    print("-" * 88)
    iam_resource = boto3.resource("iam")
    user = None
    role = None
    try:
        user, user_key, role = setup(iam_resource)
        print(f"Created {user.name} and {role.name}.")
        show_access_denied_without_role(user_key)
        list_buckets_from_assumed_role(user_key, role.arn, "AssumeRoleDemoSession")
    except Exception:
        print("Something went wrong!")
    finally:
        if user is not None and role is not None:
            teardown(user, role)
        print("Thanks for watching!")


if __name__ == "__main__":
    usage_demo()

API 세부 사항은 AWS SDK for Python (Boto3) API Reference의 AttachRolePolicy, CreateAccessKey, CreatePolicy, CreateRole, CreateUser, DeletePolicy, DeleteUser, DeleteUserPolicy, DetachRolePolicy, PutUserPolicy, GetUser 토픽을 참고하세요.

Ruby (SDK for Ruby) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

IAM 요구 사항 시나리오 (IAM)를 보여줘요. API 세부 사항은 AWS SDK for Ruby API Reference의 해당 토픽을 참고하세요.

Rust (SDK for Rust) 코드 예시

참고

GitHub에 더 많은 내용이 있어요. AWS Code Examples Repository에서 완전한 예시를 찾을 수 있어요.

역할 수임과 함께 IAM 사용자·역할·정책 관리를 보여줘요. API 세부 사항은 AWS SDK for Rust API reference의 해당 토픽을 참고하세요.

더 알아보기 (Learn more)