如何从远程执行的 fargate 任务访问 S3 对象? 编辑

问题描述

我编写了一个 Java 程序来读取 S3 存储桶,该存储桶在 AWS 上的 Fargate 任务中运行,但失败并显示 AccessDeniedException 该程序位于一个 jar 文件中,该文件正在使用 ECS Exec 远程执行 Fargate 任务的任务角色具有以下权限,但以下行仍然失败并出现以下异常

{
    "Version": "2012-10-17","Statement": [
        {
            "Sid": "VisualEditor0","Effect": "Allow","Action": "s3:ListBucket","Resource": "arn:aws:s3:::*"
        },{
            "Sid": "VisualEditor1","Action": [
                "s3:PutObject","s3:PutObjectacl","s3:Getobject","s3:DeleteObject"
            ],"Resource": "arn:aws:s3:::*"
        }
    ]
}

ListObjectsV2Request req = new ListObjectsV2Request().withBucketName("myBucket").withMaxKeys(200);
ListObjectsV2Result result = amazonS3.listObjectsV2(req);

com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: 0Z58XY0CF91Q6H4Y; S3 Extended Request ID: sVoHHMEM4+5ti+MlcaHsgvJxyvbFlJrMVZMC4cBOFI1hPg/QtsKExqFiqNECH2ZKoUXuJMYwAt0=),S3 Extended Request ID: sVoHHMEM4+5ti+MlcaHsgvJxyvbFlJrMVZMC4cBOFI1hPg/QtsKExqFiqNECH2ZKoUXuJMYwAt0=
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1811)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1395)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1371)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1145)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:770)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:744)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:704)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:686)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:550)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:530)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4914)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4860)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4854)
    at com.amazonaws.services.s3.AmazonS3Client.listObjectsV2(AmazonS3Client.java:923)
    at com.mycompany.ReadS3Object.getFilesOnS3(ReadS3Object.java:263)
    at com.mycompany.ReadS3Object.run(ReadS3Object.java:141)
    at picocli.CommandLine.executeUserObject(CommandLine.java:1939)
    at picocli.CommandLine.access$1300(CommandLine.java:145)
    at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2346)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2311)
    at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
    at picocli.CommandLine.execute(CommandLine.java:2078)
    at com.mycompany.ReadS3Object.main(ReadS3Object.java:132)

需要更改哪些内容才能完成 listObjectsV2 调用

编辑

所以事实证明问题是代码试图列出的存储桶不存在!当我在本地运行代码时,它给出了正确的存储桶未找到异常,但远程运行它给出了 AccessDeniedException。创建存储桶解决了问题

解决方法

您的 S3 V1 代码似乎缺少引用有权调用 S3 操作的 IAM 用户的凭据。作为测试,请为该角色提供完整的 S3 访问权限,看看是否仍会出现此问题。

此外,作为一般性建议,您应该考虑放弃旧版 V1 Amazon S3 API 并考虑使用 V2 - 这是亚马逊在编写 Java 代码以调用 Amazon S3 操作时推荐使用的版本。

当您看到像这样使用 new 运算符时:

ListObjectsV2Request req = new ListObjectsV2Request().withBucketName("myBucket").withMaxKeys(200);

这是 V1 代码。 V2 代码不使用 new 运算符来创建对象,而是使用 builder()

ListObjectsRequest listObjects = ListObjectsRequest.builder()
                    .bucket(bucketName)
                    .build();