我继承了一个代码库,它利用Java AWS SDK为the和the对象生成预签名的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,我猜这可能涉及到通过AWS SDK下载KMS密钥并使用它对请求进行签名,还可能添加一些Authorization和其他头部。
选项1似乎工作量较少,但也不太理想,因为谁知道是否会始终支持安全性较低的加密形式。从概念上看,选项2似乎是更好的选择,但也引发了一些担忧,因为它确实看起来像是更多的工作,并且我担心必须包括额外的头部。上面显示的代码反映了PutObject请求的等价物(通过生成的URL代理),但也有下载图像的GetObject请求的等价物,这些图像可能直接呈现在浏览器中。在那里编写前端代码来使用不同的头来渲染图像会困难得多。(我想知道是否可以用查询参数代替头部?)
无论如何,我需要在我的Java中进行哪些更改才能使其与AWS KMS一起工作?我是否需要像我怀疑的那样,先使用AWS SDK“下载”KMS密钥?我应该这样做吗,或者AES-256真的是更好的选择吗?
发布于 2018-04-30 06:20:08
签名版本4几年来一直是默认的。除非您在AWS SDK配置文件中覆盖签名,否则您使用的是版本4。您可以使用以下代码覆盖此版本:
AmazonS3Client s3 = new AmazonS3Client(new ClientConfiguration().withSignerOverride("AWSS3V4SignerType"));真正的问题很可能是在创建预签名URL时需要指定服务器端加密。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
myBucket, myKey, HttpMethod.PUT)
.withSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");
URL puturl = s3.generatePresignedUrl(request);https://stackoverflow.com/questions/50090241
复制相似问题