【问题标题】:How to allow users to delete objects in S3 bucket?如何允许用户删除 S3 存储桶中的对象?
【发布时间】:2020-04-07 07:42:02
【问题描述】:

我有一个移动应用程序,它让用户通过 AWS Cognito 进行身份验证,他们最终进入用户池。他们能够将对象放入桶中没有问题,但他们不能删除。我想要做的是让每个登录用户都能够删除存储桶中的文件。

文件的路径例如:my_bucket_name/protected/eu-west-2:de55c2rf-8f1e-836d-88f9-82da662aau6dt/videos/video1

要删除,我称之为:

import { Storage } from 'aws-amplify'; 

。 . .

delFromS3 = async () => {
      Storage.remove('protected/eu-west-2:de55c2rf-8f1e-836d-88f9-82da662aau6dt/videos/video1')  
         .then(result => console.log('Deleted Video from S3'))
         .catch(err => console.log('Deleting video from S3 error: ', err));
  }

我在调用这个时一直收到错误访问被拒绝,所以我添加了一个存储桶策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
            },
            "Action": "s3:DeleteObject",
            "Resource": "arn:aws:s3:::my_bucket_name/*"
        }
    ]
}

这个函数唯一一次返回结果是当我输入"Principal": "*" 时,但这会使我的存储桶公开给任何人,我不想这样做。它也不接受这是有效的主要政策:

"Principal": { "AWS": [ "arn:aws:cognito-idp:eu-west-2:968257789397:userpool/eu-west-2_2ecGAT74q" ] }. 

所以我需要知道正确的校长是什么。

所以我要么需要一种方法来允许 cognito 用户池中的用户被授权删除对象。或者因为我手动知道每个用户子存储桶中文件的路径(例如/protected/eu-west-2:de55c2rf-8f1e-836d-88f9-82da662aau6dt/videos/video1),只需将其传递给我的delFromS3() 函数。我的存储桶策略应该读什么?我还有什么遗漏的吗?

请帮忙!

【问题讨论】:

  • 你读过${cognito-identity.amazonaws.com:sub}(见docs.aws.amazon.com/cognito/latest/developerguide/…)吗?
  • 是的,我尝试像这样添加:"Resource": "arn:aws:s3:::my_bucket_name/protected/${cognito-identity.amazonaws.com:sub}/*" 但它还是不行
  • 你有api后端吗
  • 我使用 AWS Amplify,只是为了实例化 DynamoDB 和 Cognito,仅此而已。

标签: amazon-web-services amazon-s3 amazon-cognito amazon-iam aws-amplify


【解决方案1】:

我会为 DELETE 等操作创建一个 IAM 用户,并仅使用您的 cognito id 进行访问。对于 IAM 用户,您的 Principal 如下所示:

"Principal": {
    "AWS": "arn:aws:iam::841367581918:user/your-iam-name"
},

您可以在 api 文件的顶部为该用户提供 accessKey,如下所示:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();
s3.config.update({
    region: process.env.BUCKET_REGION,
    accessKeyId: process.env.IAM_ACCESS_KEY,
    secretAccessKey: process.env.IAM_SECRET_KEY
});

然后,删除你的对象:

deleteObject: async (req, res) => {

    const bucket = process.env.YOUR_BUCKET;

    try {
        // delete record in DB
        //....
        let cognitoId = req.user.cognitoId;
        let key = cognitoId + '/' + path; // my folder name is user's cognitoId and path is the rest of url.

        const params = {
            Bucket: bucket,
            Key: key
        }

        try {
            await s3.headObject(params).promise();
            console.log("File found");
            try {
                await s3.deleteObject(params).promise();
                console.log("deleted successfully");
            }
            catch (error) {
                console.log(error);
                res.status(500).send(error.message);
            }
        }
        catch (error) {
            console.log(error);
            res.status(500).send(error.message);
        }
        res.status(200).send("success");
    }
    catch (error) {
        console.log(error);
        res.status(500).send(error.message);
    }
}

【讨论】:

  • 所以我使用 import { Storage } from 'aws-amplify' 而不是 AWS.S3 这使得代码有所不同。这对 Storage.Put() 有效。每次通过 Cognito 首次登录时,可能会有成千上万的 IAM 用户。对于每个用户来说,拥有一个 accessKey 听起来有点矫枉过正。我知道我的用户池的 arn,但是当我尝试时:“Principal”:{“AWS”:[“arn:aws:cognito-idp:eu-west-2:968257789397:userpool/eu-west-2_2ecGAT74q”]}在我的存储桶策略中仍然不起作用。我错过了什么吗?
  • @chai86 这不是每个用户的访问密钥,它是您的 api 的访问密钥。您的用户使用您的 api 进行身份验证,您的 api 代表用户执行操作。
【解决方案2】:

Amplify CLI 将帮助您针对“public”、“protected”和“private”文件夹配置正确的 S3 存储桶策略。 https://aws-amplify.github.io/docs/ios/storage#restrict-access要完成你想做的事,你可以

  1. 使用Amplify.Storage,使用accessLevel: .protected上传,这会将对象上传到<bucket>/protected/<key>下的S3

  2. 使用相同的访问级别下载以在<bucket>/protected/<key>检索

let options = StorageDownloadDataRequest.Options(accessLevel: .protected)
Amplify.Storage.downloadData(key: "myKey", options: options) { (event) in
    ...
}

Essentially Amplify Storage 插件为您在密钥前面添加了存储访问级别。当调用中没有指定 accessLevel 时,默认会在前面加上“public”。

您可以在这里找到相关的博文:https://aws.amazon.com/blogs/mobile/introducing-aws-amplify-for-ios-and-android/

对应的示例应用:https://github.com/nikhil-dabhade/amplify-ios-samples/tree/master/samples/ios/amplify/storage/AmplifyStorageSampleApp

【讨论】:

    猜你喜欢
    • 2017-03-20
    • 2017-05-06
    • 2010-10-16
    • 1970-01-01
    • 2023-03-22
    • 2013-08-23
    • 2021-06-28
    • 2018-07-12
    • 2023-03-21
    相关资源
    最近更新 更多