S3 Bucket Lambda事件:无法验证以下目标配置

时间:2017-11-10 04:09:13

标签: node.js amazon-web-services amazon-s3 lambda aws-sdk

我试图创建一个S3存储桶并立即为其分配一个lambda通知事件。

这是我写的节点测试脚本:

first <= last

创建工作正常,但从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

我使用分配给lambda的角色运行它,我认为它是所需的所有策略。我可能会遗漏一些东西。我使用root访问密钥来运行此脚本。

Role

我认为这可能是一个时间错误,S3在添加事件之前需要时间来创建存储桶,但是我已经等了一段时间,硬编码了存储桶名称,并再次运行我的脚本同样的错误。

奇怪的是,如果我在S3 UI中创建事件挂钩并立即将其删除,那么如果我将该桶名称硬编码到其中,我的脚本就会起作用。似乎在UI中创建事件会添加一些所需的权限,但我不确定在SDK或控制台UI中会出现什么。

S3 Event Config

任何想法或事情要尝试?谢谢你的帮助

5 个答案:

答案 0 :(得分:16)

您收到此消息是因为您的s3存储桶缺少调用lambda函数的权限。

根据AWS documentation!需要两种类型的权限:

  1. Lambda函数调用服务的权限
  2. Amazon S3调用Lambda函数的权限
  3. 您应该创建一个&#39; AWS :: Lambda :: Permission&#39;它看起来应该类似于:

    {
      "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>"
            }
          }
        }
      ]
    }
    

答案 1 :(得分:2)

一年后终于再次看了看。这是我们去年取消的黑客马拉松项目。 @ davor.obilinovic的回答非常有帮助,使我指向需要添加的Lambda权限。还是花了我一点时间才能弄清楚我需要它的外观。

以下是AWS JavaScript SDK和Lambda API文档 https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#addPermission-property https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html

JS SDK文档包含以下内容:

SourceArn: "arn:aws:s3:::examplebucket/*",

我无法使它工作最长时间,并且仍然出现Unable to validate the following destination configurations错误。

更改为

SourceArn: "arn:aws:s3:::examplebucket",

解决了该问题。 /*显然是错误的,我应该仔细看看我在这里得到的答案,但是正在尝试关注AWS文档。

在开发了一段时间并创建了很多存储桶,Lambda权限和S3 Lambda通知之后,调用addPermission开始抛出The final policy size (...) is bigger than the limit (20480).。为每个存储桶添加新的,单独的权限会将它们添加到Lambda功能策略的底部而且显然该策略具有最大大小。

该策略在AWS管理控制台中似乎不可编辑,因此我很高兴使用SDK删除了每个条目。我复制了策略JSON,将Sid抽出并在循环中调用了removePermission(这抛出了速率限制错误,我不得不运行多次)。

最后,我发现省略SourceArn键将向Lambda授予所有S3存储桶的权限。

这是我使用SDK添加所需权限的最终代码。我只为功能运行一次。

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

aws.config.update({
  accessKeyId:     process.env.AWS_ACCESS,
  secretAccessKey: process.env.AWS_SECRET,
  region:          process.env.AWS_REGION,
});

// Creates Lambda Function Policy which must be created once for each Lambda function
// Must be done before calling s3.putBucketNotificationConfiguration(...)
function createLambdaPermission() {
  const lambda = new aws.Lambda();

  const params = {
    Action:        'lambda:InvokeFunction',
    FunctionName:  process.env.AWS_LAMBDA_ARN,
    Principal:     's3.amazonaws.com',
    SourceAccount: process.env.AWS_ACCOUNT_ID,
    StatementId:   `example-S3-permission`,
  };

  lambda.addPermission(params, function (err, data) {
    if (err) {
      console.log(err);
    } else {
      console.log(data);
    }
  });
}

答案 2 :(得分:0)

控制台是允许s3调用lambda的另一种方式:

  

注意

     

当您使用Lambda控制台向函数添加触发器时,   控制台会更新功能的基于资源的策略,以允许   服务来调用它。授予其他帐户权限或   Lambda控制台中不可用的服务,请使用AWS CLI。

因此,您只需要从aws控制台向lambda添加并配置s3触发器

https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html

答案 3 :(得分:0)

对于我来说,Lambda希望整个存储桶都得到许可,而存储桶和键则是

答案 4 :(得分:0)

如果它仍然对某人有用,这就是我使用java向lambda函数添加权限的方式:

AWSLambda client = AWSLambdaClientBuilder.standard().withRegion(clientRegion).build();

AddPermissionRequest requestLambda = new AddPermissionRequest()
                    .withFunctionName("XXXXX")
                    .withStatementId("XXXXX")
                    .withAction("lambda:InvokeFunction")
                    .withPrincipal("s3.amazonaws.com")
                    .withSourceArn("arn:aws:s3:::XXXXX" )
                    .withSourceAccount("XXXXXX");

                    client.addPermission(requestLambda);

请检查 https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/lambda/AWSLambda.html#addPermission-com.amazonaws.services.lambda.model.AddPermissionRequest-