使用 KMS 加密的 S3 PutObject 失败并出现 403 "Access Denied" 错误

S3 PutObject with KMS encryption fails with 403 "Access Denied" error

我一直在尝试对 AWS S3 进行 PutObject 调用,同时使用带有 KMS 密钥的服务器端加密,但调用一直失败并显示 403 代码,消息显示 "Access Denied"。

这是我正在使用的 C# 代码:

const string fileName = "test.txt";
using (var stream = new MemoryStream())
{
    using (var sw = new StreamWriter(stream))
    {
        sw.AutoFlush = true;
        sw.Write("letsseeifthisworks");

        var por = new PutObjectRequest
        {
            BucketName = _bucketname,
            Key = fileName,
            InputStream = stream,
            ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS,
            ServerSideEncryptionKeyManagementServiceKeyId = _kmsKeyId
        };

        var response = _s3Client.PutObject(por);
    }
}

HTTP 请求如下所示:

PUT https://notarealcorp.s3.us-west-1.amazonaws.com/test.txt HTTP/1.1
Content-Type: text/plain
x-amz-server-side-encryption: aws:kms
x-amz-server-side-encryption-aws-kms-key-id: arn:aws:kms:us-west-1:<account>:key/<kms-key-guid>
User-Agent: aws-sdk-dotnet-45/3.3.16.2 aws-sdk-dotnet-core/3.3.21.6 .NET_Runtime/4.0 .NET_Framework/4.0 OS/Microsoft_Windows_NT_6.1.7601_Service_Pack_1 ClientSync
host: notarealcorp.s3.us-west-1.amazonaws.com
X-Amz-Date: 20180109T072431Z
X-Amz-Decoded-Content-Length: 18
X-Amz-Content-SHA256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
Authorization: AWS4-HMAC-SHA256 Credential=<access-key>/20180109/us-west-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;user-agent;x-
amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id, Signature=<signature>
Content-Length: 191
Expect: 100-continue

12;chunk-signature=<another-signature>
letsseeifthisworks
0;chunk-signature=<yet-another-signature>

这是回复:

HTTP/1.1 403 Forbidden
x-amz-request-id: <request-id>
x-amz-id-2: <host-id>
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Tue, 09 Jan 2018 07:24:31 GMT
Connection: close
Server: AmazonS3

f3
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message>
<RequestId>request-id</RequestId><HostId>host-id</HostId></Error>
0

这些是我设置的 IAM 权限。首先,S3:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

然后是 KMS:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "kms:*",
            "Resource": "*"
        }
    ]
}

当我注释掉加密时,调用成功,我可以看到正在创建的文件。

我不确定 'Access Denied' 是什么意思。我被拒绝访问哪些资源?任何帮助将不胜感激。

A​​WS 不提供访问被拒绝的详细信息。这在出于安全目的而精心设计的系统中是正常的,但这对开发人员没有帮助。

使用 AWS CLI 验证您的 KMS 密钥是否有效。

aws s3 cp SourceFile s3://mybucket/DestinationFile --sse aws:kms --sse-kms-key-id <ReplaceWithYourKeyId>

如果 CLI 正常工作,则说明您的代码有问题(我没有看到)。如果 CLI 也报告错误,那么您可能遇到了 KMS 密钥用户问题。

创建 KMS 密钥时,您设置了密钥的使用权限。转到 AWS IAM 控制台。仔细检查代码为 运行 的 IAM 用户是否有权使用 KMS 密钥。在 "Key Users".

下查看

如果您已正确定义密钥用户,请转至 S3 控制台并使用相同的 KMS 密钥测试上传文件并确保其正常工作。

原来我缺少密钥策略的 'grant' 权限,它允许您将密钥权限委托给支持 KMS 服务器端加密的 AWS 服务。一旦我添加了它,它就起作用了。

{
  "Sid": "Allow attachment of persistent resources",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::<account>:user/<user>"
  },
  "Action": [
    "kms:CreateGrant",
    "kms:ListGrants",
    "kms:RevokeGrant"
  ],
  "Resource": "*",
  "Condition": {
    "Bool": {
      "kms:GrantIsForAWSResource": "true"
    }
  }
}

这里有更多信息:https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users