亚马逊S3:加密来自亚马逊SES的消息

4

我正在使用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

用户策略(详见附图)

此处使用的用户名称为delivery

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 policy

{
"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个回答

4

感谢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);
}

2
我发现了同样的事情;在构建器中除了.withRegion之外,您还需要提供CryptoConfiguration().withAwsKmsRegion() - eugenevd

1

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 S3进行存储之前,由Amazon SES使用Amazon S3加密客户端进行加密。它不会使用Amazon S3服务器端加密进行加密。这意味着您必须使用Amazon S3加密客户端在从Amazon S3检索电子邮件后解密它,因为该服务无法访问您的AWS KMS密钥以进行解密。此加密客户端可在AWS SDK for Java中获得。

感谢Sudharsan的回答!它起作用了!由于Amazon的示例已过时,我不得不进行一些更改。我将粘贴我使用的代码。 感谢您所有的澄清! - Cccompany


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接