S3 Bucket Lambda Event: невозможно проверить следующие конфигурации назначения

Я пытаюсь создать корзину 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>

Я запустил его с ролью, назначенной лямбде, и, как мне кажется, все необходимые ей политики. Я мог что-то упустить. Я использую мои корневые ключи доступа для запуска этого скрипта.

Role

Я подумал, что это может быть ошибка синхронизации, когда S3 нужно время для создания сегмента перед добавлением события, но я подождал некоторое время, жестко закодировал имя блока и снова запустил свой скрипт, который выдает ту же ошибку.

Странно то, что если я создаю ловушку событий в пользовательском интерфейсе S3 и немедленно удаляю ее, мой сценарий работает, если я жестко закодирую это имя сегмента. Кажется, что создание события в пользовательском интерфейсе добавляет некоторые необходимые разрешения, но я не уверен, что это будет в SDK или в пользовательском интерфейсе консоли.

S3 Event Config

Любые мысли или вещи, чтобы попробовать? Спасибо за вашу помощь

Ответ 1

Вы получаете это сообщение, потому что в вашем ведомости s3 отсутствуют разрешения для вызова вашей лямбда-функции.

Согласно документации AWS ! требуется два типа разрешений:

  1. Разрешения для вашей функции Lambda для вызова служб
  2. Разрешения для Amazon S3 для вызова вашей лямбда-функции

Вы должны создать объект типа 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 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 ошибку 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). Добавление новых индивидуальных разрешений для каждого сегмента добавляет их в конец политики функций лямбда и, очевидно, этот размер имеет максимальный размер.

Политика не выглядит редактируемой в Консоли управления AWS, поэтому я с удовольствием удалил каждую запись с помощью SDK. Я скопировал политику JSON, вытащил Sid и вызвал removePermission в цикле (который removePermission ошибки ограничения скорости, и мне приходилось запускать его много раз).

Наконец, я обнаружил, что SourceArn ключа 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);
    }
  });
}

Ответ 3

Консоль - это еще один способ разрешить s3 вызывать лямбду:

Заметка

Когда вы добавляете триггер к своей функции с помощью консоли Lambda, консоль обновляет политику функции на основе ресурсов, чтобы позволить службе вызывать ее. Чтобы предоставить разрешения другим учетным записям или службам, которые недоступны в консоли Lambda, используйте интерфейс командной строки AWS.

Так что вам просто нужно добавить и настроить триггер s3 для вашей лямбды из консоли aws

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

Ответ 4

Для меня это была лямбда, ожидающая разрешения на все ведро, а не ведро и ключи

Ответ 5

Если это все еще полезно для кого-то, вот как я добавляю разрешение к лямбда-функции, используя java:

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-