wake-up-neo.com

aws lambda-funktion wird bei getObject von s3 den Zugriff verweigert

Ich bekomme vom S3 AWS-Dienst einen Fehler in Bezug auf den Zugriff auf meine Lambda-Funktion.

Dies ist der Code:

// dependencies
var async = require('async');
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true }); // Enable ImageMagick integration.

exports.handler = function(event, context) {
    var srcBucket = event.Records[0].s3.bucket.name;
    // Object key may have spaces or unicode non-ASCII characters.
    var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
/*
{
    originalFilename: <string>,
    versions: [
        {
            size: <number>,
            crop: [x,y],
            max: [x, y],
            rotate: <number>
        }
    ]
}*/
    var fileInfo;
    var dstBucket = "xmovo.transformedimages.develop";
    try {
        //TODO: Decompress and decode the returned value
        fileInfo = JSON.parse(key);
        //download s3File

        // get reference to S3 client
        var s3 = new AWS.S3();

        // Download the image from S3 into a buffer.
        s3.getObject({
                Bucket: srcBucket,
                Key: key
            },
            function (err, response) {
                if (err) {
                    console.log("Error getting from s3: >>> " + err + "::: Bucket-Key >>>" + srcBucket + "-" + key + ":::Principal>>>" + event.Records[0].userIdentity.principalId, err.stack);
                    return;
                }

                // Infer the image type.
                var img = gm(response.Body);
                var imageType = null;
                img.identify(function (err, data) {
                    if (err) {
                        console.log("Error image type: >>> " + err);
                        deleteFromS3(srcBucket, key);
                        return;
                    }
                    imageType = data.format;

                    //foreach of the versions requested
                    async.each(fileInfo.versions, function (currentVersion, callback) {
                        //apply transform
                        async.waterfall([async.apply(transform, response, currentVersion), uploadToS3, callback]);

                    }, function (err) {
                        if (err) console.log("Error on excecution of watefall: >>> " + err);
                        else {
                            //when all done then delete the original image from srcBucket
                            deleteFromS3(srcBucket, key);
                        }
                    });
                });
            });
    }
    catch (ex){
        context.fail("exception through: " + ex);
        deleteFromS3(srcBucket, key);
        return;
    }
        function transform(response, version, callback){
            var imageProcess = gm(response.Body);
            if (version.rotate!=0) imageProcess = imageProcess.rotate("black",version.rotate);
            if(version.size!=null) {
                if (version.crop != null) {
                    //crop the image from the coordinates
                    imageProcess=imageProcess.crop(version.size[0], version.size[1], version.crop[0], version.crop[1]);
                }
                else {
                    //find the bigger and resize proportioned the other dimension
                    var widthIsMax = version.size[0]>version.size[1];
                    var maxValue = Math.max(version.size[0],version.size[1]);
                    imageProcess=(widthIsMax)?imageProcess.resize(maxValue):imageProcess.resize(null, maxValue);
                }
            }


            //finally convert the image to jpg 90%
            imageProcess.toBuffer("jpg",{quality:90}, function(err, buffer){
                if (err) callback(err);
                callback(null, version, "image/jpeg", buffer);
            });

        }

        function deleteFromS3(bucket, filename){
            s3.deleteObject({
                Bucket: bucket,
                Key: filename
            });
        }

        function uploadToS3(version, contentType, data, callback) {
            // Stream the transformed image to a different S3 bucket.
            var dstKey = fileInfo.originalFilename + "_" + version.size + ".jpg";
            s3.putObject({
                Bucket: dstBucket,
                Key: dstKey,
                Body: data,
                ContentType: contentType
            }, callback);
        }
};

Dies ist der Fehler in Cloudwatch:

AccessDenied: Access Denied

Dies ist der Stapelfehler:

at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/s3.js:329:35)

at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20) 

at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)

at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:596:14)

at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:21:10) 

at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12) 

at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10 

at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:37:9) 

at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:598:12) 

at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)

Ohne eine andere Beschreibung oder Info Auf S3 können Bucket-Berechtigungen für alle Put-Listen und -Löschungen verwendet werden.

Was kann ich tun, um auf den S3-Bucket zuzugreifen?

PS: Bei Lambda-Ereigniseigenschaften ist der Principal korrekt und verfügt über Administratorrechte.

30
cyberdantes

Ihr Lambda hat keine Berechtigungen (S3:GetObject).

Gehen Sie zum IAM-Dashboard und überprüfen Sie die Rolle, die Ihrer Lambda-Ausführung zugeordnet ist. Wenn Sie den AWS-Assistenten verwenden, wird automatisch eine Rolle mit dem Namen oneClick_lambda_s3_exec_role erstellt. Klicken Sie auf Show Policy. Es sollte etwas ähnlich dem angehängten Bild zeigen. Stellen Sie sicher, dass S3:GetObject aufgeführt ist.

 enter image description here

29
helloV

Ich bin auf dieses Problem gestoßen und nach stundenlangem Wahnsinn der IAM-Politik bestand die Lösung darin:

  1. Gehen Sie zur S3-Konsole
  2. Klicken Sie auf den Eimer, an dem Sie interessiert sind.
  3. Klicken Sie auf "Eigenschaften".
  4. "Berechtigungen" aufklappen
  5. Klicken Sie auf "Weitere Berechtigungen hinzufügen".
  6. Wählen Sie "Alle authentifizierten AWS-Benutzer" aus der Dropdown-Liste. Wählen Sie "Hochladen/Löschen" und "Liste" (oder was auch immer Sie für Ihr Lambda benötigen).
  7. Klicken Sie auf "Speichern".

Fertig .. __ Ihre sorgfältig geschriebenen IAM-Rollenrichtlinien spielen keine Rolle, ebenso wie bestimmte Bucket-Richtlinien (ich habe auch diese geschrieben, damit sie funktionieren). Oder sie arbeiten einfach nicht auf meinem Konto, wer weiß.

[BEARBEITEN]

Nach vielem Basteln ist der obige Ansatz nicht der beste. Versuche dies:

  1. Behalten Sie Ihre Rollenpolitik wie im Hallo-Beitrag.
  2. Gehe zu S3. Wählen Sie Ihren Eimer aus. Klicken Sie auf Berechtigungen. Klicken Sie auf Bucket-Richtlinie.
  3. Versuchen Sie etwas so:
{
    "Version": "2012-10-17",
    "Id": "Lambda access bucket policy",
    "Statement": [
        {
            "Sid": "All on objects in bucket lambda",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AWSACCOUNTID:root"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::BUCKET-NAME/*"
        },
        {
            "Sid": "All on bucket by lambda",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AWSACCOUNTID:root"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::BUCKET-NAME"
        }
    ]
}

Hat für mich gearbeitet und muss nicht mit allen authentifizierten AWS-Benutzern geteilt werden (was meistens nicht ideal ist).

17
Adam Owczarczyk

Interessanterweise gibt AWS 403 zurück (Zugriff verweigert), wenn die Datei nicht vorhanden ist. Stellen Sie sicher, dass sich die Zieldatei im S3-Bucket befindet.

14
vedat

Wenn Sie die Resource angeben, vergessen Sie nicht, auch die Unterordnerspezifikation hinzuzufügen. So was:

"Resource": [
  "arn:aws:s3:::BUCKET-NAME",
  "arn:aws:s3:::BUCKET-NAME/*"
]
10
TheVTM

Auch ich bin auf dieses Problem gestoßen. Ich habe dieses Problem behoben, indem in der ACL s3:GetObject* angegeben wurde, während versucht wird, eine Version dieses Objekts abzurufen.

2
Steven Lu

Ich habe versucht, eine grundlegende Blaupause-Python-Lambda-Funktion [Beispielcode] auszuführen, und ich hatte das gleiche Problem. Meine Ausführungsrolle war lambda_basic_execution

Ich ging zu S3> (mein Bucket-Name hier)> Berechtigungen.

 S3:BucketPolicyView

Weil ich Anfänger bin, habe ich den Policy Generator von Amazon verwendet, anstatt selbst JSON zu schreiben: http://awspolicygen.s3.amazonaws.com/policygen.html diese:

{
    "Id": "Policy153536723xxxx",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt153536722xxxx",
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::tokabucket/*",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::82557712xxxx:role/lambda_basic_execution"
                ]
            }
        }
    ]

Und dann der Code schön ausgeführt:

 foo

1
O95

Wenn sich alle anderen Richtlinienenten in einer Reihe befinden, gibt S3 weiterhin eine Access Denied-Meldung zurück, wenn das Objekt nicht vorhanden ist UND der Anforderer keine ListObjects-Berechtigung für den Bucket hat.

Von https://docs.aws.Amazon.com/AmazonS3/latest/API/RESTObjectGET.html :

... Wenn das von Ihnen angeforderte Objekt nicht vorhanden ist, wird der Fehler Amazon S3 .__ angezeigt. Returns hängt davon ab, ob Sie auch über die Berechtigung s3: ListBucket verfügen.

Wenn Sie die s3: ListBucket-Berechtigung für den Bucket haben, wird Amazon S3 einen HTTP-Statuscode 404 ("Kein solcher Schlüssel") zurückgeben. wenn Sie nicht Wenn Sie über die Berechtigung "s3: ListBucket" verfügen, gibt Amazon S3 ein HTTP .__ zurück. Statuscode 403 ("Zugriff verweigert") Fehler.

1
Jeremiah

Wenn Sie für Ihren S3-Bucket (z. B. AWS KMS) eine Verschlüsselung festgelegt haben, müssen Sie möglicherweise sicherstellen, dass die IAM-Rolle, die auf Ihre Lambda-Funktion angewendet wird, zur Liste der IAM> Verschlüsselungsschlüssel> region hinzugefügt wird> key> Key Users für den entsprechenden Schlüssel, mit dem Sie Ihren S3-Bucket im Ruhezustand verschlüsselt haben. 

In meinem Screenshot habe ich beispielsweise die Rolle CyclopsApplicationLambdaRole hinzugefügt, die ich auf meine Lambda-Funktion als Key-Benutzer in IAM für denselben AWS-KMS-Schlüssel angewendet habe, den ich zum Verschlüsseln meines S3-Bucket verwendet habe. Vergessen Sie nicht, den richtigen Bereich für Ihren Schlüssel auszuwählen, wenn Sie die Benutzeroberfläche Encryption keys öffnen.

Suchen Sie die Ausführungsrolle, die Sie auf Ihre Lambda-Funktion angewendet haben:  screenshot of Lambda execution role

Suchen Sie den Schlüssel, den Sie verwendet haben, um Ihrem S3-Bucket eine Verschlüsselung hinzuzufügen:  screenshot of the key selected for the S3 bucket

Wählen Sie in IAM> Verschlüsselungsschlüssel Ihre Region aus und klicken Sie auf den Namen des Schlüssels:  screenshot of region dropdown in IAM

Fügen Sie die Rolle als Schlüsselbenutzer in IAM-Verschlüsselungsschlüsseln für den in S3 angegebenen Schlüssel hinzu:  screenshot of IAM key users selection

0
Danny Bullis

Ich hatte stundenlang mit diesem Thema zu kämpfen. Ich habe AmazonS3EncryptionClient verwendet und nichts hat mir geholfen. Dann bemerkte ich, dass der Client tatsächlich veraltet ist. Ich dachte, ich würde versuchen, zu dem Builder-Modell zu wechseln, das sie haben:

var builder = AmazonS3EncryptionClientBuilder.standard()
  .withEncryptionMaterials(new StaticEncryptionMaterialsProvider(encryptionMaterials))
if (accessKey.nonEmpty && secretKey.nonEmpty) builder = builder.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey.get, secretKey.get)))
builder.build()

Und ... das hat es gelöst. Sieht aus, als hätte Lambda Probleme beim Einfügen der Anmeldeinformationen im alten Modell, funktioniert aber im neuen Modell gut.

0
yi1

Ich habe versucht, eine Datei aus S3 zu lesen und eine neue Datei zu erstellen, indem der Inhalt der Datei gelesen wird (Lambda + Node). Das Lesen der Datei aus S3 hatte kein Problem. Sobald ich versucht habe, in den S3-Bucket zu schreiben, erhalte ich die Fehlermeldung "Zugriff verweigert". 

Ich habe alles ausprobiert, aber ich konnte 'Access Denied' nicht loswerden. Endlich konnte ich es zum Laufen bringen, indem ich jedem in meinem Bucket die Berechtigung "Objekt auflisten" erteilte . S3 Bucket Access Control List

Offensichtlich ist dies nicht der beste Ansatz, aber sonst hat nichts funktioniert.

0
imTheManager