[#spring-cloud-aws-secrets-manager]
== Secrets Manager Integration

https://aws.amazon.com/secrets-manager/[Secrets Manager] helps to 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.

Spring Cloud AWS adds support for loading configuration properties from Secrets Manager through Spring Boot https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-files-importing[config import feature].

Maven coordinates, using <<index.adoc#bill-of-materials, Spring Cloud AWS BOM>>:

[source,xml]
----
<dependency>
	<groupId>io.awspring.cloud</groupId>
	<artifactId>spring-cloud-aws-starter-secrets-manager</artifactId>
</dependency>
----

=== Loading External Configuration

To fetch secrets from Secrets Manager and add them to Spring's environment properties, add `spring.config.import` property to `application.properties`:

For example, assuming that the secret name in Secrets Manager is `/secrets/database-secrets`:

[source,properties]
----
spring.config.import=aws-secretsmanager:/secrets/database-secrets
----

If a secret with given name does not exist in Secrets Manager, application will fail to start. If secret value is not required for the application, and it should continue to startup even when secret is missing, add `optional` before prefix:

[source,properties]
----
spring.config.import=optional:aws-secretsmanager:/secrets/database-secrets
----

To load multiple secrets, separate their names with `;`:

[source,properties]
----
spring.config.import=aws-secretsmanager:/secrets/database-secrets;/secrets/webclient-secrets
----

If some secrets are required, and other ones are optional, list them as separate entries in `spring.config.import` property:

[source,properties]
----
spring.config.import[0]=optional:aws-secretsmanager=/secrets/required-secret
spring.config.import[1]=aws-secretsmanager=/secrets/optional-secret
----

Fetched secrets can be referenced with `@Value`, bound to `@ConfigurationProperties` classes, or referenced in `application.properties` file.

==== Using Key-Value (JSON) Secrets

Secrets resolved with `spring.config.import` can be also referenced in `application.properties`.
When a content of `SecretString` in a JSON, all top level JSON keys are added as properties to Spring Environment.

For example, with a file `mycreds.json` containing following JSON structure:

[source,json]
----
{
      "username": "saanvi",
      "password": "EXAMPLE-PASSWORD"
}
----

Secret is created with a command:

[source]
----
$ aws secretsmanager create-secret --name /secrets/database-secrets --secret-string file://mycreds.json
----

`spring.config.import` entry is added to `application.properties`:

[source, properties]
----
spring.config.import=aws-secretsmanager:/secrets/database-secrets
----

Secret values can be referenced by JSON key names:

[source, java]
----
@Value("${username}"
private String username;

@Value("${password}"
private String password;
----

==== Using plain text secrets

If a `SecretString` is a plain text, use secret name to retrieve its value.
For example, we will JDBC saved as plain text secret type with name `/secrets/my-certificate`:

[source]
----
$ aws secretsmanager create-secret --name /secrets/prod/jdbc-url --secret-string jdbc:url
----

`spring.config.import` entry is added to `application.properties`:

[source, properties]
----
spring.config.import=aws-secretsmanager:/secrets/prod/jdbc-url
----

Secret value can be retrieved by referencing secret name:

[source,properties]
----
spring.datasource.url=${jdbc-url}
----

=== Using SecretsManagerClient

The starter automatically configures and registers a `SecretsManagerClient` bean in the Spring application context. The `SecretsManagerClient` bean can be used to create or retrieve secrets imperatively.

[source,java]
----
import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.CreateSecretRequest;
...
@Autowired
private SecretsManagerClient secretsManagerClient;
...
secretsManagerClient.createSecret(CreateSecretRequest.builder().name(name).secretString(secret).build());
----

=== Customizing SecretsManagerClient

To use custom `SecretsManagerClient` in `spring.config.import`, provide an implementation of `BootstrapRegistryInitializer`. For example:

[source,java]
----
package com.app;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;

import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;

public class SecretsManagerBootstrapConfiguration implements BootstrapRegistryInitializer {

    @Override
    public void initialize(BootstrapRegistry registry) {
        registry.register(SecretsManagerClient.class, context -> {
            AwsCredentialsProvider awsCredentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create("yourAccessKey", "yourSecretKey"));
            return SecretsManagerClient.builder().credentialsProvider(awsCredentialsProvider).region(Region.EU_WEST_2).build();
        });
    }
}
----

Note that this class must be listed under `org.springframework.boot.BootstrapRegistryInitializer` key in `META-INF/spring.factories`:

[source, properties]
----
org.springframework.boot.BootstrapRegistryInitializer=com.app.SecretsManagerBootstrapConfiguration
----

=== Configuration

The Spring Boot Starter for Secrets Manager provides the following configuration options:

[cols="2,3,1,1"]
|===
| Name | Description | Required | Default value
| `spring.cloud.aws.secretsmanager.enabled` | Enables the Secrets Manager integration. | No | `true`
| `spring.cloud.aws.secretsmanager.endpoint` | Configures endpoint used by `SecretsManagerClient`. | No | `null`
| `spring.cloud.aws.secretsmanager.region` | Configures region used by `SecretsManagerClient`. | No | `null`
|===

=== IAM Permissions
Following IAM permissions are required by Spring Cloud AWS:

[cols="2"]
|===
|  Get secret value:
| `secretsmanager:GetSecretValue`
|===

Sample IAM policy granting access to Secrets Manager:

[source,json,indent=0]
----
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "yourArn"
        }
    ]
}
----

