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

Автор: | 01/24/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 роль можно из его метаданных:

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"
}

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

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

Подготовка IAM

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

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

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"
}
}

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:

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"
}
}

Сохраняем её ARN — «arn:aws:iam::534***385:policy/example-policy».

Attach IAM policy

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

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"

Проверяем:

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"
}
]
}

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, который создали выше:

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"
}
}
}
}

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

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

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

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"
}
]
}

Проверка

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

Access keys

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

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"
}
}

AWS profile

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

aws configure --profile iam-test-user
AWS Access Key ID [None]: AKIAXY5JMBMEY36IZVFY
AWS Secret Access Key [None]: tPFS2hnC3SWbOL00XtdA1yJQ1DPUkTQGkXDHW9Ee
Default region name [None]: eu-west-3
Default output format [None]: json

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

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

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

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

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

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

Отлично.

Assume the IAM role

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

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"
]
]

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

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"
}
}

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

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

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

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"
}

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

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"
}

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

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

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.

И RDS:

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

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:

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"
}

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

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"
],
...

Готово.