在宅勤務ベースになってオンラインのイベントに参加しやすくなっているので色々手を出している。

先日は JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン&LT(オンライン) に参加して、へーとかほーとか思いながら Lambda やら API Gateway やらを触った (Translate と Transcribe はサービスそのものを初めて知った)。

当日は資料通りにマネジメントコンソールから操作していたが、復習の意味も込めて CLI 経由で改めてやってみる。

ロール作成

とりあえずフル権限で作成。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
$ aws iam create-role \
    --role-name translate-function-role \
    --assume-role-policy-document file://translate-function-role.json
{
    "Role": {
        "Path": "/",
        "RoleName": "translate-function-role",
        "RoleId": "AROA3B7TBQZDJUTAZJSOD",
        "Arn": "arn:aws:iam::760182048326:role/translate-function-role",
        "CreateDate": "2020-05-03T07:39:02+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

ロールが何のためのものかは #AWS Lambda の実行ロールを作成する ( SQSの実行権限を与える例 ) の内容がしっくりきた。

AWS Lambda 「が」AWSの他のサービス「を」使うときの許可、ポリシーみたいだ。

Lambda Function を作成

今回はサンプルコードを clone してそのまま使用した。

$ zip translate-function.zip translate-function.py
  adding: translate-function.py (deflated 42%)

$ aws lambda create-function \
    --function-name translate-function \
    --runtime python3.8 \
    --role "arn:aws:iam::760182048326:role/translate-function-role" \
    --handler translate-function.lambda_handler \
    --zip-file fileb://translate-function.zip
{
    "FunctionName": "translate-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function",
    "Runtime": "python3.8",
    "Role": "arn:aws:iam::760182048326:role/translate-function-role",
    "Handler": "translate-function.lambda_handler",
    "CodeSize": 454,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2020-05-03T08:01:57.762+0000",
    "CodeSha256": "undpq1zH+AaJrMaEzHNUAws+D0+g5+6puU/1ieb62kQ=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "17bfdf82-b17c-4a62-b70d-85a71d735432",
    "State": "Active",
    "LastUpdateStatus": "Successful"
}

実行してみると、

$ aws lambda invoke --function-name translate-function outfile.json
{
    "StatusCode": 200,
    "FunctionError": "Unhandled",
    "ExecutedVersion": "$LATEST"
}

FunctionError らしい。

{
  "errorMessage": "An error occurred (AccessDeniedException) when calling the TranslateText operation: User: arn:aws:sts::760182048326:assumed-role/translate-function-role/translate-function is not authorized to perform: translate:TranslateText",
  "errorType": "ClientError",
  "stackTrace": [
    "  File \"/var/task/translate-function.py\", line 9, in lambda_handler\n    response = translate.translate_text(\n",
    "  File \"/var/runtime/botocore/client.py\", line 316, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n",
    "  File \"/var/runtime/botocore/client.py\", line 626, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"
  ]
}

Amazon Translate のポリシーをアタッチするのを忘れていた。

仕切り直し

TranslateFullAccess をアタッチ。

$ aws iam attach-role-policy \
    --role-name translate-function-role \
    --policy-arn "arn:aws:iam::aws:policy/TranslateFullAccess"

$ aws iam get-role --role-name translate-function-role
{
    "Role": {
        "Path": "/",
        "RoleName": "translate-function-role",
        "RoleId": "AROA3B7TBQZDJUTAZJSOD",
        "Arn": "arn:aws:iam::760182048326:role/translate-function-role",
        "CreateDate": "2020-05-03T07:39:02+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2020-05-03T08:06:35+00:00",
            "Region": "ap-northeast-1"
        }
    }
}

Lambda Function を改めて実行。

$ aws lambda invoke --function-name translate-function outfile.json
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

今度は成功した。

{
  "statusCode": 200,
  "body": "{\"output_text\": \"Are you well?\"}"
}

参考