diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index f50fce1b..e27ae476 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,12 @@ [[new-features]] == New & Noteworthy +[[new-features.2-0-0]] +=== What's new in Spring Vault 2.0 + +* Authentication steps DSL to <>. +* Reactive Vault client via `ReactiveVaultOperations`. + [[new-features.1-0-0]] === What's new in Spring Vault 1.0 diff --git a/src/main/asciidoc/reference/authentication.adoc b/src/main/asciidoc/reference/authentication.adoc index f2a06a0a..c7bd4c99 100644 --- a/src/main/asciidoc/reference/authentication.adoc +++ b/src/main/asciidoc/reference/authentication.adoc @@ -435,3 +435,73 @@ See also: * https://www.vaultproject.io/docs/concepts/tokens.html[Vault Documentation: Tokens] * https://www.vaultproject.io/docs/secrets/cubbyhole/index.html[Vault Documentation: Cubbyhole Secret Backend] * https://www.vaultproject.io/docs/concepts/response-wrapping.html[Vault Documentation: Response Wrapping] + + +[[vault.authentication.steps]] +== Authentication Steps + +`ClientAuthentication` objects describe the authentication flow and perform the actual +authentication steps. Pre-composed authentications are easy to use and to configure with +a tight binding to synchronous execution. + +The composition of authentication methods and reusing common steps, such as posting login +payload to Vault or retrieving authentication input from an HTTP source is not intended +with `ClientAuthentication` objects. + +Authentication steps provide reusability of common authentication activity. +Steps created via `AuthenticationSteps` describe an authentication flow in a functional +style leaving the actual authentication execution to specific executors. + +.Stored token authentication flow. +==== +[source,java] +---- +AuthenticationSteps.just(VaultToken.of(…)); <1> +---- +<1> Creates `AuthenticationSteps` from just a `VaultToken`. +==== + +A single-step authentication flow can be created from a single input. Flows declaring +multiple authentication steps start with a `Supplier` or `HttpRequest` that provide an +authentication state object which can be used to map or post to Vault for login. + +.AppRole authentication flow +==== +[source,java] +---- +AuthenticationSteps.fromSupplier( <1> + + () -> getAppRoleLogin(options.getRoleId(), options.getSecretId())) <2> + + .login("auth/{mount}/login", options.getPath()); <3> +---- +<1> Start declaring `AuthenticationSteps` accepting a `Supplier`. The state +object type depends on the `Supplier` response type which can be mapped in a later step. +<2> The actual `Supplier` implementation. Creating a `Map` in this case. +<3> Perform a Vault login by posting the state object (`Map`) to a Vault endpoint +for Vault token creation. +==== + +Authentication flows require an executor to perform the actual login. We provide two executors +for different execution models: + +* `AuthenticationStepsExecutor` as a drop-in replacement for synchronous `ClientAuthentication`. +* `AuthenticationStepsOperator` for reactive execution. + +Many ``ClientAuthentication``'s come with static factory methods to create `AuthenticationSteps` +for their authentication-specific options: + +.Synchronous `AuthenticationSteps` execution +==== +[source,java] +---- +CubbyholeAuthenticationOptions options = … +RestOperations restOperations = … + +AuthenticationSteps steps = CubbyholeAuthentication.createAuthenticationSteps(options); + +AuthenticationStepsExecutor executor = new AuthenticationStepsExecutor(steps, restOperations); + +VaultToken token = executor.login(); +---- +==== diff --git a/src/main/asciidoc/reference/client-support.adoc b/src/main/asciidoc/reference/client-support.adoc index 3786c282..645d81fd 100644 --- a/src/main/asciidoc/reference/client-support.adoc +++ b/src/main/asciidoc/reference/client-support.adoc @@ -1,7 +1,7 @@ [[vault.core.client.support]] = Client support -Spring Vault supports a various HTTP clients to access Vault's HTTP API. Spring Vault uses +Spring Vault supports various HTTP clients to access Vault's HTTP API. Spring Vault uses http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/remoting.html#rest-resttemplate[`RestTemplate`] as primary interface accessing Vault. Dedicated client support originates from <> that is scoped only to Spring Vault's client components. @@ -64,3 +64,34 @@ dependencies to your project. You can omit the version number if using ---- ==== + +[[vault.client-ssl]] +== Vault Client SSL configuration + +SSL can be configured using `SslConfiguration` by setting various properties. +You can set either `javax.net.ssl.trustStore` to configure +JVM-wide SSL settings or configure `SslConfiguration` +to set SSL settings only for Spring Vault. + +==== +[source,java] +---- + +SslConfiguration sslConfiguration = new SslConfiguration( <1> + new FileSystemResource("client-cert.jks"), "changeit", + new FileSystemResource("truststore.jks"), "changeit"); + +SslConfiguration.forTrustStore(new FileSystemResource("keystore.jks"), <2> + "changeit") + +SslConfiguration.forKeyStore(new FileSystemResource("keystore.jks"), <3> + "changeit") +---- +<1> Full configuration. +<2> Configuring only trust store settings. +<3> Configuring only key store settings. +==== + +Please note that providing `SslConfiguration` can be only +applied when either Apache Http Components or the OkHttp client +is on your class-path. diff --git a/src/main/asciidoc/reference/getting-started.adoc b/src/main/asciidoc/reference/getting-started.adoc index 2c93217d..b499dcda 100644 --- a/src/main/asciidoc/reference/getting-started.adoc +++ b/src/main/asciidoc/reference/getting-started.adoc @@ -140,398 +140,3 @@ additional metadata (though you can optionally provide that information). * Mapping conventions can use field access. Notice the `Secrets` class has only getters. * If the constructor argument names match the field names of the stored document, they will be used to instantiate the object. - - -[[vault.core.template]] -== Introduction to VaultTemplate - -The class `VaultTemplate`, located in the package `org.springframework.vault.core`, -is the central class of the Spring's Vault support providing a rich feature set to -interact with Vault. The template offers convenience operations to read, write and -delete data in Vault and provides a mapping between your domain objects and Vault data. - -NOTE: Once configured, `VaultTemplate` is thread-safe and can be reused across -multiple instances. - -The mapping between Vault documents and domain classes is done by delegating to -`RestTemplate`. Spring Web support provides the mapping infrastructure. - -The `VaultTemplate` class implements the interface `VaultOperations`. -In as much as possible, the methods on `VaultOperations` are named after methods -available on the Vault API to make the API familiar to existing Vault developers -who are used to the API and CLI. For example, you will find methods such as -"write", "delete", "read", and "revoke". -The design goal was to make it as easy as possible to transition between -the use of the Vault API and `VaultOperations`. A major difference in between -the two APIs is that `VaultOperations` can be passed domain objects instead of -JSON Key-Value pairs. - -NOTE: The preferred way to reference the operations on `VaultTemplate` instance -is via its interface `VaultOperations`. - -While there are many convenience methods on `VaultTemplate` to help you easily -perform common tasks if you should need to access the Vault API directly to access -functionality not explicitly exposed by the `VaultTemplate` you can use one of -several execute callback methods to access underlying APIs. The execute callbacks -will give you a reference to a `RestOperations` object. -Please see the section <> for more information. - -Now let's look at a examples of how to work with Vault in the context of the Spring container. - -[[vault.core.template.beans]] -=== Registering and configuring Spring Vault beans - -Using Spring Vault does not require a Spring Context. However, instances of `VaultTemplate` and `SessionManager` registered inside a managed context will participate -in http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature[lifecycle events] -provided by the Spring IoC container. This is useful to dispose active Vault sessions upon -application shutdown. You also benefit from reusing the same `VaultTemplate` -instance across your application. - -Spring Vault comes with a supporting configuration class that provides bean definitions -for use inside a Spring context. Application configuration -classes typically extend from `AbstractVaultConfiguration` and are required to -provide additional details that are environment specific. - -Extending from `AbstractVaultConfiguration` requires to implement -` VaultEndpoint vaultEndpoint()` and `ClientAuthentication clientAuthentication()` -methods. - -.Registering Spring Vault objects using Java based bean metadata -==== -[source,java] ----- -@Configuration -public class AppConfig extends AbstractVaultConfiguration { - - /** - * Specify an endpoint for connecting to Vault. - */ - @Override - public VaultEndpoint vaultEndpoint() { - return new VaultEndpoint(); <1> - } - - /** - * Configure a client authentication. - * Please consider a more secure authentication method - * for production use. - */ - @Override - public ClientAuthentication clientAuthentication() { - return new TokenAuthentication("…"); <2> - } -} ----- -<1> Create a new `VaultEndpoint` that points by default to `\https://localhost:8200`. -<2> This sample uses `TokenAuthentication` to get started quickly. -See <> for details on supported authentication methods. -==== - -.Registering Spring Vault applying injected properties -==== -[source,java] ----- -@Configuration -public class AppConfig extends AbstractVaultConfiguration { - - @Value("${vault.uri}") - URI vaultUri; - - /** - * Specify an endpoint that was injected as URI. - */ - @Override - public VaultEndpoint vaultEndpoint() { - return VaultEndpoint.from(vaultUri); <1> - } - - /** - * Configure a Client Certificate authentication. - * {@link RestOperations} can be obtained from {@link #restOperations()}. - */ - @Override - public ClientAuthentication clientAuthentication() { - return new ClientCertificateAuthentication(restOperations()); <2> - } -} ----- -<1> `VaultEndpoint` can be constructed using various factory methods such as -`from(URI uri)` or `VaultEndpoint.create(String host, int port)`. -<2> Dependencies for `ClientAuthentication` methods can be obtained either from -`AbstractVaultConfiguration` or provided by your configuration. -==== - -NOTE: Creating a custom configuration class might be cumbersome in some cases. -Take a look at `EnvironmentVaultConfiguration` that allows configuration by using -properties from existing property sources and Spring's `Environment`. Read more -in <>. - -[[vault.core.template.sessionmanagement]] -=== Session Management - -Spring Vault requires a `ClientAuthentication` to login and access Vault. -See <> on details regarding authentication. -Vault login should not occur on each authenticated Vault interaction but -must be reused throughout a session. This aspect is handled by a -`SessionManager` implementation. A `SessionManager` decides how often it -obtains a token, about revocation and renewal. Spring Vault comes with two implementations: - -* `SimpleSessionManager`: Just obtains tokens from the supplied -`ClientAuthentication` without refresh and revocation -* `LifecycleAwareSessionManager`: This `SessionManager` schedules token -renewal if a token is renewable and revoke a login token on disposal. -Renewal is scheduled with an `AsyncTaskExecutor`. `LifecycleAwareSessionManager` -is configured by default if using `AbstractVaultConfiguration`. - -[[vault.client-ssl]] -== Vault Client SSL configuration - -SSL can be configured using `SslConfiguration` by setting various properties. -You can set either `javax.net.ssl.trustStore` to configure -JVM-wide SSL settings or configure `SslConfiguration` -to set SSL settings only for Spring Vault. - -==== -[source,java] ----- - -SslConfiguration sslConfiguration = new SslConfiguration( <1> - new FileSystemResource("client-cert.jks"), "changeit", - new FileSystemResource("truststore.jks"), "changeit"); - -SslConfiguration.forTrustStore(new FileSystemResource("keystore.jks"), <2> - "changeit") - -SslConfiguration.forKeyStore(new FileSystemResource("keystore.jks"), <3> - "changeit") ----- -<1> Full configuration. -<2> Configuring only trust store settings. -<3> Configuring only key store settings. -==== - -Please note that providing `SslConfiguration` can be only -applied when either Apache Http Components or the OkHttp client -is on your class-path. - - -[[vault.core.environment-vault-configuration]] -== Using `EnvironmentVaultConfiguration` - -Spring Vault includes `EnvironmentVaultConfiguration` configure the Vault client from Spring's `Environment` and a set of predefined -property keys. `EnvironmentVaultConfiguration` supports frequently applied configurations. Other configurations are supported by deriving from the most appropriate configuration class. Include `EnvironmentVaultConfiguration` with `@Import(EnvironmentVaultConfiguration.class)` to existing -Java-based configuration classes and supply configuration properties through any of Spring's ``PropertySource``s. - -.Using EnvironmentVaultConfiguration with a property file -==== - -.Java-based configuration class -[source,java] ----- -@PropertySource("vault.properties") -@Import(EnvironmentVaultConfiguration.class) -public class MyConfiguration{ -} ----- - -.vault.properties -[source,properties] ----- -vault.uri=https://localhost:8200 -vault.token=00000000-0000-0000-0000-000000000000 ----- -==== - -**Property keys** - -* Vault URI: `vault.uri` -* SSL Configuration - ** Keystore resource: `vault.ssl.key-store` (optional) - ** Keystore password: `vault.ssl.key-store-password` (optional) - ** Truststore resource: `vault.ssl.trust-store` (optional) - ** Truststore password: `vault.ssl.trust-store-password` (optional) -* Authentication method: `vault.authentication` (defaults to `TOKEN`, supported authentication methods are: `TOKEN`, `APPID`, `APPROLE`, `AWS_EC2`, `CERT`, `CUBBYHOLE`) - - -**Authentication-specific property keys** - -**<>** - -* Vault Token: `vault.token` - -**<>** - -* AppId: `vault.app-id.app-id` -* UserId: `vault.app-id.user-id`. `MAC_ADDRESS` and `IP_ADDRESS` use `MacAddressUserId`, respective `IpAddressUserId` user id mechanisms. Any other value is used with `StaticUserId`. - -**<>** - -* RoleId: `vault.app-role.role-id` -* SecretId: `vault.app-role.secret-id` (optional) - -**<>** - -* RoleId: `vault.aws-ec2.role-id` -* Identity Document URL: `vault.aws-ec2.identity-document` (optional) - -**<>** - -No configuration options. - -**<>** - -* Initial Vault Token: `vault.token` - - -[[vault.core.propertysupport]] -== Vault Property Source Support - -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 http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-property-source-abstraction[PropertySource abstraction]. - -NOTE: 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. - -NOTE: Spring Boot/Spring Cloud users can benefit from https://github.com/spring-cloud-incubator/spring-cloud-vault-config[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. - -==== -[source,java] ----- -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. - -.Properties stored in Vault -==== -[source,json] ----- -{ - // … - - "data": { - "database": { - "password": ... - }, - "user.name": ..., - } - - // … -} ----- -==== - -.Declaring a `@VaultPropertySource` -==== -[source,java] ----- -@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; - } -} ----- -==== - -.Declaring a `@VaultPropertySource` with credential rotation and prefix -==== -[source,java] ----- -@Configuration -@VaultPropertySource(value = "aws/creds/s3-access", - propertyNamePrefix = "aws.", - renewal = Renewal.ROTATE) -public class AppConfig { - // provides aws.access_key and aws.secret_key properties -} ----- -==== - -NOTE: 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. - -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 http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/ConfigurableEnvironment.html[`ConfigurableEnvironment`] and -http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/MutablePropertySources.html[`MutablePropertySources`] for details. - - -[[vault.core.executioncallback]] -== Execution callbacks - -One common design feature of all Spring template classes is that all functionality -is routed into one of the templates execute callback methods. This helps ensure -that exceptions and any resource management that maybe required are performed -consistency. While this was of much greater need in the case of JDBC and JMS -than with Vault, it still offers a single spot for access and logging to occur. -As such, using the execute callback is the preferred way to access the Vault API -to perform uncommon operations that we've not exposed as methods on `VaultTemplate`. - -Here is a list of execute callback methods. - -* ` T` *doWithVault* `(RestOperationsCallback callback)` Executes the given -`RestOperationsCallback`, allows to interact with Vault using `RestOperations` without requiring a session. - -* ` T` *doWithSession* `(RestOperationsCallback callback)` Executes the given -`RestOperationsCallback`, allows to interact with Vault in an authenticated session. - -Here is an example that uses the `ClientCallback` to initialize Vault: - -==== -[source,java] ----- -vaultOperations.doWithVault(new RestOperationsCallback() { - - @Override - public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) { - - ResponseEntity exchange = restOperations - .exchange("/sys/init", HttpMethod.PUT, - new HttpEntity(request), - VaultInitializationResponse.class); - - return exchange.getBody(); - } -}); - ----- -==== diff --git a/src/main/asciidoc/reference/imperative-template.adoc b/src/main/asciidoc/reference/imperative-template.adoc new file mode 100644 index 00000000..c96854b0 --- /dev/null +++ b/src/main/asciidoc/reference/imperative-template.adoc @@ -0,0 +1,251 @@ +[[vault.core.template]] += Introduction to VaultTemplate + +The class `VaultTemplate`, located in the package `org.springframework.vault.core`, +is the central class of the Spring's Vault support providing a rich feature set to +interact with Vault. The template offers convenience operations to read, write and +delete data in Vault and provides a mapping between your domain objects and Vault data. + +NOTE: Once configured, `VaultTemplate` is thread-safe and can be reused across +multiple instances. + +The mapping between Vault documents and domain classes is done by delegating to +`RestTemplate`. Spring Web support provides the mapping infrastructure. + +The `VaultTemplate` class implements the interface `VaultOperations`. +In as much as possible, the methods on `VaultOperations` are named after methods +available on the Vault API to make the API familiar to existing Vault developers +who are used to the API and CLI. For example, you will find methods such as +"write", "delete", "read", and "revoke". +The design goal was to make it as easy as possible to transition between +the use of the Vault API and `VaultOperations`. A major difference in between +the two APIs is that `VaultOperations` can be passed domain objects instead of +JSON Key-Value pairs. + +NOTE: The preferred way to reference the operations on `VaultTemplate` instance +is via its interface `VaultOperations`. + +While there are many convenience methods on `VaultTemplate` to help you easily +perform common tasks if you should need to access the Vault API directly to access +functionality not explicitly exposed by the `VaultTemplate` you can use one of +several execute callback methods to access underlying APIs. The execute callbacks +will give you a reference to a `RestOperations` object. +Please see the section <> for more information. + +Now let's look at a examples of how to work with Vault in the context of the Spring container. + +[[vault.core.template.beans]] +== Registering and configuring Spring Vault beans + +Using Spring Vault does not require a Spring Context. However, instances of `VaultTemplate` and `SessionManager` registered inside a managed context will participate +in http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature[lifecycle events] +provided by the Spring IoC container. This is useful to dispose active Vault sessions upon +application shutdown. You also benefit from reusing the same `VaultTemplate` +instance across your application. + +Spring Vault comes with a supporting configuration class that provides bean definitions +for use inside a Spring context. Application configuration +classes typically extend from `AbstractVaultConfiguration` and are required to +provide additional details that are environment specific. + +Extending from `AbstractVaultConfiguration` requires to implement +` VaultEndpoint vaultEndpoint()` and `ClientAuthentication clientAuthentication()` +methods. + +.Registering Spring Vault objects using Java based bean metadata +==== +[source,java] +---- +@Configuration +public class AppConfig extends AbstractVaultConfiguration { + + /** + * Specify an endpoint for connecting to Vault. + */ + @Override + public VaultEndpoint vaultEndpoint() { + return new VaultEndpoint(); <1> + } + + /** + * Configure a client authentication. + * Please consider a more secure authentication method + * for production use. + */ + @Override + public ClientAuthentication clientAuthentication() { + return new TokenAuthentication("…"); <2> + } +} +---- +<1> Create a new `VaultEndpoint` that points by default to `\https://localhost:8200`. +<2> This sample uses `TokenAuthentication` to get started quickly. +See <> for details on supported authentication methods. +==== + +.Registering Spring Vault applying injected properties +==== +[source,java] +---- +@Configuration +public class AppConfig extends AbstractVaultConfiguration { + + @Value("${vault.uri}") + URI vaultUri; + + /** + * Specify an endpoint that was injected as URI. + */ + @Override + public VaultEndpoint vaultEndpoint() { + return VaultEndpoint.from(vaultUri); <1> + } + + /** + * Configure a Client Certificate authentication. + * {@link RestOperations} can be obtained from {@link #restOperations()}. + */ + @Override + public ClientAuthentication clientAuthentication() { + return new ClientCertificateAuthentication(restOperations()); <2> + } +} +---- +<1> `VaultEndpoint` can be constructed using various factory methods such as +`from(URI uri)` or `VaultEndpoint.create(String host, int port)`. +<2> Dependencies for `ClientAuthentication` methods can be obtained either from +`AbstractVaultConfiguration` or provided by your configuration. +==== + +NOTE: Creating a custom configuration class might be cumbersome in some cases. +Take a look at `EnvironmentVaultConfiguration` that allows configuration by using +properties from existing property sources and Spring's `Environment`. Read more +in <>. + +[[vault.core.template.sessionmanagement]] +== Session Management + +Spring Vault requires a `ClientAuthentication` to login and access Vault. +See <> on details regarding authentication. +Vault login should not occur on each authenticated Vault interaction but +must be reused throughout a session. This aspect is handled by a +`SessionManager` implementation. A `SessionManager` decides how often it +obtains a token, about revocation and renewal. Spring Vault comes with two implementations: + +* `SimpleSessionManager`: Just obtains tokens from the supplied +`ClientAuthentication` without refresh and revocation +* `LifecycleAwareSessionManager`: This `SessionManager` schedules token +renewal if a token is renewable and revoke a login token on disposal. +Renewal is scheduled with an `AsyncTaskExecutor`. `LifecycleAwareSessionManager` +is configured by default if using `AbstractVaultConfiguration`. + + + + +[[vault.core.environment-vault-configuration]] +== Using `EnvironmentVaultConfiguration` + +Spring Vault includes `EnvironmentVaultConfiguration` configure the Vault client from Spring's `Environment` and a set of predefined +property keys. `EnvironmentVaultConfiguration` supports frequently applied configurations. Other configurations are supported by deriving from the most appropriate configuration class. Include `EnvironmentVaultConfiguration` with `@Import(EnvironmentVaultConfiguration.class)` to existing +Java-based configuration classes and supply configuration properties through any of Spring's ``PropertySource``s. + +.Using EnvironmentVaultConfiguration with a property file +==== + +.Java-based configuration class +[source,java] +---- +@PropertySource("vault.properties") +@Import(EnvironmentVaultConfiguration.class) +public class MyConfiguration{ +} +---- + +.vault.properties +[source,properties] +---- +vault.uri=https://localhost:8200 +vault.token=00000000-0000-0000-0000-000000000000 +---- +==== + +**Property keys** + +* Vault URI: `vault.uri` +* SSL Configuration + ** Keystore resource: `vault.ssl.key-store` (optional) + ** Keystore password: `vault.ssl.key-store-password` (optional) + ** Truststore resource: `vault.ssl.trust-store` (optional) + ** Truststore password: `vault.ssl.trust-store-password` (optional) +* Authentication method: `vault.authentication` (defaults to `TOKEN`, supported authentication methods are: `TOKEN`, `APPID`, `APPROLE`, `AWS_EC2`, `CERT`, `CUBBYHOLE`) + + +**Authentication-specific property keys** + +**<>** + +* Vault Token: `vault.token` + +**<>** + +* AppId: `vault.app-id.app-id` +* UserId: `vault.app-id.user-id`. `MAC_ADDRESS` and `IP_ADDRESS` use `MacAddressUserId`, respective `IpAddressUserId` user id mechanisms. Any other value is used with `StaticUserId`. + +**<>** + +* RoleId: `vault.app-role.role-id` +* SecretId: `vault.app-role.secret-id` (optional) + +**<>** + +* RoleId: `vault.aws-ec2.role-id` +* Identity Document URL: `vault.aws-ec2.identity-document` (optional) + +**<>** + +No configuration options. + +**<>** + +* Initial Vault Token: `vault.token` + +[[vault.core.executioncallback]] +== Execution callbacks + +One common design feature of all Spring template classes is that all functionality +is routed into one of the templates execute callback methods. This helps ensure +that exceptions and any resource management that maybe required are performed +consistency. While this was of much greater need in the case of JDBC and JMS +than with Vault, it still offers a single spot for access and logging to occur. +As such, using the execute callback is the preferred way to access the Vault API +to perform uncommon operations that we've not exposed as methods on `VaultTemplate`. + +Here is a list of execute callback methods. + +* ` T` *doWithVault* `(RestOperationsCallback callback)` Executes the given +`RestOperationsCallback`, allows to interact with Vault using `RestOperations` without requiring a session. + +* ` T` *doWithSession* `(RestOperationsCallback callback)` Executes the given +`RestOperationsCallback`, allows to interact with Vault in an authenticated session. + +Here is an example that uses the `ClientCallback` to initialize Vault: + +==== +[source,java] +---- +vaultOperations.doWithVault(new RestOperationsCallback() { + + @Override + public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) { + + ResponseEntity exchange = restOperations + .exchange("/sys/init", HttpMethod.PUT, + new HttpEntity(request), + VaultInitializationResponse.class); + + return exchange.getBody(); + } +}); + +---- +==== diff --git a/src/main/asciidoc/reference/propertysource.adoc b/src/main/asciidoc/reference/propertysource.adoc new file mode 100644 index 00000000..dd7d7cf1 --- /dev/null +++ b/src/main/asciidoc/reference/propertysource.adoc @@ -0,0 +1,109 @@ +[[vault.core.propertysupport]] += Vault Property Source Support + +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 http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-property-source-abstraction[PropertySource abstraction]. + +NOTE: 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. + +NOTE: Spring Boot/Spring Cloud users can benefit from https://github.com/spring-cloud-incubator/spring-cloud-vault-config[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. + +==== +[source,java] +---- +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. + +.Properties stored in Vault +==== +[source,json] +---- +{ + // … + + "data": { + "database": { + "password": ... + }, + "user.name": ..., + } + + // … +} +---- +==== + +.Declaring a `@VaultPropertySource` +==== +[source,java] +---- +@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; + } +} +---- +==== + +.Declaring a `@VaultPropertySource` with credential rotation and prefix +==== +[source,java] +---- +@Configuration +@VaultPropertySource(value = "aws/creds/s3-access", + propertyNamePrefix = "aws.", + renewal = Renewal.ROTATE) +public class AppConfig { + // provides aws.access_key and aws.secret_key properties +} +---- +==== + +NOTE: 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. + +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 http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/ConfigurableEnvironment.html[`ConfigurableEnvironment`] and +http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/MutablePropertySources.html[`MutablePropertySources`] for details. diff --git a/src/main/asciidoc/reference/reactive-template.adoc b/src/main/asciidoc/reference/reactive-template.adoc new file mode 100644 index 00000000..3b42e43c --- /dev/null +++ b/src/main/asciidoc/reference/reactive-template.adoc @@ -0,0 +1,151 @@ +[[vault.core.reactive.template]] += Introduction to ReactiveVaultTemplate + +This section covers basic information on the reactive programming support using Spring Vault. + +== What is Reactive Programming? + +In plain terms reactive programming is about non-blocking applications that are +asynchronous and event-driven and require a small number of threads to scale vertically +(i.e. within the JVM) rather than horizontally (i.e. through clustering). + +A key aspect of reactive applications is the concept of backpressure which is a mechanism +to ensure producers don’t overwhelm consumers. For example in a pipeline of reactive +components extending from the database to the HTTP response when the HTTP connection is +too slow the data repository can also slow down or stop completely until network capacity frees up. + +== Reactive Vault Client + +Spring Vault's reactive client support is built on top of <> and Spring's functional `WebClient` via Reactor Netty, which features a fully non-blocking, event-driven HTTP client. + +It exposes `VaultTokenSupplier` as supplier of `VaultToken` to authenticate HTTP requests and `ReactiveVaultOperations` +as the primary entry point. The core configuration of `VaultEndpoint`, `ClientOptions` and +<> are reused across the various client implementation. + +The class `ReactiveVaultTemplate`, located in the package `org.springframework.vault.core`, +is the central class of the Spring's reactive Vault support providing a rich feature set to +interact with Vault. The template offers convenience operations to read, write and +delete data in Vault and provides a mapping between your domain objects and Vault data. + +NOTE: Once configured, `ReactiveVaultTemplate` is thread-safe and can be reused across +multiple instances. + +The mapping between Vault documents and domain classes is done by delegating to +`WebClient` and its codecs. + +The `ReactiveVaultTemplate` class implements the interface `ReactiveVaultOperations`. +In as much as possible, the methods on `ReactiveVaultOperations` are named after methods +available on the Vault API to make the API familiar to existing Vault developers +who are used to the API and CLI. For example, you will find methods such as +"write", "delete", and "read". +The design goal was to make it as easy as possible to transition between +the use of the Vault API and `ReactiveVaultOperations`. A major difference in between +the two APIs is that `ReactiveVaultOperations` can be passed domain objects instead of +JSON Key-Value pairs. + +NOTE: The preferred way to reference the operations on `ReactiveVaultTemplate` instance +is via its interface `ReactiveVaultOperations`. + +Functionality not explicitly exposed by the `ReactiveVaultTemplate` you can use one of +several execute callback methods to access underlying APIs. The execute callbacks +will give you a reference to a `WebClient` object. +Please see the section <> for more information. + +Now let's look at a examples of how to work with Vault in the context of the Spring container. + +[[vault.core.reactive.template.beans]] +== Registering and configuring Spring Vault beans + +Using Spring Vault does not require a Spring Context. However, instances of +`ReactiveVaultTemplate` and `VaultTokenSupplier` registered inside a managed context will participate +in http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature[lifecycle events] +provided by the Spring IoC container. This is useful to dispose active Vault sessions upon +application shutdown. You also benefit from reusing the same `ReactiveVaultTemplate` +instance across your application. + +Spring Vault comes with a supporting configuration class that provides bean definitions +for use inside a Spring context. Application configuration +classes typically extend from `AbstractVaultConfiguration` and are required to +provide additional details that are environment specific. + +Extending from `AbstractVaultConfiguration` requires to implement +` VaultEndpoint vaultEndpoint()` and `ClientAuthentication clientAuthentication()` +methods. + +.Registering Spring Vault objects using Java based bean metadata +==== +[source,java] +---- +@Configuration +public class AppConfig extends AbstractReactiveVaultConfiguration { + + /** + * Specify an endpoint for connecting to Vault. + */ + @Override + public VaultEndpoint vaultEndpoint() { + return new VaultEndpoint(); <1> + } + + /** + * Configure a client authentication. + * Please consider a more secure authentication method + * for production use. + */ + @Override + public ClientAuthentication clientAuthentication() { + return new TokenAuthentication("…"); <2> + } +} +---- +<1> Create a new `VaultEndpoint` that points by default to `\https://localhost:8200`. +<2> This sample uses `TokenAuthentication` to get started quickly. +See <> for details on supported authentication methods. +==== + +[[vault.core.reactive.template.sessionmanagement]] +== Session Management + +Spring Vault requires a token to authenticate Vault requests. +See <> on details regarding authentication. +The reactive client requires a non-blocking token supplier whose contract is defined +in `VaultTokenSupplier`. Tokens can be static or obtained through a +<>. +Vault login should not occur on each authenticated Vault interaction but +must be reused throughout a session. This aspect is handled by a +session manager implementing `VaultTokenSupplier`. + +[[vault.core.reactive.executioncallback]] +== Execution callbacks + +One common design feature of all Spring template classes is that all functionality +is routed into one of the templates execute callback methods. This helps ensure +that exceptions and any resource management that maybe required are performed +consistency. While this was of much greater need in the case of JDBC and JMS +than with Vault, it still offers a single spot for access and logging to occur. +As such, using the execute callback is the preferred way to access the Vault API +to perform uncommon operations that we've not exposed as methods on `ReactiveVaultTemplate`. + +Here is a list of execute callback methods. + +* ` T` *doWithVault* `(Function clientCallback)` Composes a reactive +sequence the given `WebClient`, allows to interact with Vault without a session context. + +* ` T` *doWithSession* `(Function clientCallback)` Composes a reactive +sequence the given `WebClient`, allows to interact with Vault in an authenticated session. + +Here is an example that uses the callback to initialize Vault: + +==== +[source,java] +---- +reactiveVaultOperations.doWithVault(webClient -> { + + return webClient.put() + .uri("/sys/init") + .syncBody(request) + .retrieve() + .toEntity(VaultInitializationResponse.class); +}); +---- +==== diff --git a/src/main/asciidoc/reference/vault.adoc b/src/main/asciidoc/reference/vault.adoc index ce4e37a6..36fab84c 100644 --- a/src/main/asciidoc/reference/vault.adoc +++ b/src/main/asciidoc/reference/vault.adoc @@ -4,13 +4,13 @@ The Vault support contains a wide range of features which are summarized below. * Spring configuration support using Java based @Configuration classes -* `VaultTemplate` helper class that increases productivity performing common +* `VaultTemplate` helper class that increases productivity performing common Vault operations. Includes integrated object mapping between Vault responses and POJOs. For most tasks, you will find yourself using `VaultTemplate` that leverages the -rich communication functionality. `VaultTemplate` is the place to look for -accessing functionality such as reading data from Vault or issuing -administrative commands. `VaultTemplate` also provides callback methods so that it is easy for you to +rich communication functionality. `VaultTemplate` is the place to look for +accessing functionality such as reading data from Vault or issuing +administrative commands. `VaultTemplate` also provides callback methods so that it is easy for you to get a hold of the low-level API artifacts such as `RestTemplate` to communicate directly with Vault. @@ -19,6 +19,12 @@ include::dependencies.adoc[] include::getting-started.adoc[] +include::imperative-template.adoc[] + +include::reactive-template.adoc[] + +include::propertysource.adoc[] + include::client-support.adoc[] include::authentication.adoc[]