1. ホーム
  2. node.js

[解決済み] S3 Bucket Lambdaのイベント。次の宛先設定を検証できません。

2022-03-01 09:26:41

質問

S3バケットを作成し、すぐにラムダ通知イベントを割り当てようとしています。

以下は、私が書いたノードテストスクリプトです。

const aws = require('aws-sdk');
const uuidv4 = require('uuid/v4');

aws.config.update({
  accessKeyId: 'key',
  secretAccessKey:'secret',
  region: 'us-west-1'
});

const s3 = new aws.S3();

const params = {
  Bucket: `bucket-${uuidv4()}`,
  ACL: "private",
  CreateBucketConfiguration: {
    LocationConstraint: 'us-west-1'
  }
};

s3.createBucket(params, function (err, data) {
  if (err) {
    throw err;
  } else {
    const bucketUrl = data.Location;

    const bucketNameRegex = /bucket-[a-z0-9\-]+/;
    const bucketName = bucketNameRegex.exec(bucketUrl)[0];

    const params = {
      Bucket: bucketName,
      NotificationConfiguration: {
        LambdaFunctionConfigurations: [
          {
            Id: `lambda-upload-notification-${bucketName}`,
            LambdaFunctionArn: 'arn:aws:lambda:us-west-1:xxxxxxxxxx:function:respondS3Upload',
            Events: ['s3:ObjectCreated:CompleteMultipartUpload']
          },
        ]
      }
    };

    // Throws "Unable to validate the following destination configurations" until an event is manually added and deleted from the bucket in the AWS UI Console
    s3.putBucketNotificationConfiguration(params, function(err, data) {
      if (err) {
        console.error(err);
        console.error(this.httpResponse.body.toString());
      } else {
        console.log(data);
      }
    });
  }
});

作成はうまくいきますが s3.putBucketNotificationConfiguration から aws-sdk を投げる。

{ InvalidArgument: Unable to validate the following destination configurations
    at Request.extractError ([...]/node_modules/aws-sdk/lib/services/s3.js:577:35)
    at Request.callListeners ([...]/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
    at Request.emit ([...]/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
    at Request.emit ([...]/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition ([...]/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo ([...]/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at [...]/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> ([...]/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> ([...]/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners ([...]/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
  message: 'Unable to validate the following destination configurations',
  code: 'InvalidArgument',
  region: null,
  time: 2017-11-10T02:55:43.004Z,
  requestId: '9E1CB35811ED5828',
  extendedRequestId: 'tWcmPfrAu3As74M/0sJL5uv+pLmaD4oBJXwjzlcoOBsTBh99iRAtzAloSY/LzinSQYmj46cwyfQ=',
  cfId: undefined,
  statusCode: 400,
  retryable: false,
  retryDelay: 4.3270874729153475 }

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidArgument</Code>
    <Message>Unable to validate the following destination configurations</Message>
    <ArgumentName1>arn:aws:lambda:us-west-1:xxxxxxxxxx:function:respondS3Upload, null</ArgumentName1>
    <ArgumentValue1>Not authorized to invoke function [arn:aws:lambda:us-west-1:xxxxxxxxxx:function:respondS3Upload]</ArgumentValue1>
    <RequestId>9E1CB35811ED5828</RequestId>
    <HostId>tWcmPfrAu3As74M/0sJL5uv+pLmaD4oBJXwjzlcoOBsTBh99iRAtzAloSY/LzinSQYmj46cwyfQ=</HostId>
</Error>

lambdaに割り当てられたロールと、必要なポリシーがすべて揃っていると思われる状態で実行しました。何か見落としているかもしれません。このスクリプトを実行するために、私のルートアクセスキーを使用しています。

S3がイベントを追加する前にバケットを作成する時間が必要なタイミングエラーかもしれないと思いましたが、しばらく待ってバケット名をハードコードし、スクリプトを再度実行しても同じエラーがスローされます。

不思議なのは、S3のUIでイベントフックを作ってすぐに削除しても、そのバケット名をハードコードすれば、私のスクリプトは動作することです。UIでイベントを作成すると、必要なパーミッションが追加されるようですが、SDKやコンソールUIではそれが何なのかよくわかりません。

何か感想や試してみたいことがあれば教えてください。よろしくお願いします。

解決方法は?

S3バケットにラムダ関数を呼び出すための権限がないため、このメッセージが表示されます。

によると AWSのドキュメント 必要なパーミッションは2種類です。

  1. Lambda関数がサービスを呼び出すためのパーミッション
  2. Amazon S3がLambda関数を呼び出すためのパーミッション

AWS::Lambda::Permission' タイプのオブジェクトを作成し、以下のような外観にします。

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "<optional>",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "<ArnToYourFunction>",
      "Condition": {
        "StringEquals": {
          "AWS:SourceAccount": "<YourAccountId>"
        },
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:s3:::<YourBucketName>"
        }
      }
    }
  ]
}