我正在继承一个代码库,该代码库利用Java AWS SDK为Putting和Getting Objects生成预先指定的S3 URL。代码看起来像这样:
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, filename);
request.setMethod(HttpMethod.PUT);
request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");
String url = awss3.generatePresignedUrl(request);
现有的代码库始终有效,并且非常接近工作。但是,改变的一个业务需求是我们需要加密S3存储桶的内容。所以,当然,我将存储桶上的默认加密设置为AWS-KMS(因为它看起来像是最现代的),并选择为我的帐户创建的默认“aws / s3”密钥。
但是,现在当最终用户尝试实际使用我在浏览器中生成的URL时,会出现以下错误消息:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<code>InvalidArgument</code>
<Message>Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>null</ArgumentValue>
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
我的问题是:我怎么能再次使用它?我认为有两种不同的路径可以采取。要么:1)我可以将桶加密从AWS-KMS降级到AES-256并希望它一切正常,或2)我可以对我的客户端代码进行一些更改以支持KMS,我猜这可能涉及下载KMS密钥通过AWS SDK并使用它来签署请求,还可能添加一些授权和其他标头。
选项1似乎工作量较少但也不太理想,因为谁知道是否始终支持不太安全的加密形式。选项2在概念上似乎是更好的选择,但也引起了一些担忧,因为它确实看起来更多的工作,我担心必须包含额外的标题。我上面显示的代码反映了PutObject请求的等价物(通过生成的URL代理),但也有等效的GetObject请求下载图像,这些请求可能直接在浏览器中呈现。在那里编写前端代码以使用不同的标题来渲染图像要困难得多。 (我想知道查询参数是否可以代替标题?)
无论如何,我需要在Java中进行哪些更改以使其与AWS KMS一起使用?我怀疑是否需要首先使用AWS SDK“下载”KMS密钥?我应该这样做,还是AES-256真的是更好的选择?
答案 0 :(得分:0)
签名签名版本4已成为多年的默认值。除非您覆盖AWS SDK配置文件中的签名,否则您使用的是版本4.您可以使用以下代码覆盖此签名:
obj.method();
最有可能真正的问题是,您需要在创建预签名URL时指定服务器端加密。
AmazonS3Client s3 = new AmazonS3Client(new ClientConfiguration().withSignerOverride("AWSS3V4SignerType"));