AWS Assume IAM role 的使用

AWS 要授权给他人访问指定资源有哪几种方式呢?

  1. 创建一个 AWS 帐号让别人用,那是 AWS 干的事
  2. 在自己帐号下创建一个用户,把 Access Key ID 和 Secret Access Key 告诉别人。可为该用户限定权限,但任何获得那两个 Key 的人都能使用该用户。
  3. 创建一个 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

这里的 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,执行后输出如下

这时候得到一组新的 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>
$ export AWS_SECRET_ACCESS_KEY=<Credentials.SecretAccessKey>
$ export AWS_SESSION_TOKEN=<Credentials.SessionToken>

替换上面的 <Credentials.*> 为 aws sts assume-role ... 返回的实际的相应字符串

这时候执行 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 包实现是完全一样的。

帐号 B 登陆,调用 boto3 的 sts.assume_role() 函数切换到帐号 A 下的 IAM Role test-assumed-role,之后的操作就限定到 test-assumed-role 的约束中了。

当然,使用 Python 的话可以进一步封装,比如默认以帐号 B 登陆,然后执行一个函数 switch_role(role_arn) 后,后续的 boto3 client 就全部变成了 assumed role 的角色了

sts_res['Credentials'] 转换为 session 要求的格式是简化,但是要注意以后 assume_role() 响应格式的变化有可能影响到程序的正常执行。

链接:

  1. How do I assume an IAM role using the AWS CLI?

类别: AWS. 标签: , . 阅读(62). 订阅评论. TrackBack.
guest
2 Comments
Inline Feedbacks
View all comments
robin
robin
29 days ago

好文,不错。baidu 里居然搜到你的文章。

Yanbin Qiu
28 days ago
Reply to  robin

哪位 robin? 为什么我自己在 baidu 里搜不到这篇 “assume site:yanbin.blog”

2
0
Would love your thoughts, please comment.x
()
x