amazon-s3 - 使用 AWS SDK 时,为什么 S3 用户策略的条件策略语句中使用双引号 (") be parsed as (\")?

标签 amazon-s3 sdk subdirectory policy bucket

要求是通过 AWS 开发工具包限制 IAM 用户对 S3 存储桶中特定子文件夹的访问。通过AWS控制台配置用户策略要容易得多,但使用AWS SDK将其转换为java代码时失败了。

例如,我希望 IAM 用户只能访问“mybucket”存储桶中的“subfolder1”文件夹。 以下是可以与AWS控制台完美配合的用户策略: (解决方案本身请引用 here - 我在 AWS 控制台中验证成功)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Sid": "2",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::mybucket"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:prefix": [
                        "",
                        "subfolder1/"
                    ],
                    "s3:delimiter": [
                        "/"
                    ]
                }
            }
        },
        {
            "Sid": "3",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::mybucket/subfolder1/*"
            ]
        }
    ]
}

下面是生成上述策略的 java 代码片段。

// Attach the required permission user policy to the new user
// 1. Permission to list all the buckets (view)
final Statement allowListStatement = new Statement(Effect.Allow)
    .withActions(
            S3Actions.ListBuckets,
            S3Actions.GetBucketLocation
        )
    .withResources(new Resource("arn:aws:s3:::*"));

// 2. Permission to list the objects within the bucket
final String dq = (char)(34) + "";
final String prefix = dq + dq + "," + dq + "subfolder1/" + dq;

final Statement allowBucketListStatement = new Statement(Effect.Allow)
.withActions(
        S3Actions.ListObjects
    )
.withResources(
        new S3BucketResource(bucketName)
    )
.withConditions(
        new StringCondition(
                StringComparisonType.StringEquals,
                S3ConditionFactory.PREFIX_CONDITION_KEY,
                prefix
            ),
        new StringCondition(
                StringComparisonType.StringEquals,
                S3ConditionFactory.DELIMITER_CONDITION_KEY,
                "/"
            )
    );

// 3. Permission to update the bucket content
final Statement allowBucketOperationsStatement = new Statement(Effect.Allow)
    .withActions(
            S3Actions.PutObject,
            S3Actions.GetObject,
            S3Actions.DeleteObject
        )
    .withResources(
            new S3ObjectResource(
                    bucketName,
                    usernameIAM + "/*"
                )
   );

final Policy policy = new Policy()
    .withStatements(
            allowListStatement,
            allowBucketListStatement,
            allowBucketOperationsStatement
        );

final PutUserPolicyRequest policyRequest = new PutUserPolicyRequest(
        usernameIAM,
        "policy_subfolder1",
        policy.toJson()

    );
client.putUserPolicy(policyRequest);

问题发生在“withConditions”行(除此行之外的所有其他策略行均正确生成)。

预期的行将如下所示(在 AWS 控制台中运行良好):

"Condition":{"StringEquals":{"s3:prefix":["","subfolder1/"], "s3:delimiter":["/"]}}

但实际生成的行是这样的:

"Condition":{"StringEquals":{"s3:prefix":["\"\",\"subfolder1/\""], "s3:delimiter":["/"]}}

奇怪的是,AWS SDK 无法正确解析语句中的双引号 ("):所有双引号 (") 都被解析为 (\")。

“前缀”的定义看起来很奇怪。在我的原始代码中,我使用的是:

final String prefix = "\"\",\"" + usernameIAM + "/\"";

但这给出了与我当前的方法相同的问题(使用 dq 的 ascii 代码)。

我不确定这是否是AWS SDK的错误。任何人都可以阐明这个问题吗?或者任何其他方法或建议来实现我的要求(但必须使用 SDK)?


最佳答案

感谢用户2864740的建议。在此我只是发表我对这个问题的回答。希望其他人可以更容易找到。 正如 user2864740 所指出的,API 需要一个值而不是“手动 JSON 文本”,双引号 (") 将使用转义格式 (\") 进行解析。

解决方案是将 StringCondition 拆分成不同的部分,而不是手动生成 JSON 字符串。这是最终可行的解决方案:

final String prefix1 = "";
final String prefix2 = "subfolder1/";
final Statement allowBucketListStatement = new Statement(Effect.Allow)
.withActions(
        S3Actions.ListObjects
    )
.withResources(
        new S3BucketResource(bucketName)
    )
.withConditions(
        new StringCondition(
                StringComparisonType.StringEquals,
                S3ConditionFactory.PREFIX_CONDITION_KEY,
                prefix1
            ),
        new StringCondition(
                StringComparisonType.StringEquals,
                S3ConditionFactory.PREFIX_CONDITION_KEY,
                prefix2
            ),
        new StringCondition(
                StringComparisonType.StringEquals,
                S3ConditionFactory.DELIMITER_CONDITION_KEY,
                "/"
            )
    );

关于amazon-s3 - 使用 AWS SDK 时,为什么 S3 用户策略的条件策略语句中使用双引号 (") be parsed as (\")?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31889056/

相关文章:

java - 使用java AWS S3客户端sdk和cloudfront CDN端点从AWS S3下载图像

amazon-web-services - 如何从具有必要策略的 S3 存储桶将 SSL 证书下载到在我的 FARGATE 容器上运行的 Gradle 应用程序

python - 如何使用 python 在 aws s3 预签名的 url 中隐藏我的访问 key

javascript - 如何使用Rally SDK2.1添加google图表

git - 正确忽略特定文件夹下除特定文件类型外的所有文件

linux - 使用 "find"命令时如何排除多个子目录?

android - 从 Amazon S3 下载图像时如何使用 Picasso 库?

ios - 谁能帮我设置适用于 iOS 的 Salesforce Mobile SDK?

java - 什么是最可靠和最新的 foursquare Java/Android SDK?

c++ - 如何使用 C++ 在 Windows 中列出子目录?