密文是指一个不存在的客户主密钥。

32

我有一段lambda代码可以访问S3

之前,这个lambda程序运行良好。但最近我更改了S3的KMS密钥或某些其他安全组设置(lambda源代码没有更改)。

出现了错误。

我猜测这个lambdaS3不在VPC上,因此安全组并不相关。

那么,与KMS密钥有关吗?

S3被加密为bf3cf318-1376-44de-a014-XXXXXXXXX,因此我必须给这个lambda授予kms访问权限?但是如何操作?

或者,我完全错了吗?

[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)
[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 角色

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "kms:Decrypt",
            "Resource": "arn:aws:kms:*:678100228133:key/*"
        }
    ]
}

消息已更改

[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)
[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)

请务必检查用于加密对象本身的密钥。我已经为存储桶配置了对默认KMS密钥的访问权限,但由于对象是使用不同的密钥进行加密的,所以一直出现这个错误。 - gary69
4个回答

17

尽管我已经在Lambda上附加了“kms decrypt”策略,但我仍然遇到了这个错误:The ciphertext refers to a customer master key...。问题是,我必须在KMS密钥的基于资源的策略中添加以下策略声明,如下所示:

{
  "Sid": "AllowLambdaDecrypt",
  "Action": [
    "kms:Decrypt", "<add more required actions here>"
  ],
  "Effect": "Allow",
  "Resource": "arn:aws:s3:::<bucketName>/*",
  "Principal": {
    "AWS": [
      "arn:aws:iam:::<account_id>:role/service-role/<lambdaRole>"
    ]
  }
}

注意:如果您使用的是 AWS 管理的 KMS 密钥,则无法修改其策略。(了解该限制)因此,请确保您正在使用自己生成的客户管理的 KMS 密钥。详情请查看我的YouTube视频


在将环境变量添加到 Lambda 后,我遇到了这个错误。我创建了一个密钥,并将其添加到我的密钥策略中,以及通过 IAM 对策略进行访问,这解决了问题。 - Michael Olafisoye

11

请查看错误信息中加粗的部分:

[错误] ClientError: 在调用GetObject操作时发生错误(AccessDenied): 密文引用一个不存在的客户主密钥,该密钥不存在于此区域,或您无权访问

而您的问题是:

因此我必须为这个Lambda提供kms访问权限

看起来您没有在IAM角色中为Lambda函数提供KMS权限

KMS密钥也有一个访问策略,可能会阻止Lambda访问。如果修复Lambda函数的IAM角色不能解决此问题,则应检查该策略。


谢谢,我已经将策略添加到角色中,消息已更改。 - whitebear
请阅读新的错误信息。现在它告诉您缺少 S3 权限,因此您还需要将其添加到 IAM 角色中。 - Mark B
我将 kms:* 添加到策略中,它可以正常工作。 - whitebear
4
我的角色和关键策略都在所有资源上具有kms:*权限。然而,我仍然收到错误信息。我也检查了区域。 - Waleed Ahmad

1
我们没有设置KMS加密密钥,所以默认密钥被使用了。如果您尝试访问跨账户,则密钥将不匹配。因此,在CodePipeline上添加EncryptionKey属性可以确保在推送/拉取工件活动中跨账户使用相同的密钥。

enter image description here

enter image description here


谢谢!我也在设置跨账户管道,但一直无法弄清楚为什么在目标账户的ElasticBeanstalk中总是显示"您没有权限将 Amazon S3 对象复制到另一个 S3 位置"。在花费数小时调整 IAM、存储桶和密钥策略后,我找到了您的答案。原来我没有将 KMS 密钥添加到管道中。添加后,它完美地工作了! - Jan

0
我在删除 IAM 角色策略后重新创建具有相同名称的策略时遇到了此问题。我所做的是将 Lambda 执行角色切换到另一个角色,然后再切换回来,问题就解决了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接