6

I am trying to use Amazon S3 as a file system with encryption.

I am successfully able to achieve uploading file on AWS S3 server using KMS Encrypted key (Server side Encryption). Please find below working code :

For Encrypt:

private static final String AWS_KMS_KEY = "---KMS Key---"
private static final String BUCKET_NAME = "---bucket name---"
private static final String keyName = "---display key name---"
private static final String filePath = "---File Path---"
private static final String ACCESS_KEY_ID = "---aws accesskey---"
private static final String SECRET_ACCESS_KEY = "---aws secret key---"

AWSCredentials awsCredentials = new BasicAWSCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
    .withRegion(Regions.US_WEST_2).withForceGlobalBucketAccessEnabled(true).build();

FileInputStream stream = new FileInputStream(filePath);

ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());

PutObjectRequest putObjectRequest = new PutObjectRequest(amazonFileUploadLocationOriginal, keyName, stream, objectMetadata);
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead);
putObjectRequest.withSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(AWS_KMS_KEY));

PutObjectResult result = s3Client.putObject(putObjectRequest);

I am facing issue while retriving file with server side decryption. I want to access directly aws url to retrieve that file with decryption. Please find below code which is not working :

For object read :

Object Read without KMS key :

GetObjectRequest request = new GetObjectRequest(existingBucketName, amazonFileUploadLocationOriginal);
s3Client.getUrl(BUCKET_NAME, keyName); 

Above Code is for read object without kms encrypted key which shows below error.

Code : InvalidArgument

Message : Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.


Object Read with KMS key :

GeneratePresignedUrlRequest genreq = new GeneratePresignedUrlRequest(BUCKET_NAME, keyName, HttpMethod.GET)
            .withSSEAlgorithm(SSEAlgorithm.KMS)
            .withKmsCmkId(AWS_KMS_KEY);

URL puturl = s3Client.generatePresignedUrl(genreq);

Above Code is for read object with kms encrypted key presign URL, which shows below error.

Code : SignatureDoesNotMatch

Message : The request signature we calculated does not match the signature you provided. Check your key and signing method.

Is it right way to do? Is there any suggestions? Please help.

Community
  • 1
  • 1
Jaimin Darji
  • 374
  • 2
  • 19
  • 1
    I believe you need to [force Signature Version 4](https://stackoverflow.com/a/37900263/1695906)... but don't use `withSSEAlgorithm(SSEAlgorithm.KMS)` when generating a `GET` URL. This probably causes the SDK to make an incorrect assumption about the contents of the actual request you'll be making, with the signed URL. – Michael - sqlbot Jun 29 '17 at 09:58
  • Thank you @Michael-sqlbot it's working... – Jaimin Darji Jun 29 '17 at 10:40
  • 1
    Now I get the correct working URL which download automatically pdf/image file, but I want to display in browser viewer support rather than downloading automatically. Any other way? or any configuration? – Jaimin Darji Jul 06 '17 at 07:26
  • If you check the object metadata in the S3 console, do they show the correct `Content-Type`? – Michael - sqlbot Jul 06 '17 at 10:21
  • @JaiminDarji , I'm trying to do the same thing as you but didn't work, could put your new code here? – Ahmed E. Eldeeb May 30 '19 at 07:54
  • it give me this error --> Generating a new signing key as the signing key not available in the cache for the date 1559174400000 – Ahmed E. Eldeeb May 30 '19 at 08:10
  • @Ahmed E. Eldeeb can you please explain your issue ? – Jaimin Darji Jun 07 '19 at 10:29
  • @Ahmed E. Eldeeb if you are using server-side encryption with `Key Management Service (KMS)` than pre-sign URL required with signing key this URL always new and it has been used for a limited time period. and you are not using server-side encryption than no need to generate pre-sign URL directly access your bucket file – Jaimin Darji Nov 28 '19 at 05:17

1 Answers1

1

if the signature not match please use the following code to add manually for reference AWS java SDK manually set signature version

System.setProperty(SDKGlobalConfiguration.ENABLE_S3_SIGV4_SYSTEM_PROPERTY, "true");

We can use the below code to get presided URL get

GeneratePresignedUrlRequest genreq = new GeneratePresignedUrlRequest(BUCKET_NAME, keyName, HttpMethod.GET)
 .withExpiration(expiration);

URL puturl = s3Client.generatePresignedUrl(genreq);

This URL will contain the expiry of time and signature like following

output

https://mybucket.s3.amazonaws.com/abc_count.png?AWSAccessKeyId=AKIAJXXXXXXXXXXXXXXX&Expires=1503602631&Signature=ibOGfAovnhIF13DALdAgsdtg2s%3D

Hope some one helps this ans

Jaimin Darji
  • 374
  • 2
  • 19