如何在S3与亚马逊LAMBDA创建的文件设置打开/下载权限?亚马逊、权限、文件、如何在

2023-09-11 23:50:27 作者:口紅待在桌腳

我有一个亚马逊的lambda功能,成功地将文件写入到Amazon S3的桶中。然而,在默认情况下这些文件是不向公众开放。我该如何让他们自动访问被写入当他们?

I have an Amazon Lambda function that successfully writes files to an Amazon S3 bucket. However, by default these files are not publicly accessible. How do I make them automatically accessible when they are written?

有没有办法来改变桶本身,使所有项目都公开可读(开/下载)?

Is there a way to change the bucket itself so that all items are publicly readable (open/download)?

另外,我已经收集,这可能与IAM作用的政策来实现。这是我有:

Alternatively, I've gleaned that this can be done with the IAM role policy. This is what I have:

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

我认为这是资源需要改变这一点,但我不知道怎么样。

I think it's the "Resource" that needs to be changed, but I'm not sure how.

有关完整(如果任何人需要做类似的事情,并涉水入泥潭即拉姆达文档),这是我在客户方AJAX调用(我正在写一个图像到S3,需要的文件名后面)

For completeness (in case anyone else needs to do something similar and is wading into the morass that is the Lambda documentation), here's my ajax call on the clientside (I'm writing an image to S3 and need the filename back):

$.ajax({
url: 'https://mylambdafunctionurl/',
type: 'POST',
crossDomain: true,
contentType: 'application/json',
data: JSON.stringify(data),
dataType: 'json',
success: function(data) {
    var path = "https://myregion.amazonaws.com/mybucket/";
    var filename = JSON.parse(data).filename;
    document.getElementById('finalimage').innerHTML = "<a href='"+path+filename+"'>Your image</a>";
},
error: function(xhr, ajaxOptions, thrownError) {
    if (xhr.status == 200) {
        console.log(ajaxOptions);
    } else {
        console.log("Error: ");
        console.log(xhr.status);
        console.log(thrownError);
    }
}
});

这里是LAMBDA POST功能(nodejs):

And here is the Lambda POST function (nodejs):

var AWS = require('aws-sdk');
var s3 = new AWS.S3();

exports.handler = function(event,context) {
    var s3 = new AWS.S3();
    var nowtime = new Date();
    var bodycontent = event.image;

    mykey = nowtime.getTime() + '.png';
    var param = {Bucket: 'mybucket', Key: mykey, Body: bodycontent};
    var successdata = {filename:mykey};
    s3.upload(param, function(e,data) {
        if (e) {
            console.log(e,e.stack);
        } else {
            console.log(event);
        }
        context.done(null,JSON.stringify(successdata));
    });
}

警告:使用当前时间为文件名不是生产做好准备。这仅仅是一个快速的方法来产生一个合理的唯一的文件名。

Caveat: using the current time for the filename is not production ready. It was just a quick way to produce a reasonably unique filename.

推荐答案

根据此页例如:的 http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html 你可以设置这样的IAM角色策略

as per this page example: http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html you could set a IAM role policy like this

...
 {
  "Effect": "Allow",
  "Action": [
    "s3:PutObject",
    "s3:GetObject",
    "s3:DeleteObject"
  ],
  "Resource": "arn:aws:s3:::EXAMPLE-BUCKET-NAME/*"
}
...

所以,你可以用一个文件夹,如 ARN结合起来:AWS:S3 :::实例桶名称/公/ * 我觉得

或者你可以创建一个整桶公共访问所有文件只是上传。

Or you could create a whole bucket with public access to all files just for uploading.

或者,也许你可以使用 getSignedUrl 从SDK到刚刚上传的文件,并返回该网址到客户端,这将使通过URL对于给定的访问的文件时间(不记得了,现在多久,他们是有效的),像这样的:

Or maybe you could use getSignedUrl from the sdk to the just uploaded file and return that url to the client, that will make the file accessible through that url for a given time(don't remember right now how long they are valid), like this:

s3.putObject({
  Bucket: bucket,  
  Key: key,
  Body: fs.createReadStream(path),
  ContentType: contentType,
}, function(err, data) {  
  if (err)
    return callback(err, null);  

  s3.getSignedUrl('getObject', {
    Bucket: 'mybucket',    
    Key: 'mypublicfiles/myfile.txt'
  }, function(err, url) {    
    if (err)
      return callback(err, null)
    else
      return callback(null, url)
  });
});