One of the main concerns when developing an application is where/how to store the application secrets such as database passwords, tokens, etc.
This post explores the use of AWS Key Management Service to manage the secrets in a Spring Boot application. The steps followed to configure AWS KMS are described in the next sections.
Create new encryption key on AWS
The service IAM on AWS contains a section called ‘Encryption Keys’ to create and manage different keys by region.
The permissions on the keys (keys administrators, keys users) can be established at user level. The image below shows that the users ‘admin’ and ‘myapp’ can use the key to encrypt/decrypt data.
Encrypt the secret making use of the AWS encryption key
We will use the credentials of the user ‘myapp’ to encrypt the secret. To do so, it is necessary to:
- install AWS CLI locally
- create the file ~/.aws/credentials with the values of ‘aws_access_key_id’ and ‘aws_secret_access_key’ of the user ‘myapp’.
- create the file ~/.aws/config with the value of ‘region’ where the key was created. In this case, the region is ‘eu-west-1’.
After getting the environment configured, we will run the command:
aws kms encrypt --key-id arn:aws:kms:eu-west-1:<accountId>:key/1a0bbf69-1f00-4ced-8ca8-2d0273c12fbd --plaintext fileb://myfile --output text --query CiphertextBlob
‘myfile’ contains the secret we want to encrypt, in this case it is just the string: “hello world”. The result of encrypting the content of ‘myfile’ using the above command is the plain text encrypted and then encoded in Base64.
The result is then put in the properties file of the application, ‘application.yml’, using the standard Spring Boot prefix ‘{cipher}’ to signal an encrypted value :
test:
'{cipher}CiCW798w++VEme0XUVPnOTwn1utyvhOeGwSTzwzT7q9MvRKTAQEBAgB4lu/fMPvlRJntF1FT5zk8J9brcr4TnhsEk88M0+6vTL0AAABqMGgGCSqGSIb3DQEHBqBbMFkCAQAwVAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAyjqOgp4m0+u2D+3h0CARCAJ+yMkS9FkYy28aNQuWjLfhSsZG17874KwtJOj5hyeM6hsUANYWbu9w=='
Configuring the application to be able to decrypt the secrets
For the application to be able to decrypt the secrets, it is necessary to extend ‘org.springframework.security.crypto.encrypt.TextEncryptor’ to make use of AWS API. This can be achieved with the library https://github.com/zalando/spring-cloud-config-aws-kms, that can be included in the project as a dependency:
<dependency> <groupId>org.zalando</groupId> <artifactId>spring-cloud-config-aws-kms</artifactId> <version>1.3</version> </dependency>
Additionally, it is necessary to add the following configuration in ‘bootstrap.yml’ specifying the same key as the one used to encrypt the secret:
aws: kms: keyId: 'arn:aws:kms:eu-west-1:<accountId>:key/1a0bbf69-1f00-4ced-8ca8-2d0273c12fbd' region: eu-west-1
The files ~/.aws/credentials and ~/.aws/config must also be present in the machine where the service runs.
Conclusion
The use of AWS KMS allows us to have the keys used to encrypt the application secrets centralised in a single place and to manage the permissions to use those keys.
Hello,
I tried following your steps and from https://github.com/zalando/spring-cloud-config-aws-kms as well, however, I keep getting Failed to instantiate [com.amazonaws.services.kms.AWSKMS]. My main concern is on startup my application should decrypt my encrypted texts in my datasource of my application.yml.