Amazon S3: шифрование сообщений от Amazon SES

Я использую Amazon SES для получения электронных писем, которые затем сохраняются в Amazon S3 через набор правил. Эти сообщения затем извлекаются моей программой, написанной на Java.

Весь процесс в настоящее время работает как шарм. Проблемы приходят, когда я пытаюсь зашифровать письма...

Вот шаги моего процесса:

  1. Письма получены SES
  2. SES шифрует электронную почту с помощью ключа KMS (благодаря набору правил SES).
  3. SES хранит электронные письма на Amazon S3
  4. Мое приложение Java получает письма от S3.

Однако, когда я звоню, чтобы получить электронную почту на S3, я получаю следующую ошибку:

com.amazonaws.services.kms.model.AWSKMSException: 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. (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: 8de11099-1706-11e8-a931-c7b8c61f94bc)

Как описано в этой ошибке, я думал, что пользователь, которого я использую для извлечения объектов S3, не имеет доступа к ключу, используемому для шифрования сообщения. Но насколько я понимаю, как работают политики Amazon, я считаю, что все правильно (что, очевидно, не так).

Кто-то имеет представление о том, что я сделал не так или что я мог бы попытаться сделать эту работу?

Ниже приведены сведения о текущей конфигурации, такие как политики моего пользователя и ключ KMS, а также код Java, который я использую.

Область, край

The S3 bucket is in EU_WEST_1 (Ireland)
The key has been created in the EU_WEST_1 (Ireland) region

Политика пользователя (подробности см. На прикрепленном изображении)

Используемое здесь имя пользователя - доставка

AmazonS3FullAccess
AWSKeyManagementServicePowerUser

Ключевая политика

{
  "Version": "2012-10-17",
  "Id": "key-consolepolicy-3",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111222333444:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
{
  "Sid": "Allow access for Key Administrators",
  "Effect": "Allow",
  "Principal": {
    "AWS": [
      "AIDAIEIV9CCM6CQJBN7HA",
      "arn:aws:iam::111222333444:user/delivery"
    ]
  },
  "Action": [
    "kms:Create*",
    "kms:Describe*",
    "kms:Enable*",
    "kms:List*",
    "kms:Put*",
    "kms:Update*",
    "kms:Revoke*",
    "kms:Disable*",
    "kms:Get*",
    "kms:Delete*",
    "kms:TagResource",
    "kms:UntagResource",
    "kms:ScheduleKeyDeletion",
    "kms:CancelKeyDeletion"
  ],
  "Resource": "*"
},
{
  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": {
    "AWS": [
      "AIDAIEIV9CCM6CQJBN7HA",
      "arn:aws:iam::111222333444:user/delivery"
    ]
  },
  "Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:ReEncrypt*",
    "kms:GenerateDataKey*",
    "kms:DescribeKey"
  ],
  "Resource": "*"
},
{
  "Sid": "Allow attachment of persistent resources",
  "Effect": "Allow",
  "Principal": {
    "AWS": [
      "AIDAIEIV9CCM6CQJBN7HA",
      "arn:aws:iam::111222333444:user/delivery"
    ]
  },
  "Action": [
    "kms:CreateGrant",
    "kms:ListGrants",
    "kms:RevokeGrant"
  ],
  "Resource": "*",
  "Condition": {
    "Bool": {
      "kms:GrantIsForAWSResource": "true"
    }
  }
},
{
  "Sid": "AllowSESToEncryptMessagesBelongingToThisAccount",
  "Effect": "Allow",
  "Principal": {
    "Service": "ses.amazonaws.com"
  },
  "Action": [
    "kms:Encrypt",
    "kms:GenerateDataKey*"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "kms:EncryptionContext:aws:ses:source-account": "111222333444"
    },
    "Null": {
      "kms:EncryptionContext:aws:ses:rule-name": "false",
      "kms:EncryptionContext:aws:ses:message-id": "false"
    }
  }
}
]
}

Политика S3 Bucket

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "AllowSESPuts-111222333444",
        "Effect": "Allow",
        "Principal": {
            "Service": "ses.amazonaws.com"
        },
        "Action": "s3:PutObject",
        "Resource": "arn:aws:s3:::received-emails.my-company-name/*",
        "Condition": {
            "StringEquals": {
                "aws:Referer": "111222333444"
            }
        }
    }
]
}

Java-код

private static void getS3Object() {
    // Use credentials to login.
    BasicAWSCredentials awsCred = new BasicAWSCredentials("user access key", "user secret");
    AWSCredentialsProvider credentialProvider = new AWSStaticCredentialsProvider(awsCred);

    KMSEncryptionMaterialsProvider materialsProvider = new KMSEncryptionMaterialsProvider("id of the key");
    AmazonS3Encryption s3Client = AmazonS3EncryptionClientBuilder
            .standard()
            .withCryptoConfiguration(new CryptoConfiguration(CryptoMode.EncryptionOnly))
            .withEncryptionMaterials(materialsProvider)
            .withCredentials(credentialProvider)
            .withRegion(Regions.EU_WEST_1).build();

    // Get the object from S3
    GetObjectRequest request = new GetObjectRequest(new S3ObjectId("Bucket name", "Object key"));
    S3Object object = s3Client.getObject(request);
}

Заранее спасибо за помощь!

3 ответа

Решение

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

https://docs.aws.amazon.com/AmazonS3/latest/dev/client-side-using-kms-java.html

https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-s3.html

Ваша почта шифруется Amazon SES с помощью клиента шифрования Amazon S3 перед отправкой почты в Amazon S3 для хранения. Он не шифруется с помощью шифрования на стороне сервера Amazon S3. Это означает, что вы должны использовать клиент шифрования Amazon S3 для дешифрования электронной почты после ее получения из Amazon S3, поскольку у службы нет доступа к использованию ключей AWS KMS для дешифрования. Этот клиент шифрования доступен в AWS SDK для Java

Благодаря Sudharsan, вот ответ на мой вопрос;

Кажется, что даже если бы я использовал правильный клиент (для шифрования на стороне клиента), я как-то забыл некоторые аргументы (скорее всего, witAwshKmsRegion() параметр).

Вот код, который работал:

private static void getS3Object() {
  // Use credentials to login.
  BasicAWSCredentials awsCred = new BasicAWSCredentials("user access key", "user secret");
  AWSCredentialsProvider credentialProvider = new AWSStaticCredentialsProvider(awsCred);

  KMSEncryptionMaterialsProvider materialsProvider = new KMSEncryptionMaterialsProvider("id of the key");
  AmazonS3Encryption s3Client = AmazonS3EncryptionClientBuilder
        .withCryptoConfiguration(new CryptoConfiguration().withAwsKmsRegion(com.amazonaws.regions.Region.getRegion(Regions.EU_WEST_1)))
        .withEncryptionMaterials(materialsProvider)
        .withCredentials(credentialProvider)
        .withRegion(Regions.EU_WEST_1).build();

  // Get the object from S3
  GetObjectRequest request = new GetObjectRequest(new S3ObjectId("Bucket name", "Object key"));
  S3Object object = s3Client.getObject(request);
}
Другие вопросы по тегам