Temporary Credential Using Cross Account Roles


AWS 跨帳號權限需要透過 Cross Account Roles 的方式來做,可以達到權責分離,不需要每個人在每個 AWS Account 開 IAM 帳號,達到管理便利的平衡。

使用場景

  • 依照不同環境拆分 AWS 帳號,常見的 Practice 會把 Production、Development、Test、Operation 各一個帳號,以符合權責分離、安全管控的原則。
  • 需要跨帳號存取資源,但是不想放 Access Key,像是 Deployment 或者資料交換的時候
  • 需要動態調整 VPC Peering 設定的時候
  • 不同的 AWS Account,不想要開重複的 IAM 帳號,減少管理成本

以下用 Jenkins 部署到正式環境的例子做說明。一台位在 Operation Account 的 Jenkins,需要部署新的 Release 到 Production Account

設定 IAM Role, Trust Relationship

要讓 IAM User / Group / Role 可以執行 Cross Account Role,以下權限要請系統管理員設定。

這邊用 Operation Account 需要存取 Production Account 做例子:

  • Production Account 建立一個 IAM Role 叫做 CA_ServiceDeployer,用來部署應用程式使用,需要有部署時的權限,主要的 IAM Policies 會在這裡設定。
  • Operation Account 建立一個 IAM Role 叫做 JenkinsRole,套在安裝 Jenkins 的 EC2 上,用來跨帳號部署,同時可以切換到 Production Account 的 CA_ServiceDeployer 角色,執行需要的權限。基本的流程如下圖:

1. 設定 CA_ServiceDeployer Role in Production Account

在 AWS Console IAM 新增 Role 步驟如下:




完成新增後,修改 CA_ServiceDeployer Role 的 Trust Relationship ,在 Principal 新增 JenkinsRole 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{OPERATION_ACCOUNT_NUM}:root",
"AWS": "arn:aws:iam::{OPERATION_ACCOUNT_NUM}:role/JenkinsRole"
},
"Action": "sts:AssumeRole"
}
]
}

設定 Permissions (IAM Policy),例如給予 S3 ReadOnly、CodeDeployer 的權限。

2. 設定 Operation 的 JenkinsService Role

在 Operation Account 新增 JenkinsService Role,把這個 Role 套用到 EC2 or AWS Services,允許執行 sts:AssumeRole,IAM Policy 如下:

1
2
3
4
5
6
7
8
9
10
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
}
]
}

也可以在 IAM User / Group 新增 Policy,讓 Developer 可以在 workstation 測試。

使用 Temporary Credential

取的臨時的 Credential and Session Token

SSH 到 Jenkins 的 EC2 裡面,執行以下 CLI。

1
2
3
4
5
root:# date
Sat Jun 17 06:23:10 UTC 2017
root:# aws sts assume-role \
> --role-arn "arn:aws:iam::{PRODUCTION_ACCOUNT_NUM}:role/CA_ServiceDeployer" \
> --role-session-name "Ops_JenkinsService"

取得臨時的 Credential 和 STS token,有效期限一個小時,資訊如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"AssumedRoleUser": {
"AssumedRoleId": "AROAJXESQxxxxxxxxxx:CA_ServiceDeployer",
"Arn": "arn:aws:sts::{PRODUCTION_ACCOUNT_NUM}:assumed-role/CA_ServiceDeployer/Ops_JenkinsService"
},
"Credentials": {
"SecretAccessKey": "i7dxPRu7xTAkWMxxxxxxxxxxx",
"SessionToken": "xxxxxxxxxYXdzEEAaDC6sE7hlNRoyce7a6CLVAVleA==",
"Expiration": "2017-06-17T07:24:20Z",
"AccessKeyId": "ASIAI26ILHxxxxxxxxxxxxx"
}
}

如果是使用 CLI 取得 STS Token,那麼可以搭配 jq 這個小工具協助解析 json,把它變成 script:

1
2
3
4
5
6
PRODUCTION_ACCOUNT_NUM=12345667222
sts_json=$(aws sts assume-role --role-arn "arn:aws:iam::{PRODUCTION_ACCOUNT_NUM}:role/CA_ServiceDeployer" --role-session-name "Ops_JenkinsService")
export AWS_ACCESS_KEY_ID=$(echo $sts_json | jq -r '.Credentials | .AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $sts_json | jq -r '.Credentials | .SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $sts_json | jq -r '.Credentials | .SessionToken')

使用臨時 Credential & STS Token 切換 Role

以下使用 CLI 做例子,使用 SDK 也是一樣的。先更改 AWS CLI 環境變數,export 臨時的 credential & token

1
2
3
export AWS_ACCESS_KEY_ID=ASIAI26ILHxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=i7dxPRu7xTAkWMxxxxxxxxxxx
export AWS_SESSION_TOKEN=xxxxxxxxxYXdzEEAaDC6sE7hlNRoyce7a6CLVAVleA==

執行動作:

1
2
~$ aws s3 ls
2016-12-03 23:18:07 prod-us-east-1-artifacts

成功在 Operation Account 裡的機器,執行 ls s3 bucket ,這個 s3 bucekt 是位在 Production Account 裡。

結論

以上是透過 Cross Account Role ,執行跨帳號權限的設定,最常用的案例就是部署的時候,以及跨帳號資料交換的時候。

這樣的應用,除了在 AWS CLI/SDK,同時也可以應用在 AWS Console 的 Switch Role,可以用 AWS Console 在不同的帳號之間穿梭,可以增加帳號管理便利性。

延伸閱讀

參考資料


留言