[Lambdaでクロスアカウント] Lambda 関数で AssumeRole して他の AWS アカウントのリソースにアクセスする

2018.05.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、菊池です。

Lambda関数で異なるAWSアカウントのリソースにアクセスしたい場合、S3やSQSのようにリソース側でアクセスポリシーを設定可能なサービスであれば、それを利用してクロスアカウントのアクセス許可を与えるのが一般的です。

しかし、リソース側でポリシーを設定できないサービスの場合にはそうもいきません。そのようなケースでは、信頼関係を結んだIAMロールを使って、一時クレデンシャルを発行してアクセスする方法があります。

PythonのAWS SDKであるBoto3を使った例が以前紹介されていました。

AWS SDK For Python (Boto3) で AssumeRole を使ってみた

今回は、これを応用してLambda関数で同様の処理を行い、他のAWSアカウントのリソースにアクセスすることを試してみました。

動作イメージ

処理のイメージは以下のようになります。

あらかじめアカウントBで、アカウントAのIAMロールAを信頼した、IAMロールBを作成しておきます。Lambda関数はまず、IAMロールAの認証情報を利用して、IAMロールBの一時クレデンシャルを取得します。その認証情報を利用して、アカウントBのリソースにアクセスします。

サンプルコード

import boto3
from boto3.session import Session

# 異なるAWSアカウント/ロールのクレデンシャル取得を実行する
def sts_assume_role(account_id,role_name):
    role_arn = "arn:aws:iam::" + account_id + ":role/" + role_name
    session_name = "foobar"
    region = "ap-northeast-1"

    client = boto3.client('sts')

    # AssumeRoleで一時クレデンシャルを取得
    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 lambda_handler(event,context):
    account_id = event['account']
    role_name = event['role']

    # イベントで指定されたAWSアカウント/ロールのクレデンシャルを取得
    session = sts_assume_role(account_id,role_name)

    sts = session.client('sts')

    # 取得したクレデンシャルを使って処理を実行
    response = sts.get_caller_identity()["Account"]
    return response

イベントとして、アクセス先のAWSアカウントIDとIAMロール名(上記図の、アカウントB/IAMロールBに相当)を入力することで動作します。

{
  "account": (AWSアカウントID),
  "role": (IAMロール名)
}

上記サンプルでは、取得した認証情報のAWSアカウントIDをsts.get_caller_identityで出力するのみの処理です。

まとめ

Lambdaを使ったクロスアカウントアクセスを柔軟にできないかと思い、試してみました。

Lambda関数に元々割り当てていたIAMロールで直接アクセスするのに比べ、AssumeRoleが必要な分、処理のオーバーヘッドがありますので、パフォーマンスにシビアなユースケースでは注意が必要です。