LoginSignup
1
1

More than 1 year has passed since last update.

Lambda関数内で、別AWSアカウントのLambda関数を呼び出す

Posted at

AWSアカウントA内のLambda関数から、AWSアカウントB内にあるLambda関数を呼び出す方法の備忘録です。

もともとのゴールは、アカウントA内のAmazon Lexボットから、アカウントB内のLambda関数を直接呼び出すことでした。

しかし現状無理そうなので、アカウントA内の(プロキシ)Lambda関数を経由して、間接的にアカウントBの(本命)Lambda関数を呼び出すことにしました。

概要

Lexボットがある、呼び出し側のAWSアカウントをアカウントA(ID:999999999999)呼び出される本命Lambda関数がある側のAWSアカウントをアカウントB(ID:000000000000)とします。

アカウントA内に作成するプロキシLambda関数が、アカウントB内の本命Lambda関数を呼び出すには、アカウントBの側でアカウントAのアクセスを許可する必要があります。

セットアップ全体の流れは次のとおり。

  1. アカウントB内に、本命Lambdaの実行権限を持つIAM Roleを作成
  2. アカウントA内に、上記のRoleと連携するRoleを作成
  3. アカウントA内で、このRoleの下にプロキシLambda関数を作成
  4. プロキシLambda内で、Roleの権限を行使して本命Lambdaを実行
  5. (おまけ)LexボットがプロキシLambda関数を呼び出すようにする

Step 1:アカウントB内に IAM Roleを作成

まずアカウントB側で、本命Lambdaを実行できる権限を持つ、アカウントA用のIAM Roleを作成します。

アカウントB(ID:000000000000、本命Lambda側)上で、AWS管理コンソールのメニューから IAM > Access management > Rolesを開きCreate roleボタンをクリック。
image.png

Select type of trusted entityセクションでAnother AWS accountを選択し、Account ID欄にアカウントAのIDを入力。アカウントAがこのロールを担う主体となります。
Next: Permissionsをクリック。

image.png

Attach permissions policiesセクションでは、このロールが持つ権限としてAWSLambdaRoleポリシーを選択し、次に進みます。
image.png

Tagsセクションでは、必要であればタグを指定して次に進みます。

次のReviewセクションで、Role name欄に任意のロール名を入力して、Create roleボタンをクリック。
ロールが新規作成されます。
image.png

作成されたロールを開き、ロールのRole ARNを控えておきます。(Step 2と3で使用する)
image.png

Step 2:アカウントA側にもロールを作成

次はアカウントA側に、Step 1で作成したロールと連携するロールを新規作成します。

アカウントA(ID:999999999999、LexボットとプロキシLambda側)上で、AWS管理コンソールのメニューから IAM > Access management > Roles を開き、Create roleボタンをクリック。
image.png

Select type of trusted entityセクションでAWS service、Choose a use caseセクションではLambdaを選択。
image.png

Attach permissions policiesセクションで、Create policyボタンをクリック。
image.png

新しいブラウザーウィンドウ(またはタブ)が開きます。JSONタブに移動し、下記のようなインラインポリシーを作成します。
image.png

インラインポリシーのテキストはこちら↓。
Resourceの値として、Step 1で作成したロールのARNを指定します。

AssumeRolePolicy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::000000000000:role/myIntegrationLambda" //アカウントBで作成したロールのARN
        }
    ]
}

Tagsセクションは、必要であればタグを指定して次に進みます。

次のReview policyセクションで、Name欄に任意のポリシー名を入力し、Create policyボタンをクリック。
インラインポリシーが新規作成されます。
このウィンドウ(またはタブ)を閉じて、手続き途中だったCreate roleのウィンドウに戻ります。
image.png

Create roleのブラウザーウィンドウに戻り、Attach permissions policiesセクションで、ロールに付与するポリシーを選択します。
ここではAWSLambdaBasicExecutionRoleと、今作成したインラインポリシーを選択。
image.png
AWSLambdaBasicExecutionRoleはアカウントA内のLambdaを実行する権限、インラインポリシーはStep 1で作成した、アカウントB側のロールを執行する権限を付与するポリシーです。

Next: Tagsボタンをクリック。
image.png

Tagsセクションでは、必要であればタグを指定して、次に進みます。

次のReviewセクションで、Role name欄に任意のロール名を入力してCreate roleボタンをクリック。
アカウントA側のロールが新規作成されます。
image.png

Step 3:アカウントA側で(アカウントB内の本命Lambdaを呼び出す)プロキシLambdaを作成

アカウントA(ID:999999999999)のAWS管理コンソールで、Lambdaを開き、Create functionボタンをクリック。プロキシLambda関数を新規作成します。
image.png

Author from scratchを選び、Function name 欄に任意の関数名を入力。
RuntimeはNode.js 14.xを選択し、Change default execution roleセクションをクリックして開く。
image.png

Change default execution roleセクションでは、Step 2で作成したロールを指定するのでUse an existing roleを選択します。
image.png

Existing roleのドロップダウンリストで、Step 2で作成したロールを選びます。
このロール選択により、プロキシLambdaがアカウントBの本命Lambdaを実行できる権限を持ちます。
Create functionボタンをクリックして、Lambda関数を新規作成します。
image.png

Step 4:プロキシLambda内で、Roleの権限を行使して本命Lambdaを実行

本命Lambda関数を呼び出して実行するプロキシLambda関数のコードを書きます。

Lambda関数の画面では、上部右側に、その関数のARNが表示されています。プロキシLambdaのコード内で、本命LambdaのARNが必要になるので、予めアカウントB内の本命Lambdaから取得しておきます。
image.png
index.jsに、下記のコードを入力します。

ProxyLambda
const aws = require('aws-sdk');

"use strict";


// --------------- Main handler -----------------------

// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = async (event, context, callback) => {
        console.log("Started");
        const lexPost = JSON.stringify(event);
        console.log(lexPost);


        var sts = new aws.STS({apiVersion: '2011-06-15'});
        var stsParams = {
            RoleArn: "arn:aws:iam::000000000000:role/myIntegrationLambda", //Step 1で作成したロールのARN
            DurationSeconds: 3600,
            RoleSessionName: "assumeRoleSession"
        };

        const stsResults = await sts.assumeRole(stsParams).promise();
        console.log("STS Result: ", stsResults);

        var lambda = new aws.Lambda({
            region: 'ap-northeast-1', //アカウントAのlambdaがあるリージョン
            accessKeyId: stsResults.Credentials.AccessKeyId,
            secretAccessKey:stsResults.Credentials.SecretAccessKey,
            sessionToken: stsResults.Credentials.SessionToken
        });


        console.log("Got new Lambda");

        const params = {
            FunctionName: "arn:aws:lambda:ap-northeast-1:000000000000:function:myMainLambda", //アカウントAのlambdaのARN
            InvocationType: "RequestResponse",
            Payload: JSON.stringify(event)
        };
        console.log("Params: ", params);

        const res = await lambda.invoke(params, (err, data) => {
            let res = data;
            if (err) {
              console.log("呼び出し失敗");
              console.log(err);
              callback(err, err);       
            } else {
              console.log("呼び出し成功");
              console.log("response:", res);
              callback(null, JSON.parse(res.Payload));
            }
        }).promise();

};
  • 18行目のRoleArnには、Step 1の最後で控えたARNを指定します。
  • 37行目のFunctionNameには、アカウントBにある本命lambda関数のARNを指定します。

Deployボタンでコードをデプロイします。

Step 5:(おまけ)LexボットがプロキシLambda関数を呼び出すようにする

LexボットのインテントがプロキシLambda関数実行できるよう、FulfillmentセクションでStep 3、4のプロキシLambda関数を指定します。

まず、Step 4の最後でコードをデプロイしたあと、Versionsタブに移動します。
image.png

Publish new versionボタンをクリックして新しいバージョンを作成します。
image.png

バージョンを発行することで、LexボットがIntentのFulfillmentにこのlambda関数を利用できるようになります。

アカウントA上で、AWS管理コンソールのメニューからAmazon Lexをクリックして移動し、Lambda関数を実行させたいIntentを開きます。

IntentのFulfillmentセクションで、プロキシLambda関数を指定し、Intentを保存します。
image.png

1
1
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
1
1