How to safely store AWS credentials in a Java application?

Asked

Viewed 122 times

0

I have a Java Desktop application that is distributed to customers.

I need, from now on, send data from this application to Amazon S3. For this you need to set the credentials AWS (accessKeyId and secretKey).

Among the possible options in documentation (environment variables, file with the data on the machine and properties file), at first none of them protects the application’s own user.

I have seen in other languages the use of RSA encryption where the key to encrypt the data was compiled in the application itself. However, the Java binary is easily "decompiled", which makes this method impossible.

In this scenario, how can I safely distribute/store AWS credentials for use by my Java application?

2 answers

1

Like @eduardosouza, I also recommend that you do not store these keys in your code, or even in bundled files. Your application probably doesn’t need to store these credentials, but the safest way depends on where your application is running:

  • In EC2 or Lambda simply assign an IAM Role to the instance or function that automatically the java SDK finds the temporary credentials via the metadata service.
  • Outside of AWS, as in your development machine, you can use environment variables to configure access.
  • Even if your application accesses AWS on behalf of a client, where some applications store keys, it is safer to use IAM Roles. In this case, consider Amazon Cognito to manage this authentication and authorization process automatically.

Related links in the documentation:

Roles of IAM

Credentials in the Java SDK

Amazon Cognito

1

You can use an approach that does not rely on Amazon AWS credentials directly in your code, but uses a credential that you generate.

Create a unique token for each customer. This token will be used for the customer to make requests to a system of his or her own. You can revoke this customer token at the time you think best, if the contract is terminated or you suspect that the token has leaked.

Let’s say the token generated for your X client is d17ce9bd-98d2-4f98-add3-f0af4d49620b. With this token in hand, when you need to upload some file to Amazon S3, the application will access a URL, say, https://meu.sistema.com.br/getUploadUrl?token=d17ce9bd-98d2-4f98-add3-f0af4d49620b and the return of this request will return a signed Amazon AWS URL to which the application must upload, with a validity determined by you.

The code to generate the URL will be more or less like the code below:

System.out.println("Generating pre-signed URL.");
java.util.Date expiration = new java.util.Date();
long milliSeconds = expiration.getTime();
milliSeconds += 1000 * 60 * 60; // Adiciona 1 hora.
expiration.setTime(milliSeconds);

GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey);
generatePresignedUrlRequest.setMethod(HttpMethod.PUT); 
generatePresignedUrlRequest.setExpiration(expiration);

URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest); 

Since the URL has validity, if it happens to leak, it will become useless after the expiration date. This approach is interesting because you don’t need to distribute your credentials along with your code.

The complete documentation of how to generate these Urls is in the official Amazon AWS documentation, at Upload an Object Using a Pre-signed URL (AWS SDK for Java)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.