AWS跨账号授权:账号B读取解密账号A的KMS加密DynamoDB数据(Java)
解决跨账号访问加密DynamoDB时的KMS密钥找不到问题
问题根源
你遇到的NotFoundException核心原因很明确:你的AWSKMS客户端用的是账号B的原生凭证,它默认会在账号B的KMS服务里查找密钥,但密钥实际在账号A。虽然你给DynamoDB客户端配置了AssumeRole凭证(通过STSAssumeRoleSessionCredentialsProvider),但KMS客户端并没有复用这个角色身份,还是在用账号B自己的权限去访问KMS,自然找不到账号A的密钥。
解决方案:让KMS客户端复用AssumeRole角色身份
要解决这个问题,你需要让KMS客户端也使用和DynamoDB客户端一样的跨账号角色凭证,这样KMS请求会以账号A中角色的身份发起,就能正确访问账号A的KMS密钥了。
修改你的KMS客户端创建代码,把凭证换成arscp(也就是你创建DynamoDB客户端时用的那个STSAssumeRoleSessionCredentialsProvider):
// 复用之前创建的AssumeRole凭证提供者arscp AWSKMS kms = AWSKMSClientBuilder.standard() .withRegion(region) .withCredentials(arscp) // 这里替换成AssumeRole的凭证,而不是账号B的原生凭证 .build(); EncryptionMaterialsProvider encryptionProvider = new DirectKmsMaterialProvider(kms, keyId); // 后续创建DynamoDBMapper的逻辑保持不变 return new DynamoDBMapper(client, dynamoDBMapperConfig, new AttributeEncryptor(encryptionProvider));
额外权限检查
除了代码修改,还要确保以下权限配置正确:
- 账号A的KMS密钥策略:需要允许你创建的跨账号角色(账号A中的那个角色)拥有
kms:Decrypt权限,比如添加这样的语句:{ "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<账号A ID>:role/<你的跨账号角色名>" }, "Action": "kms:Decrypt", "Resource": "*" } - 账号A的跨账号角色权限:该角色需要同时拥有DynamoDB的读取权限和KMS的解密权限(可以通过IAM策略附加到角色上)。
- 账号B的IAM用户权限:确保用户有
sts:AssumeRole权限可以扮演账号A的那个角色。
小提示
建议你在代码中使用完整的KMS密钥ARN(比如arn:aws:kms:us-east-1:<账号A ID>:key/<密钥ID>)来指定keyId,这样能彻底避免账号混淆的问题,减少出错概率。
内容的提问来源于stack exchange,提问作者Bonton255
相关产品推荐
相关产品推荐

