2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AssumeRoleできるかをローカルで検証する

2
Posted at

事の発端

Bアカウントが作成したS3バケットにAアカウントで書き込みたい。
Bアカウントの人にお願いしてバケットポリシーを書いてもらい、AアカウントからS3バケットへ書き込めるようにしてもらった。
無事に書き込めたが、BアカウントからS3オブジェクトに対して操作ができないと言われた。

なぜか?

ご存知だと思うが、この方法を使ってBアカウントの持つS3バケットにAアカウントを使ってオブジェクトを書き込めるが、
オブジェクトに対する操作ができない。これはオブジェクトの所有者がAアカウントになっている為である。
具体的にはオブジェクトに対する閲覧、権限変更ができない。しかしバケット自体に権限はあるのでBアカウントからオブジェクトを削除することは可能。
どうすればAアカウントからアップロードしたS3オブジェクトに対し、Bアカウントにも権限を付与できるか。

解決策

AssumeRoleを使ってBアカウントとして書き込めば、そのオブジェクトはBアカウントが所有者となるので、自由に権限を操作できる。
Bアカウントにお願いし、Aアカウントで用意したRole(以下、A-role)にのみAssumeでき、S3バケットに対して操作できるRole(以下、B-role)を用意してもらった。
これでAssumeRoleすれば書き込めるぞ!

ここで壁に当たる。

本当にA-roleでAssumeRoleできるのか検証しないといけない。
しかも操作するのはAWS Batchであった為、いちいちコンテナにスクリプト入れて試行錯誤する必要があって、とても手間がかかる。面倒。
AssumeできるのはA-roleにのみ許可されているので、Aアカウントに所属するIAMユーザーを使ってクレデンシャルを発行してもそのIAMユーザーにはB-RoleをAssumeできる権限はない。
あくまでA-Roleでないといけない。しかしA-Roleにクレデンシャルは発行できない。どうする・・・

ここで思いつく。

そうだ!A-RoleをさらにAssumeできるIAMユーザーを発行して、A-roleにAssumeし、
さらにそこからB-roleをAssumeすればいいんだ!

コードだと以下のような感じ。

import boto3
from boto3.session import Session

def main():
    # ユーザーとして入る。このユーザーはA-roleをAssumeできる権限があり、A-roleから信頼済みアカウントとして定義されている。
    client = boto3.client(
        'sts', 
        aws_access_key_id="A:User:xxx", 
        aws_secret_access_key="yyy")
    
    account_id = client.get_caller_identity()
    print("1. {}".format(account_id))

    # ユーザーとしてA-roleの権限をAssumeする。
    response = client.assume_role(
                RoleArn="arn:aws:iam::A:role/A-role",
                RoleSessionName="A-role"
            )
    
    # A-roleでクライアントを作る。
    A_session = Session(aws_access_key_id=response['Credentials']['AccessKeyId'],
                    aws_secret_access_key=response['Credentials']['SecretAccessKey'],
                    aws_session_token=response['Credentials']['SessionToken'],
                    region_name=REGION_NAME)
    A_client = A_session.client('sts')
    account_id = A_client.get_caller_identity()
    print("2. {}".format(account_id))
    
    # A-roleのクライアントを使ってAssumeRoleを行う。このRoleであれば許可されている為、Assumeできる。
    # このRoleにS3のアクセス権限がある。このRoleをAssumeできるのはA-roleのみ。
    response = A_client.assume_role(
                RoleArn="arn:aws:iam::B:role/B-role",
                RoleSessionName="Assume",
            )
    
    B_session = Session(aws_access_key_id=response['Credentials']['AccessKeyId'],
                    aws_secret_access_key=response['Credentials']['SecretAccessKey'],
                    aws_session_token=response['Credentials']['SessionToken'],
                    region_name=REGION_NAME)  
    B_client = B_session.client('sts')
    account_id = B_client.get_caller_identity()
    print("3. {}".format(account_id))

    # S3バケットにアップロードしてみる。B-roleにはS3バケットへの操作権限があるので書き込める。
    # またAssumeしているのでそのオブジェクトの所有者もBアカウントとなる。
    s3 = B_session.resource('s3')
    s3.meta.client.upload_file('A.png', "B-bucket", 'A.png')


if __name__ == "__main__":
    main()

まとめ

結局何がしたかったのかというと、RoleにのみAssumeが許可されている場合、いちいちEC2等にアタッチして検証するのは面倒なので、IAMユーザーを使って疑似的にEC2が行っている権限情報をSTSから貰う仕組みをやっている感じです。
EC2ならいいけど、これがコンテナ経由だとコンテナデプロイやって試行錯誤していると時間がもったいないので、お手軽にできるかと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?