it-swarm.com.de

S3-Bucket-Lambda-Ereignis: Folgende Zielkonfigurationen können nicht überprüft werden

Ich versuche, einen S3-Bucket zu erstellen und ihm sofort ein Lambda-Benachrichtigungsereignis zuzuweisen.

Hier ist das Knotentestskript, das ich geschrieben habe:

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

Die Erstellung funktioniert gut, aber der Aufruf von s3.putBucketNotificationConfiguration aus dem aws-sdk löst aus:

{ 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>

Ich habe es mit einer Rolle ausgeführt, die Lambda zugewiesen wurde, mit allen meiner Meinung nach all den erforderlichen Richtlinien. Ich könnte etwas vermissen. Ich verwende meine Root-Zugriffsschlüssel, um dieses Skript auszuführen.

 Role

Ich dachte, es könnte ein Timing-Fehler sein, bei dem S3 vor dem Hinzufügen des Ereignisses Zeit benötigt, um den Bucket zu erstellen, aber ich habe eine Weile gewartet, den Bucket-Namen hartcodiert und das Skript erneut ausgeführt, was den gleichen Fehler auslöst.

Das Seltsame ist, dass wenn ich den Event-Hook in der S3-Benutzeroberfläche erstelle und sofort lösche, mein Skript funktioniert, wenn ich diesen Bucket-Namen darin hartcodiere. Es scheint, als würde das Erstellen des Ereignisses in der Benutzeroberfläche einige erforderliche Berechtigungen hinzufügen, aber ich bin nicht sicher, was sich im SDK oder in der Konsolen-Benutzeroberfläche befinden würde.

 S3 Event Config

Irgendwelche Gedanken oder Dinge zum Ausprobieren? Danke für Ihre Hilfe

7
Scotty Waggoner

Sie erhalten diese Meldung, weil Ihrem S3-Bucket die Berechtigungen zum Aufrufen der Lambda-Funktion fehlen.

Laut AWS-Dokumentation ! Es sind zwei Arten von Berechtigungen erforderlich:

  1. Berechtigungen für Ihre Lambda-Funktion zum Aufrufen von Diensten
  2. Berechtigungen für Amazon S3 zum Aufrufen Ihrer Lambda-Funktion

Sie sollten ein Objekt vom Typ 'AWS :: Lambda :: Permission' erstellen, das ungefähr so ​​aussehen sollte:

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

Endlich nach einem Jahr noch einmal angeschaut. Dies war ein Hackathon-Projekt aus dem letzten Jahr, das wir aufgegriffen haben. @ davor.obilinovics Antwort war sehr hilfreich, als er mich auf die Lambda-Erlaubnis hinwies, die ich hinzufügen musste. Ich brauchte immer noch ein bisschen, um herauszufinden, wie ich es brauchte.

Hier sind die AWS JavaScript SDK- und Lambda-API-Dokumente __. https://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#addPermission-propertyhttps://docs.aws.Amazon.com/lambda/latest/dg/API_AddPermission.html

Die JS SDK-Dokumente haben folgende Zeile:

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

Ich konnte es nicht die längste Zeit zum Laufen bringen und erhielt immer noch den Unable to validate the following destination configurations-Fehler.

Ändern Sie es in

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

dieses Problem behoben. Der /* war anscheinend falsch und ich hätte mir die Antwort genauer anschauen sollen, die ich hier bekam, aber ich wollte den AWS-Dokumenten folgen.

Nachdem Sie eine Weile entwickelt und viele Buckets, Lambda-Berechtigungen und S3-Lambda-Benachrichtigungen erstellt hatten, wurde mit dem Aufruf von addPermission eine The final policy size (...) is bigger than the limit (20480). ausgelöst. Durch Hinzufügen neuer, individueller Berechtigungen für jeden Bucket werden diese am Ende der Lambda-Funktionsrichtlinie hinzugefügt Größe.

Die Richtlinie scheint in der AWS Management Console nicht bearbeitbar zu sein. Daher machte es mir Spaß, jeden Eintrag mit dem SDK zu löschen. Ich kopierte die JSON-Richtlinie, zog die Variable Sids heraus und rief in einer Schleife removePermission auf (was die Rate Limit-Fehler warf und ich es viele Male ausführen musste).

Schließlich entdeckte ich, dass das Weglassen der SourceArn-Taste Lambda-Berechtigung für alle S3-Buckets erteilt.

Hier ist mein endgültiger Code, der das SDK verwendet, um die erforderliche Berechtigung hinzuzufügen. Ich habe dies nur einmal für meine Funktion ausgeführt.

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);
    }
  });
}
0
Scotty Waggoner

Die Konsole ist eine weitere Möglichkeit, mit der s3 ein Lambda aufrufen kann:

Hinweis

Wenn Sie Ihrer Funktion mit der Lambda-Konsole einen Trigger hinzufügen, aktualisiert die Konsole die ressourcenbasierte Richtlinie der Funktion, damit der Service sie aufrufen kann. Verwenden Sie die AWS-CLI, um anderen Konten oder Diensten Berechtigungen zu erteilen, die in der Lambda-Konsole nicht verfügbar sind.

Sie müssen also nur einen S3-Trigger von der aws-Konsole aus zu Ihrem Lambda hinzufügen und konfigurieren

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

0
Spiff

Für mich erwartete Lambda die Erlaubnis für den gesamten Eimer und nicht den Eimer und die Schlüssel

0
supa_command

Wenn es für jemanden noch nützlich ist, füge ich die Berechtigung der Lambda-Funktion mit Java folgendermaßen hinzu:

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

Bitte überprüfen Sie https://docs.aws.Amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/lambda/AWSLambda.html#addPermission-com.amazonaws.services.lambda .model.AddPermissionRequest -

0
James130490