やりたい事
AアカウントからBアカウントへAssumeRoleして、Bアカウントが持つS3バケットへファイルのアップロードを行う。
なぜAssumeRoleが必要なのか
アクセスを許可すればAアカウントからBアカウントのもつS3バケットへのアップロードは可能だが、オブジェクトのオーナーがAアカウントになってしまう。
こうなると、Bアカウントが持つS3バケットに設定するバケットポリシーが無視されたり、オブジェクトのアクセスができなくなるなど、不都合なことが起こる。
なので、AssumeRoleしてBアカウントとしてファイルをアップロードすることで、S3バケットの管理者とオブジェクトの管理者を統一しておく。
これでアクセス権限などの予期せぬ問題を起こしにくくする。
手順
- Aアカウント管理者はA-Roleを作る。例としてLambdaの実行ロールとかBatchのタスクロールとか。これのARNをコピーしてBアカウント管理者に送る。
- Bアカウント管理者はB-Roleを作る。これはBアカウントが持つS3バケットへの書き込み権限を付与する。
- B-Roleの信頼エンティティにA-RoleのARNを入れ、A-RoleからのAssumeRoleリクエストを承認できるようにしておく。「信頼関係の編集」より、
Principal
にKeyをAWS,Valueに信頼するIAMロールのARNを入力します。Action
にはsts:AssumeRole
を入力する。これでA-RoleからのAssumeRoleリクエストを承認する事ができる。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxx:role/A-Role"
},
"Action": "sts:AssumeRole"
}
]
}
- B-RoleのARNをコピーしてAアカウント管理者に送る。
- A-RoleにAssumeRoleする為のポリシーを設定する。インラインポリシーで大丈夫。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::yyy:role/B-Role"
}
]
}
これで作業は完了。A-Roleを使ってB-RoleをAssumeする為のサンプルコードは以下
# A-Roleの権限を使って、B-RoleのAssumeリクエストを送信。この時にA-RoleにAssumeRoleのポリシーがないと権限不足でエラーとなる。
sts_default_provider_chain = boto3.client('sts')
creds = sts_default_provider_chain.assume_role(
RoleArn="arn:aws:iam::yyy:role/B-Role",
RoleSessionName="session-test",
DurationSeconds=900
)
# 受け取ったB-Roleのクレデンシャル情報を使って、Sessionを作る。
session = Session(aws_access_key_id=creds['Credentials']['AccessKeyId'],
aws_secret_access_key=creds['Credentials']['SecretAccessKey'],
aws_session_token=creds['Credentials']['SessionToken'],
region_name='ap-northeast-1')
# 作成したSessionで新たにリソースを作る。S3へのアクセスがしたいのでS3を指定。
s3 = session.resource('s3')
# ファイルをアップロード。ここで出来なければB-RoleにS3関連の権限がないので確認する。
s3.meta.client.upload_file('A.png', "B-bucket", 'A.png')