AWS STSを使って、Lambdaから別環境のDynamoDBにクロスアカウントアクセスする

# 注意
当記事を参考にし実装された内容に関して、当記事は責任を負いません。
あくまでも自分向けに記録したものであり、
ご参考いただく際は各自ご判断ください。

# 参考
当記事は、こちらの記事を参考にさせていただきました。ありがとうございます。
https://dev.classmethod.jp/cloud/aws/assume-role-in-lambda-function/

# 何をするの？
AWS STSを使って、Lambdaから別環境のDynamoDBにクロスアカウントアクセスします。

とある案件で、自社サービスを運用しているAアカウントから、追加機能をBアカウントに移行しました。
ただし、追加機能の設定テーブルはAアカウントのままで、BアカウントのLambdaからAアカウントのDynamoDBを参照しないといけない状況でした。
アクセスキーを発行してもいいのですが、それを保存するDBはどうするのか…などの問題があり、今回はクロスアカウントアクセスというものを試してみました。

# やること
STSを使い、AssumeRoleをし、発行した一時キーを使ってアカウントを跨いでLambda→DynamoDBのアクセスを行います。

以下、**AアカウントのLambda　→　BアカウントのDynamoDBテーブルのクロスアカウントアクセス**の設定方法です。

# IAMの準備
AアカウントとBアカウントの両方でロールを作成する必要があります。
Aアカウントのロール…参照元。LambdaにSTSの権限を与えるポリシーをアタッチしたロール
Bアカウントのロール…参照先。信頼したアカウントIDのLambdaからのアクセスを特定のサービスに許可するポリシーをアタッチしたロール

## 参照元のロールの設定(Aアカウント側)
Lambda関数を作成し、新規ロールを作成して紐付けてください。
以下はそのロールの編集です。

[アクセス権限]>[インラインポリシーの追加]から以下のポリシーを追加してください。

![IAM_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/123008/0b738be4-d444-bbcf-cd4a-5dbc57cdfc54.png)

```
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "参照先のロールのARN"
    }
}
```


## 参照先のロールの設定(Bアカウント側)
参照先のBアカウントでロールを作成し、[信頼関係]>[信頼関係の編集]から、信頼するロールを記述します。

<img width="1307" alt="IAM_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/123008/9688af1e-4695-652a-ae5d-234d0ab082fa.png">

以下のポリシーを上書きしてください。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "許可するアカウントのロールのARN"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
```

[アクセス権限]>[インラインポリシーの追加]から以下のポリシーを追加してください。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:GetRecords"
            ],
            "Resource": "許可するDynamoDBテーブルのARN"
        }
    ]
}
```



# STSを利用したLambdaのコーディング(Python 3.7)
STSで発行した一時キーを利用し、信頼関係にあるDynamoDBからget_itemします。
`role_arn` はクロスアカウントアクセスを許可しているロールのARNを当ててください。

```python:caa.py
import boto3
from boto3.session import Session
 
def get_sts_session():
    role_arn = "リソース側のロールのARN" # クロスアカウントアクセスを許可しているロール
    session_name = "なんか適当な名前"
    region = "us-east-1"
    client = boto3.client('sts')
 
    # assume_roleでロールに設定された権限のクレデンシャル(一時キー)を発行する
    response = client.assume_role(
        RoleArn=role_arn,
        RoleSessionName=session_name
    )
    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
    )
    return session

def get_item_cross_account(session):
    # 新しく発行したsessionを使って実行する
    dynamodb = session.resource("dynamodb")
    table = dynamodb.Table("hoge")
    id = "id001"
    items = table.get_item(
            Key={
                 "device_id": id
            }
    )
    print(items)

def lambda_handler(event,context):
    session = get_sts_session()
    get_item_cross_account(session)
```

無事、アカウントをまたいでget_itemすることができました！
以上でクロスアカウントアクセスの説明を終わります。

![Lambda_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/123008/2167801b-96ff-ae64-dcd4-fd6ed2a2fef8.png)