ConfigData API

Spring Boot provides since version 2.4 a ConfigData API that allows the declaration of configuration sources and importing these as property sources.

Spring Cloud Vault uses as of version 3.0 the ConfigData API to mount Vault’s secret backends as property sources. In previous versions, the Bootstrap context was used. The ConfigData API is much more flexible as it allows specifying which configuration systems to import and in which order.

You can enable the bootstrap context either by setting the configuration property spring.cloud.bootstrap.enabled=true or by including the dependency org.springframework.cloud:spring-cloud-starter-bootstrap. Using the boostrap context should be only rarely required hence we recommend using the Config Data API for more flexibility regarding property source ordering.

ConfigData Locations

You can mount Vault configuration through one or more PropertySource that are materialized from Vault. Spring Cloud Vault supports two config locations:

  • vault:// (default location)

  • vault:///<context-path> (contextual location)

Using the default location mounts property sources for all enabled Secret Backends. Without further configuration, Spring Cloud Vault mounts the key-value backend at /secret/${spring.application.name}. Each activated profile adds another context path following the form /secret/$\{spring.application.name}/${profile}. Adding further modules to the classpath, such as spring-cloud-config-databases, provides additional secret backend configuration options which get mounted as property sources if enabled.

If you want to control which context paths are mounted from Vault as PropertySource, you can either use a contextual location (vault:///my/context/path) or configure a VaultConfigurer.

Contextual locations are specified and mounted individually. Spring Cloud Vault mounts each location as a unique PropertySource. You can mix the default locations with contextual locations (or other config systems) to control the order of property sources. This approach is useful in particular if you want to disable the default key-value path computation and mount each key-value backend yourself instead.

application.yml
spring.config.import: vault://first/context/path, vault://other/path, vault://

Property names within a Spring Environment must be unique to avoid shadowing. If you use the same secret names in different context paths and you want to expose these as individual properties you can distinguish them by adding a prefix query parameter to the location.

Example 1. application.yml
spring.config.import: vault://my/path?prefix=foo., vault://my/other/path?prefix=bar.
secret: ${foo.secret}
other.secret: ${bar.secret}
Prefixes are added as-is to all property names returned by Vault. If you want key names to be separated with a dot between the prefix and key name, make sure to add a trailing dot to the prefix.

Conditionally enable/disable Vault Configuration

In some cases, it can be required to launch an application without Vault. You can express whether a Vault config location should be optional or mandatory (default) through the location string:

  • optional:vault:// (default location)

  • optional:vault:///<context-path> (contextual location)

Optional locations are skipped during application startup if Vault support was disabled through spring.cloud.vault.enabled=false.

Vault context paths that cannot be found (HTTP Status 404) are skipped regardless of whether the config location is marked optional. Vault Client Fail Fast allows failing on start if a Vault context path cannot be found because of HTTP Status 404.

Infrastructure Customization

Spring Cloud Vault requires infrastructure classes to interact with Vault. When not using the ConfigData API (meaning that you haven’t specified spring.config.import=vault:// or a contextual Vault path), Spring Cloud Vault defines its beans through VaultAutoConfiguration and VaultReactiveAutoConfiguration. Spring Boot bootstraps the application before a Spring Context is available. Therefore VaultConfigDataLoader registers beans itself to propagate these later on into the application context.

You can customize the infrastructure used by Spring Cloud Vault by registering custom instances using the Bootstrapper API:

Customizing ClientHttpRequestFactory
ClientOptions options = new ClientOptions();
SslConfiguration sslConfiguration = SslConfiguration.unconfigured();
HttpClientBuilder builder = HttpComponents.getHttpClientBuilder(options, sslConfiguration);

InstanceSupplier<ClientFactoryWrapper> supplier = context ->
new ClientFactoryWrapper(new HttpComponentsClientHttpRequestFactory(builder.build()));

SpringApplication application = new SpringApplication(MyApplication.class);
application.addBootstrapRegistryInitializer(registry -> registry.register(ClientFactoryWrapper.class, supplier));
Customizing RestTemplateBuilder
InstanceSupplier<RestTemplateBuilder> supplier = context -> {

	return RestTemplateBuilder
			.builder()
			.requestFactory(context.get(ClientFactoryWrapper.class).getClientHttpRequestFactory())
			.defaultHeader("X-Vault-Namespace", "my-namespace");
};

SpringApplication application = new SpringApplication(MyApplication.class);
application.addBootstrapRegistryInitializer(registry -> registry.register(RestTemplateBuilder.class, supplier));

See also Customize which secret backends to expose as PropertySource and the source of VaultConfigDataLoader for customization hooks.