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.
Порядок выполнения запроса будет следующим:
- вызываем
rds:Describe
(командойaws rds describe-db-instances
) - AWS CLI выполняет запрос к AWS IAM сервису, передавая ему arseniy как пользователя, и выполнит попытку assume role роли iam-test-role
- AWS IAM проверит Trust Policy роли iam-test-role, в частности —
Principal
, указанный там - если пользователь arseniy входит в
Principal
(а «Principal»: { «AWS»: «arn:aws:iam::534***385:root» } включает всех пользователей аккаунта) — то IAM разрешит использование политики iam-test-role - и 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]
Готово.