跨账号CodeBuild同步至SSE-KMS加密S3时遇AccessDenied错误
问题描述
使用场景
通过部署在us-west-2区域、包含CodeCommit和CodeBuild阶段的AWS CodePipeline,将Beta账号CodeCommit仓库的文件同步至us-east-1区域的Prod账号S3存储桶,buildspec.yml文件中包含复制/同步文件的命令。
错误信息
上传失败:jam/bie/core_pipeline/folding.json 至 s3://temp-bucket-aev/temp/folding.json,调用PutObject操作时发生(AccessDenied)错误:权限拒绝。
现象
- 将存储桶加密类型改为SSE-S3(亚马逊S3托管密钥服务端加密)时,错误消失;
- 切换为SSE-KMS(AWS密钥管理服务密钥服务端加密)时,错误重现。
账号配置详情
A. Beta账号:xxxxxxxxx
A.1 IAM角色:cicdBuildRole
A.1.1 IAM策略:s3crossaccountaccess_temp
{"Version": "2012-10-17","Statement": [{"Sid": "AllowCrossAccountAccess","Effect": "Allow","Action": "s3:PutObject","Resource": "arn:aws:s3:::temp-bucket-aev/*","Condition": {"StringEquals": {"aws:SourceAccount": "<prod_account_number>"}}}]}
A.1.2 IAM策略:cross_account_access_for_code_build
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "sts:AssumeRole","Resource": "arn:aws:iam::<prod_account_number>:role/cicdCrossAccountRole"}]}
A.1.3 IAM托管策略
- AmazonS3FullAccess
- AWSCodeCommitReadOnly
- AWSCodeBuildReadOnlyAccess
A.1.4 信任关系
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "codebuild.amazonaws.com"},"Action": "sts:AssumeRole"}]}
A.2 角色:codePipelineServiceRole
IAM策略:CodePipelineRolePolicy
{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject*","s3:GetBucket*","s3:List*","s3:DeleteObject*","s3:PutObject","s3:PutObjectLegalHold","s3:PutObjectRetention","s3:PutObjectTagging","s3:PutObjectVersionTagging","s3:Abort*"],"Resource": ["arn:aws:s3:::artifact-beta-cicd-us-west-2","arn:aws:s3:::artifact-beta-cicd-us-west-2/*"],"Effect": "Allow"},{"Action": "sts:AssumeRole","Resource": "arn:aws:iam::<prod_account_number>:role/pipeline-beta-CIC-CodePipelineSourceCodeCo-1R53MXYY2ECRC","Effect": "Allow"},{"Action": "sts:AssumeRole","Resource": "arn:aws:iam::<prod_account_number>:role/pipeline-beta-CIC-CodePipelineBuildCodeBui-73K6MQ3LCRG7","Effect": "Allow"}]}
信任关系
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "codepipeline.amazonaws.com"},"Action": "sts:AssumeRole"}]}
A.3 buildspec.yml
version: 0.2 env: variables: phases: build: commands: - echo "Sync files from the CodeCommit repo to the S3 bucket." post_build: commands: - echo "Syncing changed files from CodeCommit repo to S3 bucket in the Beta account..." # Copy files from CodeCommit repo to S3 bucket in the Prod account - echo "Syncing files from CodeCommit repo to S3 bucket in the Prod account..." - aws s3 sync jam/bie/core_pipeline/ s3://temp-bucket-aev/temp/ --region us-east-1 artifacts: files: - '**/*'
B. Prod账号:yyyyyyyyyy
S3存储桶:arn:aws:s3:::temp-bucket-aev
IAM角色:cicdCrossAccountRole
IAM策略:temp_policy_code_pipeline
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["codecommit:List*","codecommit:Get*","codecommit:GitPull","codebuild:StartBuild","s3:PutObject","s3:GetObject","s3:ListBucket"],"Resource": ["arn:aws:codecommit:us-west-2:<beta-account-number>:CodeRepo","arn:aws:s3:::temp-bucket-aev/*"]}]}
存储桶策略:temp-bucket-aev
{"Version": "2012-10-17","Statement": [{"Sid": "AllowCrossAccountAccess","Effect": "Allow","Principal": {"AWS": "arn:aws:iam::<beta-account-number>:role/cicdBuildRole"},"Action": ["s3:PutObject","s3:GetObject","s3:ListBucket"],"Resource": ["arn:aws:s3:::temp-bucket-aev/*","arn:aws:s3:::temp-bucket-aev"]}]}
加密类型
采用AWS密钥管理服务密钥进行服务端加密(SSE-KMS)
KMS密钥策略(ARN:arn:aws:kms:us-east-1:<prod_account_number>:key/zzz-zzzz-000-2222-ttttttt)
{"Version": "2012-10-17","Id": "key-policy","Statement": [{"Sid": "AllowRootAndCICDAccess","Effect": "Allow","Principal": {"AWS": ["arn:aws:iam::<prod_account_number>:role/cicdCrossAccountRole","arn:aws:iam::<prod_account_number>:root"]},"Action": ["kms:Decrypt","kms:Encrypt","kms:ReEncrypt*","kms:GenerateDataKey*","kms:DescribeKey"],"Resource": "*"},{"Sid": "AllowRootAccess","Effect": "Allow","Principal": {"AWS": "arn:aws:iam::<prod_account_number>:root"},"Action": "kms:*","Resource": "*"},{"Sid": "AllowCloudWatchLogsAccess","Effect": "Allow","Principal": {"Service": "logs.us-east-1.amazonaws.com"},"Action": ["kms:Encrypt*","kms:Decrypt*","kms:ReEncrypt*","kms:GenerateDataKey*","kms:Describe*"],"Resource": "*","Condition": {"StringEquals": {"kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:us-east-1:*:*"}}}]}
已尝试操作
修改KMS密钥策略并尝试多种策略组合,但问题仍未解决。
解决方案
问题核心是KMS密钥权限缺失:当前KMS密钥策略仅授权了Prod账号的cicdCrossAccountRole,但实际执行s3 sync的是Beta账号的cicdBuildRole,该角色未被允许使用目标KMS密钥。
修复步骤
- 更新Prod账号的KMS密钥策略
在AllowRootAndCICDAccess语句的Principal列表中加入Beta账号的cicdBuildRoleARN:
{"Sid": "AllowRootAndCICDAccess","Effect": "Allow","Principal": {"AWS": [ "arn:aws:iam::<prod_account_number>:role/cicdCrossAccountRole", "arn:aws:iam::<prod_account_number>:root", "arn:aws:iam::<beta-account-number>:role/cicdBuildRole" // 添加该行 ]},"Action": ["kms:Decrypt","kms:Encrypt","kms:ReEncrypt*","kms:GenerateDataKey*","kms:DescribeKey"],"Resource": "*"}
- 补充Beta账号角色的KMS权限
在Beta账号cicdBuildRole的IAM策略中添加KMS操作权限:
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["kms:GenerateDataKey*","kms:Encrypt"],"Resource": "arn:aws:kms:us-east-1:<prod_account_number>:key/zzz-zzzz-000-2222-ttttttt"}]}
原理说明
当S3使用SSE-KMS加密时,执行PutObject操作的身份不仅需要S3的PutObject权限,还需要对应KMS密钥的GenerateDataKey和Encrypt权限——因为S3会调用KMS生成数据密钥来加密对象。之前Beta账号的角色缺少这部分权限,导致权限拒绝错误。
内容的提问来源于stack exchange,提问作者datacookie93
相关产品推荐
相关产品推荐

