Amazon S3 + Lamba访问被拒绝

时间:2019-07-11 17:23:07

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

我按照创建缩略图(https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html)的示例创建了lambda函数和角色,并使其正常工作。我正在尝试根据自己的特定需求对其进行自定义,但是突然出现错误“ ACCESS_DENIED”,我不确定自己做了什么。

17:10:02
2019-07-11T17:10:02.007Z    301100e3-87c6-4c5e-b944-50c32cfd53aa    Unable to resize my-bucket-test/user40226/7seg1_WEB.jpg and upload to my-thumbnails/user40226/7seg1_WEB.jpg due to an error: AccessDenied: Access Denied
2019-07-11T17:10:02.007Z    301100e3-87c6-4c5e-b944-50c32cfd53aa    Unable to resize my-bucket-test/user40226/7seg1_WEB.jpg and upload to my-thumbnails/user40226/7seg1_WEB.jpg due to an error: AccessDenied: Access Denied

根据示例设置了策略。我什至尝试为lambda角色设置特定的自定义策略,并具有在该存储桶中创建对象的特定权限。

政策示例:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}

添加了自定义政策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:ReplicateObject",
                "s3:PutObject",
                "s3:PutObjectRetention",
                "s3:DeleteObjectVersion",
                "s3:PutReplicationConfiguration",
                "s3:RestoreObject",
                "s3:UpdateJobPriority",
                "s3:UpdateJobStatus",
                "s3:DeleteObject",
                "s3:PutBucketCORS",
                "s3:PutBucketVersioning",
                "s3:ReplicateDelete"
            ],
            "Resource": "arn:aws:s3:::my-thumbnails"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:CreateJob",
            "Resource": "*"
        }
    ]
}

lambda代码:

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

// constants
var MAX_WIDTH  = 100;
var MAX_HEIGHT = 100;

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

exports.handler = function(event, context, callback) {
    // Read options from the event.
    console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
    var srcBucket = event.Records[0].s3.bucket.name;
    // Object key may have spaces or unicode non-ASCII characters.
    var srcKey    = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
    var dstBucket = "my-thumbnails";
    var dstKey    = srcKey;

    // Sanity check: validate that source and destination are different buckets.
    //if (srcBucket == dstBucket) {
    //    callback("Source and destination buckets are the same.");
    //    return;
    //}

    // Infer the image type.
    var typeMatch = srcKey.match(/\.([^.]*)$/);
    if (!typeMatch) {
        callback("Could not determine the image type.");
        return;
    }
    var imageType = typeMatch[1].toLowerCase();
    if (imageType != "jpg" && imageType != "png") {
        callback(`Unsupported image type: ${imageType}`);
        return;
    }

    // Download the image from S3, transform, and upload to a different S3 bucket.
    async.waterfall([
            function download(next) {
                // Download the image from S3 into a buffer.
                s3.getObject({
                        Bucket: srcBucket,
                        Key: srcKey
                    },
                    next);
            },
            function transform(response, next) {
                gm(response.Body).size(function(err, size) {
                    // Infer the scaling factor to avoid stretching the image unnaturally.
                    var scalingFactor = Math.min(
                        MAX_WIDTH / size.width,
                        MAX_HEIGHT / size.height
                    );
                    var width  = scalingFactor * size.width;
                    var height = scalingFactor * size.height;

                    // Transform the image buffer in memory.
                    this.resize(width, height)
                        .toBuffer(imageType, function(err, buffer) {
                            if (err) {
                                next(err);
                            } else {
                                next(null, response.ContentType, buffer);
                            }
                        });
                });
            },
            function upload(contentType, data, next) {
                // Stream the transformed image to a destination S3 bucket.
                s3.putObject({
                        Bucket: dstBucket,
                        Key: dstKey,
                        Body: data,
                        ContentType: contentType,
                        ACL: 'public-read'
                    },
                    next);
            }
        ], function (err) {
            if (err) {
                console.error(
                    'Unable to resize ' + srcBucket + '/' + srcKey +
                    ' and upload to ' + dstBucket + '/' + dstKey +
                    ' due to an error: ' + err
                );
            } else {
                console.log(
                    'Successfully resized ' + srcBucket + '/' + srcKey +
                    ' and uploaded to ' + dstBucket + '/' + dstKey
                );
            }

            callback(null, "message");
        }
    );
};

在创建新文件时,我要尝试做的一件事情是通过基于数字ID的键前缀将它们放在单独的“子文件夹”中。因此,例如,将使用“ 12345 / image.jpg”之类的图片(使用dropzone.js)上传新图片。我已经有了像“ john”这样的测试字符串才能以这种方式工作的文件和缩略图。我以为可能是数字搞砸了,所以我尝试了'user12345 / image.jpg'

图像上传到第一个存储分区,但是lambda函数失败,并显示上述ACCESS_DENIED消息。

感谢您的帮助

0 个答案:

没有答案