From aa4661bdc327d4a4871b084360a8c329e347a35d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 27 Oct 2016 14:21:39 +0200 Subject: [PATCH] Extend reference documentation. Refine Spring Vault with Spring Context use. Add line breaks at about 80 chars. See gh-22. --- src/main/asciidoc/index.adoc | 4 + .../asciidoc/reference/client-support.adoc | 19 +- src/main/asciidoc/reference/dependencies.adoc | 13 +- .../asciidoc/reference/getting-started.adoc | 247 ++++++++++-------- src/main/asciidoc/reference/introduction.adoc | 7 +- src/main/asciidoc/reference/vault.adoc | 3 +- 6 files changed, 177 insertions(+), 116 deletions(-) diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index d6e264ab..8e5262a2 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -12,11 +12,15 @@ NOTE: _Copies of this document may be made for your own use and for distribution toc::[] include::preface.adoc[] + include::new-features.adoc[] ifndef::ebook-format[= Reference documentation [[reference-documentation]]] :leveloffset: +1 + include::reference/introduction.adoc[] + include::reference/vault.adoc[] + :leveloffset: -1 diff --git a/src/main/asciidoc/reference/client-support.adoc b/src/main/asciidoc/reference/client-support.adoc index 1cfece30..eea880fd 100644 --- a/src/main/asciidoc/reference/client-support.adoc +++ b/src/main/asciidoc/reference/client-support.adoc @@ -1,7 +1,10 @@ [[vault.core.client.support]] = Client support -Spring Vault supports a 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. +Spring Vault supports a 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. Spring Vault supports following HTTP clients: @@ -10,15 +13,23 @@ Spring Vault supports following HTTP clients: * Netty * OkHttp 2 -Using a specific client requires the according dependency to be available on the classpath so Spring Vault can use the available client for communicating with Vault. +Using a specific client requires the according dependency to be available on the classpath +so Spring Vault can use the available client for communicating with Vault. == Java's builtin `HttpURLConnection` -Java's builtin `HttpURLConnection` is available out-of-the-box without additional configuration. Using `HttpURLConnection` comes with a limitation regarding SSL configuration. Spring Vault won't apply <> as it would require a deep reconfiguration of the JVM. This configuration would affect all components relying on the default SSL context. Configuring SSL settings using `HttpURLConnection` requires you providing these settings as System Properties. See +Java's builtin `HttpURLConnection` is available out-of-the-box without additional +configuration. Using `HttpURLConnection` comes with a limitation regarding SSL configuration. +Spring Vault won't apply <> as it would +require a deep reconfiguration of the JVM. This configuration would affect all +components relying on the default SSL context. Configuring SSL settings using +`HttpURLConnection` requires you providing these settings as System Properties. See https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization[Customizing JSSE] for further details. == External Clients -You can use external clients to access Vault's API. Simply add one of the following dependencies to your project. You can omit the version number if using <> +You can use external clients to access Vault's API. Simply add one of the following +dependencies to your project. You can omit the version number if using +<> .Apache Http Components Dependency diff --git a/src/main/asciidoc/reference/dependencies.adoc b/src/main/asciidoc/reference/dependencies.adoc index 71e1cf3b..62fc186f 100644 --- a/src/main/asciidoc/reference/dependencies.adoc +++ b/src/main/asciidoc/reference/dependencies.adoc @@ -1,7 +1,10 @@ [[dependencies]] == Dependencies -The easiest way to find compatible versions of Spring Vault dependencies is by relying on the Spring Vault BOM we ship with the compatible versions defined. In a Maven project you would declare this dependency in the `` section of your `pom.xml`: +The easiest way to find compatible versions of Spring Vault dependencies +is by relying on the Spring Vault BOM we ship with the compatible versions +defined. In a Maven project you would declare this dependency in the +`` section of your `pom.xml`: .Using the Spring Vault BOM ==== @@ -22,7 +25,8 @@ The easiest way to find compatible versions of Spring Vault dependencies is by r ==== [[dependencies.names]] -The current version is `{version}`. The version name follows the following pattern: `$\{version\}-$\{release\}` where release can be one of the following: +The current version is `{version}`. The version name follows the following +pattern: `$\{version\}-$\{release\}` where release can be one of the following: * `BUILD-SNAPSHOT` - current snapshots * `M1`, `M2` etc. - milestones @@ -46,4 +50,7 @@ The current version is `{version}`. The version name follows the following patte [[dependencies.spring-framework]] === Spring Framework -The current version of Spring Vault requires Spring Framework in version {springVersion} or better. The modules might also work with an older bugfix version of that minor version. However, using the most recent version within that generation is highly recommended. \ No newline at end of file +The current version of Spring Vault requires Spring Framework in version +{springVersion} or better. The modules might also work with an older bugfix +version of that minor version. However, using the most recent version +within that generation is highly recommended. diff --git a/src/main/asciidoc/reference/getting-started.adoc b/src/main/asciidoc/reference/getting-started.adoc index febf2e72..2d3360ac 100644 --- a/src/main/asciidoc/reference/getting-started.adoc +++ b/src/main/asciidoc/reference/getting-started.adoc @@ -2,11 +2,15 @@ === Getting Started Spring Vault support requires Vault 0.5 or higher and Java SE 6 or higher. -An easy way to bootstrap setting up a working environment is to create a Spring based project in http://spring.io/tools/sts[STS]. +An easy way to bootstrap setting up a working environment is to create a +Spring based project in http://spring.io/tools/sts[STS]. -First you need to set up a running Vault server. Refer to the https://www.vaultproject.io/intro/[Vault] for an explanation on how to startup a Vault instance. +First you need to set up a running Vault server. +Refer to the https://www.vaultproject.io/intro/[Vault] for an explanation on how to startup a Vault instance. -To create a Spring project in STS go to File -> New -> Spring Template Project -> Simple Spring Utility Project -> press Yes when prompted. Then enter a project and a package name such as org.spring.vault.example. +To create a Spring project in STS go to File -> New -> +Spring Template Project -> Simple Spring Utility Project -> +press Yes when prompted. Then enter a project and a package name such as `org.spring.vault.example`. Then add the following to `pom.xml` dependencies section. @@ -28,7 +32,8 @@ Then add the following to `pom.xml` dependencies section. ---- ==== -You will also need to add the location of the Spring Milestone repository for maven to your `pom.xml` which is at the same level of your `` element. +You will also need to add the location of the Spring Milestone repository for maven to your +`pom.xml` which is at the same level of your `` element. ==== [source,xml] @@ -45,26 +50,6 @@ You will also need to add the location of the Spring Milestone repository for ma The repository is also http://repo.spring.io/milestone/org/springframework/vault/[browseable here]. -You may also want to set the logging level to `DEBUG` to see some additional information, edit the `logback.xml` file to have - -[source] ----- - - - - - %d %5p %40.40c:%4L - %m%n - - - - - - - - - - ----- Create a simple `Secrets` class to persist: .Mapped data object @@ -126,9 +111,10 @@ public class VaultApp { Even in this simple example, there are few things to take notice of -* You can instantiate the central helper class of Spring Vault, +* You can instantiate the central class of Spring Vault, <>, using the `org.springframework.vault.client.VaultClient` -object and the `ClientAuthentication`. +object and the `ClientAuthentication`. +You are not required to spin up a Spring Context to use Spring Vault. * Vault is expected to be configured with a root token of `00000000-0000-0000-0000-000000000000` to run this application. * The mapper works against standard POJO objects without the need for any @@ -137,43 +123,6 @@ additional metadata (though you can optionally provide that information). * If the constructor argument names match the field names of the stored document, they will be used to instantiate the object. -[[vault.core.connection]] -== Connecting to Vault with Spring - -One of the first tasks when using Vault and Spring is to create a `org.springframework.vault.client.VaultClient` object using the IoC container. This is useful to use `VaultOperations` from different places inside of your code. Using Spring Vault with bean management ensures a consistent session management where the session is disposed as your application terminates. - -[[vault.core.vault-java-config]] -=== Registering a Vault instance using Java based metadata - -An example of using Java based bean metadata to register common Vault support classes. - -.Registering a 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(); - } - - /** - * Configure a client authentication. - * Please consider a more secure authentication method - * for production use. - */ - @Override - public ClientAuthentication clientAuthentication() { - return new TokenAuthentication("…"); - } -} ----- -==== [[vault.core.template]] == Introduction to VaultTemplate @@ -183,7 +132,8 @@ is the central class of the Spring's Vault support providing a rich feature set 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. +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. @@ -195,65 +145,121 @@ 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. +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`. +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 either a `RestTemplate` or a `VaultClient` object. Please see the section <> for more information. +will give you a reference to either a `RestTemplate` or a `VaultClient` object. +Please see the section <> for more information. -Now let's look at a examples of how to work with the `VaultTemplate` in the context of the Spring container. +Now let's look at a examples of how to work with Vault in the context of the Spring container. -[[vault.core.template.instantiating]] -=== Instantiating VaultTemplate +[[vault.core.template.beans]] +=== Registering and configuring Spring Vault beans -You can use Java to create and register an instance of `VaultTemplate` as shown below. +Using Spring Vault does not require a Spring Context. However, instances of `VaultTemplate`, +`VaultClient` and `SessionManagers` 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` and `VaultClient` +instances across your application. -.Registering a `VaultTemplate` object +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 -class AppConfig { +public class AppConfig extends AbstractVaultConfiguration { - @Bean - public VaultTemplate vaultTemplate() { - - VaultTemplate vaultTemplate = new VaultTemplate(); - vaultTemplate.setSessionManager(sessionManager()); - vaultTemplate.setVaultClientFactory(clientFactory()); - - return vaultTemplate; + /** + * Specify an endpoint for connecting to Vault. + */ + @Override + public VaultEndpoint vaultEndpoint() { + return new VaultEndpoint(); <1> } - - @Bean - public DefaultVaultClientFactory clientFactory() { - return new DefaultVaultClientFactory(); - } - - @Bean - public SimpleSessionManager sessionManager() { - return new SimpleSessionManager(new TokenAuthentication("…")); + + /** + * 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. ==== -There are several overloaded constructors of `VaultTemplate`. These are +.Registering Spring Vault applying injected properties +==== +[source,java] +---- +@Configuration +public class AppConfig extends AbstractVaultConfiguration { -* `VaultTemplate(VaultClient, ClientAuthentication)` - takes the `VaultClient` object and client authentication -* `VaultTemplate(VaultClientFactory, SessionManager)` - takes a client factory for resource management and a `SessionManager`. + @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 VaultClient} can be obtained from {@link #vaultClient()}. + */ + @Override + public ClientAuthentication clientAuthentication() { + return new ClientCertificateAuthentication(vaultClient()); <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. +==== [[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: +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`. +* `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 @@ -289,11 +295,15 @@ is on your class-path. [[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]. +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]. === 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. +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] @@ -304,17 +314,25 @@ 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`. The `MutablePropertySources` API exposes a number of methods that allow for precise manipulation of the set of property sources. +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`. +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. Example usage -Given a Vault path `secret/my-application` containing the configuration data pair `database.password=mysecretpassword`, the following `@Configuration` class uses `@VaultPropertySource` to contribute `secret/my-application` to the `Environment`'s set of `PropertySources`. +Given a Vault path `secret/my-application` containing the configuration data +pair `database.password=mysecretpassword`, the following `@Configuration` +class uses `@VaultPropertySource` to contribute `secret/my-application` to +the `Environment`'s set of `PropertySources`. ==== [source,java] @@ -335,21 +353,38 @@ public class AppConfig { ---- ==== -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 javadocs for details. +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`. +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* `(ClientCallback clientCallback)` Executes the given `ClientCallback`, allows to interact with Vault using `VaultClient` without requiring a session. +* ` T` *doWithVault* `(ClientCallback clientCallback)` Executes the given +`ClientCallback`, allows to interact with Vault using `VaultClient` without requiring a session. -* ` T` *doWithVault* `(SessionCallback sessionCallback)` Executes the given `SessionCallback`, allows to interact with Vault in an authenticated session.. +* ` T` *doWithVault* `(SessionCallback sessionCallback)` Executes the given +`SessionCallback`, allows to interact with Vault in an authenticated session. -* ` T` *doWithRestTemplate* `(String pathTemplate, Map variables, RestTemplateCallback callback)` Expands the `pathTemplate` to an `java.net.URI` and allows low-level interaction with the underlying `org.springframework.web.client.RestTemplate`. +* ` T` *doWithRestTemplate* `(String pathTemplate, Map variables, RestTemplateCallback callback)` +Expands the `pathTemplate` to an `java.net.URI` and allows low-level interaction +with the underlying `org.springframework.web.client.RestTemplate`. Here is an example that uses the `ClientCallback` to initialize Vault: diff --git a/src/main/asciidoc/reference/introduction.adoc b/src/main/asciidoc/reference/introduction.adoc index c16659a7..327ecfd7 100644 --- a/src/main/asciidoc/reference/introduction.adoc +++ b/src/main/asciidoc/reference/introduction.adoc @@ -9,5 +9,8 @@ This part of the reference documentation explains the core functionality offered <> introduces the Vault module feature set. Spring Vault provides client-side support for accessing, storing and revoking secrets. -With https://www.vaultproject.io[Hashicorp's Vault] you have a central place to manage external secret data for applications across all environments. -Vault can manage static and dynamic secrets such as application data, username/password for remote applications/resources and provide credentials for external services such as MySQL, PostgreSQL, Apache Cassandra, Consul, AWS and more. \ No newline at end of file +With https://www.vaultproject.io[Hashicorp's Vault] you have a central place to +manage external secret data for applications across all environments. +Vault can manage static and dynamic secrets such as application data, +username/password for remote applications/resources and provide credentials +for external services such as MySQL, PostgreSQL, Apache Cassandra, Consul, AWS and more. diff --git a/src/main/asciidoc/reference/vault.adoc b/src/main/asciidoc/reference/vault.adoc index 5e307642..3b4edae7 100644 --- a/src/main/asciidoc/reference/vault.adoc +++ b/src/main/asciidoc/reference/vault.adoc @@ -9,7 +9,8 @@ Vault operations. Includes integrated object mapping between Vault responses an 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 +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.