东东's Blog

AWS Role / AssumeRole 使用场景及权限验证


最近花了些时间将服务的 AKSK 切换为 Role 认证方式,本篇博文对 AWS Role 及 AssumeRole 的一些知识点整理如下。

什么是 AWS Role?#

先从 AWS AKSK 说起,以往程序使用 S3、SQS 等 AWS 服务,一般是通过 KeyID、Secret Access Key 进行鉴权,好处是使用方便,但无法避免安全问题,一旦泄露就会对服务安全构成威胁。

使用 Role 可以解决这一问题,AWS 的 EC2 和 ECS Task 等资源都可以绑定 Role,从近期改造 Jenkins、Golang、Vector 的配置从 AKSK 到 Role 来看,使用 Role 很方便。

备忘记录。

什么是 AssumeRole?#

AssumeRole是AWS Identity and Access Management(IAM) 中的一个 API 操作,他允许一个 AWS 角色(Role) 临时地假设另一个角色,从而获得该角色的权限。当你需要一个 AWS 角色临时获得另一个角色的权限时,可以调用 AssumeRole API,让该角色假设目标角色身份,实现跨账号访问。

一个说不定有用的小 Tips:一个 Role 授权允许的情况下可以 AssumeRole 到自身,当多个服务公用配置的时候很灵活。

以下是几个使用 Role 的场景

场景1:ECS Task 内拉取 Code Commit 配置#

在这个场景下,Git CodeCommit 插件自动使用本机 Role 信息,即 Task Role,所以需要 ECS Task Role 具备访问 CodeCommit 的权限,Git 配合 CodeCommit 插件无需任何配置,即可使用本机的权限。

补充:通过设置 AWS_ROLE_ARN 和 AWS_ROLE_SESSION_NAME 两个环境变量,可以让 git-remote-codecommit 插件 AssumeRole 到其他角色。

场景2:ECS Task 内使用 Vector 上报 S3#

在 ECS Task 的 Vector 容器中,将收集到的日志发送到 S3,需要注意的是 S3 和 Vector 服务不在一个账号内。

Vector 服务跟 CodeCommit 插件的不同是,CodeCommit 自动使用本机的 Task Role,而 Vector 可以指定 assume_role,这样,我们可以在 S3 所在区域创建一个 IAM Role,为其赋予读写 S3 的权限。

再赋予 ECS Task Role 权限,使其能够具备 AssumeRole 的能力。这样,Vector 使用 Task Role 自动切换到 S3 Role,具备读写 S3 的能力。

场景3:EC2 下 Jenkins 使用 Role#

Jenkins 在使用 Jenkinsfile 调用 ansible 部署服务到正式环境时,使用 Role 进行认证。

使用 AWS 插件提供的 withAWS step,可以指定 Role 信息,跟 Vector 中指定 Assume Role 是类似的,需要 EC2 的基础 Role 具备切换为指定 Role 的权限,使得 ansible 具备访问 ECR / ECS 的能力。

EC2 和 ECS Task 配置 Role 在使用上有无区别?#

通过在不同场景的实践,可以得出以下结论

  • ECS Task Role 可以理解为 EC2 Role,在使用 Role 上没有区别。
  • 如果 Task 未绑定 ECS Task Role,那么在 Task 的容器内部获取到的 Role 即部署 Task 的 EC2 的 Role。
  • 如果 Task 绑定了 ECS Task Role,那么在 Task 的容器内部获取到的 Role 是 ECS Task Role。

通过 AWS CLI 获取本机绑定的 Role#

首先,安装 aws-cli 后需要先配置地区,AKSK 不用填写,回车即可。

[root@jumpserver ~]# aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: json

而后获取当前身份

$ aws sts get-caller-identity

输出

{
    "UserId": "AROA772VM***N4XQO3LPZ:i-0d8426c3***12cb43",
    "Account": "AIOAM62***2S712R83HN",
    "Arn": "arn:aws-cn:sts::AIOAM62***2S712R83HN:assumed-role/Role-allprompts-server-dev/i-0d843273d0b24cc2z"
}

测试其是否有 AssumeRole 到指定 Role 的权限#

AssumeRole 即程序可以借助当前机器的 Role,切换到另一个 Role,是否有权限切换,由绑定在机器上的 Role 权限决定。

$ aws sts assume-role --role-arn "arn:aws-cn:iam::AIOAM62***2S712R83HN:role/1122_server_ec2_dev_role" --role-session-name AWSCLI-Session

输出

{
    "Credentials": {
        "AccessKeyId": "<REDACTED_ACCESS_KEY_ID>",
        "SecretAccessKey": "<REDACTED_SECRET_ACCESS_KEY>",
        "SessionToken": "<REDACTED_SESSION_TOKEN>",
        "Expiration": "2023-07-24T11:07:48+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "<ACCOUNT_ID>:AWSCLI-Session",
        "Arn": "arn:aws-cn:sts::<ACCOUNT_ID>:assumed-role/1122_server_ec2_dev_role/AWSCLI-Session"
    }
}

正确输出如上,即机器绑定的 Role 允许用户或程序切换使用 1122_server_ec2_dev_role 角色。反之会提示权限错误

测试角色是否有 S3 权限#

$ aws s3 ls s3://my-bucket

如果当前机器 Role 拥有权限,则会输出目录,一般在使用时,也倾向于机器上配置比较基础的 Role,访问资源时 AssumeRole 到资源 Role,这样权限解耦,同时也能应对跨账号问题。

假设我们的机器绑定的是很基础的 Role,没有访问 S3 的权限,需要 AssumeRole 到指定 Role,如何通过 AWS CLI 模拟呢?

需要使用小节命令 aws sts assume-role ... 获取到的 Token,设置环境变量

$ export AWS_ACCESS_KEY_ID=<REDACTED_ACCESS_KEY_ID>
 
$ export AWS_SECRET_ACCESS_KEY=<REDACTED_SECRET_ACCESS_KEY>
 
$ export AWS_SESSION_TOKEN=<REDACTED_SESSION_TOKEN>

而后再次执行命令,即可查询 S3 桶下目录。

备注:如需要进一步确认可写权限,可以使用如下命令

$ echo "test file" > test_file.txt
$ aws s3 cp test_file.txt s3://my-bucket/test_file.txt

测试角色是否有 SQS 权限#

$ aws sqs get-queue-url --queue-name user_identity_event

结果

{
    "QueueUrl": "https://sqs.cn-northwest-1.amazonaws.com.cn/AIOAM62***2S712R83HN/user_identity_event"
}

AssumeRole 使用方式跟 S3 使用临时 Token 的方式同理。

总结#

最后,Role 和 AssumeRole 的使用容易,但要避免混乱的权限分配,角色的命名和使用也需要设计一套方案来约束,保障安全的同时也便于维护。