Skip to main content

AWS Secrets as Spring Properties

Introduction to AWS Secret Manager

AWS Secrets Manager helps you protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle.

Users and applications retrieve secrets with a call to Secrets Manager APIs, eliminating the need to hardcode sensitive information in plain text. Secrets Manager offers secret rotation with built-in integration for Amazon Relational Database Service (Amazon RDS), Amazon Redshift, and Amazon DocumentDB. Also, the service is extensible to other types of secrets, including API keys and OAuth tokens. In addition, Secrets Manager enables you to control access to secrets using fine-grained permissions and audit secret rotation centrally for resources in the AWS Cloud, third-party services, and on-premises.

Usage within Ensono Stacks

Support for AWS Secret Manager within Ensono Stacks is demonstrated as the provision of a number of secrets defined in AWS that are used as properties within the codebase. As the purpose of this is to simply showcase functionality, the use-case is that some secrets are defined in the AWS Management Console and provided to a class within the application.

Ensono Stacks uses Spring Cloud integration capability to allow a developer to access a secret as if it were a property defined locally. This reduces the amount of coding required (for example, they don't need to access the AWS SDK directly) by allowing the developer to simply specify an additional property source to their application through a series of properties in the application property files under resources.

Giving Spring Cloud permission to access AWS Secrets

Spring Cloud uses the AWS SDK to access resources, and it needs AWS credentials with permission to do that.

On Amazon EC2, the daemon uses the instance's instance profile role automatically. Locally, save your access keys to a file named credentials in your user directory under a folder named .aws.

Example ~/.aws/credentials

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Defining Secrets in AWS Secret Manager

NOTE: In order to work around an outstanding issue in Spring Cloud please ensure that the name of any secrets defined in the AWS Management Console end with a trailing /. See the screenshots below for examples.

Defining a Secret

Ensure that the Secret Name ends with a trailing /.

Defining a Secret

Defining Secret Values

Multiple secret keys and values can de defined within a single secret definition. In the example below, two are defined.

Defining Secret Values

Using AWS Secret Property Providers

Within the Ensono Stacks code, property providers can be specified within the application resource files: -

spring.config.import:
- optional:aws-secretsmanager:/stacks-secret/example-1/
- optional:aws-secretsmanager:/stacks-secret/example-2/

Note that the name of the secrets defined in AWS from the first screenshot are referenced above. It is also possible to mark each property provider with the optional: flag meaning that if the secret cannot be found then no exception will be thrown at startup (please adjust for your own specific use-case).

Accessing Secret Values via Property Placeholders

It is possible to enable (or disable) AWS Secrets Manager support using the following environment variable prior to starting the application: -

export AWS_SECRETS_ENABLED=true

Within the Java code, Spring Cloud now provides support for accessing secret values as any other property. This is through the use of standard Spring @Value annotated property placeholders as follows: -

  @Value(value = "${stacks-secret-1:secret-not-available}")
private String secret1;

As with any other properties it is possible to specify a default should the secret not be defined (or inaccessible due to invalid credentials) - in this example the value "secret-not-available" would be returned.

If no default values is specified and then the secret is unavailable then it follows the same rules as other Spring property providers in that an exception will be generated.

Testing the Secret Properties

Assuming the system has been configured properly, it should be possible to start the Ensono Stacks application and then access the configured secret values using a simple cURL command via a test controller endpoint, as follows:

curl http://localhost:9000/v1/secrets

Secrets -> SECRET-VALUE-1, SECRET-VALUE-2, SECRET-VALUE-3, SECRET-VALUE-4

As described above, if the values are not as seen here please check that the following are correct: -

  1. AWS Credentials are correct
  2. User/Role being used has been granted permission to read AWS Secrets
  3. AWS Secret Manager for the Organisation used contains the named secrets being accessed

Reloading Secrets after modification

If any of the secrets have been changed by an administrator in the AWS Secrets Manager console an already running application will not see these changes unless it is restarted or refreshed. Support for online refresh is provided via Spring Actuator. There are two development activities to allow for this: -

Add the refresh option to the Actuator management preferences: -

management:
endpoints:
web:
base-path: /
exposure:
include: health, info, beans, refresh

and to annotate any Spring Beans that read properties with the @RefreshScope annotation: -

@Service
@RefreshScope
public class SecretsService { ... }

It is then possible to POST a request to the actuator endpoint to request a refresh: -

curl -X POST http://localhost:9000/refresh

[stacks-secret-1,stacks-secret-2]

Any property values that were detected as having changed are returned as an array in the response.