LoginSignup
2
0

More than 5 years have passed since last update.

サービスロールを使ったクロスアカウント連携の設定方法(S3 + Lambda + STS)

Posted at

サービスロールとSTSを利用してクロスアカウント連携をしたい場合の設定方法です。

この設定ができると、サービスロールによるクロスアカウントのアクセス制御ができると、
IPが固定されないLambdaでも制御できるようになりますし、連携先のアカウントにもキーを発行などする必要がなくなるので
便利です。(ただ、テストのためにちょっと工夫する必要がありますが・・・。)

■こんな感じ

サービスロールを利用したクロスアカウント連携.jpg

サンプル実装

0. policyの作成

  1. 「サービスの選択」> "STS"を選択
  2. 「アクション」の"All STS actions (sts:*)"を選択
  3. 「リソース」すべてのリソース
  4. 「Review policy」を押し、名前を入力して「Create Policy」から作成

1. サービスロールAの作成

  1. サービス> IAM > ロール
  2. ロールの作成 -「信頼されたエンティティの種類を選択」で「AWSサービス」の「Lambda」を選択
  3. ポリシーに上記 「0. policyの作成」で作成したポリシーを指定
  4. ロール名を入力し作成

2. サービスロールBの作成

  1. サービス> IAM > ロール
  2. ロールの作成
  3. 「信頼されたエンティティの種類を選択」で「AWSサービス」の「Lambda」を選択
  4. ポリシーに「AmazonS3FullAccess」を選択
  5. ロール名を入力し作成
  6. 作成したサービスロールBを選択し、「信頼関係」タブをひらく。
  7. 「信頼関係の編集」をひらき、以下の内容で上書きして「信頼ポリシーの更新」をおして更新
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::`{アカウントAのID}`:role/`{サービスロールAの名前}`"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

3. データの準備(バケットの作成とテストファイルの作成)

  • AWSアカウントB側に適当なバケットを作成する。
  • sample.txtとしてアップロードする。

4. Lambdaファンクションの作成

  • サービス > Lambda > 「関数の作成」
  • 「一から作成」から適当に関数を作成。
    • "ランタイム" は Python3.6
    • "ロール"は、サービスロールAを指定
  • 「関数コード」セクションの「コードエントリータイプ」を"コードをインラインで編集"に設定
    • lambda_functionに書きのコードをコピーして貼る
# -*- Coding: utf-8 -*-
from __future__ import print_function

import boto3
import botocore


ROLE_ARN='arn:aws:iam::{アカウントBのID}:role/{サービスロールBの名前}'

def get_credentials():
    # // STS Client
    sts_client = boto3.client('sts', 'ap-northeast-1')
    assumeRoleObject = sts_client.assume_role(
        RoleArn=ROLE_ARN,
        RoleSessionName="s3-access"
    )
    return assumeRoleObject['Credentials']

def s3_resource():
    credentials = get_credentials()
    s3_resource = boto3.resource(
        's3',
        aws_access_key_id = credentials['AccessKeyId'],
        aws_secret_access_key = credentials['SecretAccessKey'],
        aws_session_token = credentials['SessionToken']
    )
    return s3_resource


def lambda_handler(event, context):

    bucket = '{作成したバケット名}'
    key = 'sample.txt'

    try:
        obj = s3_resource().Object(bucket, key)
        response = obj.get()

        print("CONTENT TYPE: " + response['ContentType'])
        print("Body        : " + response['Body'].read(1024*256).decode('utf-8'))

#        with open('sample.txt','a') as output:
#            chunk = response['Body'].read(1024*256)
#            while chunk:
#                output.write(chunk.decode('utf-8'))
#                chunk = response['Body'].read(1024*256)

        return response['ContentType']
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e


■こんな感じで。

lambdaファンクションの作成1.PNG

■サービスロールがSTSにアクセス権限があることがこれで確認できます
lambdaファンクションの作成2.PNG

動作確認

・「3.Lambdaファンクションの作成」で作成した Lambdaでテストを実行すれば確認できるはず・・・。

実行結果サンプル.PNG

この機能のポイント

  • リソースを提供する側(アカウントB側)が、アカウントAのアクションを制御できる。
  • 設定する場合は、リソースを提供される側(アカウントA)が、連携するサービスロールのARNを 提供する側に教える。
  • 今回のようにLambdaが別アカウントのS3を利用するだけであれば、Lambdaのサービスロールに Amazon S3のアクションを付与する必要はない。

こんなときは?

  • クロスアカウントでS3からS3へファイルを移したいとき。
    • 直接、S3間のコピーはできないので一度、一時ファイルを作成してから、2回にわけて移動させる。 ⇒この場合は、サービスロールA側にもAmazonS3へのアクセス権限が必要になる。
  • 開発環境と本番環境どうわける?
    • ROLE_ARNをきりかえられるようにすれば自動的に環境先のサービスロールが切り替わります。 ⇒ サービスロールBのポリシーでうまいことアクセスを絞ると良いかと。

以上です。
アカウント二つないと試せないですが、どういう設定をすればいいのかがわかってもらえたらいいな・・。

明日は、@maemoriさんです。

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