使用 KMS 托管 CMK 时复制到 redshift 失败并出现错误

Posted

技术标签:

【中文标题】使用 KMS 托管 CMK 时复制到 redshift 失败并出现错误【英文标题】:Copy to redshift fails with an error when using KMS Managed CMK 【发布时间】:2017-07-05 19:15:51 【问题描述】:

我正在尝试编写一个使用 KMS 密钥 ID 加密数据的 Java 程序。我正在使用默认的 java 代码将对象上传到 S3。我正在将要上传到 S3 的值更改为记录,以便我可以将其加载到 redshift。

import java.io.ByteArrayInputStream;
import java.util.Arrays;

import junit.framework.Assert;

import org.apache.commons.io.IOUtils;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3EncryptionClient;
import com.amazonaws.services.s3.model.CryptoConfiguration;
import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;

public class testKMSkeyUploadObject 

    private static AmazonS3EncryptionClient encryptionClient;

    public static void main(String[] args) throws Exception  
       String bucketName = "***bucket name***"; 
        String objectKey  = "ExampleKMSEncryptedObject";
        String kms_cmk_id = "***AWS KMS customer master key ID***";

        KMSEncryptionMaterialsProvider materialProvider = new KMSEncryptionMaterialsProvider(kms_cmk_id);

        encryptionClient = new AmazonS3EncryptionClient(new ProfileCredentialsProvider(), materialProvider,
                new CryptoConfiguration().withKmsRegion(Regions.US_EAST_1))
            .withRegion(Region.getRegion(Regions.US_EAST_1));

        // Upload object using the encryption client.
        byte[] plaintext = "xyz,abc,1"
                .getBytes();
        System.out.println("plaintext's length: " + plaintext.length);
        encryptionClient.putObject(new PutObjectRequest(bucketName, objectKey,
                new ByteArrayInputStream(plaintext), new ObjectMetadata()));

     // Download the object.
        S3Object downloadedObject = encryptionClient.getObject(bucketName,
                objectKey);
        byte[] decrypted = IOUtils.toByteArray(downloadedObject
                .getObjectContent());

        // Verify same data.
        Assert.assertTrue(Arrays.equals(plaintext, decrypted));
    

我正在使用具有以下语法的 Redhsift 复制命令将记录复制到 redshift。

copy table_name from 's3://bucket-name/KMSEncryptedObject' credentials as
'aws_access_key_id=<access-key-id>;aws_secret_access_key=<secret-access-key>;master_symmetric_key=<master-key>'

在复制命令上方运行时,我遇到以下错误:

Query execution failed 
Reason: SQL Error [500310] [XX000]: [Amazon](500310) Invalid operation: Failed writing body (0 != 16) 
Cause: S3 object 'KMSEncyptedObjecr does not have 'x-amz-meta-x-amz-key metadata 
Details: 
----------------
error: Failed writing body (0 != 16) Cause: S3 object 'KMSEncyptedObjeci does not have 'x-amz-meta-x-amz-key metadata 

【问题讨论】:

我遇到了同样的问题。您还记得解决方案是什么吗? 我猜,我正在使用 aws sdk 2 上传 s3 对象,将 aws sdk 版本切换到旧版本有帮助。 【参考方案1】:

AFAIK 在从 S3 复制数据时,您不必指定 KMS 密钥 ID。只需从您的凭据字符串中删除 master_symmetric_key 参数。

查看http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html,您只需要上传 KMS 密钥 ID(当然 IAM 用户/角色需要有权访问此密钥)。

【讨论】:

以上是关于使用 KMS 托管 CMK 时复制到 redshift 失败并出现错误的主要内容,如果未能解决你的问题,请参考以下文章

配置用于复制加密对象的源 KMS 密钥

AWS 错误消息:使用 AWS KMS 托管密钥指定服务器端加密的请求需要 AWS 签名版本 4

DynamoDB 如何使用 AWS KMS

使用默认 aws/S3 KMS 密钥对解密对象进行跨账户访问

更改现有 EFS 的加密密钥

复制数据库快照的最低 KMS 权限