Cognito用户如何授权访问S3对象?

4
我有一些使用Cognito的用户需要写入S3存储桶,以下是我认为的处理过程(但也许有更好的方法?):
1)创建存储桶
2)让用户通过Cognito进行身份验证,然后将其资源写入存储桶。
3)允许用户从存储桶检索资源,但仅限于该用户写入资源到存储桶中(额外的要求是必须给对象打上布尔值标签,设置为true,因此我假设必须通过lambda端点来执行此操作?)。
我想到的一个想法是,也许有一种方法可以创建只有用户才能访问的存储桶,这样每个用户都有自己的存储桶?
另一个想法是用用户ID标记对象,并只允许lambda端点返回对象如果用户具有正确的用户ID并且布尔值标记已设置为true。
你对此有何想法?

“cognito users that will write to an S3 bucket(s)” 是什么意思?例如,您有一个带有认证的 Cognito Web 应用程序,用户可以通过 AWS JavaScript SDK 上传到 S3 吗? - Michał Z.
Web应用程序使用Cognito身份验证和文件上传到存储桶或多个存储桶(如果S3支持为每个用户分配专用存储桶或存储桶名称空间),并且通过JavaScript SDK访问AWS,或者仅使用REST并通过AWS网关传递请求,在此处应用程序可以在存储桶访问之前进行验证。 - Ole
除了@MichaelZ的回答中提供的所有优秀材料外,我还发现这个教程非常有帮助:https://sanderknape.com/2017/08/using-pre-signed-urls-upload-file-private-s3-bucket/ - Ole
1个回答

6
可以这样做:
  • S3 Bucket - 一个存储桶将用于所有用户的文件。

  • IAM 角色 - 具有允许为上述存储桶编写对象的策略声明。

  • Lambda 函数 - 将扮演上述角色并返回临时凭证。

为每个用户将文件存储在与 Cognito 用户名相同的路径下(例如 s3://my-bucket/some-user/file.zip)

从 S3 下载

Lambda 函数可以 生成预签名 URL 并返回它。检查 Cognito 用户名(来自 JWT)是否等于文件夹名称(如果不是,则返回例如 403 状态),或者只需获取文件名并连接 Cognito 用户名和文件名作为输入。

示例(Node.js):

...
const preSignedUrl = s3.getSignedUrl('getObject', {
    Bucket: '<BUCKET NAME>',
    Key: '<cognito user name>/<file name>', // path to object in bucket above
    Expires: 3600 // expiration time in seconds
});
....

Lambda角色需要允许从存储桶中读取对象的策略。
上传到S3:
Lambda函数可以扮演角色(重要提示:仅限于cognito用户名文件夹的限制策略-例如s3://my-bucket/some-user/*),并返回临时凭证。使用这些凭证,用户只能从浏览器上传到自己的目录。
示例(Node.js):
...
const BUCKET_NAME = <...>
const COGNITO_USER_NAME = <...>

const restrictedPolicy = {
    Version:'2012-10-17',
    Statement: [{
        Effect: 'Allow',
        Action: 's3:PutObject',
        Resource: `arn:aws:s3:::${BUCKET_NAME}/${COGNITO_USERNAME}/*`
    }]
}

sts.assumeRole({
    DurationSeconds: 3600, // expiration time in seconds
    RoleArn: '<...>', // role that has write access to whole s3 bucket
    RoleSessionName: '<cognito username>', // not much importance
    Policy: JSON.stringify(restrictedPolicy) // write access only for Cognito username folder
}, (err, data) => {
    if(err) {
        ...
    } else {
        const temporaryCredentials = data.Credentials // Lambda needs to return that to API Gateway via callback
        ...
    }
});
...

Lambda角色需要允许扮演角色的策略。

你有可以分享的代码片段(Javascript?)来执行READ吗?刚意识到也许链接就是为此而设。现在正在查看它。 - Ole
我喜欢预签名URL的想法 - 太聪明了!所以,如果我理解正确,首先检查文件并查看布尔标记是否为true,如果是,则生成预签名URL并将其返回给客户端。然后客户端可以在指定的时间间隔内读取文件,该时间间隔允许URL有效? - Ole
好的 - 所以编写Lambda函数实际上并不会这样做。它将为客户端获取临时凭据,然后客户端将使用这些凭据直接访问S3?谢谢,这帮了很大的忙! - Ole
1
真是太棒了 - 谢谢!! - Ole
1
对于一些问题,你希望你的 Lambda 返回一个预签名 URL 以进行写入,而不是让 Lambda 进行写入。Lambda 有大小限制(6MB)。 - Jack Marchetti
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接