【问题标题】:S3 Bucket Lambda Event: Unable to validate the following destination configurationsS3 存储桶 Lambda 事件:无法验证以下目标配置
【发布时间】:2018-04-23 06:08:02
【问题描述】:

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

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

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);
      }
    });
  }
});

创建工作正常,但从 aws-sdk 调用 s3.putBucketNotificationConfiguration 会抛出:

{ 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 中会是什么。

有什么想法或尝试吗?感谢您的帮助

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    【解决方案2】:

    一年后终于又看了一遍。这是我们重新审视的去年的黑客马拉松项目。 @davor.obilinovic 的回答非常有助于向我指出我需要添加的 Lambda 权限。我仍然花了一点时间来弄清楚我需要它的样子。

    这里是 AWS JavaScript 开发工具包和 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,将Sids 拉出并在循环中调用removePermission(这引发了速率限制错误,我不得不多次运行它)。

    最后我发现省略 SourceArn 键会给所有 S3 存储桶授予 Lambda 权限。

    这是我使用 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);
        }
      });
    }
    

    【讨论】:

    【解决方案3】:

    如果它仍然对某人有用,这就是我使用 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-

    【讨论】:

      【解决方案4】:

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

      注意

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

      所以您只需要从 aws 控制台向您的 lambda 添加和配置一个 s3 触发器

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

      【讨论】:

      • 是的。最初我以为我必须为每个存储桶添加一个新的权限条目。我的存储桶是动态创建的。省略SourceArn 并只为所有存储桶添加一个权限是解决方案,因此通过 Web 控制台创建一个权限也应该同样有效。
      【解决方案5】:

      对我来说,是 Lambda 期望获得整个存储桶的权限,而不是存储桶和密钥

      【讨论】:

        【解决方案6】:

        看看这里可能会有所帮助:AWS Lambda : creating the trigger

        当您在存储桶中有冲突的事件时,会出现一种不清楚的错误。您需要清除其他事件以创建新事件。

        【讨论】:

          猜你喜欢
          • 2017-12-17
          • 2021-08-27
          • 2020-05-16
          • 2020-06-06
          • 1970-01-01
          • 1970-01-01
          • 2021-11-26
          • 1970-01-01
          • 2021-06-16
          相关资源
          最近更新 更多