Property Sources

Vault can be used in many different ways. One specific use-case is using Vault to store encrypted properties. Spring Vault supports Vault as property source to obtain configuration properties using Spring’s PropertySource abstraction.

You can reference properties stored inside Vault in other property sources or use value injection with @Value(…). Special attention is required when bootstrapping beans that require data stored inside of Vault. A VaultPropertySource must be initialized at that time to retrieve properties from Vault.
Spring Boot/Spring Cloud users can benefit from Spring Cloud Vault's configuration integration that initializes various property sources during application startup.

Registering VaultPropertySource

Spring Vault provides a VaultPropertySource to be used with Vault to obtain properties. It uses the nested data element to expose properties stored and encrypted in Vault.

ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new VaultPropertySource(vaultTemplate, "secret/my-application"));

In the code above, VaultPropertySource has been added with highest precedence in the search. If it contains a ´foo` property, it will be detected and returned ahead of any foo property in any other PropertySource. MutablePropertySources exposes a number of methods that allow for precise manipulation of the set of property sources.

@VaultPropertySource

The @VaultPropertySource annotation provides a convenient and declarative mechanism for adding a PropertySource to Spring’s Environment to be used in conjunction with @Configuration classes.

@VaultPropertySource takes a Vault path such as secret/my-application and exposes the data stored at the node in a PropertySource. @VaultPropertySource supports lease renewal for secrets associated with a lease (i. e. credentials from the mysql backend) and credential rotation upon terminal lease expiration. Lease renewal is disabled by default.

Example 1. Properties stored in Vault
{
  // …

  "data": {
    "database": {
      "password": ...
    },
    "user.name": ...,
  }

  // …
}
Example 2. Declaring a @VaultPropertySource
@Configuration
@VaultPropertySource("secret/my-application")
public class AppConfig {

    @Autowired Environment env;

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setUser(env.getProperty("user.name"));
        testBean.setPassword(env.getProperty("database.password"));
        return testBean;
    }
}
Example 3. Declaring a @VaultPropertySource with credential rotation and prefix
@Configuration
@VaultPropertySource(value = "aws/creds/s3-access",
                     propertyNamePrefix = "aws.",
                     renewal = Renewal.ROTATE)
public class AppConfig {
  // provides aws.access_key and aws.secret_key properties
}
Secrets obtained from generic secret backends are associated with a TTL (refresh_interval) but not a lease Id. Spring Vault’s PropertySource rotates generic secrets when reaching its TTL.
You can use @VaultPropertySource to obtain the newest secret version from the versioned Key-Value backend. Make sure to not include the data/ segment in the path.

Any ${…​} placeholders present in a @VaultPropertySource path are resolved against the set of property sources already registered against the environment, as the following example shows:

Example 4. Declaring a @VaultPropertySource path using placeholders
@Configuration
@VaultPropertySource(value = "aws/creds/${my.placeholder:fallback/value}",
                     propertyNamePrefix = "aws.",
                     renewal = Renewal.ROTATE)
public class AppConfig {
}

Assuming that my.placeholder is present in one of the property sources already registered (for example, system properties or environment variables), the placeholder is resolved to the corresponding value. If not, then fallback/value is used as a default. If no default is specified and a property cannot be resolved, an IllegalArgumentException is thrown.

In certain situations, it may not be possible or practical to tightly control property source ordering when using @VaultPropertySource annotations. For example, if the @Configuration classes above were registered via component-scanning, the ordering is difficult to predict. In such cases - and if overriding is important - it is recommended that the user fall back to using the programmatic PropertySource API. See ConfigurableEnvironment and MutablePropertySources for details.