要求是通过 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/