前提条件
Lambdaへの権限
Lambdaに対してフル権限があること。
AWS CLI
以下のバージョンで動作確認済
- AWS CLI 1.10.38
コマンド
aws --version
結果(例)
aws-cli/1.10.38 Python/2.7.11 Darwin/15.5.0 botocore/1.4.28
IAM Role
'lambdaBasicExecution'ロールが存在すること。
変数の設定
IAM_ROLE_NAME='lambdaBasicExecution'
コマンド
aws iam get-role \
--role-name ${IAM_ROLE_NAME}
結果(例)
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
},
"RoleId": "AROAXXXXXXXXXXXXXXXXX",
"CreateDate": "2015-10-26T01:55:54Z",
"RoleName": "lambdaBasicExecution",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution"
}
}
存在しない場合は、
http://qiita.com/tcsh/items/455fcea33fc1171a5502
の手順に従って作成してください。
- 準備
=======
0.1. 変数の確認
プロファイルが想定のものになっていることを確認します。
変数の確認
aws configure list
結果(例)
Name Value Type Location
---- ----- ---- --------
profile lambdaFull-prjz-mbp13 env AWS_DEFAULT_PROFILE
access_key ****************XXXX shared-credentials-file
secret_key ****************XXXX shared-credentials-file
region ap-northeast-1 env AWS_DEFAULT_REGION
0.2. IAM RoleのARN取得
変数の設定
IAM_ROLE_NAME='lambdaBasicExecution'
コマンド
IAM_ROLE_ARN=$( \
aws iam get-role \
--role-name ${IAM_ROLE_NAME} \
--query 'Role.Arn' \
--output text \
) \
&& echo ${IAM_ROLE_ARN}
結果(例)
arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution
0.3. トピックの指定
通知先を登録するトピックを指定します。
変数の設定
SNS_TOPIC_NAME="$(date +%Y%m%d)-handson-topic" \
&& echo ${SNS_TOPIC_NAME}
0.4. トピックARNの取得
コマンド
SNS_TOPIC_ARN=$( \
aws sns list-topics \
--query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)].TopicArn" \
--output text \
) \
&& echo ${SNS_TOPIC_ARN}
結果(例)
arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:20160620-handson-topic
- 事前作業
===========
1.1. Lambda関数名の決定
変数の設定
LAMBDA_FUNC_NAME="sns-message-$( date '+%Y%m%d' )"
同名のLambda関数の不存在確認
コマンド
aws lambda get-function \
--function-name ${LAMBDA_FUNC_NAME}
結果(例)
A client error (ResourceNotFoundException) occurred when calling the GetFunction operation: Function not found: arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sns-message-20160620
1.2. Lambda関数
変数の設定
FILE_LAMBDA_FUNC="${LAMBDA_FUNC_NAME}.py"
変数の確認
cat << ETX
FILE_LAMBDA_FUNC: ${FILE_LAMBDA_FUNC}
ETX
コマンド
cat << EOF > ${FILE_LAMBDA_FUNC}
from __future__ import print_function
import json
print('Loading function')
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
message = event['Records'][0]['Sns']['Message']
print("From SNS: " + message)
return message
EOF
cat ${FILE_LAMBDA_FUNC}
コマンド
zip ${LAMBDA_FUNC_NAME}.zip ${FILE_LAMBDA_FUNC}
結果(例)
adding: sns-message-20160620.py (deflated 43%)
- Lambda関数の作成
===================
変数の設定
LAMBDA_FUNC_DESC='An Amazon SNS trigger that logs the message pushed to the SNS topic.'
LAMBDA_RUNTIME='python2.7'
LAMBDA_HANDLER="${LAMBDA_FUNC_NAME}.lambda_handler"
FILE_LAMBDA_ZIP="${LAMBDA_FUNC_NAME}.zip"
変数の確認
cat << ETX
LAMBDA_FUNC_NAME: ${LAMBDA_FUNC_NAME}
LAMBDA_FUNC_DESC: "${LAMBDA_FUNC_DESC}"
LAMBDA_RUNTIME: ${LAMBDA_RUNTIME}
FILE_LAMBDA_ZIP ${FILE_LAMBDA_ZIP}
IAM_ROLE_ARN: ${IAM_ROLE_ARN}
LAMBDA_HANDLER: ${LAMBDA_HANDLER}
ETX
コマンド
aws lambda create-function \
--function-name ${LAMBDA_FUNC_NAME} \
--description "${LAMBDA_FUNC_DESC}" \
--zip-file fileb://${FILE_LAMBDA_ZIP} \
--runtime ${LAMBDA_RUNTIME} \
--role ${IAM_ROLE_ARN} \
--handler ${LAMBDA_HANDLER}
結果(例)
{
"CodeSha256": "y8yjqcUI8TGWAxqVt3x3BVzOv3Pb+rGr+0KPghz36i8=",
"FunctionName": "sns-message-20160620",
"CodeSize": 380,
"MemorySize": 128,
"FunctionArn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:sns-message-20160620",
"Version": "$LATEST",
"Role": "arn:aws:iam::xxxxxxxxxxxx:role/lambdaBasicExecution",
"Timeout": 3,
"LastModified": "2016-06-19T15:10:47.747+0000",
"Handler": "sns-message-20160620.lambda_handler",
"Runtime": "python2.7",
"Description": "An Amazon SNS trigger that logs the message pushed to the SNS topic."
}
コマンド
aws lambda list-functions
結果(例)
{
"Functions": [
{
"Version": "$LATEST",
"CodeSha256": "y8yjqcUI8TGWAxqVt3x3BVzOv3Pb+rGr+0KPghz36i8=",
"FunctionName": "sns-message-20160620",
"MemorySize": 128,
"CodeSize": 380,
"FunctionArn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:sns-message-20160620",
"Handler": "sns-message-20160620.lambda_handler",
"Role": "arn:aws:iam::xxxxxxxxxxxx:role/lambdaBasicExecution",
"Timeout": 3,
"LastModified": "2016-06-19T15:10:47.747+0000",
"Runtime": "python2.7",
"Description": "An Amazon SNS trigger that logs the message pushed to the SNS topic."
}
]
}
コマンド
aws lambda get-function \
--function-name ${LAMBDA_FUNC_NAME}
結果(例)
{
"Code": {
"RepositoryType": "S3",
"Location": "https://awslambda-us-west-2-tasks.s3-us-west-2.amazonaws.com/snapshots/xxxxxxxxxxxx/sns-message-20160620-94f6e8eb-ee3b-4c00-8c8a-954642396e71?x-amz-security-token=FQoDYXdzEO%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDEruHidCLdnnzUDGQyK0A4dUQtu%2B4zoY%2FrVVjjQEHA3PZ4wZmeokZ4wNGVvL6Gl05QSctL4dRe79VgjBK%2BtYIUm1p6HgzxlWcrpV%2BhNgZsxsCqinRcBg79210XdopPa0wlPbswNIhqsHMyJS0Gs4x6eiKKJ9Gq2vMsiPoPKN8yKECvkDhCcSRs2wxCZrDybDutmqWKZowrNABgM4hzJGNz9xAh4dxN4Pr8fh%2F185glbq2iusjf3JP9gRIQKlT%2Bn9Xry1Jvj4qE0bl0iptY%2BRb%2FrzxTiz393p%2BYC0MJ63FR85T8GYtlhXzqAntufp4bxbkAKJFSsvEiO0LqssF%2Fse8aMTeIaPOfKOhOelT49HrbM0WLuRu7DBU416etC1AjkNCKMdPBPc9x%2FrCEcJKVfy5uENqrM8bKEFAdGMBMwFyUSHHnklsMTY8GSJtisBQIUVHNVTE5jbELx5kH9SaTolRfyTTVWLBn4Amlcobjhf1adlW58BmGa5Jge%2Bm1SzuvocaMRZQms%2BN6lNv9dLEgqT%2BlvVObkEqBk8m0O0ZLZat61SNoR81ymItLyuhmyg1QNbkOqpATQCg0wXg3WReKGqWUR1%2FckoucyauwU%3D&AWSAccessKeyId=ASIAJHC2NNIWC2M5YV3Q&Expires=1466349693&Signature=a%2FeD%2F%2FLuqd9HX23v4uDDAMMcuzQ%3D"
},
"Configuration": {
"Version": "$LATEST",
"CodeSha256": "y8yjqcUI8TGWAxqVt3x3BVzOv3Pb+rGr+0KPghz36i8=",
"FunctionName": "sns-message-20160620",
"MemorySize": 128,
"CodeSize": 380,
"FunctionArn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:sns-message-20160620",
"Handler": "sns-message-20160620.lambda_handler",
"Role": "arn:aws:iam::xxxxxxxxxxxx:role/lambdaBasicExecution",
"Timeout": 3,
"LastModified": "2016-06-19T15:10:47.747+0000",
"Runtime": "python2.7",
"Description": "An Amazon SNS trigger that logs the message pushed to the SNS topic."
}
}
コマンド
aws lambda get-function-configuration \
--function-name ${LAMBDA_FUNC_NAME}
結果(例)
{
"CodeSha256": "y8yjqcUI8TGWAxqVt3x3BVzOv3Pb+rGr+0KPghz36i8=",
"FunctionName": "sns-message-20160620",
"CodeSize": 380,
"MemorySize": 128,
"FunctionArn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:sns-message-20160620",
"Version": "$LATEST",
"Role": "arn:aws:iam::xxxxxxxxxxxx:role/lambdaBasicExecution",
"Timeout": 3,
"LastModified": "2016-06-19T15:10:47.747+0000",
"Handler": "sns-message-20160620.lambda_handler",
"Runtime": "python2.7",
"Description": "An Amazon SNS trigger that logs the message pushed to the SNS topic."
}
- Lambda関数の動作確認
=======================
3.1. サンプルデータの作成
変数の設定
FILE_INPUT="${LAMBDA_FUNC_NAME}-data.json" \
&& echo ${FILE_INPUT}
コマンド
cat << EOF > ${FILE_INPUT}
{
"Records": [
{
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:EXAMPLE",
"EventSource": "aws:sns",
"Sns": {
"SignatureVersion": "1",
"Timestamp": "1970-01-01T00:00:00.000Z",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "Hello from SNS!",
"MessageAttributes": {
"Test": {
"Type": "String",
"Value": "TestString"
},
"TestBinary": {
"Type": "Binary",
"Value": "TestBinary"
}
},
"Type": "Notification",
"UnsubscribeUrl": "EXAMPLE",
"TopicArn": "${SNS_TOPIC_NAME}",
"Subject": "TestInvoke"
}
}
]
}
EOF
cat ${FILE_INPUT}
JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。
コマンド
jsonlint -q ${FILE_INPUT}
エラーが出力されなければOKです。
3.2. lambda関数の手動実行
変数の設定
FILE_OUTPUT_LAMBDA="${LAMBDA_FUNC_NAME}-out.txt"
FILE_LOG_LAMBDA="${LAMBDA_FUNC_NAME}-$(date +%Y%m%d%H%M%S).log"
変数の確認
cat << ETX
LAMBDA_FUNC_NAME: ${LAMBDA_FUNC_NAME}
FILE_INPUT: ${FILE_INPUT}
FILE_OUTPUT_LAMBDA: ${FILE_OUTPUT_LAMBDA}
FILE_LOG_LAMBDA: ${FILE_LOG_LAMBDA}
ETX
コマンド
aws lambda invoke \
--function-name ${LAMBDA_FUNC_NAME} \
--log-type Tail \
--payload file://${FILE_INPUT} \
${FILE_OUTPUT_LAMBDA} \
> ${FILE_LOG_LAMBDA}
コマンド
cat ${FILE_LOG_LAMBDA} \
| jp.py 'StatusCode'
結果(例)
200
3.3. lambda関数の実行結果の確認
コマンド
cat ${FILE_OUTPUT_LAMBDA}
結果(例)
1970-01-01T00:00:00Z
3.4. lambda関数のログの確認
コマンド
cat ${FILE_LOG_LAMBDA} \
| jp.py 'LogResult' \
| sed 's/"//g' \
| base64 --decode
結果(例)
- permissionの追加
======================
4.1. Lambda実行権限の付与
変数の設定
LAMBDA_STAT_ID='AllowSNS'
LAMBDA_PERMIT_ACTION='lambda:InvokeFunction'
LAMBDA_PERMIT_PRINCIPAL='sns.amazonaws.com'
変数の確認
cat << ETX
LAMBDA_FUNC_NAME: ${LAMBDA_FUNC_NAME}
LAMBDA_STAT_ID: "${LAMBDA_STAT_ID}"
LAMBDA_PERMIT_ACTION: ${LAMBDA_PERMIT_ACTION}
LAMBDA_PERMIT_PRINCIPAL: ${LAMBDA_PERMIT_PRINCIPAL}
ETX
コマンド
aws lambda add-permission \
--function-name ${LAMBDA_FUNC_NAME} \
--statement-id "${LAMBDA_STAT_ID}" \
--action ${LAMBDA_PERMIT_ACTION} \
--principal ${LAMBDA_PERMIT_PRINCIPAL}
結果(例)
{
"Statement": "{\"Action\":[\"lambda:InvokeFunction\"],\"Resource\":\"arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:sns-message-20160620\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"sns.amazonaws.com\"},\"Sid\":\"AllowSNS\"}"
}