S3 PutObject с шифрованием KMS завершается с ошибкой 403 Access Denied

Я пытался выполнить вызов PutObject для AWS S3, используя шифрование на стороне сервера с помощью ключа KMS, но вызов продолжает завершаться ошибкой с кодом 403, а в сообщении говорится «Отказано в доступе».

Вот код С#, который я использую для вызова:

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, которые я настроил. Во-первых, С3:

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

а затем КМС:

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

Когда я комментирую шифрование, вызов проходит, и я вижу, как создается файл.

Я не уверен, что означает «Отказано в доступе». К какому ресурсу мне отказано в доступе? Любая помощь будет принята с благодарностью.


person Ramesh Muraleedharan    schedule 09.01.2018    source источник


Ответы (2)


AWS не предоставляет подробностей об отказе в доступе. Это нормально в хорошо спроектированных системах в целях безопасности, но это не помогает разработчикам.

Убедитесь, что ваш ключ KMS работает с помощью интерфейса командной строки AWS.

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

Если CLI работает, значит проблема в вашем коде (которой я не вижу). Если интерфейс командной строки также сообщает об ошибке, возможно, у вас возникла проблема с ключевыми пользователями KMS.

При создании ключа KMS вы устанавливаете разрешения на использование для ключа. Перейдите в консоль AWS IAM. Дважды проверьте, есть ли у пользователя IAM, под которым выполняется код, разрешения на использование ключа KMS. Посмотрите в разделе «Ключевые пользователи».

Если вы правильно определили ключевых пользователей, перейдите в консоль S3 и протестируйте загрузку файла с использованием того же ключа KMS и убедитесь, что он работает.

person John Hanley    schedule 09.01.2018
comment
Я немного новичок в IAM, поэтому мне помогло предложение «Ключевые пользователи». Оказывается, ключ был создан без привилегий «предоставления», поэтому он мог выполнять шифрование только на стороне клиента. Как только я добавил разрешения kms:CreateGrant, kms:ListGrants, kms:RevokeGrant, все заработало! Спасибо, Джон! - person Ramesh Muraleedharan; 09.01.2018

Оказывается, мне не хватало разрешений «предоставить» в политике ключей, которая позволяет делегировать разрешения ключей службам AWS, которые поддерживают шифрование на стороне сервера KMS. Как только я добавил это, это сработало.

{
  "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

person Ramesh Muraleedharan    schedule 09.01.2018
comment
Использование"Resource": "*" может быть слишком открытым. Я знаю, что в документах есть такой пример, но вы должны использовать там фактический ключ KMS ARN (или их список), а не *. Если основным пользователем являетесь вы, то, возможно, это нормально для разрешения на уровне администратора, но если это роль IAM, вы предоставляете сервису доступ ко всем без исключения ключам в KMS. Может быть, это нормально для небольшого проекта с одним ключом, но лучше использовать разные ключи для разных целей. - person Davos; 25.10.2018