概要
Salesforce.com(以下 SFDC)からAWS LambdaをInvokeします。
具体的には、SFDCの指定ログイン情報(Named Credential)へAWSのIAMユーザークレデンシャルを保存し、Apexからコールアウト、Lambdaを実行します。
自前で実装するとなると面倒であろうAWS署名バージョン4にSFDCが対応しているため、シンプルな記述で実行可能になっています。
前提
- Salesforceについては無償で誰でも利用可能な Salesforce Developer Edition で確認します。
- AWS Lambdaは東京リージョン(ap-northeast-1) を利用します
手順
AWS Lambda関数を作成
実行するLambda関数 MyFunction
を作成します。
今回は Pythonで記述しました。
def lambda_handler(event, context):
name = event.get('name')
return {
'statusCode': 200,
'body': f'Hello {name} !'
}
IAMポリシーを作成
MyFunctionInvokePolicy
を作成します。
東京リージョンのLambda関数 MyFunction
を実行できるように指定しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:InvokeAsync"
],
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:MyFunction"
}
]
}
IAMユーザーを作成
MyFunctionInvokeUser
という名前のIAMユーザーを作成しました。
AWS認証情報タイプは アクセスキー・プログラムによるアクセス
を選択、ポリシーへ上記手順で作成したポリシーを指定します。
作成完了時にアクセスキーID、シークレットアクセスキーを控えておきます。
指定ログイン情報(Named Credentials)1 を作成
次のように指定しました。
項目 | 値 |
---|---|
表示ラベル | InvokeLambda |
名前 | InvokeLambda |
URL | https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions |
ID種別 | 指定ユーザ |
認証プロトコル | AWS 署名バージョン 4 |
AWSアクセスキーID | 上記手順で作成したIAMユーザーのアクセスキーID |
AWSシークレットアクセスキー | 上記手順で作成したIAMユーザーのシークレットアクセスキー |
AWSリージョン | ap-northeast-1 |
AWSサービス | lambda |
動作確認
デベロッパーコンソールの Anonymous WindowからApexコードを実行して確認します。
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:InvokeLambda/MyFunction/invocations');
req.setMethod('POST');
req.setBody('{"name": "Justin"}');
Http http = new Http();
HttpResponse res = http.send(req);
System.debug(res.getBody());
実行ログ
コード2行目の callout:InvokeLambda
が 指定ログイン情報で設定したURL https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions
に置き換わり、https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions/MyFunction/invocations
というURLが生成されているのがわかりますね。
HttpResponse::getBody() でLambdaの実行結果が取得できています。
CALLOUT_REQUEST|[7]|System.HttpRequest[Endpoint=callout:InvokeLambda/MyFunction/invocations, Method=POST]
NAMED_CREDENTIAL_REQUEST|NamedCallout[Named Credential Id=0XA5h0000004DDd, Named Credential Name=InvokeLambda, Endpoint=https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions/MyFunction/invocations, Method=POST, External Credential Type=EXTERNAL, HTTP Header Authorization=Not Set, Content-Type=null, Request Size bytes=18, Retry on 401=True]
NAMED_CREDENTIAL_RESPONSE|NamedCallout[Named Credential Id=0XA5h0000004DDd, Named Credential Name=InvokeLambda, Status Code=200, Content-Type=application/json, Response Size bytes=45, Overall Callout Time ms=647, Connect Time ms=3
CALLOUT_RESPONSE|[7]|System.HttpResponse[Status=OK, StatusCode=200]
USER_DEBUG|[8]|DEBUG|{"statusCode": 200, "body": "Hello Justin !"}
その他
Lambdaを非同期実行したい
リクエストヘッダ X-Amz-Invocation-Type: Event
を指定します。
req.setHeader('X-Amz-Invocation-Type', 'Event');
実行ログを取得したい
リクエストヘッダ X-Amz-Log-Type: Tail
を指定します。
req.setHeader('X-Amz-Log-Type', 'Tail');
レスポンスヘッダ X-Amz-Log-Result
に最後の4KBがBASE64エンコードされてセットされます。
利用する場合はデコードが必要です。
System.debug(
EncodingUtil.base64Decode(
res.getHeader('X-Amz-Log-Result')
).toString());
最後に
SFDCからAWS Lambdaをコールするシーンとしては、企業の業務システム連携で検討する場面が多いだろうと推察します。
この方法はAWS CLIでLambda実行するのと同等ということになると思います。
API Gatewayで公開エンドポイントにしても同じことは実現できますが、IAMユーザーを固定することは、権限ポリシーを厳密に設定できたり、実行監査もしやすいのではないでしょうか。
参考リンク
-
英語だと
Named Credentials
なのですが、日本語訳の指定ログイン情報
と関連付けて記憶しにくいなと感じています。SFDCの設定ページでいつも 「名前・・・」なんだっけ?みたいになり、named credentials
でググって、あー、、となっています。 ↩