如何配置S3存储桶:仅允许指定IAM角色执行上传操作
排查S3桶上传权限限制失效的问题
我之前也踩过类似的权限配置坑,咱们一步步拆解来看,应该能快速找到根源:
1. 桶策略的Resource范围不完整(最常见原因)
你当前的桶策略里,Resource只写了桶的ARN arn:aws:s3:::MyExampleBucket,但s3:PutObject是对象级操作,对应的Resource需要包含桶内所有对象的路径(也就是arn:aws:s3:::MyExampleBucket/*)。原策略只限制了桶级别的操作(比如创建桶、删除桶),完全没覆盖对象上传这类核心操作,所以权限限制自然不生效。
修改后的桶策略应该把Resource改成数组,同时包含桶和对象路径:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::MyExampleBucket", "arn:aws:s3:::MyExampleBucket/*" ], "Condition": { "StringNotLike": { "aws:userId": [ "AROAEXAMPLEID:*", "111111111111" ] } } } ] }
2. 确认当前调用身份的aws:userId是否匹配策略
策略里只允许AROAEXAMPLEID:*(角色ID前缀)和账号ID111111111111的身份操作桶,你需要确认Java SDK使用的凭证对应的userId是否在这个范围内:
可以在代码里加一段STS调用,直接获取当前身份的信息:
import com.amazonaws.services.securitytoken.AmazonSTS; import com.amazonaws.services.securitytoken.AmazonSTSClientBuilder; import com.amazonaws.services.securitytoken.model.GetCallerIdentityResult; public class CheckCallerIdentity { public static void main(String[] args) { AmazonSTS stsClient = AmazonSTSClientBuilder.defaultClient(); GetCallerIdentityResult result = stsClient.getCallerIdentity(); System.out.println("当前身份的User ID: " + result.getUserId()); System.out.println("所属账号ID: " + result.getAccount()); } }
- 如果是使用IAM角色的临时凭证,
userId格式是AROAEXAMPLEID:会话名称,会匹配AROAEXAMPLEID:*; - 如果是用IAM用户的永久凭证,
userId是AIDAxxxxxx开头的,不在策略允许范围内,会被拒绝(如果这不是你想要的,需要把用户ID加入策略)。
3. 确认Java SDK使用的是目标角色的凭证
如果你的目标是只允许特定IAM角色上传,要确保s3Client确实使用了该角色的临时凭证,而不是其他用户/角色的凭证。比如通过AssumeRole获取角色凭证的代码示例:
import com.amazonaws.auth.BasicSessionCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; import com.amazonaws.services.securitytoken.model.AssumeRoleResult; public class S3UploadWithRole { public static void main(String[] args) { // 1. 调用STS获取目标角色的临时凭证 AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard().build(); AssumeRoleRequest roleRequest = new AssumeRoleRequest() .withRoleArn("arn:aws:iam::111111111111:role/你的目标角色名") .withRoleSessionName("s3-upload-session"); AssumeRoleResult roleResponse = stsClient.assumeRole(roleRequest); // 2. 用临时凭证创建S3客户端 BasicSessionCredentials sessionCredentials = new BasicSessionCredentials( roleResponse.getCredentials().getAccessKeyId(), roleResponse.getCredentials().getSecretAccessKey(), roleResponse.getCredentials().getSessionToken()); AmazonS3 s3Client = AmazonS3ClientBuilder.standard() .withCredentials(new AWSStaticCredentialsProvider(sessionCredentials)) .build(); // 3. 执行上传操作 // s3Client.putObject(request); } }
4. 排查其他权限冲突
IAM权限遵循Deny优先于Allow的原则,但如果有其他策略(比如IAM角色/用户的内联策略、托管策略)允许了s3:PutObject,但你的桶策略因为Resource范围问题没覆盖到对象操作,那还是会允许上传。所以确保修改桶策略后,所有不符合条件的请求都会被Deny。
按照上面的步骤排查和调整,应该就能实现你想要的上传权限限制了。
内容的提问来源于stack exchange,提问作者sdc
相关产品推荐
相关产品推荐

