エンジニア

2022.11.22

AWSで別アカウントの情報を取得したい

こんにちは。ハンズラボにJoinして早3ヶ月。
日々新しいことにチャレンジさせていただいているささきです。

先日、業務で別アカウントにあるアクセストークン情報を自アカウントにコピーするツールを作成してほしいとの依頼を受けて、
勉強がてらlambda関数で作成したので、その備忘録として残しておきます。

そもそも処理中に別アカウントにログインできるんだっけ・・・?

別アカウントにログインする方法を勉強不足のため知らなかったのですが
“IAM Role AssumeRole” を使用して実装します。

AssumeRole とは

IAM ロールを使用して、他アカウントにAWS リソースのアクセス許可を委任します。信頼するAWSアカウントと他の信頼される AWS アカウントとの信頼関係が確立されます。

簡潔に言うと、”別AWSアカウントを操作できるようになるよ。”と言うことです。

今回やることはこちら。

① 接続先アカウントにIAMロールを作成
② 接続元IAMロールに接続先のロールを指定

これだけです。

コンソール上で構成する

① 接続先アカウントにIAMロールを作成

接続先アカウントにスウィッチするためのIAMロールを作成します。
 1. 信頼されたエンティティを選択画面で ”AWSアカウント”を選択
 2. 別のAWSアカウント のラジオボタンを選択し、添付画像の赤枠のテキストボックスに接続元のアカウントIDを入力
 3. やりたいことのポリシーをアタッチ(自分は今回DynamoDBに接続したかったので”AmazonDynamoDBReadOnlyAccess”をアタッチしました。)

② 接続元IAMロールに接続先のロールを指定

接続元アカウントにAssumeRoleするために、IAMロールのポリシーを追加します。
 1. 接続元IAMロール画面移動(今回はlambda関数で接続するのでlambda関数のIAMロールを編集しました。)
 2. 許可を追加→ポリシーをアタッチ
 3. ポリシーを作成
 4. 以下のJSONで作成

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Sid": "AllowAssumeCrossAccountRole",
           "Effect": "Allow",
           "Action": "sts:AssumeRole",
           "Resource": "arn:aws:iam::[接続先アカウントID]/[接続先IAMロール]"
       }
   ]
}

とっても簡単でした。

CloudFormation / Serverless で構成する

コンソールで構築できたので次はCloudFormation / Serverless で構成してみようと思います。

① 接続先アカウントにIAMロールを作成

IAMロールのみの作成なのでCloudFormationで作成します。
ymlファイルの中身は以下です。

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  IamRoleHoge:
    Type: AWS::IAM::Role
    Properties:
      RoleName: iam_role_hoge
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
            Effect: "Allow"
            Principal:
              AWS:
                - "arn:aws:iam::<<接続元のアカウントID>>:root" 
            Action:
              - "sts:AssumeRole"
      Description: "hoge hoge iam role"
      ManagedPolicyArns: 
        - "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess"

② 接続元IAMロールに接続先のロールを指定

こちらはlambda関数も作成するので、Serverless Frameworkで作成します。
ymlファイルの中身は以下です。

  # IAMロールの作成
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - dynamodb:UpdateItem
            - dynamodb:Scan
            - dynamodb:Query
            - dynamodb:DeleteItem
          Resource:
            - arn:aws:dynamodb:<<自アカウントのリージョン>>:<<自アカウントID>>:table/<<DynamoDbテーブル名>>
            - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - Effect: Allow
          Action:
            - sts:AssumeRole
          Resource:
            - "arn:aws:iam::<<接続先アカウントID>>:role/<<接続先IAMロール(①で作成したIAMロール名)>>"

やっぱりとっても簡単でした。

AssumeRole するためのlambdaのコード(Pythonで実装しています)

※今回はboto3のライブラリを使用しAssumeRoleします。

	import boto3

        # ------------------------------------------
        # 別アカウントにログインするためSessionを定義(assume_roleで接続)
        # ------------------------------------------
        # 接続先のAWS認証
        sts = boto3.client('sts')
        access_info = sts.assume_role(
            RoleArn=f'arn:aws:iam::<接続先のアカウントID>>:role/<接続先のIAMロール名>',
            RoleSessionName='cross_acct_lambda'
        )

        session = boto3.Session(
            aws_access_key_id=access_info['Credentials']['AccessKeyId'],
            aws_secret_access_key=access_info['Credentials']['SecretAccessKey'],
            aws_session_token=access_info['Credentials']['SessionToken'],
        )
		
		# セッション情報からDynamoDBオブジェクト取得
		dynamodb = session.resource('dynamodb')
		
		# テーブルオブジェクト作成
		table = dynamodb.Table(<テーブル名>)

AssumeRoleを使用し、セッション情報を取得。
取得したセッション情報を元に、DynamoDBにアクセスしています。

無事、AssumeRoleを使用し、別AWSアカウントへのログイン確認が取れました。
別AWSアカウントにログインしたい場合は是非”AssumeRole”を活用ください。
完全に余談ですが、AssumeRoleと初めて聞いた時、たくさんの顔がある怪物を想像してしまいました。
とっても怖い怪物でした。

終わります。

一覧に戻る