I am using Amazon SES to receive emails, which are then stored in Amazon S3 through a rule set. These messages are then retrieved by my program, written in Java.
The whole process is currently working like a charm. The troubles come when I try to encrypt the emails...
Here are the steps of my process:
However, when I make the call to retrieve the email on S3 I get the following error:
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)
As described in this error, I thought that the user I use to retrieve S3 objects doesn't have access to the key used to encrypt the message. But as far as I understood how the Amazon's policies work, I believe everything is correct (which obviously is not).
Does someone have an idea of what I did wrong or what I could try to make this work?
Bellow are information about the current configuration, such as the policies of my user and the KMS key, plus the Java code I'm using.
The S3 bucket is in EU_WEST_1 (Ireland)
The key has been created in the EU_WEST_1 (Ireland) region
The user's name used here is delivery
AmazonS3FullAccess
AWSKeyManagementServicePowerUser
Key policy
{
"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"
}
}
}
]
}
{
"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"
}
}
}
]
}
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);
}
Thanks in advance for your help!
SES uses S3 Client-side encryption, you must use the Amazon S3 encryption client to decrypt the email after retrieving it from Amazon S3, Here is the code sample and reference from AWS Documentation.
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
Your mail is encrypted by Amazon SES using the Amazon S3 encryption client before the mail is submitted to Amazon S3 for storage. It is not encrypted using Amazon S3 server-side encryption. This means that you must use the Amazon S3 encryption client to decrypt the email after retrieving it from Amazon S3, as the service has no access to use your AWS KMS keys for decryption. This encryption client is available in the AWS SDK for Java