it-swarm.com.ru

aws лямбда-функция получает доступ, когда getObject от s3

Я получаю сообщение об отказе в доступе от службы S3 AWS в своей функции Lambda.

Это код:

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

Это ошибка в Cloudwatch:

AccessDenied: Access Denied

Это ошибка стека:

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)

Без какого-либо другого описания или информации На S3 ведро разрешений позволяет каждому ставить список и удалять.

Что я могу сделать, чтобы получить доступ к корзине S3?

PS: в свойствах события Lambda принципал правильный и имеет права администратора.

30
cyberdantes

Ваша лямбда не имеет привилегий (S3:GetObject).

Перейдите на панель инструментов IAM и проверьте роль, связанную с выполнением Lambda. Если вы используете мастер AWS, он автоматически создает роль с именем oneClick_lambda_s3_exec_role. Нажмите на Show Policy. На нем должно быть что-то похожее на прикрепленное изображение. Убедитесь, что S3:GetObject указан.

 enter image description here

29
helloV

Я столкнулся с этой проблемой, и после нескольких часов безумия политики IAM, решение было:

  1. Перейти к консоли S3
  2. Нажмите ведро, в котором вы заинтересованы.
  3. Нажмите «Свойства»
  4. Развернуть «Разрешения»
  5. Нажмите «Добавить дополнительные разрешения»
  6. Выберите «Любой аутентифицированный пользователь AWS» из выпадающего списка. Выберите «Загрузить/Удалить» и «Список» (или все, что вам нужно для вашей лямбды).
  7. Нажмите «Сохранить»

Готово .. Ваши тщательно написанные политики ролей IAM не имеют значения, также как и конкретные политики сегментов (я написал их тоже, чтобы они работали). Или они просто не работают на моем счете, кто знает.

[Правка]

После многих переделок вышеуказанный подход не самый лучший. Попробуй это:

  1. Сохраняйте свою ролевую политику, как в приветственном сообщении.
  2. Перейти к S3. Выберите свое ведро. Нажмите Разрешения. Нажмите Bucket Policy.
  3. Попробуйте что-то вроде этого:
{
    "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"
        }
    ]
}

Работал для меня и не требует от вас, чтобы поделиться со всеми аутентифицированными пользователями AWS (что в большинстве случаев не является идеальным).

17
Adam Owczarczyk

Интересно, что AWS возвращает 403 (доступ запрещен), когда файл не существует. Убедитесь, что целевой файл находится в корзине S3.

14
vedat

Если вы указываете Resource , не забудьте также добавить спецификацию подпапок. Как это:

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

Я тоже столкнулся с этой проблемой, я исправил это, предоставив s3:GetObject* в ACL, когда он пытается получить версию этого объекта.

2
Steven Lu

Я попытался выполнить простую лямбда-функцию Python [пример кода], и у меня возникла та же проблема. Моя исполнительная роль была lambda_basic_execution

Я пошел к S3> (мое имя ведра здесь)> разрешения.

 S3:BucketPolicyView

Поскольку я новичок, я использовал Policy Generator, предоставленный Amazon, а не сам писал JSON: http://awspolicygen.s3.amazonaws.com/policygen.html Мой JSON выглядит так этот:

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

И тогда код выполняется красиво:

 foo

1
O95

Если все другие политики утки находятся в ряду, S3 по-прежнему будет возвращать сообщение «Отказано в доступе», если объект не существует И запрашивающая сторона не имеет разрешения ListObjects на ведро.

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

... Если запрашиваемый вами объект не существует, выдается ошибка Amazon S3 возврат зависит от того, есть ли у вас разрешение s3: ListBucket.

Если у вас есть разрешение s3: ListBucket для корзины, Amazon S3 будет вернуть код ошибки HTTP 404 («нет такого ключа»). если вы не Если у вас есть разрешение s3: ListBucket, Amazon S3 вернет HTTP ошибка кода состояния 403 («доступ запрещен»).

1
Jeremiah

Если у вас установлено шифрование в корзине S3 (например, AWS KMS), вам может потребоваться убедиться, что роль IAM, примененная к вашей функции Lambda, добавлена ​​в список IAM> Ключи шифрования> регион> ключ> Key Users для соответствующего ключа, который вы использовали для шифрования своей корзины S3 в состоянии покоя. 

Например, на своем снимке экрана я добавил роль CyclopsApplicationLambdaRole, которую я применил к своей функции Lambda в качестве пользователя Key в IAM для того же ключа AWS KMS, который я использовал для шифрования своей корзины S3. Не забудьте выбрать правильный регион для вашего ключа при открытии пользовательского интерфейса Encryption keys.

Найдите роль выполнения, которую вы применили к своей лямбда-функции:  screenshot of Lambda execution role

Найдите ключ, который вы использовали для добавления шифрования в корзину S3:  screenshot of the key selected for the S3 bucket

В IAM> Ключи шифрования выберите свой регион и нажмите на имя ключа:  screenshot of region dropdown in IAM

Добавьте роль в качестве ключевого пользователя в ключах шифрования IAM для ключа, указанного в S3:  screenshot of IAM key users selection

0
Danny Bullis

Я боролся с этой проблемой в течение нескольких часов. Я использовал AmazonS3EncryptionClient и ничего не помогло. Затем я заметил, что клиент фактически устарел, поэтому я решил попробовать перейти на модель построителя, которую он имеет:

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

И ... это решило это. Похоже, у Lambda проблемы с введением учетных данных в старой модели, но она хорошо работает в новой.

0
yi1

Я пытался прочитать файл из s3 и создать новый файл, изменив содержимое файла чтения (Lambda + Node). Чтение файла с S3 не было проблем. Как только я попытался записать в корзину S3, я получаю сообщение об ошибке «Отказано в доступе». 

Я перепробовал все перечисленные выше вещи, но не смог избавиться от «Отказано в доступе». Наконец я смог заставить его работать, дав разрешение «Список объектов» всем на моем ведре .  S3 Bucket Access Control List

Очевидно, что это не лучший подход, но больше ничего не сработало.

0
imTheManager