AWS Assume IAM role 的使用
AWS 要授权给他人访问指定资源有哪几种方式呢?
用 Assume Role 的方式具有更高的安全可控性,还不用维护 Access Key ID 和 Secret Access Key。比如在构建和部署时通常是有一个特定的 Account, 然后 Assume 到别的 IAM Role 去操作资源。
本文将详细介绍在帐号 A 创建一个 IAM Role(标注为 R) 并分配一些权限,然后允许另一个帐号 B 以 IAM Role - R 的身份来访问帐号 A 下的资源。IAM Role 将用 awscli 来创建,Assume Role 的过程用 awscli 和 boto3 Python 代码两种方式来演示。
比如说在
准备 role-trust-policy.json
这里的
这时候得到一组新的 AccessKeyId, SecretAccessKey 和 SessionToken,可以在
2024-02-01
一种更便捷一步到位的切换 role 的方式
这时候执行
帐号 B 登陆,调用 boto3 的 sts.assume_role() 函数切换到帐号 A 下的 IAM Role test-assumed-role,之后的操作就限定到 test-assumed-role 的约束中了。
当然,使用 Python 的话可以进一步封装,比如默认以帐号 B 登陆,然后执行一个函数
把
链接:
永久链接 https://yanbin.blog/how-to-assume-aws-iam-role/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
- 创建一个 AWS 帐号让别人用,那是 AWS 干的事
- 在自己帐号下创建一个用户,把 Access Key ID 和 Secret Access Key 告诉别人。可为该用户限定权限,但任何获得那两个 Key 的人都能使用该用户。
- 创建一个 IAM Role, 并指定谁(帐号或 Role) 能以该 Role 的身份来访问。被 Assume 的 Role 可限定权限和会话有效期。
用 Assume Role 的方式具有更高的安全可控性,还不用维护 Access Key ID 和 Secret Access Key。比如在构建和部署时通常是有一个特定的 Account, 然后 Assume 到别的 IAM Role 去操作资源。
本文将详细介绍在帐号 A 创建一个 IAM Role(标注为 R) 并分配一些权限,然后允许另一个帐号 B 以 IAM Role - R 的身份来访问帐号 A 下的资源。IAM Role 将用 awscli 来创建,Assume Role 的过程用 awscli 和 boto3 Python 代码两种方式来演示。
帐号 A 下创建 IAM Role
首选要以帐号 A 登陆 AWS,不管哪种方式只要让aws s3 cli 能正常工作就行。AWS 获得访问资格(Credentials) 的顺序可参照 Boto3 的文档 Configuring Credentials。比如说在
~/.aws/credentials 中配置了 profile A 和 B,分别对应帐号 A 和 B 的 profile 名称,在帐号 A 下创建 IAM Role 前用 export AWS_DEFAULT_PROFILE=A 指明当前为帐号 A准备 role-trust-policy.json
1{
2 "Version": "2012-10-17",
3 "Statement": [
4 {
5 "Effect": "Allow",
6 "Principal": {
7 "AWS": "arn:aws:iam::123456789022:root"
8 },
9 "Action": "sts:AssumeRole",
10 "Condition": {}
11 }
12 ]
13}这里的
123456789022 是帐号 B 的 Account ID, 如果允许更多的帐号可以往上面的 Principal 中添加。创建 test-assumed-role$ aws iam create-role --role-name test-assumed-role --assume-role-policy-document file://role-trust-policy.json再给新建的 test-assumed-role 加上 S3 的只读权限
$ aws iam attach-role-policy --role-name test-assumed-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
帐号 B Assume 帐号 A 的 role(awscli)
在帐号 A 下创建好 test-assumed-role 后,现在为 awscli 切换到帐号 B 下,比如export AWS_DEFAULT_PROFILE=B。接着要用 aws sts assume-role 命令$ aws sts assume-role --role-arn arn:aws:iam::123456789011:role/test-assumed-role --role-session-name awscli-session其中的
123456789011 是,sts 是指 Security Token Service,执行后输出如下 1{
2 "Credentials": {
3 "AccessKeyId": "PNKDIESJGWAURFEWDLLT",
4 "SecretAccessKey": "YcYdWHbtFZEDj/GetAyqRWdgvExxVpDJgC",
5 "SessionToken": "IQoJb3JpZ2luX2VjEDoaCXVzLWVhc3QdDD1......QyAd6mnRruoJfLo1DUA==",
6 "Expiration": "2021-11-10T02:36:46+00:00"
7 },
8 "AssumedRoleUser": {
9 "AssumedRoleId": "EXYARBWXQYCCAUONCJHG:awscli-session",
10 "Arn": "arn:aws:sts::123456789011:assumed-role/test-assumed-role/awscli-session"
11 }
12}这时候得到一组新的 AccessKeyId, SecretAccessKey 和 SessionToken,可以在
~/.aws/credentials 中配置一个新的 profile C, 然后 export AWS_DEFAULT_PROFILE=C 来使用。
或都用 export 分别导出三个环境变量 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, 和 AWS_SESSION_TOKEN, 分别对应前面的三个值。$ export AWS_ACCESS_KEY_ID=<Credentials.AccessKeyId>替换上面的 <Credentials.*> 为
$ export AWS_SECRET_ACCESS_KEY=<Credentials.SecretAccessKey>
$ export AWS_SESSION_TOKEN=<Credentials.SessionToken>
aws sts assume-role ... 返回的实际的相应字符串2024-02-01
一种更便捷一步到位的切换 role 的方式
1export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \
2 $(aws sts assume-role \
3 --role-arn arn:aws:iam::123456789011:role/test-assumed-role \
4 --role-session-name awscli-session \
5 --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
6 --output text))这时候执行
aws s3 ls 获得的就是帐号 A 中的 S3 Bucket 列表$ aws s3 ls想访问超出
2021-09-10 12:09:35 bucket1-of-A
2019-12-03 15:55:35 bucket2-of-A
test-assumed-role 之外的权限将被提示 Access Denied$ aws s3 cp Jenkinsfile s3://wfe-files任何时候都通过
upload failed: ./test.txt to s3://bucket-of-A/test.txte An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
aws sts get-caller-identity 来查看当前所使用的角色aws sts get-caller-identity
{
"UserId": "EXYARBWXQYCCAUONCJHG:awscli-session",
"Account": "123456789011",
"Arn": "arn:aws:sts::123456789011:assumed-role/test-assumed-role/awscli-session"
}
帐号 B Assume 帐号 A 的 role(boto3)
awscli Assume 一个 IAM Role 的方式是重新获得一组 AccessKeyId, SecretAccessKey 和 SessionToken, 然后切换到被 Assumed 的 Role。用 Python 的 boto3 包实现是完全一样的。 1import boto3
2
3aws_credentials_b = {
4 'region_name': 'us-east-1',
5 'aws_access_key_id':'PNKDIESJGWAURFEWDLLT',
6 'aws_secret_access_key':'TdTMlDUSKecRadKeMlNIBEmIkRjmZOSvtnhgQDZc',
7 'aws_session_token':'IQoJb3JpZ2luX2VjEDYabEbMG5J2lzlv......IEQisSAwzmnkv7LNf+'
8}
9
10
11sts=boto3.client('sts', **aws_credentials_b)
12
13stsresponse = sts.assume_role(
14 RoleArn="arn:aws:iam::123456789011:role/test-assumed-role", # under account A
15 RoleSessionName='assumed'
16)
17
18aws_credentials_assumed_role = {
19 'region_name':'us-east-1',
20 'aws_access_key_id':stsresponse["Credentials"]["AccessKeyId"],
21 'aws_secret_access_key':stsresponse["Credentials"]["SecretAccessKey"],
22 'aws_session_token':stsresponse["Credentials"]["SessionToken"]
23}
24
25
26boto3.setup_default_session(**aws_credentials_assumed_role)
27
28s3 = boto3.client('s3')
29buckets_of_a = [bucket['Name'] for bucket in s3.list_buckets()['Buckets']]帐号 B 登陆,调用 boto3 的 sts.assume_role() 函数切换到帐号 A 下的 IAM Role test-assumed-role,之后的操作就限定到 test-assumed-role 的约束中了。
当然,使用 Python 的话可以进一步封装,比如默认以帐号 B 登陆,然后执行一个函数
switch_role(role_arn) 后,后续的 boto3 client 就全部变成了 assumed role 的角色了 1import boto3
2
3def switch_role(assume_role_arn):
4 sts=boto3.client('sts')
5 sts_res = sts.assume_role(RoleArn=assume_role_arn, RoleSessionName='new_session')
6
7 new_credentials = {'aws' + re.sub('([A-Z]+)', r'_\1', key).lower(): value
8 for (key, value) in sts_res["Credentials"].items() if key != 'Expiration'}
9
10 boto3.setup_default_session(**new_credentials)
11
12switch_role('arn:aws:iam::123456789011:role/test-assumed-role')
13
14s3 = boto3.client('s3')
15buckets_of_a = [bucket['Name'] for bucket in s3.list_buckets()['Buckets']]把
sts_res['Credentials'] 转换为 session 要求的格式是简化,但是要注意以后 assume_role() 响应格式的变化有可能影响到程序的正常执行。链接:
永久链接 https://yanbin.blog/how-to-assume-aws-iam-role/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。