修改S3 KMS密钥后Lambda访问S3报AccessDenied错误排查
问题说明
- 访问
S3的Lambda函数此前运行正常,调整S3绑定的KMS密钥配置后开始报错,Lambda与S3均未部署在VPC内,已排除安全组配置影响,初步怀疑问题与KMS配置相关。 - 初始报错触发于
s3_client.get_object拉取S3对象的代码段,错误信息如下:
[ERROR] ClientError: An error occurred (AccessDenied) when calling the GetObject operation: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access. Traceback (most recent call last): File "/var/task/app.py", line 48, in handler raise e File "/var/task/app.py", line 45, in handler obj = s3_client.get_object(Bucket=bucket_name, Key=obj_key) File "/var/runtime/botocore/client.py", line 391, in _api_call return self._make_api_call(operation_name, kwargs) File "/var/runtime/botocore/client.py", line 719, in _make_api_call raise error_class(parsed_response, operation_name)
- 报错对应代码段:
try: logger.info(f"Try to get the object from bucket [{bucket_name}], key [{obj_key}]") obj = s3_client.get_object(Bucket=bucket_name, Key=obj_key) except Exception as e: logger.exception(e) raise e
- 首次修复为Lambda执行角色添加了仅包含
kms:Decrypt权限的策略,策略内容如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "kms:Decrypt", "Resource": "arn:aws:kms:*:678100228133:key/*" } ] }
- 添加上述策略后,拉取对象的报错消失,但
s3_client.put_object上传对象环节触发新报错,提示缺少kms:GenerateDataKey权限,错误信息如下:
[ERROR] ClientError: An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:sts::678100228133:assumed-role/cm-dev-resource-ResizerLambdaServiceRoleAE27CE82-1WN6YXPJAJDCX/cm-dev-lambda-resizer is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:ap-northeast-1:678100228133:key/e08d0542-a4ba-42e7-9725-106a48fd24c2 because no identity-based policy allows the kms:GenerateDataKey action Traceback (most recent call last): File "/var/task/app.py", line 82, in handler s3_client.put_object(Bucket=out_bk_name, Key=key, Body=data, ContentType=content_type) File "/var/runtime/botocore/client.py", line 391, in _api_call return self._make_api_call(operation_name, kwargs) File "/var/runtime/botocore/client.py", line 719, in _make_api_call raise error_class(parsed_response, operation_name)
根因分析
排查方向正确,问题为S3使用客户管理KMS密钥(CMK)做服务端加密时,Lambda执行角色缺少对应密钥的必要操作权限:
- S3使用AWS托管的默认S3密钥加密时,不需要用户额外配置KMS权限,AWS会自动处理服务间的权限授权;一旦换成用户自建的CMK,所有读写加密对象的主体都必须被授予CMK的对应操作权限,仅配置S3的读写权限无法完成加密/解密操作。
- 仅配置
kms:Decrypt权限只能满足下载对象时的解密需求:S3上传对象时需要调用KMS生成数据密钥完成对象加密,必须具备kms:GenerateDataKey权限。 - 两次报错对应两个不同的CMK:ID为
bf3cf318-1376-44de-a014-XXXXXXXXX的是源读取桶绑定的密钥,ID为e08d0542-a4ba-42e7-9725-106a48fd24c2的是目标写入桶绑定的密钥,两个密钥都需要给Lambda授权。
修复步骤
- 更新Lambda执行角色的内嵌权限策略,补全所需的KMS操作权限,最小权限参考配置如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowKMSAccessForS3Operation", "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:GenerateDataKey", "kms:Encrypt" ], "Resource": [ "arn:aws:kms:ap-northeast-1:678100228133:key/bf3cf318-1376-44de-a014-XXXXXXXXX", "arn:aws:kms:ap-northeast-1:678100228133:key/e08d0542-a4ba-42e7-9725-106a48fd24c2" ] } ] }
提示:如果业务中涉及S3分片上传、跨区域复制、对象重加密等场景,需要额外补充
kms:ReEncrypt*权限;测试阶段可暂时将资源范围设置为arn:aws:kms:*:678100228133:key/*快速验证,生产环境建议收敛到具体密钥ARN,遵循最小权限原则。
- 检查两个CMK的密钥策略:确认没有显式DENY Lambda执行角色的访问规则,且密钥策略允许账号下IAM身份授予对应权限(默认KMS密钥策略会放行账号根用户的IAM权限分配,若之前修改过密钥策略需要重点核对该项)。
- 保存权限配置后等待1-2分钟,待IAM权限全局生效后重新触发Lambda即可恢复正常。
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

