1. はじめに
Lambdaから別AWSアカウントのリソースにアクセスする要件がたまにあります。
別AWSリソースにアクセスすることをクロスアカウントアクセス
といいます。
ただ、私はクロスアカウントアクセスという単語を耳にしたことがありますが、自分自身で設定をおこなったことがなかったので、一度設定をしてみました。
ここでは、LambdaからクロスアカウントのS3にアクセスするための設定をまとめます。
2. 前提
-
AWSアカウントを2つ用意していること。
-
LambdaがあるアカウントをAアカウント、S3があるアカウントをBアカウントとする。
3. 関連知識
クロスアカウントアクセスに必要な知識を解説します。
3.1 AWS Security Token Service (AWS STS) とは
AWS Security Token Service (以下、AWS STS) とは、AWSリソースへのアクセスコントロールできるサービスで一時的な認証情報発行します。
AWS STSは、クロスアカウントのアクセスや他要素認証などに利用されます。この一時的なクレデンシャルは数分~最大12時間までの有効期限を設定できます。
3.2 Assume Roleとは
**Assume Role(アシュームロール)**とは、一時的に別の権限を持ったロールを使えるようにする仕組みです。
AWSでは、通常IAMユーザーやLambdaなどが操作を行いますが、Assume Roleを使うと、
一時的な認証情報を作成して、そのロールを引き受けて、そのロールが持っている権限でAWSサービスにアクセスできます。
この一時的な認証情報は**AWS STS(Security Token Service)**が発行します。
4. AWS構成図
5. クロスアカウントアクセスするための設定
5.1 Aアカウント側のLambdaの実行ロール
Lambda実行ロール作成します。
クロスアカウントアクセスするために重要なのが、sts.AssumeRole
を付与しやポリシーを作成することです。
Resourceには、クロスアカウント先のロールを取得します。
ここでは、アカウントBに作成するS3にアクセスするための、ロールを作成し、そのロールを引き受けられるように設定します。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: 'lambda-execution-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: 'allow-cloud-watchlogs-access'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
- logs:DescribeLogStreams
- logs:CreateLogGroup
Resource: '*'
- PolicyName: 'allow-access-s3-bucket'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: sts:AssumeRole
Resource: arn:aws:iam::{アカウントB}:role/CrossAccountLambdaAccessRole
5.2 Lambdaのアプリケーションコード
STSでアカウントBのCrossAccountLambdaAccessRoleへの一時的な認証情報を取得し、アカウントAのLambdaがCrossAccountLambdaAccessRoleを引き受けます。
CrossAccountLambdaAccessRoleを引き受けることによってアカウントBのS3へアクセスします。
※ Lambdaは、マネージメントコンソールから作成しました。Lambdaには、5.1 Aアカウント側のLambdaの実行ロール
を紐付けてください。
※ AWS SAMやCloudFomration、CDKで作成したい方は、別途調べて作成してください
import boto3
def lambda_handler(event, context):
sts = boto3.client('sts')
assumed = sts.assume_role(
RoleArn='arn:aws:iam::{アカウントB}:role/CrossAccountLambdaAccessRole',
RoleSessionName='LambdaSession'
)
credentials = assumed['Credentials']
s3 = boto3.client(
's3',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken']
)
s3_response = s3.get_object(
Bucket='cross-account-test-bucket', Key='file.txt'
)
print(s3_response['Body'].read().decode('utf-8'))
5.3 Bアカウント側の設定
- 作成するリソース
- S3バケット
- バケットポリシー
- IAMロール
アカウントBのポリシーはアカウントAのLambda実行ロールを信頼ポリシーに設定します。 許可ポリシーには、S3バケットへのアクセス許可を設定します。
AWSTemplateFormatVersion: 2010-09-09
Resources:
# アカウントAのLambdaがアカウントBにアクセスするためのIAMロール
S3AccessRole:
Type: AWS::IAM::Role
Properties:
RoleName: CrossAccountLambdaAccessRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: "arn:aws:iam::{アカウントA}:role/lambda-execution-role"
Action: sts:AssumeRole
Policies:
- PolicyName: AllowS3Access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
Resource: "arn:aws:s3:::cross-account-test-bucket/*"
# S3バケット
CrossAccountTestBucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: "cross-account-test-bucket"
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
# バケットポリシー
SreBlogStaticBucketPolicy:
Type: 'AWS::S3::BucketPolicy'
DependsOn: CrossAccountTestBucket
Properties:
Bucket: !Ref CrossAccountTestBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: "arn:aws:iam::{アカウントA}:role/$lambda-execution-role"
Action:
- "s3:GetObject"
- "s3:PutObject"
Resource: "arn:aws:s3:::cross-account-test-bucket/*"
6. おわりに
クロスアカウントアクセスは、はじめて設定する際、戸惑うことがありました。AWS STSやAssume Roleなど関連の単語は聞いたことがありましたが、きちんと理解できていませんでした。
やはり、わからないことを理解するには、一つ一つわからない要素を理解する必要があるなと思いました。
7. 参考ページ
IAM の一時的な認証情報 AssumeRole Amazon S3 バケットにあるオブジェクトに対するクロスアカウントアクセス許可を付与するにはどうすればよいですか?