AWS: IAM AssumeRole – описание, примеры

Автор: | 24/01/2020

AssumeRole – механизм аутентификации в AWS IAM, позволяющий получить временные данные доступа для выполнения запросов к ресурсам, к которым у вас нет доступа.

Эти временные данные доступа состоят из привычных ACCESS и SECRET ключей, плюс security token.

Одним из примеров AssumeRole может быть Jenkins в EC2, джобы которого могут выполнять операции в AWS-аккаунте, используя EC2 Instance IAM role вместо обычного набора ACCESS/SECRET ключей. См. AWS: ротация ключей IAM пользователей, EC2 IAM Roles и Jenkins.

При таком варианте код, запущенный на ЕС2, к которой подключена IAM Instance Role, фактически выполняет assume-role от имени инстанса, и получает его временные данные доступа.

Проверить подключенную к ЕС2 роль можно из его метаданных:

[simterm]

admin@bttrm-stage-console:~$ curl http://169.254.169.254/latest/meta-data/iam/info
{
  "Code" : "Success",
  "LastUpdated" : "2020-01-24T11:07:49Z",
  "InstanceProfileArn" : "arn:aws:iam::534***385:instance-profile/mobilebackend-stage-CloudWatchAccessProfile-190BQNQP5L33O",
  "InstanceProfileId" : "AIPAIB4MIE6GWWX6DP6RA"
}

[/simterm]

Документация по EC2 metadata – тут>>>.

Документация по IAM AssumeRole – тут>>>.

Подготовка IAM

Создание пользователя

Добавляем нового юзера:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy create-user --user-name iam-test-user
{
    "User": {
        "Path": "/",
        "UserName": "iam-test-user",
        "UserId": "AIDAXY5JMBME22RMBUPWJ",
        "Arn": "arn:aws:iam::534***385:user/iam-test-user",
        "CreateDate": "2020-01-24T08:41:09Z"
    }
}

[/simterm]

IAM test policy

Создаём IAM политику с разрешениями на выполнение некоторых API-вызовов к ядру AWS, назовём её iam-test-policy.json:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*",
                "iam:ListRoles",
                "sts:AssumeRole"
            ],
            "Resource": "*"
        }
    ]
}

Добавляем её в AWS:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy create-policy --policy-name example-policy --policy-document file://iam-test-user.json
{
    "Policy": {
        "PolicyName": "example-policy",
        "PolicyId": "ANPAXY5JMBMEWA6G4ZMSP",
        "Arn": "arn:aws:iam::534***385:policy/example-policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2020-01-24T08:43:26Z",
        "UpdateDate": "2020-01-24T08:43:26Z"
    }
}

[/simterm]

Сохраняем её ARN – “arn:aws:iam::534***385:policy/example-policy”.

Attach IAM policy

Подключаем эту политику к созданному ранее пользователю:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy attach-user-policy --user-name iam-test-user --policy-arn "arn:aws:iam::534***385:policy/example-policy"

[/simterm]

Проверяем:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy list-attached-user-policies --user-name iam-test-user
{
    "AttachedPolicies": [
        {
            "PolicyName": "example-policy",
            "PolicyArn": "arn:aws:iam::534***385:policy/example-policy"
        }
    ]
}

[/simterm]

AWS IAM trust policy

Создаём файл iam-test-role-trust-policy.json, описываем политику, она будет являться AssumePolicyDocument:

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": { "AWS": "arn:aws:iam::534***385:root" },
        "Action": "sts:AssumeRole"
    }
}

В “Principal”: { “AWS”: “arn:aws:iam::534***385:root” } указываем кто именно может assume роль, к которой подключена эта политика.

В данном случае значение root указывает на всех пользователей AWS-аккаунта 534***385, см. документацию тут>>>.

RDS read-only IAM role

Создаём роль, подключаем AssumePolicyDocument, который создали выше:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy create-role --role-name iam-test-role --assume-role-policy-document file://iam-test-role-trust-policy.json
{
    "Role": {
        "Path": "/",
        "RoleName": "iam-test-role",
        "RoleId": "AROAXY5JMBMEZUQEDSWLK",
        "Arn": "arn:aws:iam::534***385:role/iam-test-role",
        "CreateDate": "2020-01-24T09:50:44Z",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::534***385:root"
                },
                "Action": "sts:AssumeRole"
            }
        }
    }
}

[/simterm]

Подключаем к нашей роли встроенную полиси самого AWS – AmazonRDSReadOnlyAccess:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy attach-role-policy --role-name iam-test-role --policy-arn "arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess"

[/simterm]

Проверяем политики, подключенные к нашей роли:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy list-attached-role-policies --role-name iam-test-role
{
    "AttachedPolicies": [
        {
            "PolicyName": "AmazonRDSReadOnlyAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess"
        }
    ]
}

[/simterm]

Проверка

Проверим, что пользователь может выполнит API-вызов ec2:Describe к ядру Amazon Web Services.

Access keys

Получаем ключи доступа:

[simterm]

$ aws iam --region eu-west-3 --profile arseniy create-access-key --user-name iam-test-user
{
    "AccessKey": {
        "UserName": "iam-test-user",
        "AccessKeyId": "AKI***VFY",
        "Status": "Active",
        "SecretAccessKey": "tPF***9Ee",
        "CreateDate": "2020-01-24T09:54:57Z"
    }
}

[/simterm]

AWS profile

Настраиваем новый AWS-профиль:

[simterm]

$ aws configure --profile iam-test-user 
AWS Access Key ID [None]: AKIAXY5JMBMEY36IZVFY
AWS Secret Access Key [None]: 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
Default region name [None]: eu-west-3
Default output format [None]: json

[/simterm]

Проверяем, что мы пользуемся именно им:

[simterm]

$ aws --profile iam-test-user sts get-caller-identity
{
    "UserId": "AIDAXY5JMBME22RMBUPWJ",
    "Account": "534***385",
    "Arn": "arn:aws:iam::534***385:user/iam-test-user"
}

[/simterm]

И выполняем ec2:Describe – должен сработать:

[simterm]

$ aws ec2 --profile iam-test-user describe-instances --query "Reservations[*].Instances[*].[VpcId, InstanceId, ImageId, InstanceType]"
[
    [
        [
            "vpc-05161aa8c42ab63f0",
            "i-0c449083586521956",
            "ami-0db9a057d2e5a2554",
            "t3.medium"
        ]
    ],
...

[/simterm]

Теперь проверим доступ к RDS – должен вернуть AccessDenied:

[simterm]

$ aws rds --profile iam-test-user describe-db-instances --query "DBInstances[*].[DBInstanceIdentifier, DBName, DBInstanceStatus, AvailabilityZone, DBInstanceClass]"

An error occurred (AccessDenied) when calling the DescribeDBInstances operation: User: arn:aws:iam::534***385:user/iam-test-user is not authorized to perform: rds:DescribeDBInstances

[/simterm]

Отлично.

Assume the IAM role

Находим ARN нашей iam-test-role роли:

[simterm]

$ aws iam --profile iam-test-user list-roles --query "Roles[?RoleName == 'iam-test-role'].[RoleName, Arn]"
[
    [
        "iam-test-role",
        "arn:aws:iam::534***385:role/iam-test-role"
    ]
]

[/simterm]

Создаём новую сессию – собственно, и выполняем assume-role:

[simterm]

$ aws sts --profile iam-test-user assume-role --role-arn "arn:aws:iam::534***385:role/iam-test-role" --role-session-name AWSCLI-TestSession
{
    "Credentials": {
        "AccessKeyId": "ASI***DCU",
        "SecretAccessKey": "CuO***JgT",
        "SessionToken": "Fwo***bq0=",
        "Expiration": "2020-01-24T11:05:07Z"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "ARO***WLK:AWSCLI-TestSession",
        "Arn": "arn:aws:sts::534***385:assumed-role/iam-test-role/AWSCLI-TestSession"
    }
}

[/simterm]

Отсюда берём три переменных, задаём их в окружение:

[simterm]

$ export AWS_ACCESS_KEY_ID=ASI***DCU
$ export AWS_SECRET_ACCESS_KEY=CuO***JgT
$ export AWS_SESSION_TOKEN=Fwo***bq0=

[/simterm]

Ещё раз проверяем себя – теперь без указания профиля, что бы использовать переменные, которые только что задали (они имеют преимущество перед default профилем в /.aws/credentials):

[simterm]

$ aws sts get-caller-identity
{
    "UserId": "ARO***WLK:AWSCLI-TestSession",
    "Account": "534***385",
    "Arn": "arn:aws:sts::534***385:assumed-role/iam-test-role/AWSCLI-TestSession"
}

[/simterm]

И сравним с вызовом раньше, после создания пользователя:

[simterm]

$ aws --profile iam-test-user sts get-caller-identity
{
    "UserId": "AID***PWJ",
    "Account": "534***385",
    "Arn": "arn:aws:iam::534***385:user/iam-test-user"
}

[/simterm]

Сравните UserId и Arn.

Проверяем доступы – сначала ЕС2, должен заблокировать:

[simterm]

$ aws ec2 describe-instances --query "Reservations[*].Instances[*].[VpcId, InstanceId, ImageId, InstanceType]"

An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.

[/simterm]

И RDS:

[simterm]

$ aws rds describe-db-instances --query "DBInstances[*].[DBInstanceIdentifier, DBName, DBInstanceStatus, AvailabilityZone, DBInstanceClass]"
[
    [
        "better-datascience-1",
        "dsdb",
        "available",
        "eu-west-1a",
        "db.t2.xlarge"
    ],
...

[/simterm]

Assume IAM Role в AWS CLI

Проверяем ~/.aws/config – тут у меня есть профиль arseniy, которым изначально и пользовались:

[profile arseniy]но
region = us-east-2
output = json

Создаём новый профиль, назовём его iam-test-user-cli:

...

[profile iam-test-user-cli]
role_arn = arn:aws:iam::534***385:role/iam-test-role
source_profile = arseniy
region = eu-west-3

Теперь при вызове AWS CLI с опцией --profile iam-test-user-cli мы должны выполнить запрос от имени arseniy.

Порядок выполнения запроса будет следующим:

  1. вызываем rds:Describe (командой aws rds describe-db-instances)
  2. AWS CLI выполняет запрос к AWS IAM сервису, передавая ему arseniy как пользователя, и выполнит попытку assume role роли iam-test-role
  3. AWS IAM проверит Trust Policy роли iam-test-role, в частности – Principal, указанный там
  4. если пользователь arseniy входит в Principal“Principal”: { “AWS”: “arn:aws:iam::534***385:root” } включает всех пользователей аккаунта) – то IAM разрешит использование политики iam-test-role
  5. и AWS выполнит API-запрос к RDS

Проверяем – получим текущего пользователя, используя --profile iam-test-user-cli:

[simterm]

$ aws sts --profile iam-test-user-cli get-caller-identity
{
   "UserId": "ARO***WLK:botocore-session-1579866288",
   "Account": "534***385",
   "Arn": "arn:aws:sts::534***385:assumed-role/iam-test-role/botocore-session-1579866288"
}

[/simterm]

И проверяем доступ к RDS:

[simterm]

$ aws rds --profile iam-test-user-cli describe-db-instances --query "DBInstances[*].[DBInstanceIdentifier, DBName, DBInstanceStatus, AvailabilityZone, DBInstanceClass]"
[
    [
        "better-datascience-1",
        "dsdb",
        "available",
        "eu-west-1a",
        "db.t2.xlarge"
    ],
...

[/simterm]

Готово.