Document reactive Vault support.

Closes gh-25.
This commit is contained in:
Mark Paluch
2017-07-10 20:13:28 +02:00
parent 78b8c71770
commit a3b30fea10
8 changed files with 629 additions and 400 deletions

View File

@@ -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 <<vault.authentication.steps,compose authentication flows>>.
* Reactive Vault client via `ReactiveVaultOperations`.
[[new-features.1-0-0]]
=== What's new in Spring Vault 1.0

View File

@@ -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<T>`. 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();
----
====

View File

@@ -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 <<vault.client-ssl,customized SSL configuration>>
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
</dependency>
----
====
[[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.

View File

@@ -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 <<vault.core.executioncallback,Execution Callbacks>> 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 <<vault.core.authentication>> 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.environment-vault-configuration>>.
[[vault.core.template.sessionmanagement]]
=== Session Management
Spring Vault requires a `ClientAuthentication` to login and access Vault.
See <<vault.core.authentication>> 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.authentication.token>>**
* Vault Token: `vault.token`
**<<vault.authentication.appid>>**
* 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`.
**<<vault.authentication.approle>>**
* RoleId: `vault.app-role.role-id`
* SecretId: `vault.app-role.secret-id` (optional)
**<<vault.authentication.awsec2>>**
* RoleId: `vault.aws-ec2.role-id`
* Identity Document URL: `vault.aws-ec2.identity-document` (optional)
**<<vault.authentication.clientcert>>**
No configuration options.
**<<vault.authentication.cubbyhole>>**
* 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> T` *doWithVault* `(RestOperationsCallback<T> callback)` Executes the given
`RestOperationsCallback`, allows to interact with Vault using `RestOperations` without requiring a session.
* `<T> T` *doWithSession* `(RestOperationsCallback<T> 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<VaultInitializationResponse>() {
@Override
public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<VaultInitializationResponse> exchange = restOperations
.exchange("/sys/init", HttpMethod.PUT,
new HttpEntity<Object>(request),
VaultInitializationResponse.class);
return exchange.getBody();
}
});
----
====

View File

@@ -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 <<vault.core.executioncallback,Execution Callbacks>> 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 <<vault.core.authentication>> 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.environment-vault-configuration>>.
[[vault.core.template.sessionmanagement]]
== Session Management
Spring Vault requires a `ClientAuthentication` to login and access Vault.
See <<vault.core.authentication>> 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.authentication.token>>**
* Vault Token: `vault.token`
**<<vault.authentication.appid>>**
* 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`.
**<<vault.authentication.approle>>**
* RoleId: `vault.app-role.role-id`
* SecretId: `vault.app-role.secret-id` (optional)
**<<vault.authentication.awsec2>>**
* RoleId: `vault.aws-ec2.role-id`
* Identity Document URL: `vault.aws-ec2.identity-document` (optional)
**<<vault.authentication.clientcert>>**
No configuration options.
**<<vault.authentication.cubbyhole>>**
* 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> T` *doWithVault* `(RestOperationsCallback<T> callback)` Executes the given
`RestOperationsCallback`, allows to interact with Vault using `RestOperations` without requiring a session.
* `<T> T` *doWithSession* `(RestOperationsCallback<T> 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<VaultInitializationResponse>() {
@Override
public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<VaultInitializationResponse> exchange = restOperations
.exchange("/sys/init", HttpMethod.PUT,
new HttpEntity<Object>(request),
VaultInitializationResponse.class);
return exchange.getBody();
}
});
----
====

View File

@@ -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.

View File

@@ -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 dont 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 <<vault.authentication.steps,composable authentication steps>> 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
<<vault.client-ssl,SSL>> 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 <<vault.core.reactive.executioncallback,Execution Callbacks>> 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 <<vault.core.authentication>> for details on supported authentication methods.
====
[[vault.core.reactive.template.sessionmanagement]]
== Session Management
Spring Vault requires a token to authenticate Vault requests.
See <<vault.core.authentication>> 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.authentication.steps,declared authentication flow>>.
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> T` *doWithVault* `(Function<WebClient, ? super T> clientCallback)` Composes a reactive
sequence the given `WebClient`, allows to interact with Vault without a session context.
* `<T> T` *doWithSession* `(Function<WebClient, ? super T> 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);
});
----
====

View File

@@ -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[]