(window.webpackJsonp=window.webpackJsonp||[]).push([[340],{772:function(e,t,n){"use strict";n.r(t);var a=n(56),o=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"spring-vault-reference-documentation"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#spring-vault-reference-documentation"}},[e._v("#")]),e._v(" Spring Vault - Reference Documentation")]),e._v(" "),n("h1",{attrs:{id:"preface"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#preface"}},[e._v("#")]),e._v(" Preface")]),e._v(" "),n("p",[e._v('The Spring Vault project applies core Spring concepts to the development of solutions using HashiCorp Vault. We provide a "template" as a high-level abstraction for storing and querying documents. You will notice similarities to the REST support in the Spring Framework.')]),e._v(" "),n("p",[e._v("This document is the reference guide for Spring Vault. It explains Vault concepts and semantics and the syntax.")]),e._v(" "),n("p",[e._v("This part of the reference documentation explains the core functionality offered by Spring Vault.")]),e._v(" "),n("p",[n("a",{attrs:{href:"#vault.core"}},[e._v("Vault support")]),e._v(" introduces the Vault module feature set.")]),e._v(" "),n("h2",{attrs:{id:"_1-document-structure"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_1-document-structure"}},[e._v("#")]),e._v(" 1. Document Structure")]),e._v(" "),n("p",[e._v("This section provides basic introduction to Spring and Vault.\nIt contains details about following development and how to get support.")]),e._v(" "),n("p",[e._v("The rest of the document refers to Spring Vault features and assumes\nthe user is familiar with "),n("a",{attrs:{href:"https://www.vaultproject.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("HashiCorp Vault"),n("OutboundLink")],1),e._v("as well as Spring concepts.")]),e._v(" "),n("h2",{attrs:{id:"_2-knowing-spring"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_2-knowing-spring"}},[e._v("#")]),e._v(" 2. Knowing Spring")]),e._v(" "),n("p",[e._v("Spring Vault uses Spring framework’s "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("core"),n("OutboundLink")],1),e._v(" functionality, such as "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference//core.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("IoC"),n("OutboundLink")],1),e._v(" container. While it is not important to know the Spring APIs, understanding the concepts behind them is. At a minimum, the idea behind IoC should be familiar for whatever IoC container you choose to use.")]),e._v(" "),n("p",[e._v("The core functionality of the Vault support can be used directly, with no need to invoke the IoC services of the Spring Container. This is much like "),n("code",[e._v("RestTemplate")]),e._v(" which can be used 'standalone' without any other services of the Spring container. To leverage all the features of Spring Vault document, such as the session support, you will need to configure some parts of the library using Spring.")]),e._v(" "),n("p",[e._v("To learn more about Spring, you can refer to the comprehensive (and sometimes disarming) documentation that explains in detail the Spring Framework. There are a lot of articles, blog entries and books on the matter - take a look at the Spring framework "),n("a",{attrs:{href:"https://spring.io/docs",target:"_blank",rel:"noopener noreferrer"}},[e._v("home page "),n("OutboundLink")],1),e._v(" for more information.")]),e._v(" "),n("h2",{attrs:{id:"_3-knowing-vault"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_3-knowing-vault"}},[e._v("#")]),e._v(" 3. Knowing Vault")]),e._v(" "),n("p",[e._v("Security and working with secrets is a concern of every developer working with databases, user credentials or API keys. Vault steps in by providing a secure storage combined with access control, revocation, key rolling and auditing. In short: Vault is a service for securely accessing and storing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, and more.")]),e._v(" "),n("p",[e._v("The jumping off ground for learning about Vault is "),n("a",{attrs:{href:"https://www.vaultproject.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("www.vaultproject.io"),n("OutboundLink")],1),e._v(". Here is a list of useful resources:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("The manual introduces Vault and contains links to getting started guides, reference documentation and tutorials.")])]),e._v(" "),n("li",[n("p",[e._v("The online shell provides a convenient way to interact with a Vault instance in combination with the online tutorial.")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/intro/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("HashiCorp Vault Introduction"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("HashiCorp Vault Documentation"),n("OutboundLink")],1)])])]),e._v(" "),n("p",[e._v("Spring Vault provides client-side support for accessing, storing and revoking secrets.\nWith "),n("a",{attrs:{href:"https://www.vaultproject.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("HashiCorp’s Vault"),n("OutboundLink")],1),e._v(" you have a central place to\nmanage external secret data for applications across all environments.\nVault can manage static and dynamic secrets such as application data,\nusername/password for remote applications/resources and provide credentials\nfor external services such as MySQL, PostgreSQL, Apache Cassandra, Consul, AWS and more.")]),e._v(" "),n("h2",{attrs:{id:"_4-requirements"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_4-requirements"}},[e._v("#")]),e._v(" 4. Requirements")]),e._v(" "),n("p",[e._v("Spring Vault 2.x binaries requires JDK level 8.0 and above, and "),n("a",{attrs:{href:"https://spring.io/docs",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Framework"),n("OutboundLink")],1),e._v(" 5.3.4 and above.")]),e._v(" "),n("p",[e._v("In terms of Vault, "),n("a",{attrs:{href:"https://www.vaultproject.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault"),n("OutboundLink")],1),e._v(" at least 0.6.")]),e._v(" "),n("h2",{attrs:{id:"_5-additional-help-resources"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_5-additional-help-resources"}},[e._v("#")]),e._v(" 5. Additional Help Resources")]),e._v(" "),n("p",[e._v("Learning a new framework is not always straight forward. In this section, we try to provide what we think is an easy to follow guide for starting with Spring Vault module. However, if you encounter issues or you are just looking for advice, feel free to use one of the links below:")]),e._v(" "),n("h3",{attrs:{id:"_5-1-support"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_5-1-support"}},[e._v("#")]),e._v(" 5.1. Support")]),e._v(" "),n("p",[e._v("There are a few support options available:")]),e._v(" "),n("h4",{attrs:{id:"_5-1-1-community-forum"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_5-1-1-community-forum"}},[e._v("#")]),e._v(" 5.1.1. Community Forum")]),e._v(" "),n("p",[e._v("Post questions questions regarding Spring Vault on "),n("a",{attrs:{href:"https://stackoverflow.com/questions/tagged/spring-vault",target:"_blank",rel:"noopener noreferrer"}},[e._v("Stackoverflow"),n("OutboundLink")],1),e._v(" to share information and help each other. Note that registration is needed "),n("strong",[e._v("only")]),e._v(" for posting.")]),e._v(" "),n("h4",{attrs:{id:"_5-1-2-professional-support"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_5-1-2-professional-support"}},[e._v("#")]),e._v(" 5.1.2. Professional Support")]),e._v(" "),n("p",[e._v("Professional, from-the-source support, with guaranteed response time, is available from "),n("a",{attrs:{href:"https://pivotal.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Pivotal Sofware, Inc."),n("OutboundLink")],1),e._v(", the company behind Spring Vault and Spring.")]),e._v(" "),n("h3",{attrs:{id:"_5-2-following-development"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_5-2-following-development"}},[e._v("#")]),e._v(" 5.2. Following Development")]),e._v(" "),n("p",[e._v("For information on the Spring Vault source code repository, nightly builds and snapshot artifacts please see the "),n("a",{attrs:{href:"https://projects.spring.io/spring-vault/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Vault homepage"),n("OutboundLink")],1),e._v(". You can help make Spring Vault best serve the needs of the Spring community by interacting with developers through the Community on "),n("a",{attrs:{href:"https://stackoverflow.com/questions/tagged/spring-vault",target:"_blank",rel:"noopener noreferrer"}},[e._v("Stackoverflow"),n("OutboundLink")],1),e._v(". If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Vault issue "),n("a",{attrs:{href:"https://github.com/spring-projects/spring-vault/issues",target:"_blank",rel:"noopener noreferrer"}},[e._v("tracker"),n("OutboundLink")],1),e._v(". To stay up to date with the latest news and announcements in the Spring ecosystem, subscribe to the Spring Community "),n("a",{attrs:{href:"https://spring.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("Portal"),n("OutboundLink")],1),e._v(". Lastly, you can follow the Spring "),n("a",{attrs:{href:"https://spring.io/blog",target:"_blank",rel:"noopener noreferrer"}},[e._v("blog "),n("OutboundLink")],1),e._v("or the project team on Twitter ("),n("a",{attrs:{href:"https://twitter.com/springcentral",target:"_blank",rel:"noopener noreferrer"}},[e._v("SpringCentral"),n("OutboundLink")],1),e._v(").")]),e._v(" "),n("h2",{attrs:{id:"_6-new-noteworthy"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-new-noteworthy"}},[e._v("#")]),e._v(" 6. New & Noteworthy")]),e._v(" "),n("h3",{attrs:{id:"_6-1-what-s-new-in-spring-vault-2-3"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-1-what-s-new-in-spring-vault-2-3"}},[e._v("#")]),e._v(" 6.1. What’s new in Spring Vault 2.3")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Support for PEM-encoded certificates for keystore and truststore usage.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("ReactiveVaultEndpointProvider")]),e._v(" for non-blocking lookup of "),n("code",[e._v("VaultEndpoint")]),e._v(".")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("VaultKeyValueMetadataOperations")]),e._v(" for Key-Value metadata interaction.")])]),e._v(" "),n("li",[n("p",[e._v("Support for "),n("code",[e._v("transform")]),e._v(" backend (Enterprise Feature).")])]),e._v(" "),n("li",[n("p",[e._v("Documentation of "),n("a",{attrs:{href:"#vault.core.secret-engines"}},[e._v("how to use Vault secret backends")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("Login credentials for Kubernetes and PCF authentication are reloaded for each login attempt.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("SecretLeaseContainer")]),e._v(" publishes "),n("code",[e._v("SecretLeaseRotatedEvent")]),e._v(" instead of "),n("code",[e._v("SecretLeaseExpiredEvent")]),e._v(" and "),n("code",[e._v("SecretLeaseCreatedEvent")]),e._v(" on successful secret rotation.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("AbstractVaultConfiguration.threadPoolTaskScheduler()")]),e._v(" bean type changed to "),n("code",[e._v("TaskSchedulerWrapper")]),e._v(" instead of "),n("code",[e._v("ThreadPoolTaskScheduler")]),e._v(".")])])]),e._v(" "),n("h3",{attrs:{id:"_6-2-what-s-new-in-spring-vault-2-2"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-2-what-s-new-in-spring-vault-2-2"}},[e._v("#")]),e._v(" 6.2. What’s new in Spring Vault 2.2")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Support for Key-Value v2 (versioned backend) secrets through "),n("code",[e._v("@VaultPropertySource")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("SpEL support in "),n("code",[e._v("@Secret")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("Add support for Jetty as reactive HttpClient.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("LifecycleAwareSessionManager")]),e._v(" and "),n("code",[e._v("ReactiveLifecycleAwareSessionManager")]),e._v(" emit now "),n("code",[e._v("AuthenticationEvent")]),e._v("s.")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.authentication.pcf"}},[e._v("PCF authentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("Deprecation of "),n("code",[e._v("AppIdAuthentication")]),e._v(".\nUse "),n("code",[e._v("AppRoleAuthentication")]),e._v(" instead as recommended by HashiCorp Vault.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("CubbyholeAuthentication")]),e._v(" and wrapped "),n("code",[e._v("AppRoleAuthentication")]),e._v(" now use "),n("code",[e._v("sys/wrapping/unwrap")]),e._v(" endpoints by default.")])]),e._v(" "),n("li",[n("p",[e._v("Kotlin Coroutines support for "),n("code",[e._v("ReactiveVaultOperations")]),e._v(".")])])]),e._v(" "),n("h3",{attrs:{id:"_6-3-what-s-new-in-spring-vault-2-1"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-3-what-s-new-in-spring-vault-2-1"}},[e._v("#")]),e._v(" 6.3. What’s new in Spring Vault 2.1")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"#vault.authentication.gcpgce"}},[e._v("GCP Compute")]),e._v(", "),n("a",{attrs:{href:"#vault.authentication.gcpiam"}},[e._v("GCP IAM")]),e._v(", and "),n("a",{attrs:{href:"#vault.authentication.azuremsi"}},[e._v("Azure")]),e._v(" authentication.")])]),e._v(" "),n("li",[n("p",[e._v("Template API support for versioned and unversioned Key/Value backends and for Vault wrapping operations.")])]),e._v(" "),n("li",[n("p",[e._v("Support full pull mode in reactive AppRole authentication.")])]),e._v(" "),n("li",[n("p",[e._v("Improved Exception hierarchy for Vault login failures.")])])]),e._v(" "),n("h3",{attrs:{id:"_6-4-what-s-new-in-spring-vault-2-0"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-4-what-s-new-in-spring-vault-2-0"}},[e._v("#")]),e._v(" 6.4. What’s new in Spring Vault 2.0")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Authentication steps DSL to "),n("a",{attrs:{href:"#vault.authentication.steps"}},[e._v("compose authentication flows")]),e._v(".")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.core.reactive.template"}},[e._v("Reactive Vault client")]),e._v(" via "),n("code",[e._v("ReactiveVaultOperations")]),e._v(".")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.repositories"}},[e._v("Vault repository support")]),e._v(" based on Spring Data KeyValue.")])]),e._v(" "),n("li",[n("p",[e._v("Transit batch encrypt and decrypt support.")])]),e._v(" "),n("li",[n("p",[e._v("Policy management for policies stored as JSON.")])]),e._v(" "),n("li",[n("p",[e._v("Support CSR signing, certificate revocation and CRL retrieval.")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.authentication.kubernetes"}},[e._v("Kubernetes authentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("RoleId/SecretId unwrapping for "),n("a",{attrs:{href:"#vault.authentication.approle"}},[e._v("AppRole authentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.misc.spring-security"}},[e._v("Spring Security integration")]),e._v(" with transit backend-based "),n("code",[e._v("BytesKeyGenerator")]),e._v(" and "),n("code",[e._v("BytesEncryptor")]),e._v(".")])])]),e._v(" "),n("h3",{attrs:{id:"_6-5-what-s-new-in-spring-vault-1-1-0"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-5-what-s-new-in-spring-vault-1-1-0"}},[e._v("#")]),e._v(" 6.5. What’s new in Spring Vault 1.1.0")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"#vault.authentication.awsiam"}},[e._v("AWS IAM authentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("Configuration of encryption/decryption versions for transit keys.")])]),e._v(" "),n("li",[n("p",[e._v("Pull mode for "),n("a",{attrs:{href:"#vault.authentication.approle"}},[e._v("AppRole authentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[e._v("Transit batch encrypt and decrypt support.")])]),e._v(" "),n("li",[n("p",[e._v("TTL-based generic secret rotation.")])])]),e._v(" "),n("h3",{attrs:{id:"_6-6-what-s-new-in-spring-vault-1-0"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_6-6-what-s-new-in-spring-vault-1-0"}},[e._v("#")]),e._v(" 6.6. What’s new in Spring Vault 1.0")]),e._v(" "),n("ul",[n("li",[e._v("Initial Vault support.")])]),e._v(" "),n("h1",{attrs:{id:"reference-documentation"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#reference-documentation"}},[e._v("#")]),e._v(" Reference documentation")]),e._v(" "),n("h2",{attrs:{id:"_7-vault-support"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_7-vault-support"}},[e._v("#")]),e._v(" 7. Vault support")]),e._v(" "),n("p",[e._v("The Vault support contains a wide range of features which are summarized below.")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Spring configuration support using Java based @Configuration classes")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("VaultTemplate")]),e._v(" helper class that increases productivity performing common\nVault operations. Includes integrated object mapping between Vault responses and POJOs.")])])]),e._v(" "),n("p",[e._v("For most tasks, you will find yourself using "),n("code",[e._v("VaultTemplate")]),e._v(" that leverages the\nrich communication functionality. "),n("code",[e._v("VaultTemplate")]),e._v(" is the place to look for\naccessing functionality such as reading data from Vault or issuing\nadministrative commands. "),n("code",[e._v("VaultTemplate")]),e._v(" also provides callback methods so that it is easy for you to\nget a hold of the low-level API artifacts such as "),n("code",[e._v("RestTemplate")]),e._v(" to communicate\ndirectly with Vault.")]),e._v(" "),n("h3",{attrs:{id:"_7-1-dependencies"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_7-1-dependencies"}},[e._v("#")]),e._v(" 7.1. Dependencies")]),e._v(" "),n("p",[e._v("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.\nIn a Maven project you would declare this dependency in the"),n("code",[e._v("")]),e._v(" section of your "),n("code",[e._v("pom.xml")]),e._v(":")]),e._v(" "),n("p",[e._v("Example 1. Using the Spring Vault BOM")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n \n \n org.springframework.vault\n spring-vault-dependencies\n 2.3.1\n import\n pom\n \n \n\n")])])]),n("p",[e._v("The current version is "),n("code",[e._v("2.3.1")]),e._v(".\nThe version name follows the following patterns: "),n("code",[e._v("${version}")]),e._v(" for GA and service releases and "),n("code",[e._v("${version}-${release}")]),e._v(" for snapshots and milestones. "),n("code",[e._v("release")]),e._v(" can be one of the following:")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v("SNAPSHOT")]),e._v(" - current snapshots")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("M1")]),e._v(", "),n("code",[e._v("M2")]),e._v(" etc. - milestones")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("RC1")]),e._v(", "),n("code",[e._v("RC2")]),e._v(" etc. - release candidates")])])]),e._v(" "),n("p",[e._v("Example 2. Declaring a dependency to Spring Vault")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n \n org.springframework.vault\n spring-vault-core\n \n\n")])])]),n("h3",{attrs:{id:"_7-2-spring-framework"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_7-2-spring-framework"}},[e._v("#")]),e._v(" 7.2. Spring Framework")]),e._v(" "),n("p",[e._v("The current version of Spring Vault requires Spring Framework in version\n5.3.4 or better.\nThe modules might also work with an older bugfix version of that minor version.\nHowever, using the most recent version within that generation is highly recommended.")]),e._v(" "),n("h2",{attrs:{id:"_8-getting-started"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_8-getting-started"}},[e._v("#")]),e._v(" 8. Getting Started")]),e._v(" "),n("p",[e._v("Spring Vault support requires Vault 0.6 or higher and Java SE 6 or higher.\nAn easy way to bootstrap setting up a working environment is to create a\nSpring based project in "),n("a",{attrs:{href:"https://spring.io/tools/sts",target:"_blank",rel:"noopener noreferrer"}},[e._v("STS"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("First you need to set up a running Vault server.\nRefer to the "),n("a",{attrs:{href:"https://www.vaultproject.io/intro/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault"),n("OutboundLink")],1),e._v(" for an explanation on how to startup a Vault instance.")]),e._v(" "),n("p",[e._v("To create a Spring project in STS go to File → New →\nSpring Template Project → Simple Spring Utility Project →\npress Yes when prompted. Then enter a project and a package name such as "),n("code",[e._v("org.spring.vault.example")]),e._v(".")]),e._v(" "),n("p",[e._v("Then add the following to "),n("code",[e._v("pom.xml")]),e._v(" dependencies section.")]),e._v(" "),n("p",[e._v("Example 3. Adding Spring Vault dependency")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n\n \x3c!-- other dependency elements omitted --\x3e\n\n \n org.springframework.vault\n spring-vault-core\n 2.3.1\n \n\n\n")])])]),n("p",[e._v("If you are using a milestone or release candidate, you will also need to add the location of the Spring\nMilestone repository to your maven "),n("code",[e._v("pom.xml")]),e._v(" which is at the same level of your "),n("code",[e._v("")]),e._v(" element.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n \n spring-milestone\n Spring Maven MILESTONE Repository\n https://repo.spring.io/libs-milestone\n \n\n")])])]),n("p",[e._v("The repository is also "),n("a",{attrs:{href:"https://repo.spring.io/milestone/org/springframework/vault/",target:"_blank",rel:"noopener noreferrer"}},[e._v("browseable here"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("If you are using a SNAPSHOT, you will also need to add the location of the Spring\nSnapshot repository to your maven "),n("code",[e._v("pom.xml")]),e._v(" which is at the same level of your "),n("code",[e._v("")]),e._v(" element.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n \n spring-snapshot\n Spring Maven SNAPSHOT Repository\n https://repo.spring.io/libs-snapshot\n \n\n")])])]),n("p",[e._v("The repository is also "),n("a",{attrs:{href:"https://repo.spring.io/snapshot/org/springframework/vault/",target:"_blank",rel:"noopener noreferrer"}},[e._v("browseable here"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("Create a simple "),n("code",[e._v("Secrets")]),e._v(" class to persist:")]),e._v(" "),n("p",[e._v("Example 4. Mapped data object")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("package org.spring.vault.example;\n\npublic class Secrets {\n\n String username;\n String password;\n\n public String getUsername() {\n return username;\n }\n\n public String getPassword() {\n return password;\n }\n}\n")])])]),n("p",[e._v("And a main application to run")]),e._v(" "),n("p",[e._v("Example 5. Example application using Spring Vault")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('package org.springframework.vault.example;\n\nimport org.springframework.vault.authentication.TokenAuthentication;\nimport org.springframework.vault.client.VaultEndpoint;\nimport org.springframework.vault.core.VaultTemplate;\nimport org.springframework.vault.support.VaultResponseSupport;\n\npublic class VaultApp {\n\n public static void main(String[] args) {\n\n VaultTemplate vaultTemplate = new VaultTemplate(new VaultEndpoint(),\n new TokenAuthentication("00000000-0000-0000-0000-000000000000"));\n\n Secrets secrets = new Secrets();\n secrets.username = "hello";\n secrets.password = "world";\n\n vaultTemplate.write("secret/myapp", secrets);\n\n VaultResponseSupport response = vaultTemplate.read("secret/myapp", Secrets.class);\n System.out.println(response.getData().getUsername());\n\n vaultTemplate.delete("secret/myapp");\n }\n}\n')])])]),n("p",[e._v("Even in this simple example, there are few things to take notice of")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("You can instantiate the central class of Spring Vault,"),n("a",{attrs:{href:"#vault.core.template"}},[n("code",[e._v("VaultTemplate")])]),e._v(", using the "),n("code",[e._v("org.springframework.vault.client.VaultEndpoint")]),e._v("object and the "),n("code",[e._v("ClientAuthentication")]),e._v(".\nYou are not required to spin up a Spring Context to use Spring Vault.")])]),e._v(" "),n("li",[n("p",[e._v("Vault is expected to be configured with a root token of"),n("code",[e._v("00000000-0000-0000-0000-000000000000")]),e._v(" to run this application.")])]),e._v(" "),n("li",[n("p",[e._v("The mapper works against standard POJO objects without the need for any\nadditional metadata (though you can optionally provide that information).")])]),e._v(" "),n("li",[n("p",[e._v("Mapping conventions can use field access. Notice the "),n("code",[e._v("Secrets")]),e._v(" class has only getters.")])]),e._v(" "),n("li",[n("p",[e._v("If the constructor argument names match the field names of the stored document,\nthey will be used to instantiate the object.")])])]),e._v(" "),n("h2",{attrs:{id:"_9-introduction-to-vaulttemplate"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_9-introduction-to-vaulttemplate"}},[e._v("#")]),e._v(" 9. Introduction to VaultTemplate")]),e._v(" "),n("p",[e._v("The class "),n("code",[e._v("VaultTemplate")]),e._v(", located in the package "),n("code",[e._v("org.springframework.vault.core")]),e._v(",\nis the central class of the Spring’s Vault support providing a rich feature set to\ninteract with Vault. The template offers convenience operations to read, write and\ndelete data in Vault and provides a mapping between your domain objects and Vault data.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Once configured, "),n("code",[e._v("VaultTemplate")]),e._v(" is thread-safe and can be reused across"),n("br"),e._v("multiple instances.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("The mapping between Vault documents and domain classes is done by delegating to"),n("code",[e._v("RestTemplate")]),e._v(". Spring Web support provides the mapping infrastructure.")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("VaultTemplate")]),e._v(" class implements the interface "),n("code",[e._v("VaultOperations")]),e._v(".\nIn as much as possible, the methods on "),n("code",[e._v("VaultOperations")]),e._v(' are named after methods\navailable on the Vault API to make the API familiar to existing Vault developers\nwho are used to the API and CLI. For example, you will find methods such as\n"write", "delete", "read", and "revoke".\nThe design goal was to make it as easy as possible to transition between\nthe use of the Vault API and '),n("code",[e._v("VaultOperations")]),e._v(". A major difference in between\nthe two APIs is that "),n("code",[e._v("VaultOperations")]),e._v(" can be passed domain objects instead of\nJSON Key-Value pairs.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("The preferred way to reference the operations on "),n("code",[e._v("VaultTemplate")]),e._v(" instance"),n("br"),e._v("is via its interface "),n("code",[e._v("VaultOperations")]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("While there are many convenience methods on "),n("code",[e._v("VaultTemplate")]),e._v(" to help you easily\nperform common tasks if you should need to access the Vault API directly to access\nfunctionality not explicitly exposed by the "),n("code",[e._v("VaultTemplate")]),e._v(" you can use one of\nseveral execute callback methods to access underlying APIs. The execute callbacks\nwill give you a reference to a "),n("code",[e._v("RestOperations")]),e._v(" object.\nPlease see the section "),n("a",{attrs:{href:"#vault.core.executioncallback"}},[e._v("Execution Callbacks")]),e._v(" for more information.")]),e._v(" "),n("p",[e._v("Now let’s look at a examples of how to work with Vault in the context of the Spring container.")]),e._v(" "),n("h3",{attrs:{id:"_9-1-registering-and-configuring-spring-vault-beans"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_9-1-registering-and-configuring-spring-vault-beans"}},[e._v("#")]),e._v(" 9.1. Registering and configuring Spring Vault beans")]),e._v(" "),n("p",[e._v("Using Spring Vault does not require a Spring Context. However, instances of "),n("code",[e._v("VaultTemplate")]),e._v(" and "),n("code",[e._v("SessionManager")]),e._v(" registered inside a managed context will participate\nin "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html#beans-factory-nature",target:"_blank",rel:"noopener noreferrer"}},[e._v("lifecycle events"),n("OutboundLink")],1),e._v("provided by the Spring IoC container. This is useful to dispose active Vault sessions upon\napplication shutdown. You also benefit from reusing the same "),n("code",[e._v("VaultTemplate")]),e._v("instance across your application.")]),e._v(" "),n("p",[e._v("Spring Vault comes with a supporting configuration class that provides bean definitions\nfor use inside a Spring context. Application configuration\nclasses typically extend from "),n("code",[e._v("AbstractVaultConfiguration")]),e._v(" and are required to\nprovide additional details that are environment specific.")]),e._v(" "),n("p",[e._v("Extending from "),n("code",[e._v("AbstractVaultConfiguration")]),e._v(" requires to implement\n"),n("code",[e._v("VaultEndpoint vaultEndpoint()")]),e._v(" and "),n("code",[e._v("ClientAuthentication clientAuthentication()")]),e._v("methods.")]),e._v(" "),n("p",[e._v("Example 6. Registering Spring Vault objects using Java based bean metadata")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\npublic class AppConfig extends AbstractVaultConfiguration {\n\n /**\n * Specify an endpoint for connecting to Vault.\n */\n @Override\n public VaultEndpoint vaultEndpoint() {\n return new VaultEndpoint(); (1)\n }\n\n /**\n * Configure a client authentication.\n * Please consider a more secure authentication method\n * for production use.\n */\n @Override\n public ClientAuthentication clientAuthentication() {\n return new TokenAuthentication("…"); (2)\n }\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Create a new "),n("code",[e._v("VaultEndpoint")]),e._v(" that points by default to "),n("code",[e._v("https://localhost:8200")]),e._v(".")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("This sample uses "),n("code",[e._v("TokenAuthentication")]),e._v(" to get started quickly."),n("br"),e._v("See "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("Authentication Methods")]),e._v(" for details on supported authentication methods.")])])])]),e._v(" "),n("p",[e._v("Example 7. Registering Spring Vault applying injected properties")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\npublic class AppConfig extends AbstractVaultConfiguration {\n\n @Value("${vault.uri}")\n URI vaultUri;\n\n /**\n * Specify an endpoint that was injected as URI.\n */\n @Override\n public VaultEndpoint vaultEndpoint() {\n return VaultEndpoint.from(vaultUri); (1)\n }\n\n /**\n * Configure a Client Certificate authentication.\n * {@link RestOperations} can be obtained from {@link #restOperations()}.\n */\n @Override\n public ClientAuthentication clientAuthentication() {\n return new ClientCertificateAuthentication(restOperations()); (2)\n }\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[n("code",[e._v("VaultEndpoint")]),e._v(" can be constructed using various factory methods such as"),n("code",[e._v("from(URI uri)")]),e._v(" or "),n("code",[e._v("VaultEndpoint.create(String host, int port)")]),e._v(".")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Dependencies for "),n("code",[e._v("ClientAuthentication")]),e._v(" methods can be obtained either from"),n("code",[e._v("AbstractVaultConfiguration")]),e._v(" or provided by your configuration.")])])])]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Creating a custom configuration class might be cumbersome in some cases."),n("br"),e._v("Take a look at "),n("code",[e._v("EnvironmentVaultConfiguration")]),e._v(" that allows configuration by using"),n("br"),e._v("properties from existing property sources and Spring’s "),n("code",[e._v("Environment")]),e._v(". Read more"),n("br"),e._v("in "),n("a",{attrs:{href:"#vault.core.environment-vault-configuration"}},[e._v("Using "),n("code",[e._v("EnvironmentVaultConfiguration")])]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("h3",{attrs:{id:"_9-2-session-management"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_9-2-session-management"}},[e._v("#")]),e._v(" 9.2. Session Management")]),e._v(" "),n("p",[e._v("Spring Vault requires a "),n("code",[e._v("ClientAuthentication")]),e._v(" to login and access Vault.\nSee "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("Authentication Methods")]),e._v(" on details regarding authentication.\nVault login should not occur on each authenticated Vault interaction but\nmust be reused throughout a session. This aspect is handled by a"),n("code",[e._v("SessionManager")]),e._v(" implementation. A "),n("code",[e._v("SessionManager")]),e._v(" decides how often it\nobtains a token, about revocation and renewal. Spring Vault comes with two implementations:")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v("SimpleSessionManager")]),e._v(": Just obtains tokens from the supplied"),n("code",[e._v("ClientAuthentication")]),e._v(" without refresh and revocation")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("LifecycleAwareSessionManager")]),e._v(": This "),n("code",[e._v("SessionManager")]),e._v(" schedules token\nrenewal if a token is renewable and revoke a login token on disposal.\nRenewal is scheduled with an "),n("code",[e._v("AsyncTaskExecutor")]),e._v(". "),n("code",[e._v("LifecycleAwareSessionManager")]),e._v("is configured by default if using "),n("code",[e._v("AbstractVaultConfiguration")]),e._v(".")])])]),e._v(" "),n("h3",{attrs:{id:"_9-3-using-environmentvaultconfiguration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_9-3-using-environmentvaultconfiguration"}},[e._v("#")]),e._v(" 9.3. Using "),n("code",[e._v("EnvironmentVaultConfiguration")])]),e._v(" "),n("p",[e._v("Spring Vault includes "),n("code",[e._v("EnvironmentVaultConfiguration")]),e._v(" configure the Vault client from Spring’s "),n("code",[e._v("Environment")]),e._v(" and a set of predefined\nproperty keys. "),n("code",[e._v("EnvironmentVaultConfiguration")]),e._v(" supports frequently applied configurations. Other configurations are supported by deriving from the most appropriate configuration class. Include "),n("code",[e._v("EnvironmentVaultConfiguration")]),e._v(" with "),n("code",[e._v("@Import(EnvironmentVaultConfiguration.class)")]),e._v(" to existing\nJava-based configuration classes and supply configuration properties through any of Spring’s "),n("code",[e._v("PropertySource")]),e._v("s.")]),e._v(" "),n("p",[e._v("Example 8. Using EnvironmentVaultConfiguration with a property file")]),e._v(" "),n("p",[e._v("Java-based configuration class")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@PropertySource("vault.properties")\n@Import(EnvironmentVaultConfiguration.class)\npublic class MyConfiguration{\n}\n')])])]),n("p",[e._v("vault.properties")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("vault.uri=https://localhost:8200\nvault.token=00000000-0000-0000-0000-000000000000\n")])])]),n("p",[n("strong",[e._v("Property keys")])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Vault URI: "),n("code",[e._v("vault.uri")])])]),e._v(" "),n("li",[n("p",[e._v("SSL Configuration")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Keystore resource: "),n("code",[e._v("vault.ssl.key-store")]),e._v(" (optional)")])]),e._v(" "),n("li",[n("p",[e._v("Keystore password: "),n("code",[e._v("vault.ssl.key-store-password")]),e._v(" (optional)")])]),e._v(" "),n("li",[n("p",[e._v("Keystore type: "),n("code",[e._v("vault.ssl.key-store-type")]),e._v(" (optional, typically "),n("code",[e._v("jks")]),e._v(", supports also "),n("code",[e._v("pem")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("Truststore resource: "),n("code",[e._v("vault.ssl.trust-store")]),e._v(" (optional)")])]),e._v(" "),n("li",[n("p",[e._v("Truststore password: "),n("code",[e._v("vault.ssl.trust-store-password")]),e._v(" (optional)")])]),e._v(" "),n("li",[n("p",[e._v("Truststore type: "),n("code",[e._v("vault.ssl.trust-store-type")]),e._v(" (optional, typically "),n("code",[e._v("jks")]),e._v(", supports also "),n("code",[e._v("pem")]),e._v(")")])])])]),e._v(" "),n("li",[n("p",[e._v("Authentication method: "),n("code",[e._v("vault.authentication")]),e._v(" (defaults to "),n("code",[e._v("TOKEN")]),e._v(", supported authentication methods are: "),n("code",[e._v("TOKEN")]),e._v(", "),n("code",[e._v("APPID")]),e._v(", "),n("code",[e._v("APPROLE")]),e._v(", "),n("code",[e._v("AWS_EC2")]),e._v(", "),n("code",[e._v("AZURE")]),e._v(", "),n("code",[e._v("CERT")]),e._v(", "),n("code",[e._v("CUBBYHOLE")]),e._v(", "),n("code",[e._v("KUBERNETES")]),e._v(")")])])]),e._v(" "),n("p",[n("strong",[e._v("Authentication-specific property keys")])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.token"}},[e._v("Token authentication")])])]),e._v(" "),n("ul",[n("li",[e._v("Vault Token: "),n("code",[e._v("vault.token")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.appid"}},[e._v("AppId authentication")])])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("AppId path: "),n("code",[e._v("vault.app-id.app-id-path")]),e._v(" (defaults to "),n("code",[e._v("app-id")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("AppId: "),n("code",[e._v("vault.app-id.app-id")])])]),e._v(" "),n("li",[n("p",[e._v("UserId: "),n("code",[e._v("vault.app-id.user-id")]),e._v(". "),n("code",[e._v("MAC_ADDRESS")]),e._v(" and "),n("code",[e._v("IP_ADDRESS")]),e._v(" use "),n("code",[e._v("MacAddressUserId")]),e._v(", respective "),n("code",[e._v("IpAddressUserId")]),e._v(" user id mechanisms.\nAny other value is used with "),n("code",[e._v("StaticUserId")]),e._v(".")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.approle"}},[e._v("AppRole authentication")])])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("AppRole path: "),n("code",[e._v("vault.app-role.app-role-path")]),e._v(" (defaults to "),n("code",[e._v("approle")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("RoleId: "),n("code",[e._v("vault.app-role.role-id")])])]),e._v(" "),n("li",[n("p",[e._v("SecretId: "),n("code",[e._v("vault.app-role.secret-id")]),e._v(" (optional)")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.awsec2"}},[e._v("AWS-EC2 authentication")])])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("AWS EC2 path: "),n("code",[e._v("vault.aws-ec2.aws-ec2-path")]),e._v(" (defaults to "),n("code",[e._v("aws-ec2")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("Role: "),n("code",[e._v("vault.aws-ec2.role")])])]),e._v(" "),n("li",[n("p",[e._v("RoleId: "),n("code",[e._v("vault.aws-ec2.role-id")]),e._v(" ("),n("strong",[e._v("deprecated:")]),e._v(" use "),n("code",[e._v("vault.aws-ec2.role")]),e._v(" instead)")])]),e._v(" "),n("li",[n("p",[e._v("Identity Document URL: "),n("code",[e._v("vault.aws-ec2.identity-document")]),e._v(" (defaults to "),n("code",[e._v("[http://169.254.169.254/latest/dynamic/instance-identity/pkcs7](http://169.254.169.254/latest/dynamic/instance-identity/pkcs7)")]),e._v(")")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.azuremsi"}},[e._v("Azure (MSI) authentication")])])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Azure MSI path: "),n("code",[e._v("vault.azure-msi.azure-path")]),e._v(" (defaults to "),n("code",[e._v("azure")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("Role: "),n("code",[e._v("vault.azure-msi.role")])])]),e._v(" "),n("li",[n("p",[e._v("Metadata Service URL: "),n("code",[e._v("vault.azure-msi.metadata-service")]),e._v(" (defaults to "),n("code",[e._v("[http://169.254.169.254/metadata/instance?api-version=2017-08-01](http://169.254.169.254/metadata/instance?api-version=2017-08-01)")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("Identity TokenService URL: "),n("code",[e._v("vault.azure-msi.identity-token-service")]),e._v(" (defaults to "),n("code",[e._v("[http://169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01](http://169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01)")]),e._v(")")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.clientcert"}},[e._v("TLS certificate authentication")])])]),e._v(" "),n("p",[e._v("No configuration options.")]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.cubbyhole"}},[e._v("Cubbyhole authentication")])])]),e._v(" "),n("ul",[n("li",[e._v("Initial Vault Token: "),n("code",[e._v("vault.token")])])]),e._v(" "),n("p",[n("strong",[n("a",{attrs:{href:"#vault.authentication.kubernetes"}},[e._v("Kubernetes authentication")])])]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Kubernetes path: "),n("code",[e._v("vault.kubernetes.kubernetes-path")]),e._v(" (defaults to "),n("code",[e._v("kubernetes")]),e._v(")")])]),e._v(" "),n("li",[n("p",[e._v("Role: "),n("code",[e._v("vault.kubernetes.role")])])]),e._v(" "),n("li",[n("p",[e._v("Path to service account token file: "),n("code",[e._v("vault.kubernetes.service-account-token-file")]),e._v(" (defaults to "),n("code",[e._v("/var/run/secrets/kubernetes.io/serviceaccount/token")]),e._v(")")])])]),e._v(" "),n("h3",{attrs:{id:"_9-4-execution-callbacks"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_9-4-execution-callbacks"}},[e._v("#")]),e._v(" 9.4. Execution callbacks")]),e._v(" "),n("p",[e._v("One common design feature of all Spring template classes is that all functionality is routed into one of the templates execute callback methods.\nThis helps ensure that exceptions and any resource management that maybe required are performed consistency.\nWhile 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.\nAs such, using the execute callback is the preferred way to access the Vault API\nto perform uncommon operations that we’ve not exposed as methods on "),n("code",[e._v("VaultTemplate")]),e._v(".")]),e._v(" "),n("p",[e._v("Here is a list of execute callback methods.")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v(" T")]),e._v(" "),n("strong",[e._v("doWithVault")]),e._v(" "),n("code",[e._v("(RestOperationsCallback callback)")]),e._v(" Executes the given"),n("code",[e._v("RestOperationsCallback")]),e._v(", allows to interact with Vault using "),n("code",[e._v("RestOperations")]),e._v(" without requiring a session.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v(" T")]),e._v(" "),n("strong",[e._v("doWithSession")]),e._v(" "),n("code",[e._v("(RestOperationsCallback callback)")]),e._v(" Executes the given"),n("code",[e._v("RestOperationsCallback")]),e._v(", allows to interact with Vault in an authenticated session.")])])]),e._v(" "),n("p",[e._v("Here is an example that uses the "),n("code",[e._v("ClientCallback")]),e._v(" to initialize Vault:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('vaultOperations.doWithVault(new RestOperationsCallback() {\n\n @Override\n public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {\n\n ResponseEntity exchange = restOperations\n .exchange("/sys/init", HttpMethod.PUT,\n new HttpEntity(request),\n VaultInitializationResponse.class);\n\n return exchange.getBody();\n }\n});\n')])])]),n("h2",{attrs:{id:"_10-supporting-for-vault-s-secret-engines"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-supporting-for-vault-s-secret-engines"}},[e._v("#")]),e._v(" 10. Supporting for Vault’s Secret Engines")]),e._v(" "),n("p",[e._v("Spring Vault ships with several extensions to support Vault’s various secret engines.")]),e._v(" "),n("p",[e._v("Specifically, Spring Vault ships with extensions for:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"#vault.core.backends.kv1"}},[e._v('Key-Value Version 1 ("unversioned secrets")')])])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.core.backends.kv2"}},[e._v('Key-Value Version 2 ("versioned secrets")')])])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.core.backends.pki"}},[e._v("PKI (Public Key Infrastructure)")])])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.core.backends.token"}},[e._v("Token Authentication Backend")])])]),e._v(" "),n("li",[n("p",[e._v("Transform (Enterprise Feature)")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"#vault.core.backends.transit"}},[e._v("Transit Backend")])])]),e._v(" "),n("li",[n("p",[e._v("System Backend")])])]),e._v(" "),n("p",[e._v("You can use all other backends through methods on "),n("code",[e._v("VaultTemplate")]),e._v(" directly ("),n("code",[e._v("VaultTemplate.read(…)")]),e._v(", "),n("code",[e._v("VaultTemplate.write(…)")]),e._v(").")]),e._v(" "),n("h3",{attrs:{id:"_10-1-key-value-version-1-unversioned-secrets"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-1-key-value-version-1-unversioned-secrets"}},[e._v("#")]),e._v(' 10.1. Key-Value Version 1 ("unversioned secrets")')]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("kv")]),e._v(" secrets engine is used to store arbitrary secrets within the configured physical storage for Vault.")]),e._v(" "),n("p",[e._v("When running the "),n("code",[e._v("kv")]),e._v(" secrets engine in a non-versioned way, only the most recently written value for a key is preserved.\nThe benefits of non-versioned kv is a reduced storage size for each key, since no additional metadata or history is stored.\nAdditionally, requests going to a backend configured this way are more performant because there are fewer storage calls and no locking for any given request.")]),e._v(" "),n("p",[e._v("Spring Vault ships with a dedicated Key-Value API to encapsulate differences between the individual Key-Value API implementations."),n("code",[e._v("VaultKeyValueOperations")]),e._v(" follows the Vault CLI design.\nThat’s the primary command line tool for Vault providing commands such as "),n("code",[e._v("vault kv get")]),e._v(", "),n("code",[e._v("vault kv put")]),e._v(" and so on.")]),e._v(" "),n("p",[e._v("You can use this API with both Key-Value engine versions by specifying the version and mount path.\nThe following example uses the Key-Value version 1:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultKeyValueOperations keyValueOperations = operations.opsForKeyValue("secret",\n\t\t\t\t\t\t\tVaultKeyValueOperationsSupport.KeyValueBackend.KV_1);\n\nkeyValueOperations.put("elvis", Collections.singletonMap("password", "409-52-2002"));\n\nVaultResponse read = keyValueOperations.get("elvis");\nread.getRequiredData().get("social-security-number");\n')])])]),n("p",[n("code",[e._v("VaultKeyValueOperations")]),e._v(" supports all Key-Value operations such as "),n("code",[e._v("put")]),e._v(", "),n("code",[e._v("get")]),e._v(", "),n("code",[e._v("delete")]),e._v(", "),n("code",[e._v("list")]),e._v(".")]),e._v(" "),n("p",[e._v("Alternatively, the API can be used through "),n("code",[e._v("VaultTemplate")]),e._v(" because of its direct mapping and simple use, as keys and responses map directly to input and output keys.\nThe following example illustrates writing and reading a secret at "),n("code",[e._v("mykey")]),e._v(".\nThe "),n("code",[e._v("kv")]),e._v(" secrets engine is mounted at "),n("code",[e._v("secret")]),e._v(":")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\n\noperations.write("secret/elvis", Collections.singletonMap("social-security-number", "409-52-2002"));\n\nVaultResponse read = operations.read("secret/elvis");\nread.getRequiredData().get("social-security-number");\n')])])]),n("p",[e._v("You can find more details about the "),n("a",{attrs:{href:"https://www.vaultproject.io/api-docs/secret/kv/kv-v1",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Key-Value version 1 API"),n("OutboundLink")],1),e._v(" in the Vault reference documentation.")]),e._v(" "),n("h3",{attrs:{id:"_10-2-key-value-version-2-versioned-secrets"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-2-key-value-version-2-versioned-secrets"}},[e._v("#")]),e._v(' 10.2. Key-Value Version 2 ("versioned secrets")')]),e._v(" "),n("p",[e._v("You can run the "),n("code",[e._v("kv")]),e._v(" secrets engine in one of two versions.\nThis section explains using version 2. When running version 2 of the "),n("code",[e._v("kv")]),e._v(" backend a key can retain a configurable number of versions.\nYou can retrieve the metadata and data of the older versions.\nAdditionally, you can use check-and-set operations to avoid unintentionally overwriting data.")]),e._v(" "),n("p",[e._v("Similar to "),n("a",{attrs:{href:"#vault.core.backends.kv1"}},[e._v('Key-Value Version 1 ("unversioned secrets")')]),e._v(", Spring Vault ships with a dedicated Key-Value API to encapsulate differences between the individual Key-Value API implementations.\nSpring Vault ships with a dedicated Key-Value API to encapsulate differences between the individual Key-Value API implementations."),n("code",[e._v("VaultKeyValueOperations")]),e._v(" follows the Vault CLI design.\nThat is the primary command line tool for Vault, providing commands such as "),n("code",[e._v("vault kv get")]),e._v(", "),n("code",[e._v("vault kv put")]),e._v(", and so on.")]),e._v(" "),n("p",[e._v("You can use this API with both Key-Value engine versions by specifying the version and mount path.\nThe following example uses Key-Value version 2:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultKeyValueOperations keyValueOperations = operations.opsForKeyValue("secret",\n\t\t\t\t\t\t\tVaultKeyValueOperationsSupport.KeyValueBackend.KV_2);\n\nkeyValueOperations.put("elvis", Collections.singletonMap("social-security-number", "409-52-2002"));\n\nVaultResponse read = keyValueOperations.get("elvis");\nread.getRequiredData().get("social-security-number");\n')])])]),n("p",[n("code",[e._v("VaultKeyValueOperations")]),e._v(" supports all Key-Value operations, such as "),n("code",[e._v("put")]),e._v(", "),n("code",[e._v("get")]),e._v(", "),n("code",[e._v("delete")]),e._v(", "),n("code",[e._v("list")]),e._v(".")]),e._v(" "),n("p",[e._v("You can also interact with the specifics of the versioned key-value API. This is useful if you want to obtain a specific secret or you need access to the metadata.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultVersionedKeyValueOperations versionedOperations = operations.opsForVersionedKeyValue("secret");\n\nVersioned.Metadata metadata = versionedOperations.put("elvis",\t\t\t\t\t\t\t(1)\n\t\t\t\t\tCollections.singletonMap("social-security-number", "409-52-2002"));\n\nVersion version = metadata.getVersion();\t\t\t\t\t\t\t\t\t\t\t\t(2)\n\nVersioned ssn = versionedOperations.get("elvis", Version.from(42));\t\t\t\t(3)\n\nVersioned mappedSsn = versionedOperations.get("elvis",\t\t\t(4)\n\t\t\t\t\t\t\t\t\t\t\tVersion.from(42), SocialSecurityNumber.class);\n\nVersioned> versioned = Versioned.create(Collections\t\t\t\t\t(5)\n\t\t\t\t\t\t.singletonMap("social-security-number", "409-52-2002"),\n\t\t\t\t\t\tVersion.from(42));\n\nversionedOperations.put("elvis", version);\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Store secrets at "),n("code",[e._v("elvis")]),e._v(" in that is available under the "),n("code",[e._v("secret/")]),e._v(" mount.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Storing data in the versioned backend returns metadata such as the version number.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("The versioned Key-Value API allows retrieval of specific versions identified by the version number.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("4")])]),e._v(" "),n("td",[e._v("Versioned key-value secrets can be mapped into value objects.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("5")])]),e._v(" "),n("td",[e._v("When updating versioned secrets using CAS, the input must refer to the previously obtained version.")])])])]),e._v(" "),n("p",[e._v("While using the "),n("code",[e._v("kv")]),e._v(" v2 secrets engine through "),n("code",[e._v("VaultTemplate")]),e._v(" is possible.\nIt is not the most convenient approach since the API offers a different approach to context paths and how input/output is represented.\nSpecifically, interaction with the actual secrets requires wrapping and unwrapping of the data section and introducing a "),n("code",[e._v("data/")]),e._v(" path segment between the mount and the secrets key.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\n\noperations.write("secret/data/elvis", Collections.singletonMap("data",\n\t\t\tCollections.singletonMap("social-security-number", "409-52-2002")));\n\nVaultResponse read = operations.read("secret/data/ykey");\nMap data = (Map) read.getRequiredData().get("data");\ndata.get("social-security-number");\n')])])]),n("p",[e._v("You can find more details about the "),n("a",{attrs:{href:"https://www.vaultproject.io/api-docs/secret/kv/kv-v2",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Key-Value version 2 API"),n("OutboundLink")],1),e._v(" in the Vault reference documentation.")]),e._v(" "),n("h3",{attrs:{id:"_10-3-pki-public-key-infrastructure"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-3-pki-public-key-infrastructure"}},[e._v("#")]),e._v(" 10.3. PKI (Public Key Infrastructure)")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("pki")]),e._v(" secrets engine represents a backend for certificates by implementing certificate authority operations.")]),e._v(" "),n("p",[e._v("The PKI secrets engine generates dynamic X.509 certificates.\nWith this secrets engine, services can get certificates without going through the usual manual process of generating a private key and CSR, submitting to a CA, and waiting for a verification and signing process to complete.\nVault’s built-in authentication and authorization mechanisms provide the verification functionality.")]),e._v(" "),n("p",[e._v("Spring Vault supports issuing, signing, revoking certificates, and CRL retrieval through "),n("code",[e._v("VaultPkiOperations")]),e._v(".\nAll other PKI functionality can be used through "),n("code",[e._v("VaultOperations")]),e._v(".")]),e._v(" "),n("p",[e._v("The following examples explain briefly the use of how to issue and revoke certificates:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultPkiOperations pkiOperations = operations.opsForPki("pki");\n\nVaultCertificateRequest request = VaultCertificateRequest.builder()\t\t\t\t\t\t\t\t(1)\n\t\t\t.ttl(Duration.ofHours(48))\n\t\t\t.altNames(Arrays.asList("prod.dc-1.example.com", "prod.dc-2.example.com"))\n\t\t\t.withIpSubjectAltName("1.2.3.4")\n\t\t\t.commonName("hello.example.com")\n\t\t\t.build();\n\nVaultCertificateResponse response = pkiOperations.issueCertificate("production", request); \t\t(2)\nCertificateBundle certificateBundle = response.getRequiredData();\n\nKeyStore keyStore = certificateBundle.createKeyStore("my-keystore");\t\t\t\t\t\t\t(3)\n\nKeySpec privateKey = certificateBundle.getPrivateKeySpec();\t\t\t\t\t\t\t\t\t\t(4)\nX509Certificate certificate = certificateBundle.getX509Certificate();\nX509Certificate caCertificate = certificateBundle.getX509IssuerCertificate();\n\npkiOperations.revoke(certificateBundle.getSerialNumber());\t\t\t\t\t\t\t\t\t\t(5)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Construct a certificate request by using the "),n("code",[e._v("VaultCertificateRequest")]),e._v(" builder.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Request a certificate from Vault."),n("br"),e._v("Vault acts as certificate authority and responds with a signed X.509 certificate."),n("br"),e._v("The actual response is a "),n("code",[e._v("CertificateBundle")]),e._v(".")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("You can obtain generated certificates directly as Java KeyStore that contains public and private keys as well as the issuer certificate. KeyStore has a wide range of uses, which makes this format suitable to configure (for example a HTTP client, a database driver, or an SSL-secured HTTP server).")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("4")])]),e._v(" "),n("td",[n("code",[e._v("CertificateBundle")]),e._v(" allows accessing the private key and the public and issuer certificates directly through the Java Cryptography Extension API.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("5")])]),e._v(" "),n("td",[e._v("Once a certificate is no longer in use (or it was compromised), you can revoke it through its serial number."),n("br"),e._v("Vault includes the revoked certificate in its CRL.")])])])]),e._v(" "),n("p",[e._v("You can find more details about the "),n("a",{attrs:{href:"https://www.vaultproject.io/api-docs/secret/pki",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault PKI secrets API"),n("OutboundLink")],1),e._v(" in the Vault reference documentation.")]),e._v(" "),n("h3",{attrs:{id:"_10-4-token-authentication-backend"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-4-token-authentication-backend"}},[e._v("#")]),e._v(" 10.4. Token Authentication Backend")]),e._v(" "),n("p",[e._v("This backend is an authentication backend that does not interact with actual secrets.\nRather, it gives access to access token management.\nYou can read more about "),n("a",{attrs:{href:"#vault.authentication.token"}},[e._v("Token-based authentication")]),e._v(" in the "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("authentication methods chapter")]),e._v(".")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("token")]),e._v(" authentication method is built-in and automatically available at "),n("code",[e._v("/auth/token")]),e._v(".\nIt lets users authenticate using a token, as well to create new tokens, revoke secrets by token, and more.")]),e._v(" "),n("p",[e._v("When any other auth method returns an identity, Vault core invokes the token method to create a new unique token for that identity.")]),e._v(" "),n("p",[e._v("You can also use the token store to bypass any other auth method. You can create tokens directly, as well as perform a variety of other operations on tokens, such as renewal and revocation.")]),e._v(" "),n("p",[e._v("Spring Vault uses this backend to renew and revoke the session tokens supplied by the configured "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("authentication method")]),e._v(".")]),e._v(" "),n("p",[e._v("The following examples show how to request, renew and revoke a Vault token from within your application:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultTokenOperations tokenOperations = operations.opsForToken();\n\nVaultTokenResponse tokenResponse = tokenOperations.create(); (1)\nVaultToken justAToken = tokenResponse.getToken();\n\nVaultTokenRequest tokenRequest = VaultTokenRequest.builder().withPolicy("policy-for-myapp")\n\t\t\t\t\t\t\t\t\t.displayName("Access tokens for myapp")\n\t\t\t\t\t\t\t\t\t.renewable()\n\t\t\t\t\t\t\t\t\t.ttl(Duration.ofHours(1))\n\t\t\t\t\t\t\t\t\t.build();\n\nVaultTokenResponse appTokenResponse = tokenOperations.create(tokenRequest); (2)\nVaultToken appToken = appTokenResponse.getToken();\n\ntokenOperations.renew(appToken); (3)\n\ntokenOperations.revoke(appToken); (4)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Create an token by applying role defaults.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Using the builder API, you can define fine-grained settings for the token to request."),n("br"),e._v("Requesting a token returns a "),n("code",[e._v("VaultToken")]),e._v(", which is used as value object for Vault tokens.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("You can renew tokens through the Token API. Typically, that is done by "),n("code",[e._v("SessionManager")]),e._v(" to keep track of the Vault session token.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("4")])]),e._v(" "),n("td",[e._v("Tokens can be revoked if needed through the Token API. Typically, that is done by "),n("code",[e._v("SessionManager")]),e._v(" to keep track of the Vault session token.")])])])]),e._v(" "),n("p",[e._v("You can find more details about the "),n("a",{attrs:{href:"https://www.vaultproject.io/api-docs/auth/token",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Token Auth Method API"),n("OutboundLink")],1),e._v(" in the Vault reference documentation.")]),e._v(" "),n("h3",{attrs:{id:"_10-5-transit-backend"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_10-5-transit-backend"}},[e._v("#")]),e._v(" 10.5. Transit Backend")]),e._v(" "),n("p",[e._v('The transit secrets engine handles cryptographic functions on data in-transit.\nVault does not store the data sent to this secrets engine.\nIt can also be seen as "cryptography as a service" or "encryption as a service".\nThe transit secrets engine can also sign and verify data, generate hashes and HMACs of data, and act as a random bytes source.')]),e._v(" "),n("p",[e._v("The primary use case for transit is to encrypt data from applications while still storing that encrypted data in some primary data store.\nThis relieves the burden of proper encryption and decryption from application developers and pushes the burden onto the operators of Vault.")]),e._v(" "),n("p",[e._v("Spring Vault supports a wide range of Transit operations:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Key creation")])]),e._v(" "),n("li",[n("p",[e._v("Key reconfiguration")])]),e._v(" "),n("li",[n("p",[e._v("Encryption/Decryption/Rewrapping")])]),e._v(" "),n("li",[n("p",[e._v("HMAC computation")])]),e._v(" "),n("li",[n("p",[e._v("Signing and signature verification")])])]),e._v(" "),n("p",[e._v("All operations within "),n("code",[e._v("transit")]),e._v(" are centered around keys.\nThe Transit engine supports the versioning of keys and "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/secrets/transit",target:"_blank",rel:"noopener noreferrer"}},[e._v("a variety of key types"),n("OutboundLink")],1),e._v(".\nNote that the key type may impose a limitation on which operations can used.")]),e._v(" "),n("p",[e._v("The following examples shows how to create a key and how to encrypt and decrypt data:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultOperations operations = new VaultTemplate(new VaultEndpoint());\nVaultTransitOperations transitOperations = operations.opsForTransit("transit");\n\ntransitOperations.createKey("my-aes-key", VaultTransitKeyCreationRequest.ofKeyType("aes128-gcm96"));\t(1)\n\nString ciphertext = transitOperations.encrypt("my-aes-key", "plaintext to encrypt");\t\t\t\t\t(2)\n\nString plaintext = transitOperations.decrypt("my-aes-key", ciphertext);\t\t\t\t\t\t\t\t\t(3)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("First, we need a key to begin with."),n("br"),e._v("Each key requires the type to be specified. "),n("code",[e._v("aes128-gcm96")]),e._v(" supports encryption, decryption, key derivation, and convergent encryption, of which we need encryption and decryption for this example.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Next, we encrypt a "),n("code",[e._v("String")]),e._v(" that contains the plain text that should be encrypted."),n("br"),e._v("The input "),n("code",[e._v("String")]),e._v(" uses the default "),n("code",[e._v("Charset")]),e._v(" to encode the string into its binary representation."),n("br"),e._v("Requesting a token returns a "),n("code",[e._v("VaultToken")]),e._v(", which is used as value object for Vault tokens."),n("br"),e._v("The "),n("code",[e._v("encrypt")]),e._v(" method returns Base64-encoded ciphertext, typically starting with "),n("code",[e._v("vault:")]),e._v(".")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("To decrypt ciphertext into plain text, call the "),n("code",[e._v("decrypt")]),e._v(" method."),n("br"),e._v("It decrypts the ciphertext and returns a "),n("code",[e._v("String")]),e._v(" that is decoded using the default charset.")])])])]),e._v(" "),n("p",[e._v("The preceeding example uses simple strings for cryptographic operations.\nWhile it is a simple approach, it bears the risk of charset misconfiguration and is not binary-safe.\nBinary safety is required when the plain text uses a binary representation for data such as images, compressed data, or binary data structures.")]),e._v(" "),n("p",[e._v("To encrypt and decrypt binary data, use the "),n("code",[e._v("Plaintext")]),e._v(" and "),n("code",[e._v("Ciphertext")]),e._v(" value objects that can hold binary values:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('byte [] plaintext = "plaintext to encrypt".getBytes();\n\nCiphertext ciphertext = transitOperations.encrypt("my-aes-key", Plaintext.of(plaintext));\t\t\t(1)\n\nPlaintext decrypttedPlaintext = transitOperations.decrypt("my-aes-key", ciphertext);\t\t\t\t(2)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Assuming a key "),n("code",[e._v("my-aes-key")]),e._v(" is already in place, we’re encrypting the "),n("code",[e._v("Plaintext")]),e._v(" object."),n("br"),e._v("In return, the "),n("code",[e._v("encrypt")]),e._v(" method returns a "),n("code",[e._v("Ciphertext")]),e._v(" object.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("The "),n("code",[e._v("Ciphertext")]),e._v(" object can be used directly for decryption and returns a "),n("code",[e._v("Plaintext")]),e._v(" object.")])])])]),e._v(" "),n("p",[n("code",[e._v("Plaintext")]),e._v(" and "),n("code",[e._v("Ciphertext")]),e._v(" come with a contextual object, "),n("code",[e._v("VaultTransitContext")]),e._v(".\nIt is used to supply a nonce value for "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/secrets/transit#convergent-encryption",target:"_blank",rel:"noopener noreferrer"}},[e._v("convergent encryption"),n("OutboundLink")],1),e._v(" and for a context value to make use of key derivation.")]),e._v(" "),n("p",[e._v("Transit allows for signing plain text and verifying the signature for a given plain text.\nSign operations require an asymmetric key, typically using Elliptic Curve Cryptography or RSA.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Signatures use the public/private key split to ensure authenticity. "),n("br"),e._v("The signer uses its private key to create a signature. Otherwise, anybody would be able to sign messages in your name."),n("br"),e._v("The verifier uses the public key part to verify the signature. The actual signature is typically a hash value. "),n("br"),n("br"),e._v("Internally, the hash gets computed and encrypted using the private key to create the final signature. The verification decrypts the signature message, computes their own hash for the plain text and compares both hash values to check whether the signature is valid or not.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('byte [] plaintext = "plaintext to sign".getBytes();\n\ntransitOperations.createKey("my-ed25519-key", VaultTransitKeyCreationRequest.ofKeyType("ed25519"));\t(1)\n\nSignature signature = transitOperations.sign("my-ed25519-key", Plaintext.of(plaintext));\t\t\t(2)\n\nboolean valid = transitOperations.verify("my-ed25519-key", Plaintext.of(plaintext), signature);\t\t(3)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Signing requires an asymmetric key. You can use any Elliptic Curve Cryptography or RSA key type. Once the key is created, you have all the prerequisites in place to create a signature.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("The signature gets created for a plain text message. The returned "),n("code",[e._v("Signature")]),e._v(" contains an ASCII-safe string that uses Base64 characters.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("To verify the signature, the verification requires a Signature object and the plain text message. As the return value, you get whether the signature was valid or not.")])])])]),e._v(" "),n("p",[e._v("You can find more details about the "),n("a",{attrs:{href:"https://www.vaultproject.io/api/secret/transit",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Transit Backend"),n("OutboundLink")],1),e._v(" in the Vault reference documentation.")]),e._v(" "),n("h2",{attrs:{id:"_11-introduction-to-reactivevaulttemplate"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-introduction-to-reactivevaulttemplate"}},[e._v("#")]),e._v(" 11. Introduction to ReactiveVaultTemplate")]),e._v(" "),n("p",[e._v("This section covers basic information on the reactive programming support using Spring Vault.")]),e._v(" "),n("h3",{attrs:{id:"_11-1-what-is-reactive-programming"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-1-what-is-reactive-programming"}},[e._v("#")]),e._v(" 11.1. What is Reactive Programming?")]),e._v(" "),n("p",[e._v("In plain terms reactive programming is about non-blocking applications that are\nasynchronous and event-driven and require a small number of threads to scale vertically\n(i.e. within the JVM) rather than horizontally (i.e. through clustering).")]),e._v(" "),n("p",[e._v("A key aspect of reactive applications is the concept of backpressure which is a mechanism\nto ensure producers don’t overwhelm consumers. For example in a pipeline of reactive\ncomponents extending from the database to the HTTP response when the HTTP connection is\ntoo slow the data repository can also slow down or stop completely until network capacity frees up.")]),e._v(" "),n("h3",{attrs:{id:"_11-2-reactive-vault-client"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-2-reactive-vault-client"}},[e._v("#")]),e._v(" 11.2. Reactive Vault Client")]),e._v(" "),n("p",[e._v("Spring Vault’s reactive client support is built on top of "),n("a",{attrs:{href:"#vault.authentication.steps"}},[e._v("composable authentication steps")]),e._v(" and Spring’s functional "),n("code",[e._v("WebClient")]),e._v(" via Reactor Netty or Jetty, which feature both a fully non-blocking, event-driven HTTP client.")]),e._v(" "),n("p",[e._v("It exposes "),n("code",[e._v("VaultTokenSupplier")]),e._v(" as supplier of "),n("code",[e._v("VaultToken")]),e._v(" to authenticate HTTP requests\nand "),n("code",[e._v("ReactiveVaultOperations")]),e._v(" as the primary entry point. The core configuration of"),n("code",[e._v("VaultEndpoint")]),e._v(", "),n("code",[e._v("ClientOptions")]),e._v(" and "),n("a",{attrs:{href:"#vault.client-ssl"}},[e._v("SSL")]),e._v(" are reused across the\nvarious client implementation.")]),e._v(" "),n("p",[e._v("The class "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(", located in the package "),n("code",[e._v("org.springframework.vault.core")]),e._v(",\nis the central class of the Spring’s reactive Vault support providing a rich feature set to\ninteract with Vault. The template offers convenience operations to read, write and\ndelete data in Vault and provides a mapping between your domain objects and Vault data.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Once configured, "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(" is thread-safe and can be reused across"),n("br"),e._v("multiple instances.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("The mapping between Vault documents and domain classes is done by delegating to"),n("code",[e._v("WebClient")]),e._v(" and its codecs.")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(" class implements the interface "),n("code",[e._v("ReactiveVaultOperations")]),e._v(".\nIn as much as possible, the methods on "),n("code",[e._v("ReactiveVaultOperations")]),e._v(' are named after methods\navailable on the Vault API to make the API familiar to existing Vault developers\nwho are used to the API and CLI. For example, you will find methods such as\n"write", "delete", and "read".\nThe design goal was to make it as easy as possible to transition between\nthe use of the Vault API and '),n("code",[e._v("ReactiveVaultOperations")]),e._v(". A major difference in between\nthe two APIs is that "),n("code",[e._v("ReactiveVaultOperations")]),e._v(" can be passed domain objects instead of\nJSON Key-Value pairs.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("The preferred way to reference the operations on "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(" instance"),n("br"),e._v("is via its interface "),n("code",[e._v("ReactiveVaultOperations")]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Functionality not explicitly exposed by the "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(" you can use one of\nseveral execute callback methods to access underlying APIs. The execute callbacks\nwill give you a reference to a "),n("code",[e._v("WebClient")]),e._v(" object.\nPlease see the section "),n("a",{attrs:{href:"#vault.core.reactive.executioncallback"}},[e._v("Execution Callbacks")]),e._v(" for more information.")]),e._v(" "),n("p",[e._v("Now let’s look at a examples of how to work with Vault in the context of the Spring container.")]),e._v(" "),n("h3",{attrs:{id:"_11-3-registering-and-configuring-spring-vault-beans"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-3-registering-and-configuring-spring-vault-beans"}},[e._v("#")]),e._v(" 11.3. Registering and configuring Spring Vault beans")]),e._v(" "),n("p",[e._v("Using Spring Vault does not require a Spring Context. However, instances of"),n("code",[e._v("ReactiveVaultTemplate")]),e._v(" and "),n("code",[e._v("VaultTokenSupplier")]),e._v(" registered inside a managed context will participate\nin "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html#beans-factory-nature",target:"_blank",rel:"noopener noreferrer"}},[e._v("lifecycle events"),n("OutboundLink")],1),e._v("provided by the Spring IoC container. This is useful to dispose active Vault sessions upon\napplication shutdown. You also benefit from reusing the same "),n("code",[e._v("ReactiveVaultTemplate")]),e._v("instance across your application.")]),e._v(" "),n("p",[e._v("Spring Vault comes with a supporting configuration class that provides bean definitions\nfor use inside a Spring context. Application configuration\nclasses typically extend from "),n("code",[e._v("AbstractVaultConfiguration")]),e._v(" and are required to\nprovide additional details that are environment specific.")]),e._v(" "),n("p",[e._v("Extending from "),n("code",[e._v("AbstractVaultConfiguration")]),e._v(" requires to implement\n"),n("code",[e._v("VaultEndpoint vaultEndpoint()")]),e._v(" and "),n("code",[e._v("ClientAuthentication clientAuthentication()")]),e._v("methods.")]),e._v(" "),n("p",[e._v("Example 9. Registering Spring Vault objects using Java based bean metadata")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\npublic class AppConfig extends AbstractReactiveVaultConfiguration {\n\n /**\n * Specify an endpoint for connecting to Vault.\n */\n @Override\n public VaultEndpoint vaultEndpoint() {\n return new VaultEndpoint(); (1)\n }\n\n /**\n * Configure a client authentication.\n * Please consider a more secure authentication method\n * for production use.\n */\n @Override\n public ClientAuthentication clientAuthentication() {\n return new TokenAuthentication("…"); (2)\n }\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Create a new "),n("code",[e._v("VaultEndpoint")]),e._v(" that points by default to "),n("code",[e._v("https://localhost:8200")]),e._v(".")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("This sample uses "),n("code",[e._v("TokenAuthentication")]),e._v(" to get started quickly."),n("br"),e._v("See "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("Authentication Methods")]),e._v(" for details on supported authentication methods.")])])])]),e._v(" "),n("h3",{attrs:{id:"_11-4-session-management"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-4-session-management"}},[e._v("#")]),e._v(" 11.4. Session Management")]),e._v(" "),n("p",[e._v("Spring Vault requires a token to authenticate Vault requests.\nSee "),n("a",{attrs:{href:"#vault.core.authentication"}},[e._v("Authentication Methods")]),e._v(" on details regarding authentication.\nThe reactive client requires a non-blocking token supplier whose contract is defined\nin "),n("code",[e._v("VaultTokenSupplier")]),e._v(". Tokens can be static or obtained through a"),n("a",{attrs:{href:"#vault.authentication.steps"}},[e._v("declared authentication flow")]),e._v(".\nVault login should not occur on each authenticated Vault interaction but\nthe session token should be kept across a session. This aspect is handled by a\nsession manager implementing "),n("code",[e._v("ReactiveSessionManager")]),e._v(", such as "),n("code",[e._v("ReactiveLifecycleAwareSessionManager")]),e._v(".")]),e._v(" "),n("h3",{attrs:{id:"_11-5-execution-callbacks"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-5-execution-callbacks"}},[e._v("#")]),e._v(" 11.5. Execution callbacks")]),e._v(" "),n("p",[e._v("One common design feature of all Spring template classes is that all functionality\nis routed into one of the templates execute callback methods. This helps ensure\nthat exceptions and any resource management that maybe required are performed\nconsistency. While this was of much greater need in the case of JDBC and JMS\nthan with Vault, it still offers a single spot for access and logging to occur.\nAs such, using the execute callback is the preferred way to access the Vault API\nto perform uncommon operations that we’ve not exposed as methods on "),n("code",[e._v("ReactiveVaultTemplate")]),e._v(".")]),e._v(" "),n("p",[e._v("Here is a list of execute callback methods.")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v(" T")]),e._v(" "),n("strong",[e._v("doWithVault")]),e._v(" "),n("code",[e._v("(Function clientCallback)")]),e._v(" Composes a reactive\nsequence the given "),n("code",[e._v("WebClient")]),e._v(", allows to interact with Vault without a session context.")])]),e._v(" "),n("li",[n("p",[n("code",[e._v(" T")]),e._v(" "),n("strong",[e._v("doWithSession")]),e._v(" "),n("code",[e._v("(Function clientCallback)")]),e._v(" Composes a reactive\nsequence the given "),n("code",[e._v("WebClient")]),e._v(", allows to interact with Vault in an authenticated session.")])])]),e._v(" "),n("p",[e._v("Here is an example that uses the callback to initialize Vault:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('reactiveVaultOperations.doWithVault(webClient -> {\n\n return webClient.put()\n .uri("/sys/init")\n .syncBody(request)\n .retrieve()\n .toEntity(VaultInitializationResponse.class);\n});\n')])])]),n("h2",{attrs:{id:"_12-vault-property-source-support"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_12-vault-property-source-support"}},[e._v("#")]),e._v(" 12. Vault Property Source Support")]),e._v(" "),n("p",[e._v("Vault can be used in many different ways. One specific use-case is using\nVault to store encrypted properties. Spring Vault supports Vault as property\nsource to obtain configuration properties using Spring’s "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html#beans-property-source-abstraction",target:"_blank",rel:"noopener noreferrer"}},[e._v("PropertySource abstraction"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("You can reference properties stored inside Vault in other property sources or use value injection with "),n("code",[e._v("@Value(…)")]),e._v(". Special attention is required when bootstrapping beans that require data stored inside of Vault. A "),n("code",[e._v("VaultPropertySource")]),e._v(" must be initialized at that time to retrieve properties from Vault.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Spring Boot/Spring Cloud users can benefit from "),n("a",{attrs:{href:"https://github.com/spring-cloud/spring-cloud-vault-config",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Cloud Vault"),n("OutboundLink")],1),e._v("'s"),n("br"),e._v("configuration integration that initializes various property sources during application startup.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("h3",{attrs:{id:"_12-1-registering-vaultpropertysource"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_12-1-registering-vaultpropertysource"}},[e._v("#")]),e._v(" 12.1. Registering "),n("code",[e._v("VaultPropertySource")])]),e._v(" "),n("p",[e._v("Spring Vault provides a "),n("code",[e._v("VaultPropertySource")]),e._v(" to be used with Vault to obtain\nproperties. It uses the nested "),n("code",[e._v("data")]),e._v(" element to expose properties stored and\nencrypted in Vault.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('ConfigurableApplicationContext ctx = new GenericApplicationContext();\nMutablePropertySources sources = ctx.getEnvironment().getPropertySources();\nsources.addFirst(new VaultPropertySource(vaultTemplate, "secret/my-application"));\n')])])]),n("p",[e._v("In the code above, "),n("code",[e._v("VaultPropertySource")]),e._v(" has been added with highest precedence\nin the search. If it contains a ´foo"),n("code",[e._v("property, it will be detected and returned ahead of any")]),e._v("foo"),n("code",[e._v("property in any other")]),e._v("PropertySource"),n("code",[e._v(".")]),e._v("MutablePropertySources` exposes a number of methods that allow for precise\nmanipulation of the set of property sources.")]),e._v(" "),n("h3",{attrs:{id:"_12-2-vaultpropertysource"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_12-2-vaultpropertysource"}},[e._v("#")]),e._v(" 12.2. @VaultPropertySource")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("@VaultPropertySource")]),e._v(" annotation provides a convenient and declarative\nmechanism for adding a "),n("code",[e._v("PropertySource")]),e._v(" to Spring’s "),n("code",[e._v("Environment")]),e._v("to be used in conjunction with "),n("code",[e._v("@Configuration")]),e._v(" classes.")]),e._v(" "),n("p",[n("code",[e._v("@VaultPropertySource")]),e._v(" takes a Vault path such as "),n("code",[e._v("secret/my-application")]),e._v("and exposes the data stored at the node in a "),n("code",[e._v("PropertySource")]),e._v("."),n("code",[e._v("@VaultPropertySource")]),e._v(" supports lease renewal for secrets associated with a lease\n(i. e. credentials from the "),n("code",[e._v("mysql")]),e._v(" backend) and credential rotation upon terminal\nlease expiration. Lease renewal is disabled by default.")]),e._v(" "),n("p",[e._v("Example 10. Properties stored in Vault")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('{\n // …\n\n "data": {\n "database": {\n "password": ...\n },\n "user.name": ...,\n }\n\n // …\n}\n')])])]),n("p",[e._v("Example 11. Declaring a "),n("code",[e._v("@VaultPropertySource")])]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\n@VaultPropertySource("secret/my-application")\npublic class AppConfig {\n\n @Autowired Environment env;\n\n @Bean\n public TestBean testBean() {\n TestBean testBean = new TestBean();\n testBean.setUser(env.getProperty("user.name"));\n testBean.setPassword(env.getProperty("database.password"));\n return testBean;\n }\n}\n')])])]),n("p",[e._v("Example 12. Declaring a "),n("code",[e._v("@VaultPropertySource")]),e._v(" with credential rotation and prefix")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\n@VaultPropertySource(value = "aws/creds/s3-access",\n propertyNamePrefix = "aws.",\n renewal = Renewal.ROTATE)\npublic class AppConfig {\n // provides aws.access_key and aws.secret_key properties\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Secrets obtained from "),n("code",[e._v("generic")]),e._v(" secret backends are associated with a TTL ("),n("code",[e._v("refresh_interval")]),e._v(") but not a lease Id. Spring Vault’s "),n("code",[e._v("PropertySource")]),e._v(" rotates generic secrets when reaching its TTL.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("You can use "),n("code",[e._v("@VaultPropertySource")]),e._v(" to obtain the newest secret version from the versioned Key-Value backend. Make sure to not include the "),n("code",[e._v("data/")]),e._v(" segment in the path.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Any "),n("code",[e._v("${…​}")]),e._v(" placeholders present in a "),n("code",[e._v("@VaultPropertySource")]),e._v(" path are resolved against the set of property sources already registered against the environment, as the following example shows:")]),e._v(" "),n("p",[e._v("Example 13. Declaring a "),n("code",[e._v("@VaultPropertySource")]),e._v(" path using placeholders")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\n@VaultPropertySource(value = "aws/creds/${my.placeholder:fallback/value}",\n propertyNamePrefix = "aws.",\n renewal = Renewal.ROTATE)\npublic class AppConfig {\n}\n')])])]),n("p",[e._v("Assuming that "),n("code",[e._v("my.placeholder")]),e._v(" is present in one of the property sources already registered (for example, system properties or environment variables), the placeholder is resolved to the corresponding value.\nIf not, then "),n("code",[e._v("fallback/value")]),e._v(" is used as a default.\nIf no default is specified and a property cannot be resolved, an "),n("code",[e._v("IllegalArgumentException")]),e._v(" is thrown.")]),e._v(" "),n("p",[e._v("In certain situations, it may not be possible or practical to tightly control\nproperty source ordering when using "),n("code",[e._v("@VaultPropertySource")]),e._v(" annotations.\nFor example, if the "),n("code",[e._v("@Configuration")]),e._v(" classes above were registered via\ncomponent-scanning, the ordering is difficult to predict.\nIn such cases - and if overriding is important - it is recommended that the\nuser fall back to using the programmatic PropertySource API.\nSee "),n("a",{attrs:{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/ConfigurableEnvironment.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("ConfigurableEnvironment")]),n("OutboundLink")],1),e._v(" and"),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/MutablePropertySources.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("MutablePropertySources")]),n("OutboundLink")],1),e._v(" for details.")]),e._v(" "),n("h2",{attrs:{id:"_13-vault-repositories"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_13-vault-repositories"}},[e._v("#")]),e._v(" 13. Vault Repositories")]),e._v(" "),n("p",[e._v("Working with "),n("code",[e._v("VaultTemplate")]),e._v(" and responses mapped to Java classes allows basic data operations like read, write\nand delete. Vault repositories apply Spring Data’s repository concept on top of Vault.\nA Vault repository exposes basic CRUD functionality and supports query derivation with predicates constraining\nthe Id property, paging and sorting.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Read more about Spring Data Repositories in the "),n("a",{attrs:{href:"https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Data Commons reference documentation"),n("OutboundLink")],1),e._v(". The reference documentation will give you an introduction to Spring Data repositories.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("h3",{attrs:{id:"_13-1-usage"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_13-1-usage"}},[e._v("#")]),e._v(" 13.1. Usage")]),e._v(" "),n("p",[e._v("To access domain entities stored in Vault you can leverage repository support that eases implementing those quite significantly.")]),e._v(" "),n("p",[e._v("Example 14. Sample Credentials Entity")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Secret\npublic class Credentials {\n\n @Id String id;\n String password;\n String socialSecurityNumber;\n Address address;\n}\n")])])]),n("p",[e._v("We have a pretty simple domain object here. Note that it has a property named "),n("code",[e._v("id")]),e._v(" annotated with"),n("code",[e._v("org.springframework.data.annotation.Id")]),e._v(" and a "),n("code",[e._v("@Secret")]),e._v(" annotation on its type.\nThose two are responsible for creating the actual key used to persist the object as JSON inside Vault.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Properties annotated with "),n("code",[e._v("@Id")]),e._v(" as well as those named "),n("code",[e._v("id")]),e._v(" are considered as the identifier properties."),n("br"),e._v("Those with the annotation are favored over others.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("The next step is to declare a repository interface that uses the domain object.")]),e._v(" "),n("p",[e._v("Example 15. Basic Repository Interface for "),n("code",[e._v("Credentials")]),e._v(" entities")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("public interface CredentialsRepository extends CrudRepository {\n\n}\n")])])]),n("p",[e._v("As our repository extends "),n("code",[e._v("CrudRepository")]),e._v(" it provides basic CRUD and query methods. Vault repositories\nrequire Spring Data components. Make sure to include "),n("code",[e._v("spring-data-commons")]),e._v(" and "),n("code",[e._v("spring-data-keyvalue")]),e._v(" artifacts in your class path.")]),e._v(" "),n("p",[e._v("The easiest way to achive this, is by setting up dependency management and adding the artifacts to your "),n("code",[e._v("pom.xml")]),e._v(":")]),e._v(" "),n("p",[e._v("Then add the following to "),n("code",[e._v("pom.xml")]),e._v(" dependencies section.")]),e._v(" "),n("p",[e._v("Example 16. Using the Spring Data BOM")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n \n \n org.springframework.data\n spring-data-bom\n 2020.0.2\n import\n pom\n \n \n\n\n\n\n \x3c!-- other dependency elements omitted --\x3e\n\n \n org.springframework.vault\n spring-vault-core\n 2.3.1\n \n\n \n org.springframework.data\n spring-data-keyvalue\n \x3c!-- Version inherited from the BOM --\x3e\n \n\n\n")])])]),n("p",[e._v("The thing we need in between to glue things together is the according Spring configuration.")]),e._v(" "),n("p",[e._v("Example 17. JavaConfig for Vault Repositories")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\n@EnableVaultRepositories\npublic class ApplicationConfig {\n\n @Bean\n public VaultTemplate vaultTemplate() {\n return new VaultTemplate(…);\n }\n}\n")])])]),n("p",[e._v("Given the setup above we can go on and inject "),n("code",[e._v("CredentialsRepository")]),e._v(" into our components.")]),e._v(" "),n("p",[e._v("Example 18. Access to Person Entities")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Autowired CredentialsRepository repo;\n\npublic void basicCrudOperations() {\n\n Credentials creds = new Credentials("heisenberg", "327215", "AAA-GG-SSSS");\n rand.setAddress(new Address("308 Negra Arroyo Lane", "Albuquerque", "New Mexico", "87104"));\n\n repo.save(creds); (1)\n\n repo.findOne(creds.getId()); (2)\n\n repo.count(); (3)\n\n repo.delete(creds); (4)\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Stores properties of "),n("code",[e._v("Credentials")]),e._v(" inside Vault Hash with a key pattern "),n("code",[e._v("keyspace/id")]),e._v(","),n("br"),e._v("in this case "),n("code",[e._v("credentials/heisenberg")]),e._v(", in the generic secret backend.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Uses the provided id to retrieve the object stored at "),n("code",[e._v("keyspace/id")]),e._v(".")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("Counts the total number of entities available within the keyspace "),n("em",[e._v("credentials")]),e._v(" defined by "),n("code",[e._v("@Secret")]),e._v(" on "),n("code",[e._v("Credentials")]),e._v(".")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("4")])]),e._v(" "),n("td",[e._v("Removes the key for the given object from Vault.")])])])]),e._v(" "),n("h3",{attrs:{id:"_13-2-object-to-vault-json-mapping"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_13-2-object-to-vault-json-mapping"}},[e._v("#")]),e._v(" 13.2. Object to Vault JSON Mapping")]),e._v(" "),n("p",[e._v("Vault repositories store objects in Vault using JSON as interchange format. Object mapping between JSON and\nthe entity is done by "),n("code",[e._v("VaultConverter")]),e._v(". The converter reads and writes "),n("code",[e._v("SecretDocument")]),e._v(" that contains the body\nfrom a "),n("code",[e._v("VaultResponse")]),e._v(". "),n("code",[e._v("VaultResponse")]),e._v("s are read from Vault and the body is deserialized by\nJackson into a "),n("code",[e._v("Map")]),e._v(" of "),n("code",[e._v("String")]),e._v(" and "),n("code",[e._v("Object")]),e._v(".\nThe default "),n("code",[e._v("VaultConverter")]),e._v(" implementation reads the "),n("code",[e._v("Map")]),e._v(" with nested values, "),n("code",[e._v("List")]),e._v(" and "),n("code",[e._v("Map")]),e._v(" objects and\nconverts these to entities and vice versa.")]),e._v(" "),n("p",[e._v("Given the "),n("code",[e._v("Credentials")]),e._v(" type from the previous sections the default mapping is as follows:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('{\n "_class": "org.example.Credentials", (1)\n "password", "327215", (2)\n "socialSecurityNumber": "AAA-GG-SSSS",\n "address": { (3)\n "street": "308 Negra Arroyo Lane",\n "city": "Albuquerque",\n "state": "New Mexico",\n "zip":"87104"\n }\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("The "),n("code",[e._v("_class")]),e._v(" attribute is included on root level as well as on any nested interface or abstract types.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Simple property values are mapped by path.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("Properties of complex types are mapped as nested objects.")])])])]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("The "),n("code",[e._v("@Id")]),e._v(" property must be mapped to "),n("code",[e._v("String")]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th",[e._v("Type")]),e._v(" "),n("th",[e._v("Sample")]),e._v(" "),n("th",[e._v("Mapped Value")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[e._v("Simple Type "),n("br"),e._v("(eg. String)")]),e._v(" "),n("td",[e._v('String firstname = "Walter";')]),e._v(" "),n("td",[e._v('firstname = "Walter"')])]),e._v(" "),n("tr",[n("td",[e._v("Complex Type "),n("br"),e._v("(eg. Address)")]),e._v(" "),n("td",[e._v('Address adress = new Address("308 Negra Arroyo Lane");')]),e._v(" "),n("td",[e._v('address: { "street": "308 Negra Arroyo Lane" }')])]),e._v(" "),n("tr",[n("td",[e._v("List "),n("br"),e._v("of Simple Type")]),e._v(" "),n("td",[e._v('List nicknames = asList("walt", "heisenberg");')]),e._v(" "),n("td",[e._v('nicknames: ["walt", "heisenberg"]')])]),e._v(" "),n("tr",[n("td",[e._v("Map "),n("br"),e._v("of Simple Type")]),e._v(" "),n("td",[e._v('Map atts = asMap("age", 51)')]),e._v(" "),n("td",[e._v('atts : {"age" : 51}')])]),e._v(" "),n("tr",[n("td",[e._v("List "),n("br"),e._v("of Complex Type")]),e._v(" "),n("td",[e._v('List
addresses = asList(new Address("308…')]),e._v(" "),n("td",[e._v('address: [{ "street": "308 Negra Arroyo Lane" }, …]')])])])]),e._v(" "),n("p",[e._v("You can customize the mapping behavior by registering a "),n("code",[e._v("Converter")]),e._v(" in "),n("code",[e._v("VaultCustomConversions")]),e._v(".\nThose converters can take care of converting from/to a type such as "),n("code",[e._v("LocalDate")]),e._v(" as well as "),n("code",[e._v("SecretDocument")]),e._v("whereas the first one is suitable for converting simple properties and the last one complex types to their JSON\nrepresentation. The second option offers full control over the resulting "),n("code",[e._v("SecretDocument")]),e._v(". Writing objects to "),n("code",[e._v("Vault")]),e._v("will delete the content and re-create the whole entry, so not mapped data will be lost.")]),e._v(" "),n("h3",{attrs:{id:"_13-3-queries-and-query-methods"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_13-3-queries-and-query-methods"}},[e._v("#")]),e._v(" 13.3. Queries and Query Methods")]),e._v(" "),n("p",[e._v("Query methods allow automatic derivation of simple queries from the method name. Vault has no query engine but\nrequires direct access of HTTP context paths. Vault query methods translate Vault’s API possibilities to queries.\nA query method execution lists children under a context path, applies filtering to the Id, optionally limits the\nId stream with offset/limit and applies sorting after fetching the results.")]),e._v(" "),n("p",[e._v("Example 19. Sample Repository Query Method")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("public interface CredentialsRepository extends CrudRepository {\n\n List findByIdStartsWith(String prefix);\n}\n")])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Query methods for Vault repositories support only queries with predicates on the "),n("code",[e._v("@Id")]),e._v(" property.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Here’s an overview of the keywords supported for Vault.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th",[e._v("Keyword")]),e._v(" "),n("th",[e._v("Sample")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("code",[e._v("After")]),e._v(", "),n("code",[e._v("GreaterThan")])]),e._v(" "),n("td",[n("code",[e._v("findByIdGreaterThan(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("GreaterThanEqual")])]),e._v(" "),n("td",[n("code",[e._v("findByIdGreaterThanEqual(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Before")]),e._v(", "),n("code",[e._v("LessThan")])]),e._v(" "),n("td",[n("code",[e._v("findByIdLessThan(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("LessThanEqual")])]),e._v(" "),n("td",[n("code",[e._v("findByIdLessThanEqual(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Between")])]),e._v(" "),n("td",[n("code",[e._v("findByIdBetween(String from, String to)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("In")])]),e._v(" "),n("td",[n("code",[e._v("findByIdIn(Collection ids)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("NotIn")])]),e._v(" "),n("td",[n("code",[e._v("findByIdNotIn(Collection ids)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Like")]),e._v(", "),n("code",[e._v("StartingWith")]),e._v(", "),n("code",[e._v("EndingWith")])]),e._v(" "),n("td",[n("code",[e._v("findByIdLike(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("NotLike")]),e._v(", "),n("code",[e._v("IsNotLike")])]),e._v(" "),n("td",[n("code",[e._v("findByIdNotLike(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Containing")])]),e._v(" "),n("td",[n("code",[e._v("findByFirstnameContaining(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("NotContaining")])]),e._v(" "),n("td",[n("code",[e._v("findByFirstnameNotContaining(String name)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Regex")])]),e._v(" "),n("td",[n("code",[e._v("findByIdRegex(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("(No keyword)")])]),e._v(" "),n("td",[n("code",[e._v("findById(String name)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Not")])]),e._v(" "),n("td",[n("code",[e._v("findByIdNot(String id)")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("And")])]),e._v(" "),n("td",[n("code",[e._v("findByLastnameAndFirstname")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Or")])]),e._v(" "),n("td",[n("code",[e._v("findByLastnameOrFirstname")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Is,Equals")])]),e._v(" "),n("td",[n("code",[e._v("findByFirstname")]),e._v(","),n("code",[e._v("findByFirstnameIs")]),e._v(","),n("code",[e._v("findByFirstnameEquals")])])]),e._v(" "),n("tr",[n("td",[n("code",[e._v("Top,First")])]),e._v(" "),n("td",[n("code",[e._v("findFirst10ByFirstname")]),e._v(","),n("code",[e._v("findTop5ByFirstname")])])])])]),e._v(" "),n("h4",{attrs:{id:"_13-3-1-sorting-and-paging"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_13-3-1-sorting-and-paging"}},[e._v("#")]),e._v(" 13.3.1. Sorting and Paging")]),e._v(" "),n("p",[e._v("Query methods support sorting and paging by selecting in memory a sublist (offset/limit) Id’s retrieved from\na Vault context path. Sorting has is not limited to a particular field, unlike query method predicates.\nUnpaged sorting is applied after Id filtering and all resulting secrets are fetched from Vault. This way\na query method fetches only results that are also returned as part of the result.")]),e._v(" "),n("p",[e._v("Using paging and sorting requires secret fetching before filtering the Id’s which impacts performance.\nSorting and paging guarantees to return the same result even if the natural order of Id returned by Vault changes.\nTherefore, all Id’s are fetched from Vault first, then sorting is applied and afterwards filtering and offset/limiting.")]),e._v(" "),n("p",[e._v("Example 20. Paging and Sorting Repository")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("public interface CredentialsRepository extends PagingAndSortingRepository {\n\n List findTop10ByIdStartsWithOrderBySocialSecurityNumberDesc(String prefix);\n\n List findByIdStarts(String prefix, Pageable pageRequest);\n}\n")])])]),n("h2",{attrs:{id:"_14-client-support"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_14-client-support"}},[e._v("#")]),e._v(" 14. Client support")]),e._v(" "),n("p",[e._v("Spring Vault supports various HTTP clients to access Vault’s HTTP API. Spring Vault uses"),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/integration.html#rest-resttemplate",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("RestTemplate")]),n("OutboundLink")],1),e._v(" as primary interface accessing Vault.\nDedicated client support originates from "),n("a",{attrs:{href:"#vault.client-ssl"}},[e._v("customized SSL configuration")]),e._v("that is scoped only to Spring Vault’s client components.")]),e._v(" "),n("p",[e._v("Spring Vault supports following HTTP imperative clients:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Java’s builtin "),n("code",[e._v("HttpURLConnection")]),e._v(" (default client)")])]),e._v(" "),n("li",[n("p",[e._v("Apache Http Components")])]),e._v(" "),n("li",[n("p",[e._v("Netty")])]),e._v(" "),n("li",[n("p",[e._v("OkHttp 3")])])]),e._v(" "),n("p",[e._v("Spring Vault’s reactive integration supports the following reactive HTTP clients:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Reactor Netty")])]),e._v(" "),n("li",[n("p",[e._v("Jetty")])])]),e._v(" "),n("p",[e._v("Using a specific client requires the according dependency to be available on the classpath\nso Spring Vault can use the available client for communicating with Vault.")]),e._v(" "),n("h3",{attrs:{id:"_14-1-java-s-builtin-httpurlconnection"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_14-1-java-s-builtin-httpurlconnection"}},[e._v("#")]),e._v(" 14.1. Java’s builtin "),n("code",[e._v("HttpURLConnection")])]),e._v(" "),n("p",[e._v("Java’s builtin "),n("code",[e._v("HttpURLConnection")]),e._v(" is available out-of-the-box without additional\nconfiguration. Using "),n("code",[e._v("HttpURLConnection")]),e._v(" comes with a limitation regarding SSL configuration.\nSpring Vault won’t apply "),n("a",{attrs:{href:"#vault.client-ssl"}},[e._v("customized SSL configuration")]),e._v(" as it would\nrequire a deep reconfiguration of the JVM. This configuration would affect all\ncomponents relying on the default SSL context. Configuring SSL settings using"),n("code",[e._v("HttpURLConnection")]),e._v(" requires you providing these settings as System Properties. See"),n("a",{attrs:{href:"https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization",target:"_blank",rel:"noopener noreferrer"}},[e._v("Customizing JSSE"),n("OutboundLink")],1),e._v(" for further details.")]),e._v(" "),n("h3",{attrs:{id:"_14-2-external-clients"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_14-2-external-clients"}},[e._v("#")]),e._v(" 14.2. External Clients")]),e._v(" "),n("p",[e._v("You can use external clients to access Vault’s API. Simply add one of the following\ndependencies to your project. You can omit the version number if using"),n("a",{attrs:{href:"#dependencies"}},[e._v("Spring Vault’s Dependency BOM")])]),e._v(" "),n("p",[e._v("Example 21. Apache Http Components Dependency")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n org.apache.httpcomponents\n httpclient\n\n")])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Apache HttpClient’s "),n("a",{attrs:{href:"https://hc.apache.org/httpcomponents-client-4.5.x/logging.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("wire logging"),n("OutboundLink")],1),e._v(" can be enabled through logging configuration. Make sure to not accidentally enable wire logging as logs may expose traffic (tokens and secrets) between your application and Vault in plain text.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Example 22. Netty Dependency")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n io.netty\n netty-all\n\n")])])]),n("p",[e._v("Example 23. Square OkHttp 3")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n com.squareup.okhttp3\n okhttp\n\n")])])]),n("p",[e._v("Example 24. Reactor Netty")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n io.projectreactor.netty\n reactor-netty\n\n")])])]),n("p",[e._v("Example 25. Jetty")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n org.eclipse.jetty\n jetty-reactive-httpclient\n\n")])])]),n("h3",{attrs:{id:"_14-3-vault-client-ssl-configuration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_14-3-vault-client-ssl-configuration"}},[e._v("#")]),e._v(" 14.3. Vault Client SSL configuration")]),e._v(" "),n("p",[e._v("SSL can be configured using "),n("code",[e._v("SslConfiguration")]),e._v(" by setting various properties.\nYou can set either "),n("code",[e._v("javax.net.ssl.trustStore")]),e._v(" to configure\nJVM-wide SSL settings or configure "),n("code",[e._v("SslConfiguration")]),e._v("to set SSL settings only for Spring Vault.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('SslConfiguration sslConfiguration = SslConfiguration.create( (1)\n\t\tnew FileSystemResource("client-cert.jks"), "changeit".toCharArray(),\n\t\tnew FileSystemResource("truststore.jks"), "changeit".toCharArray());\n\nSslConfiguration.forTrustStore(new FileSystemResource("keystore.jks"), (2)\n "changeit".toCharArray())\n\nSslConfiguration.forKeyStore(new FileSystemResource("keystore.jks"), (3)\n "changeit".toCharArray())\n\nSslConfiguration.forKeyStore(new FileSystemResource("keystore.jks"), (4)\n "changeit".toCharArray(),\n KeyConfiguration.of("key-password".toCharArray(),\n "my-key-alias"))\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Full configuration.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("Configuring only trust store settings.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("Configuring only key store settings.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("4")])]),e._v(" "),n("td",[e._v("Configuring only key store settings with providing a key-configuration.")])])])]),e._v(" "),n("p",[e._v("Please note that providing "),n("code",[e._v("SslConfiguration")]),e._v(" can be only applied when either Apache Http Components or the OkHttp client is on your class-path.")]),e._v(" "),n("p",[e._v("The SSL configuration supports also PEM-encoded certificates as alternative to a Java Key Store.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('KeyStoreConfiguration keystore = KeyStoreConfiguration\n .of(new ClassPathResource("ca.pem")).withStoreType("PEM");\nSslConfiguration configuration = SslConfiguration.forTrustStore(keystore);\n')])])]),n("p",[e._v("PEM files may contain one or more certificates (blocks of "),n("code",[e._v("-----BEGIN CERTIFICATE-----")]),e._v(" and "),n("code",[e._v("-----END CERTIFICATE-----")]),e._v(").\nCertificates added to the underlying "),n("code",[e._v("KeyStore")]),e._v(" use the full subject name as alias.")]),e._v(" "),n("h2",{attrs:{id:"_15-authentication-methods"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-authentication-methods"}},[e._v("#")]),e._v(" 15. Authentication Methods")]),e._v(" "),n("p",[e._v("Different organizations have different requirements for security\nand authentication. Vault reflects that need by shipping multiple authentication\nmethods. Spring Vault supports multiple authentications mechanisms.")]),e._v(" "),n("h3",{attrs:{id:"_15-1-externalizing-login-credentials"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-1-externalizing-login-credentials"}},[e._v("#")]),e._v(" 15.1. Externalizing login credentials")]),e._v(" "),n("p",[e._v("Obtaining first-time access to a secured system is known as secure introduction.\nAny client requires ephemeral or permanent credentials to access Vault. Externalizing credentials\nis a good pattern to keep code maintainability high but comes at a risk of increased disclosure.")]),e._v(" "),n("p",[e._v("Disclosure of login credentials to any party allows login to Vault and access secrets that\nare permitted by the underlying role. Picking the appropriate client authentication and\ninjecting credentials into the application is subject to risk evaluation.")]),e._v(" "),n("p",[e._v("Spring’s "),n("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html#beans-property-source-abstraction",target:"_blank",rel:"noopener noreferrer"}},[e._v("PropertySource abstraction"),n("OutboundLink")],1),e._v(" is a natural fit\nto keep configuration outside the application code. You can use system properties, environment\nvariables or property files to store login credentials. Each approach comes with its own properties.\nKeep in mind that the command line and environment properties can be introspected with appropriate\nOS access levels.")]),e._v(" "),n("p",[e._v("Example 26. Externalizing "),n("code",[e._v("vault.token")]),e._v(" to a properties file")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@PropertySource("configuration.properties")\n@Configuration\npublic class Config extends AbstractVaultConfiguration {\n\n @Override\n public ClientAuthentication clientAuthentication() {\n return new TokenAuthentication(getEnvironment().getProperty("vault.token"));\n }\n}\n')])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Spring allows multiple ways to obtain "),n("code",[e._v("Environment")]),e._v(". When using "),n("code",[e._v("VaultPropertySource")]),e._v(", injection via "),n("code",[e._v("@Autowired Environment environment")]),e._v(" will not provide the "),n("code",[e._v("Environment")]),e._v(" as the environment bean is still in construction and autowiring comes at a later stage. Your configuration class should rather implement "),n("code",[e._v("ApplicationContextAware")]),e._v(" and obtain the "),n("code",[e._v("Environment")]),e._v(" from "),n("code",[e._v("ApplicationContext")]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("See "),n("a",{attrs:{href:"https://github.com/spring-projects/spring-vault/blob/master/spring-vault-core/src/test/java/org/springframework/vault/demo/SecurePropertyUsage.java",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("SecurePropertyUsage.java")]),n("OutboundLink")],1),e._v("for a sample on referencing properties in components and other property sources.")]),e._v(" "),n("h3",{attrs:{id:"_15-2-token-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-2-token-authentication"}},[e._v("#")]),e._v(" 15.2. Token authentication")]),e._v(" "),n("p",[e._v("Tokens are the core method for authentication within Vault.\nToken authentication requires a static token to be provided.")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Token authentication is the default authentication method."),n("br"),e._v("If a token is disclosed an unintended party, it gains access to Vault and"),n("br"),e._v("can access secrets for the intended client.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Typically, Token authentication is used in scenarios in which the token is created and renewed\nexternally (such as "),n("a",{attrs:{href:"https://github.com/hashicorp/vault-service-broker",target:"_blank",rel:"noopener noreferrer"}},[e._v("HashiCorp Vault service broker"),n("OutboundLink")],1),e._v(").\nDepending on the actual setup, you may or may not want token renewal and revocation.\nSee "),n("a",{attrs:{href:"#vault.authentication.session"}},[n("code",[e._v("LifecycleAwareSessionManager")])]),e._v(" for details about TTL and token revocation.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n return new TokenAuthentication("…");\n }\n\n // …\n}\n')])])]),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/concepts/tokens.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Tokens"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/token.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the Token auth backend"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-3-appid-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-3-appid-authentication"}},[e._v("#")]),e._v(" 15.3. AppId authentication")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("AppId authentication is deprecated by Vault. Use "),n("a",{attrs:{href:"#vault.authentication.approle"}},[e._v("AppRole authentication")]),e._v(" instead.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Vault supports "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/app-id.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("AppId"),n("OutboundLink")],1),e._v("authentication that consists of two hard to guess tokens. The AppId\ndefaults to "),n("code",[e._v("spring.application.name")]),e._v(" that is statically configured.\nThe second token is the UserId which is a part determined by the application,\nusually related to the runtime environment. IP address, Mac address or a\nDocker container name are good examples. Spring Vault supports\nIP address, Mac address and static UserId’s (e.g. supplied via System properties).\nThe IP and Mac address are represented as Hex-encoded SHA256 hash.")]),e._v(" "),n("p",[e._v("IP address-based UserId’s use the local host’s IP address.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()\n .appId("myapp")\n .userIdMechanism(new IpAddressUserId())\n .build();\n\n return new AppIdAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[e._v("The corresponding command to generate the IP address UserId from a command line is:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("$ echo -n 192.168.99.1 | sha256sum\n")])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Including the line break of "),n("code",[e._v("echo")]),e._v(" leads to a different hash value"),n("br"),e._v("so make sure to include the "),n("code",[e._v("-n")]),e._v(" flag.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Mac address-based UserId’s obtain their network device from the\nlocalhost-bound device. The configuration also allows specifying\na "),n("code",[e._v("network-interface")]),e._v(" hint to pick the right device. The value of"),n("code",[e._v("network-interface")]),e._v(" is optional and can be either an interface\nname or interface index (0-based).")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()\n .appId("myapp")\n .userIdMechanism(new MacAddressUserId())\n .build();\n\n return new AppIdAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[e._v("The corresponding command to generate the Mac address UserId from a command line is:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("$ echo -n 0AFEDE1234AC | sha256sum\n")])])]),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("The Mac address is specified uppercase and without colons."),n("br"),e._v("Including the line break of "),n("code",[e._v("echo")]),e._v(" leads to a different hash value"),n("br"),e._v("so make sure to include the "),n("code",[e._v("-n")]),e._v(" flag.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("h4",{attrs:{id:"_15-3-1-custom-userid"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-3-1-custom-userid"}},[e._v("#")]),e._v(" 15.3.1. Custom UserId")]),e._v(" "),n("p",[e._v("A more advanced approach lets you implementing your own "),n("code",[e._v("AppIdUserIdMechanism")]),e._v(".\nThis class must be on your classpath and must implement\nthe "),n("code",[e._v("org.springframework.vault.authentication.AppIdUserIdMechanism")]),e._v(" interface\nand the "),n("code",[e._v("createUserId")]),e._v(" method. Spring Vault will obtain the UserId\nby calling "),n("code",[e._v("createUserId")]),e._v(" each time it authenticates using AppId to\nobtain a token.")]),e._v(" "),n("p",[e._v("MyUserIdMechanism.java")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("public class MyUserIdMechanism implements AppIdUserIdMechanism {\n\n @Override\n public String createUserId() {\n\n String userId = …\n return userId;\n }\n}\n")])])]),n("p",[e._v("See also: "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/app-id.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the App ID auth backend"),n("OutboundLink")],1)]),e._v(" "),n("h3",{attrs:{id:"_15-4-approle-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-4-approle-authentication"}},[e._v("#")]),e._v(" 15.4. AppRole authentication")]),e._v(" "),n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/app-id.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("AppRole"),n("OutboundLink")],1),e._v(" allows machine\nauthentication, like the deprecated (since Vault 0.6.1) "),n("a",{attrs:{href:"#vault.authentication.appid"}},[e._v("AppId authentication")]),e._v(".\nAppRole authentication consists of two hard to guess (secret) tokens: RoleId and SecretId.")]),e._v(" "),n("p",[e._v("Spring Vault supports AppRole authentication by providing either RoleId only\nor together with a provided SecretId and fetching RoleId/SecretId from Vault\n(push and pull modes with response unwrapping).")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()\n .roleId(RoleId.provided("…"))\n .secretId(SecretId.wrapped(VaultToken.of("…")))\n .build();\n\n return new AppRoleAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[e._v("Spring Vault also support full pull mode: If RoleId and SecretId are not provided,\nSpring Vault will retrieve them using the role name and an initial token. The\ninitial token may be associated with a TTL and usage limit.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n VaultToken initialToken = VaultToken.of("…");\n AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()\n .appRole("…")\n .roleId(RoleId.pull(initialToken))\n .secretId(SecretId.pull(initialToken))\n .build();\n\n return new AppRoleAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[e._v("See also: "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/approle.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the AppRole auth backend"),n("OutboundLink")],1)]),e._v(" "),n("h3",{attrs:{id:"_15-5-aws-ec2-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-5-aws-ec2-authentication"}},[e._v("#")]),e._v(" 15.5. AWS-EC2 authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/aws-ec2.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("aws-ec2"),n("OutboundLink")],1),e._v("auth backend provides a secure introduction mechanism\nfor AWS EC2 instances, allowing automated retrieval of a Vault\ntoken. Unlike most Vault authentication backends, this backend\ndoes not require first-deploying, or provisioning security-sensitive\ncredentials (tokens, username/password, client certificates, etc.).\nInstead, it treats AWS as a Trusted Third Party and uses the\ncryptographically signed dynamic metadata information that uniquely\nrepresents each EC2 instance.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n return new AwsEc2Authentication(restOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("AWS-EC2 authentication enables nonce by default to follow\nthe Trust On First Use (TOFU) principle. Any unintended party that\ngains access to the PKCS#7 identity metadata can authenticate\nagainst Vault.")]),e._v(" "),n("p",[e._v("During the first login, Spring Vault generates a nonce\nthat is stored in the auth backend aside the instance Id.\nRe-authentication requires the same nonce to be sent. Any other\nparty does not have the nonce and can raise an alert in Vault for\nfurther investigation.")]),e._v(" "),n("p",[e._v("The nonce is kept in memory and is lost during application restart.")]),e._v(" "),n("p",[e._v("AWS-EC2 authentication roles are optional and default to the AMI.\nYou can configure the authentication role by setting\nit in "),n("code",[e._v("AwsEc2AuthenticationOptions")]),e._v(".")]),e._v(" "),n("p",[e._v("See also: "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/aws-ec2.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the AWS-EC2 auth backend"),n("OutboundLink")],1)]),e._v(" "),n("h3",{attrs:{id:"_15-6-aws-iam-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-6-aws-iam-authentication"}},[e._v("#")]),e._v(" 15.6. AWS-IAM authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/aws.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("aws"),n("OutboundLink")],1),e._v("auth backend allows Vault login by using existing AWS IAM credentials.")]),e._v(" "),n("p",[e._v("AWS IAM authentication creates a signed HTTP request that is\nexecuted by Vault to get the identity of the signer using AWS STS"),n("code",[e._v("GetCallerIdentity")]),e._v(" method. AWSv4 signatures require IAM credentials.")]),e._v(" "),n("p",[e._v("IAM credentials can be obtained from either the runtime environment\nor supplied externally. Runtime environments such as AWS-EC2,\nLambda and ECS with assigned IAM principals do not require client-specific\nconfiguration of credentials but can obtain these from its metadata source.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n AwsIamAuthenticationOptions options = AwsIamAuthenticationOptions.builder()\n .credentials(new BasicAWSCredentials(…)).build();\n\n return new AwsIamAuthentication(options, restOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("Example 27. Using AWS-EC2 instance profile as credentials source")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n AwsIamAuthenticationOptions options = AwsIamAuthenticationOptions.builder()\n .credentialsProvider(InstanceProfileCredentialsProvider.getInstance()).build();\n\n return new AwsIamAuthentication(options, restOperations());\n }\n\n // …\n}\n")])])]),n("p",[n("code",[e._v("AwsIamAuthentication")]),e._v(" requires the AWS Java SDK dependency ("),n("code",[e._v("com.amazonaws:aws-java-sdk-core")]),e._v(")\nas the authentication implementation uses AWS SDK types for credentials and request signing.")]),e._v(" "),n("p",[e._v("You can configure the authentication via "),n("code",[e._v("AwsIamAuthenticationOptions")]),e._v(".")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/aws.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the AWS auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("AWS Documentation: STS GetCallerIdentity"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-7-azure-msi-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-7-azure-msi-authentication"}},[e._v("#")]),e._v(" 15.7. Azure (MSI) authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/azure.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("azure"),n("OutboundLink")],1),e._v("auth backend provides a secure introduction mechanism\nfor Azure VM instances, allowing automated retrieval of a Vault\ntoken. Unlike most Vault authentication backends, this backend\ndoes not require first-deploying, or provisioning security-sensitive\ncredentials (tokens, username/password, client certificates, etc.).\nInstead, it treats Azure as a Trusted Third Party and uses the\nmanaged service identity and instance metadata information that can be\nbound to a VM instance.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n AzureMsiAuthenticationOptions options = AzureMsiAuthenticationOptions.builder()\n .role(…).build();\n\n return new AzureMsiAuthentication(options, restOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("Azure authentication requires details about the VM environment (subscription Id,\nresource group name, VM name). These details can be either configured through"),n("code",[e._v("AzureMsiAuthenticationOptionsBuilder")]),e._v(".\nIf left unconfigured, "),n("code",[e._v("AzureMsiAuthentication")]),e._v(" queries Azure’s instance metadata service to\nobtain these details.")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/azure.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the Azure auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview",target:"_blank",rel:"noopener noreferrer"}},[e._v("Azure Documentation: Managed Service Identity"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-8-gcp-gce-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-8-gcp-gce-authentication"}},[e._v("#")]),e._v(" 15.8. GCP-GCE authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/gcp.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("gcp"),n("OutboundLink")],1),e._v("auth backend allows Vault login by using existing GCP (Google Cloud Platform) IAM and GCE credentials.")]),e._v(" "),n("p",[e._v("GCP GCE (Google Compute Engine) authentication creates a signature in the form of a\nJSON Web Token (JWT) for a service account. A JWT for a Compute Engine instance\nis obtained from the GCE metadata service using "),n("a",{attrs:{href:"https://cloud.google.com/compute/docs/instances/verifying-instance-identity",target:"_blank",rel:"noopener noreferrer"}},[e._v("Instance identification"),n("OutboundLink")],1),e._v(".\nThis API creates a JSON Web Token that can be used to confirm the instance identity.")]),e._v(" "),n("p",[e._v("Unlike most Vault authentication backends, this backend\ndoes not require first-deploying, or provisioning security-sensitive\ncredentials (tokens, username/password, client certificates, etc.).\nInstead, it treats GCP as a Trusted Third Party and uses the\ncryptographically signed dynamic metadata information that uniquely\nrepresents each GCP service account.")]),e._v(" "),n("p",[e._v("You can configure the authentication via "),n("code",[e._v("GcpComputeAuthenticationOptions")]),e._v(".")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n GcpComputeAuthenticationOptions options = GcpComputeAuthenticationOptions.builder()\n\t\t\t\t.role(…).build();\n\n\t\tGcpComputeAuthentication authentication = new GcpComputeAuthentication(options,\n\t\t\t\trestOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/gcp.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the GCP auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://cloud.google.com/compute/docs/instances/verifying-instance-identity",target:"_blank",rel:"noopener noreferrer"}},[e._v("GCP Documentation: Verifying the Identity of Instances"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-9-gcp-iam-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-9-gcp-iam-authentication"}},[e._v("#")]),e._v(" 15.9. GCP-IAM authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/gcp.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("gcp"),n("OutboundLink")],1),e._v("auth backend allows Vault login by using existing GCP (Google Cloud Platform) IAM and GCE credentials.")]),e._v(" "),n("p",[e._v("GCP IAM authentication creates a signature in the form of a JSON Web Token (JWT)\nfor a service account. A JWT for a service account is obtained by\ncalling GCP IAM’s "),n("a",{attrs:{href:"https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("projects.serviceAccounts.signJwt")]),n("OutboundLink")],1),e._v(" API. The caller authenticates against GCP IAM\nand proves thereby its identity. This Vault backend treats GCP as a Trusted Third Party.")]),e._v(" "),n("p",[e._v("IAM credentials can be obtained from either the runtime environment\nor supplied externally as e.g. JSON. JSON is the preferred form as it\ncarries the project id and service account identifier required for calling"),n("code",[e._v("projects.serviceAccounts.signJwt")]),e._v(".")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()\n\t\t\t\t.role(…).credential(GoogleCredentials.getApplicationDefault()).build();\n\n\t\tGcpIamAuthentication authentication = new GcpIamAuthentication(options,\n\t\t\t\trestOperations());\n }\n\n // …\n}\n")])])]),n("p",[n("code",[e._v("GcpIamAuthenticationOptions")]),e._v(" requires the Google Cloud Java SDK dependency\n("),n("code",[e._v("com.google.apis:google-api-services-iam")]),e._v(" and "),n("code",[e._v("com.google.auth:google-auth-library-oauth2-http")]),e._v(")\nas the authentication implementation uses Google APIs for credentials and JWT signing.")]),e._v(" "),n("p",[e._v("You can configure the authentication via "),n("code",[e._v("GcpIamAuthenticationOptions")]),e._v(".")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Google credentials require an OAuth 2 token maintaining the token lifecycle. All API"),n("br"),e._v("is synchronous therefore, "),n("code",[e._v("GcpIamAuthentication")]),e._v(" does not support "),n("code",[e._v("AuthenticationSteps")]),e._v(" which is"),n("br"),e._v("required for reactive usage.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/gcp.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the GCP auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt",target:"_blank",rel:"noopener noreferrer"}},[e._v("GCP Documentation: projects.serviceAccounts.signJwt"),n("OutboundLink")],1),n("a",{attrs:{href:""}})])])]),e._v(" "),n("h3",{attrs:{id:"_15-10-pcf-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-10-pcf-authentication"}},[e._v("#")]),e._v(" 15.10. PCF authentication")]),e._v(" "),n("p",[e._v("The "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/pcf.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("pcf"),n("OutboundLink")],1),e._v("auth backend allows Vault login for PCF instances.\nIt leverages "),n("a",{attrs:{href:"https://content.pivotal.io/blog/new-in-pcf-2-1-app-container-identity-assurance-via-automatic-cert-rotation",target:"_blank",rel:"noopener noreferrer"}},[e._v("PCF’s App and Container Identity Assurance"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("PCF authentication uses the instance key and certificate to create a signature that is validated by Vault.\nIf the signature matches, and potentially bound organization/space/application Id’s match, Vault issues an appropriately-scoped token.")]),e._v(" "),n("p",[e._v("Instance credentials are available from files at "),n("code",[e._v("CF_INSTANCE_CERT")]),e._v(" and"),n("code",[e._v("CF_INSTANCE_KEY")]),e._v(" variables.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n PcfAuthenticationOptions options = PcfAuthenticationOptions.builder()\n .role(…).build();\n\n PcfAuthentication authentication = new PcfAuthentication(options,\n restOperations());\n }\n\n // …\n}\n")])])]),n("p",[n("code",[e._v("PcfAuthenticationOptions")]),e._v(" requires the "),n("a",{attrs:{href:"https://www.bouncycastle.org/latest_releases.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("BouncyCastle"),n("OutboundLink")],1),e._v("library for creating RSA-PSS signatures.")]),e._v(" "),n("p",[e._v("You can configure the authentication via "),n("code",[e._v("PcfAuthenticationOptions")]),e._v(".")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/pcf.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation:\nUsing the PCF auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("h3",{attrs:{id:"_15-11-tls-certificate-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-11-tls-certificate-authentication"}},[e._v("#")]),e._v(" 15.11. TLS certificate authentication")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("cert")]),e._v(" auth backend allows authentication using SSL/TLS client\ncertificates that are either signed by a CA or self-signed.")]),e._v(" "),n("p",[e._v("To enable "),n("code",[e._v("cert")]),e._v(" authentication you need to:")]),e._v(" "),n("ol",[n("li",[n("p",[e._v("Use SSL, see "),n("a",{attrs:{href:"#vault.client-ssl"}},[e._v("Vault Client SSL configuration")])])]),e._v(" "),n("li",[n("p",[e._v("Configure a Java "),n("code",[e._v("Keystore")]),e._v(" that contains the client\ncertificate and the private key")])])]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n ClientCertificateAuthenticationOptions options = ClientCertificateAuthenticationOptions.builder()\n .path(…).build();\n\n return new ClientCertificateAuthentication(options, restOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("See also: "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/cert.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the Cert auth backend"),n("OutboundLink")],1)]),e._v(" "),n("h3",{attrs:{id:"_15-12-cubbyhole-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-12-cubbyhole-authentication"}},[e._v("#")]),e._v(" 15.12. Cubbyhole authentication")]),e._v(" "),n("p",[e._v("Cubbyhole authentication uses Vault primitives to provide a secured authentication\nworkflow. Cubbyhole authentication uses tokens as primary login method.\nAn ephemeral token is used to obtain a second, login VaultToken from Vault’s\nCubbyhole secret backend. The login token is usually longer-lived and used to\ninteract with Vault. The login token can be retrieved either from a wrapped\nresponse or from the "),n("code",[e._v("data")]),e._v(" section.")]),e._v(" "),n("p",[n("strong",[e._v("Creating a wrapped token")])]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("Response Wrapping for token creation requires Vault 0.6.0 or higher.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("Example 28. Crating and storing tokens")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('$ vault token-create -wrap-ttl="10m"\nKey Value\n--- -----\nwrapping_token: 397ccb93-ff6c-b17b-9389-380b01ca2645\nwrapping_token_ttl: 0h10m0s\nwrapping_token_creation_time: 2016-09-18 20:29:48.652957077 +0200 CEST\nwrapped_accessor: 46b6aebb-187f-932a-26d7-4f3d86a68319\n')])])]),n("p",[e._v("Example 29. Wrapped token response usage")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions\n .builder()\n .initialToken(VaultToken.of("…"))\n .wrapped()\n .build();\n\n return new CubbyholeAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[n("strong",[e._v("Using stored tokens")])]),e._v(" "),n("p",[e._v("Example 30. Crating and storing tokens")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("$ vault token create\nKey Value\n--- -----\ntoken f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819\ntoken_accessor 4eee9bd9-81bb-06d6-af01-723c54a72148\ntoken_duration 0s\ntoken_renewable false\ntoken_policies [root]\n\n$ vault token create -use-limit=2 -orphan -no-default-policy -policy=none\nKey Value\n--- -----\ntoken 895cb88b-aef4-0e33-ba65-d50007290780\ntoken_accessor e84b661c-8aa8-2286-b788-f258f30c8325\ntoken_duration 0s\ntoken_renewable false\ntoken_policies [none]\n\n$ export VAULT_TOKEN=895cb88b-aef4-0e33-ba65-d50007290780\n$ vault write cubbyhole/token token=f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819\n")])])]),n("p",[e._v("Example 31. Stored token response usage")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions\n .builder()\n .initialToken(VaultToken.of("…"))\n .path("cubbyhole/token")\n .build();\n\n return new CubbyholeAuthentication(options, restOperations());\n }\n\n // …\n}\n')])])]),n("p",[n("strong",[e._v("Remaining TTL/Renewability")])]),e._v(" "),n("p",[e._v("Tokens retrieved from Cubbyhole associated with a non-zero TTL start their TTL at the\ntime of token creation. That time is not necessarily identical with application\nstartup. To compensate for the initial delay, Cubbyhole authentication performs a\nself lookup for tokens associated with a non-zero TTL to retrieve the remaining TTL.\nCubbyhole authentication will not self-lookup wrapped tokens without a TTL because a\nzero TTL indicates there is no TTL associated.")]),e._v(" "),n("p",[e._v("Non-wrapped tokens do not provide details regarding renewability and TTL by just\nretrieving the token. A self-lookup will lookup renewability and the remaining TTL.")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/concepts/tokens.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Tokens"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/secrets/cubbyhole/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Cubbyhole Secret Backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/concepts/response-wrapping.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Response Wrapping"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-13-kubernetes-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-13-kubernetes-authentication"}},[e._v("#")]),e._v(" 15.13. Kubernetes authentication")]),e._v(" "),n("p",[e._v("Vault supports since 0.8.3 "),n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/kubernetes.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("kubernetes"),n("OutboundLink")],1),e._v("-based authentication using Kubernetes tokens.")]),e._v(" "),n("p",[e._v("Using Kubernetes authentication requires a Kubernetes Service Account Token,\nusually mounted at "),n("code",[e._v("/var/run/secrets/kubernetes.io/serviceaccount/token")]),e._v(".\nThe file contains the token which is read and sent to Vault.\nVault verifies its validity using Kubernetes' API during login.")]),e._v(" "),n("p",[e._v("Configuring Kubernetes authentication requires at least the role name to be provided:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("@Configuration\nclass AppConfig extends AbstractVaultConfiguration {\n\n // …\n\n @Override\n public ClientAuthentication clientAuthentication() {\n\n KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions.builder()\n .role(…).jwtSupplier(…).build();\n\n return new KubernetesAuthentication(options, restOperations());\n }\n\n // …\n}\n")])])]),n("p",[e._v("You can configure the authentication via "),n("code",[e._v("KubernetesAuthenticationOptions")]),e._v(".")]),e._v(" "),n("p",[e._v("See also:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://www.vaultproject.io/docs/auth/kubernetes.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Vault Documentation: Using the Kubernetes auth backend"),n("OutboundLink")],1)])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kubernetes Documentation: Configure Service Accounts for Pods"),n("OutboundLink")],1)])])]),e._v(" "),n("h3",{attrs:{id:"_15-14-authentication-steps"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-14-authentication-steps"}},[e._v("#")]),e._v(" 15.14. Authentication Steps")]),e._v(" "),n("p",[n("code",[e._v("ClientAuthentication")]),e._v(" objects describe the authentication flow and perform the actual\nauthentication steps. Pre-composed authentications are easy to use and to configure with\na tight binding to synchronous execution.")]),e._v(" "),n("p",[e._v("The composition of authentication methods and reusing common steps, such as posting login\npayload to Vault or retrieving authentication input from an HTTP source is not intended\nwith "),n("code",[e._v("ClientAuthentication")]),e._v(" objects.")]),e._v(" "),n("p",[e._v("Authentication steps provide reusability of common authentication activity.\nSteps created via "),n("code",[e._v("AuthenticationSteps")]),e._v(" describe an authentication flow in a functional\nstyle leaving the actual authentication execution to specific executors.")]),e._v(" "),n("p",[e._v("Example 32. Stored token authentication flow.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("AuthenticationSteps.just(VaultToken.of(…)); (1)\n")])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Creates "),n("code",[e._v("AuthenticationSteps")]),e._v(" from just a "),n("code",[e._v("VaultToken")]),e._v(".")])])]),e._v(" "),n("tbody")]),e._v(" "),n("p",[e._v("A single-step authentication flow can be created from a single input. Flows declaring\nmultiple authentication steps start with a "),n("code",[e._v("Supplier")]),e._v(" or "),n("code",[e._v("HttpRequest")]),e._v(" that provide an\nauthentication state object which can be used to map or post to Vault for login.")]),e._v(" "),n("p",[e._v("Example 33. AppRole authentication flow")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('AuthenticationSteps.fromSupplier( (1)\n\n () -> getAppRoleLogin(options.getRoleId(), options.getSecretId())) (2)\n\n .login("auth/{mount}/login", options.getPath()); (3)\n')])])]),n("table",[n("thead",[n("tr",[n("th",[n("strong",[e._v("1")])]),e._v(" "),n("th",[e._v("Start declaring "),n("code",[e._v("AuthenticationSteps")]),e._v(" accepting a "),n("code",[e._v("Supplier")]),e._v("."),n("br"),e._v("The state object type depends on the "),n("code",[e._v("Supplier")]),e._v(" response type which can be mapped in a later step.")])])]),e._v(" "),n("tbody",[n("tr",[n("td",[n("strong",[e._v("2")])]),e._v(" "),n("td",[e._v("The actual "),n("code",[e._v("Supplier")]),e._v(" implementation."),n("br"),e._v("Creating a "),n("code",[e._v("Map")]),e._v(" in this case.")])]),e._v(" "),n("tr",[n("td",[n("strong",[e._v("3")])]),e._v(" "),n("td",[e._v("Perform a Vault login by posting the state object ("),n("code",[e._v("Map")]),e._v(") to a Vault endpoint for Vault token creation."),n("br"),e._v("Note that template variables are subject to URL escaping.")])])])]),e._v(" "),n("p",[e._v("Authentication flows require an executor to perform the actual login. We provide two executors\nfor different execution models:")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v("AuthenticationStepsExecutor")]),e._v(" as a drop-in replacement for synchronous "),n("code",[e._v("ClientAuthentication")]),e._v(".")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("AuthenticationStepsOperator")]),e._v(" for reactive execution.")])])]),e._v(" "),n("p",[e._v("Many "),n("code",[e._v("ClientAuthentication")]),e._v("'s come with static factory methods to create "),n("code",[e._v("AuthenticationSteps")]),e._v("for their authentication-specific options:")]),e._v(" "),n("p",[e._v("Example 34. Synchronous "),n("code",[e._v("AuthenticationSteps")]),e._v(" execution")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("CubbyholeAuthenticationOptions options = …\nRestOperations restOperations = …\n\nAuthenticationSteps steps = CubbyholeAuthentication.createAuthenticationSteps(options);\n\nAuthenticationStepsExecutor executor = new AuthenticationStepsExecutor(steps, restOperations);\n\nVaultToken token = executor.login();\n")])])]),n("h3",{attrs:{id:"_15-15-token-lifecycle"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_15-15-token-lifecycle"}},[e._v("#")]),e._v(" 15.15. Token Lifecycle")]),e._v(" "),n("p",[e._v("Vault’s tokens can be associated with a time to live. Tokens obtained by an authentication method\nare intended to be used as long as the session is active and should not expire while the application is active.")]),e._v(" "),n("p",[e._v("Spring Vault provides with "),n("a",{attrs:{href:"https://docs.spring.io/spring-vault/docs/2.3.1/api/org/springframework/vault/authentication/LifecycleAwareSessionManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("LifecycleAwareSessionManager")]),n("OutboundLink")],1),e._v(" a session manager that can renew the token until it reaches its terminal TTL to then perform another login to obtain the next token which is associated with the session.")]),e._v(" "),n("p",[e._v("Depending on the authentication method, a login can create two kinds of tokens:")]),e._v(" "),n("ul",[n("li",[n("p",[n("a",{attrs:{href:"https://docs.spring.io/spring-vault/docs/2.3.1/api/org/springframework/vault/support/VaultToken.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("VaultToken")]),n("OutboundLink")],1),e._v(": Generic token encapsulating the actual token.")])]),e._v(" "),n("li",[n("p",[n("a",{attrs:{href:"https://docs.spring.io/spring-vault/docs/2.3.1/api/org/springframework/vault/support/LoginToken.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("LoginToken")]),n("OutboundLink")],1),e._v(": Token associated with renewability/TTL.")])])]),e._v(" "),n("p",[e._v("Authentication methods such as "),n("a",{attrs:{href:"https://docs.spring.io/spring-vault/docs/2.3.1/api/org/springframework/vault/authentication/TokenAuthentication.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("TokenAuthentication")]),n("OutboundLink")],1),e._v(" just create a "),n("code",[e._v("VaultToken")]),e._v(" which does not carry any renewability/TTL details. "),n("code",[e._v("LifecycleAwareSessionManager")]),e._v(" will run a self-lookup on the token to retrieve renewability and TTL from Vault."),n("code",[e._v("VaultToken")]),e._v(" are renewed periodically if self-lookup is enabled. Note that "),n("code",[e._v("VaultToken")]),e._v(" are never revoked, only "),n("code",[e._v("LoginToken")]),e._v(" are revoked.")]),e._v(" "),n("p",[e._v("Authentication methods creating "),n("code",[e._v("LoginToken")]),e._v(" directly (all login-based authentication methods) already provide all necessary details to setup token renewal. Tokens obtained from a login are revoked by "),n("code",[e._v("LifecycleAwareSessionManager")]),e._v(" if the session manager is shut down.")]),e._v(" "),n("h2",{attrs:{id:"_16-miscellaneous"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_16-miscellaneous"}},[e._v("#")]),e._v(" 16. Miscellaneous")]),e._v(" "),n("p",[e._v("Learn in this chapter about details worth mentioning like the Spring Security integration.")]),e._v(" "),n("h3",{attrs:{id:"_16-1-spring-security"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_16-1-spring-security"}},[e._v("#")]),e._v(" 16.1. Spring Security")]),e._v(" "),n("p",[e._v("Spring Vault integrates with Spring Security by providing implementations for "),n("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#spring-security-crypto-keygenerators",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("BytesKeyGenerator")]),n("OutboundLink")],1),e._v(" and "),n("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#spring-security-crypto-encryption",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("BytesEncryptor")]),n("OutboundLink")],1),e._v(". Both implementations use Vault’s "),n("code",[e._v("transit")]),e._v(" backend.")]),e._v(" "),n("p",[e._v("Example 35. "),n("code",[e._v("VaultBytesKeyGenerator")]),e._v(" example")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("VaultOperations operations = …;\nVaultBytesKeyGenerator generator = new VaultBytesKeyGenerator(operations);\n\nbyte[] key = generator.generateKey();\n")])])]),n("p",[e._v("Example 36. "),n("code",[e._v("VaultBytesEncryptor")]),e._v(" example")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('VaultTransitOperations transit = …;\n\nVaultBytesEncryptor encryptor = new VaultBytesEncryptor(transit, "my-key-name");\n\nbyte[] ciphertext = encryptor.encrypt(plaintext);\n\nbyte[] result = encryptor.decrypt(ciphertext);\n')])])]),n("p",[e._v("Vault encapsulates an entropy source that is decoupled from your JVM along with server-side key-management. This relieves the burden of proper encryption/decryption from application developers and pushes the burden onto the operators of Vault. Operators of Vault commonly include the security team at an organization, which means they can ensure that data is encrypted/decrypted properly. Additionally, since encrypt/decrypt operations must enter the audit log, any decryption event is recorded.")]),e._v(" "),n("p",[e._v("The backend also supports key rotation, which allows a new version of the named key to be generated. All data encrypted with the key will use the newest version of the key; previously encrypted data can be decrypted using old versions of the key. Administrators can control which previous versions of a key are available for decryption, to prevent an attacker gaining an old copy of ciphertext to be able to successfully decrypt it.")]),e._v(" "),n("p",[e._v("Vault is after all a networked service that incurs each operation with a latency. Components heavily using encryption or random bytes generation may experience a difference in throughput and performance.")])])}),[],!1,null,null,null);t.default=o.exports}}]);