Amazon S3: шифрование сообщений от Amazon SES
Я использую Amazon SES для получения электронных писем, которые затем сохраняются в Amazon S3 через набор правил. Эти сообщения затем извлекаются моей программой, написанной на Java.
Весь процесс в настоящее время работает как шарм. Проблемы приходят, когда я пытаюсь зашифровать письма...
Вот шаги моего процесса:
- Письма получены SES
- SES шифрует электронную почту с помощью ключа KMS (благодаря набору правил SES).
- SES хранит электронные письма на Amazon S3
- Мое приложение 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);
}
Может быть проблема с типом шифрования Amazon SES.
https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingEncryption.html
https://aws.amazon.com/articles/client-side-data-encryption-with-the-aws-sdk-for-java-and-amazon-s3/