Initial import.
This commit is contained in:
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.classpath
|
||||
.idea
|
||||
.project
|
||||
.settings
|
||||
.checkstyle
|
||||
bin
|
||||
build
|
||||
out
|
||||
target
|
||||
/vault/
|
||||
/download/
|
||||
/work/
|
||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
1
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
1
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
|
||||
20
.travis.yml
Normal file
20
.travis.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
language: java
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
install:
|
||||
- mkdir -p download
|
||||
- src/test/bash/create_certificates.sh
|
||||
- src/test/bash/install_vault.sh
|
||||
- src/test/bash/local_run_vault.sh &
|
||||
|
||||
script: mvn clean verify
|
||||
|
||||
after_script:
|
||||
- pkill vault
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- 'download'
|
||||
27
CODE_OF_CONDUCT.adoc
Normal file
27
CODE_OF_CONDUCT.adoc
Normal file
@@ -0,0 +1,27 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
|
||||
202
LICENSE.txt
Normal file
202
LICENSE.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
219
README.adoc
Normal file
219
README.adoc
Normal file
@@ -0,0 +1,219 @@
|
||||
|
||||
Spring Vault provides client-side support for accessing, storing and revoking secrets.
|
||||
With https://www.vaultproject.io[Hashicorp's Vault] you have a central place to manage external secret data for applications across all environments.
|
||||
Vault can manage static and dynamic secrets such as application data, username/password for remote applications/resources and provide credentials for external services such as MySQL, PostgreSQL, Apache Cassandra, Consul, AWS and more.
|
||||
|
||||
== Features
|
||||
|
||||
=== Spring Vault
|
||||
|
||||
Specifically for Spring applications:
|
||||
|
||||
* JavaConfig for Vault Client
|
||||
* https://www.vaultproject.io/docs/auth/token.html[Token], https://www.vaultproject.io/docs/auth/app-id.html[AppId] authentication,
|
||||
and https://www.vaultproject.io/docs/auth/aws-ec2.html[AWS-EC2] authentication
|
||||
|
||||
== Quick Start
|
||||
|
||||
*Prerequisites*
|
||||
|
||||
To get started with Vault and this guide you need a
|
||||
*NIX-like operating systems that provides:
|
||||
|
||||
* `wget`, `openssl` and `unzip`
|
||||
* at least Java 6 and a properly configured `JAVA_HOME` environment variable
|
||||
|
||||
*Install Vault*
|
||||
|
||||
----
|
||||
$ src/test/bash/install_vault.sh
|
||||
----
|
||||
|
||||
*Create SSL certificates for Vault*
|
||||
|
||||
----
|
||||
$ src/test/bash/create_certificates.sh
|
||||
----
|
||||
|
||||
NOTE: `create_certificates.sh` creates certificates in `work/ca` and a JKS truststore `work/keystore.jsk`. If you want to run Spring Vault using this quickstart guide you need to configure the truststore to `file:work/keystore.jks`.
|
||||
|
||||
*Start Vault server*
|
||||
|
||||
----
|
||||
$ src/test/bash/local_run_vault.sh
|
||||
----
|
||||
|
||||
Vault is started listening on `0.0.0.0:8200` using the `inmem` storage and
|
||||
`https`.
|
||||
Vault is sealed and not initialized when starting up
|
||||
so you need to initialize it first.
|
||||
|
||||
----
|
||||
$ export VAULT_ADDR="https://localhost:8200"
|
||||
$ export VAULT_SKIP_VERIFY=true # Don't do this for production
|
||||
$ vault init
|
||||
----
|
||||
|
||||
You should see something like:
|
||||
|
||||
----
|
||||
Key 1: 7149c6a2e16b8833f6eb1e76df03e47f6113a3288b3093faf5033d44f0e70fe701
|
||||
Key 2: 901c534c7988c18c20435a85213c683bdcf0efcd82e38e2893779f152978c18c02
|
||||
Key 3: 03ff3948575b1165a20c20ee7c3e6edf04f4cdbe0e82dbff5be49c63f98bc03a03
|
||||
Key 4: 216ae5cc3ddaf93ceb8e1d15bb9fc3176653f5b738f5f3d1ee00cd7dccbe926e04
|
||||
Key 5: b2898fc8130929d569c1677ee69dc5f3be57d7c4b494a6062693ce0b1c4d93d805
|
||||
Initial Root Token: 19aefa97-cccc-bbbb-aaaa-225940e63d76
|
||||
|
||||
Vault initialized with 5 keys and a key threshold of 3. Please
|
||||
securely distribute the above keys. When the Vault is re-sealed,
|
||||
restarted, or stopped, you must provide at least 3 of these keys
|
||||
to unseal it again.
|
||||
|
||||
Vault does not store the master key. Without at least 3 keys,
|
||||
your Vault will remain permanently sealed.
|
||||
----
|
||||
|
||||
Vault will initialize and return a set of unsealing keys and the root token.
|
||||
Pick 3 keys and unseal Vault.
|
||||
|
||||
----
|
||||
$ vault unseal (Key 1)
|
||||
$ vault unseal (Key 2)
|
||||
$ vault unseal (Key 3)
|
||||
----
|
||||
|
||||
Vault is now initialized and unsealed.
|
||||
|
||||
== Building
|
||||
|
||||
==== Build requirements for Vault
|
||||
|
||||
Spring Vault requires SSL certificates and a running
|
||||
Vault instance listening on `localhost:8200`. Certificates and the Vault
|
||||
setup are scripted, the scripts are located in `src/test/bash`.
|
||||
|
||||
The following scripts need to be run prior to building the project for the tests to pass.
|
||||
|
||||
$ ./src/test/bash/install_vault.sh
|
||||
$ ./src/test/bash/create_certificates.sh
|
||||
$ ./src/test/bash/local_run_vault.sh
|
||||
|
||||
Changes to the documentation should be made to the adocs found under `src/main/asciidoc/`
|
||||
|
||||
=== Basic Compile and Test
|
||||
|
||||
To build the source you will need to install JDK 1.6.
|
||||
|
||||
Spring Vault uses Maven for most build-related activities, and you
|
||||
should be able to get off the ground quite quickly by cloning the
|
||||
project you are interested in and typing
|
||||
|
||||
----
|
||||
$ ./mvnw install
|
||||
----
|
||||
|
||||
NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command
|
||||
in place of `./mvnw` in the examples below. If you do that you also
|
||||
might need to add `-P spring` if your local Maven settings do not
|
||||
contain repository declarations for spring pre-release artifacts.
|
||||
|
||||
NOTE: Be aware that you might need to increase the amount of memory
|
||||
available to Maven by setting a `MAVEN_OPTS` environment variable with
|
||||
a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in
|
||||
the `.mvn` configuration, so if you find you have to do it to make a
|
||||
build succeed, please raise a ticket to get the settings added to
|
||||
source control.
|
||||
|
||||
For hints on how to build the project look in `.travis.yml` if there
|
||||
is one. There should be a "script" and maybe "install" command. Also
|
||||
look at the "services" section to see if any services need to be
|
||||
running locally (e.g. mongo or rabbit). Ignore the git-related bits
|
||||
that you might find in "before_install" since they're related to setting git
|
||||
credentials and you already have those.
|
||||
|
||||
NOTE: If all else fails, build with the command from `.travis.yml` (usually
|
||||
`./mvnw install`).
|
||||
|
||||
=== Documentation
|
||||
|
||||
The module has a "distribute" profile, and if you switch
|
||||
that on it will try to build asciidoc sources from
|
||||
`src/main/asciidoc`.
|
||||
|
||||
=== Working with the code
|
||||
If you don't have an IDE preference we would recommend that you use
|
||||
http://www.springsource.com/developer/sts[Spring Tools Suite] or
|
||||
http://eclipse.org[Eclipse] when working with the code. We use the
|
||||
http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools
|
||||
should also work without issue as long as they use Maven 3.3.3 or better.
|
||||
|
||||
==== Importing into eclipse with m2eclipse
|
||||
We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with
|
||||
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
|
||||
marketplace".
|
||||
|
||||
NOTE: Older versions of m2e do not support Maven 3.3, so once the
|
||||
projects are imported into Eclipse you will also need to tell
|
||||
m2eclipse to use the right profile for the projects. If you
|
||||
see many different errors related to the POMs in the projects, check
|
||||
that you have an up to date installation. If you can't upgrade m2e,
|
||||
add the "spring" profile to your `settings.xml`. Alternatively you can
|
||||
copy the repository settings from the "spring" profile of the parent
|
||||
pom into your `settings.xml`.
|
||||
|
||||
==== Importing into eclipse without m2eclipse
|
||||
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
|
||||
following command:
|
||||
|
||||
[indent=0]
|
||||
----
|
||||
$ ./mvnw eclipse:eclipse
|
||||
----
|
||||
|
||||
The generated eclipse projects can be imported by selecting `import existing projects`
|
||||
from the `file` menu.
|
||||
|
||||
== Contributing
|
||||
|
||||
Spring Vault is released under the non-restrictive Apache 2.0 license,
|
||||
and follows a very standard Github development process, using Github
|
||||
tracker for issues and merging pull requests into master. If you want
|
||||
to contribute even something trivial please do not hesitate, but
|
||||
follow the guidelines below.
|
||||
|
||||
=== Sign the Contributor License Agreement
|
||||
Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||
https://cla.pivotal.io/sign/spring[Contributor License Agreement].
|
||||
Signing the contributor's agreement does not grant anyone commit rights to the main
|
||||
repository, but it does mean that we can accept your contributions, and you will get an
|
||||
author credit if we do. Active contributors might be asked to join the core team, and
|
||||
given the ability to merge pull requests.
|
||||
|
||||
=== Code of Conduct
|
||||
This project adheres to the Contributor Covenant https://github.com/spring-framework/spring-vault/blob/master/CODE_OF_CONDUCT.adoc[code of
|
||||
conduct]. By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
=== Code Conventions and Housekeeping
|
||||
None of these is essential for a pull request, but they will all help. They can also be
|
||||
added after the original pull request but before a merge.
|
||||
|
||||
* Use the Spring Framework code format conventions. If you use Eclipse
|
||||
you can import formatter settings using the
|
||||
`eclipse-code-formatter.xml` file from the
|
||||
https://raw.githubusercontent.com/spring-framework/spring-vault/master/etc/ide/eclipse-code-formatter.xml[project]. If using IntelliJ, you can use the
|
||||
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
|
||||
Plugin] to import the same file.
|
||||
* Make sure all new `.java` files to have a Javadoc class comment with at least an
|
||||
`@author` tag identifying you, and preferably at least a paragraph on what the class is
|
||||
for.
|
||||
* Add the ASF license header comment to all new `.java` files (copy from existing files
|
||||
in the project)
|
||||
* Add yourself as an `@author` to the .java files that you modify substantially (more
|
||||
than cosmetic changes).
|
||||
* Please include unit tests.
|
||||
* If no-one else is using your branch, please rebase it against the current master (or
|
||||
other target branch in the main project).
|
||||
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
|
||||
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
|
||||
message (where XXXX is the issue number).
|
||||
291
etc/ide/eclipse-code-formatter.xml
Normal file
291
etc/ide/eclipse-code-formatter.xml
Normal file
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Data" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
233
mvnw
vendored
Executable file
233
mvnw
vendored
Executable file
@@ -0,0 +1,233 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
#
|
||||
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||
# for the new JDKs provided by Oracle.
|
||||
#
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||
#
|
||||
# Oracle JDKs
|
||||
#
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=`/usr/libexec/java_home`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
local basedir=$(pwd)
|
||||
local wdir=$(pwd)
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
wdir=$(cd "$wdir/.."; pwd)
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} "$@"
|
||||
145
mvnw.cmd
vendored
Normal file
145
mvnw.cmd
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
685
pom.xml
Normal file
685
pom.xml
Normal file
@@ -0,0 +1,685 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
|
||||
<name>Spring Vault</name>
|
||||
<description>Parent project for Spring Vault</description>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<url>http://projects.spring.io/spring-vault/</url>
|
||||
|
||||
<modules>
|
||||
<module>spring-vault-dependencies</module>
|
||||
<module>spring-vault-core</module>
|
||||
<module>spring-vault-distribution</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>4.3.2.RELEASE</spring.version>
|
||||
<java.version>1.6</java.version>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-vault</dist.id>
|
||||
<project.root>${basedir}</project.root>
|
||||
</properties>
|
||||
|
||||
<inceptionYear>2016</inceptionYear>
|
||||
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/spring-projects/spring-vault</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-vault.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-vault.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub</system>
|
||||
<url>https://github.com/spring-projects/spring-vault/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<ciManagement>
|
||||
<system>Bamboo</system>
|
||||
<url>https://build.springframework.org/bamboo/browse/SPRVAULT</url>
|
||||
</ciManagement>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>sgibb</id>
|
||||
<name>Spencer Gibb</name>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpaluch</id>
|
||||
<name>Mark Paluch</name>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<comments>
|
||||
Copyright 2016 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-dependencies</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<signature>
|
||||
<groupId>org.codehaus.mojo.signature</groupId>
|
||||
<artifactId>java16</artifactId>
|
||||
<version>1.0</version>
|
||||
</signature>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce-java-6</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<pluginManagement>
|
||||
<!--
|
||||
Default versioned declarations of managed plugins
|
||||
to be overridden when the distribute profile is active.
|
||||
If this section was missing, Maven would complain about
|
||||
missing version numbers for executions without the
|
||||
profile active.
|
||||
-->
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.4</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<dependencies>
|
||||
<dependency><!-- add support for ssh/scp -->
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-ssh</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||
<version>1.15</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<version>1.5.3</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<version>1.0</version>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>springNext</id>
|
||||
<properties>
|
||||
<spring.version>5.0.0.BUILD-SNAPSHOT</spring.version>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>bootstrap</id>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>repo.spring.io-milestone</id>
|
||||
<name>Spring Framework Milestone Repository</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repo.spring.io-release</id>
|
||||
<name>Spring Framework Release Repository</name>
|
||||
<url>http://repo.spring.io/libs-release-local</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repo.spring.io-snapshot</id>
|
||||
<name>Spring Framework Maven Snapshot Repository</name>
|
||||
<url>http://repo.spring.io/libs-snapshot-local</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>milestone</id>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>repo.spring.io</id>
|
||||
<name>Spring Milestone Repository</name>
|
||||
<url>http://repo.spring.io/libs-milestone-local</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>central</id>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-snapshots</id>
|
||||
<name>Sonatype Nexus Snapshots</name>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<name>Nexus Release Repository</name>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
|
||||
<!--
|
||||
Profile to be activated when building the distribution atrifacts.
|
||||
|
||||
Generates reference documentation, aggregates JavaDoc etc. Has to be combined with
|
||||
profiles "release" or "milestone" to deploy artifacts into the appropriate places.
|
||||
-->
|
||||
|
||||
<id>distribute</id>
|
||||
|
||||
<properties>
|
||||
<shared.resources>${project.build.directory}/shared-resources</shared.resources>
|
||||
<maven.install.skip>true</maven.install.skip>
|
||||
<skipTests>true</skipTests>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-build-resources</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!--
|
||||
Unpacks the content of spring-data-build-resources into the shared resources folder.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-shared-resources</id>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<phase>generate-resources</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<includeGroupIds>org.springframework.data</includeGroupIds>
|
||||
<includeArtifactIds>spring-data-build-resources</includeArtifactIds>
|
||||
<includeTypes>zip</includeTypes>
|
||||
<excludeTransitive>true</excludeTransitive>
|
||||
<outputDirectory>${shared.resources}</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Configures JavaDoc generation.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>aggregate-javadoc</id>
|
||||
<goals>
|
||||
<goal>aggregate</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Copies all namespaces schemas to target/schemas flatten the directory structure.
|
||||
Depended on by the site.xml assembly descriptor.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
|
||||
<execution>
|
||||
<id>copy-documentation-resources</id>
|
||||
<phase>generate-resources</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<copy todir="${project.root}/target/site/reference/html">
|
||||
<fileset dir="${shared.resources}/asciidoc" erroronmissingdir="false">
|
||||
<include name="**/*.css"/>
|
||||
</fileset>
|
||||
<flattenmapper/>
|
||||
</copy>
|
||||
<copy todir="${project.root}/target/site/reference/html/images">
|
||||
<fileset dir="${basedir}/src/main/asciidoc" erroronmissingdir="false">
|
||||
<include name="**/*.png"/>
|
||||
<include name="**/*.gif"/>
|
||||
<include name="**/*.jpg"/>
|
||||
</fileset>
|
||||
<flattenmapper/>
|
||||
</copy>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>collect-schema-files</id>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<copy todir="${project.build.directory}/schemas">
|
||||
<fileset dir="${basedir}" erroronmissingdir="false">
|
||||
<include name="**/src/main/resources/**/config/spring-*.xsd"/>
|
||||
</fileset>
|
||||
<flattenmapper/>
|
||||
</copy>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>rename-reference-docs</id>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<copy failonerror="false"
|
||||
file="${project.build.directory}/generated-docs/index.pdf"
|
||||
tofile="${project.root}/target/site/reference/pdf/${dist.id}-reference.pdf"/>
|
||||
<copy failonerror="false"
|
||||
file="${project.build.directory}/generated-docs/index.epub"
|
||||
tofile="${project.root}/target/site/reference/epub/${dist.id}-reference.epub"/>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
</executions>
|
||||
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
|
||||
<!--
|
||||
JavaDoc
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<breakiterator>true</breakiterator>
|
||||
<header>${project.name}</header>
|
||||
<source>${java.version}</source>
|
||||
<quiet>true</quiet>
|
||||
<javadocDirectory>${shared.resources}/javadoc</javadocDirectory>
|
||||
<overview>${shared.resources}/javadoc/overview.html</overview>
|
||||
<stylesheetfile>${shared.resources}/javadoc/spring-javadoc.css</stylesheetfile>
|
||||
<!-- copies doc-files subdirectory which contains image resources -->
|
||||
<docfilessubdirs>true</docfilessubdirs>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
<links>
|
||||
<link>http://docs.spring.io/spring/docs/4.2.x/javadoc-api/</link>
|
||||
<link>http://docs.spring.io/spring-data/commons/docs/current/api/</link>
|
||||
<link>http://docs.oracle.com/javase/6/docs/api</link>
|
||||
</links>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Asciidoctor
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctorj-pdf</artifactId>
|
||||
<version>1.5.0-alpha.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctorj-epub3</artifactId>
|
||||
<version>1.5.0-alpha.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
|
||||
<execution>
|
||||
<id>html</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>process-asciidoc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<backend>html5</backend>
|
||||
<outputDirectory>${project.root}/target/site/reference/html</outputDirectory>
|
||||
<sectids>false</sectids>
|
||||
<sourceHighlighter>prettify</sourceHighlighter>
|
||||
<attributes>
|
||||
<linkcss>true</linkcss>
|
||||
<icons>font</icons>
|
||||
<sectanchors>true</sectanchors>
|
||||
<stylesheet>spring.css</stylesheet>
|
||||
</attributes>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>epub</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>process-asciidoc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<backend>epub3</backend>
|
||||
<sourceHighlighter>coderay</sourceHighlighter>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>pdf</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>process-asciidoc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<backend>pdf</backend>
|
||||
<sourceHighlighter>coderay</sourceHighlighter>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
</executions>
|
||||
|
||||
<configuration>
|
||||
<sourceDirectory>${project.root}/src/main/asciidoc</sourceDirectory>
|
||||
<sourceDocumentName>index.adoc</sourceDocumentName>
|
||||
<doctype>book</doctype>
|
||||
<attributes>
|
||||
<version>${project.version}</version>
|
||||
<projectName>${project.name}</projectName>
|
||||
<projectVersion>${project.version}</projectVersion>
|
||||
<springVersion>${spring.version}</springVersion>
|
||||
<allow-uri-read>true</allow-uri-read>
|
||||
<toclevels>3</toclevels>
|
||||
<numbered>true</numbered>
|
||||
</attributes>
|
||||
</configuration>
|
||||
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Creates two zip files for download as well as API and reference documentation distribution.
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>static</id>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${shared.resources}/assemblies/static-resources.xml</descriptor>
|
||||
</descriptors>
|
||||
<finalName>static-resources</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<fromDir>${project.build.directory}</fromDir>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
||||
<!-- Distribute static resources -->
|
||||
|
||||
<execution>
|
||||
<id>upload-static-resources</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>upload</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fromDir>${project.build.directory}/static-resources</fromDir>
|
||||
<includes>**</includes>
|
||||
<serverId>static-dot-s2</serverId>
|
||||
<url>scp://static.springsource.org</url>
|
||||
<toDir>
|
||||
/var/www/domains/springsource.org/www/htdocs/autorepo/docs/${dist.id}/${project.version}
|
||||
</toDir>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
113
spring-vault-core/pom.xml
Normal file
113
spring-vault-core/pom.xml
Normal file
@@ -0,0 +1,113 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-vault-core</artifactId>
|
||||
<name>Spring Vault Core</name>
|
||||
<description>Spring Vault Core Components</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<url>http://projects.spring.io/spring-vault/</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.10</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* AppId implementation of {@link ClientAuthentication}. {@link AppIdAuthentication} uses a configured
|
||||
* {@link AppIdUserIdMechanism} to obtain or calculate a UserId. AppId and UserId are sent in the login request to Vault
|
||||
* to obtain a {@link VaultToken}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthenticationOptions
|
||||
* @see VaultClient
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/app-id.html">Auth Backend: App ID</a>
|
||||
*/
|
||||
public class AppIdAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AppIdAuthentication.class);
|
||||
|
||||
private final AppIdAuthenticationOptions options;
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a {@link AppIdAuthentication} using {@link AppIdAuthenticationOptions} and {@link VaultClient}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public AppIdAuthentication(AppIdAuthenticationOptions options, VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(options, "AppIdAuthenticationOptions must not be null");
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
|
||||
this.options = options;
|
||||
this.vaultClient = vaultClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() {
|
||||
return createTokenUsingAppId();
|
||||
}
|
||||
|
||||
private VaultToken createTokenUsingAppId() {
|
||||
|
||||
Map<String, String> login = getAppIdLogin(options.getAppId(), options.getUserIdMechanism().createUserId());
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient
|
||||
.postForEntity(String.format("auth/%s/login", options.getPath()), login, VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using app-id: %s", entity.getMessage()));
|
||||
}
|
||||
|
||||
VaultResponse body = entity.getBody();
|
||||
String token = (String) body.getAuth().get("client_token");
|
||||
|
||||
logger.debug("Login successful using AppId authentication");
|
||||
|
||||
return VaultToken.of(token, body.getLeaseDuration());
|
||||
}
|
||||
|
||||
private Map<String, String> getAppIdLogin(String appId, String userId) {
|
||||
|
||||
Map<String, String> login = new HashMap<String, String>();
|
||||
login.put("app_id", appId);
|
||||
login.put("user_id", userId);
|
||||
return login;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Authentication options for {@link AppIdAuthentication}. Authentication options provide the path, appId and a
|
||||
* {@link AppIdUserIdMechanism}. {@link AppIdAuthentication} can be constructed using {@link #builder()}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
* @see #builder()
|
||||
*/
|
||||
public class AppIdAuthenticationOptions {
|
||||
|
||||
public final static String DEFAULT_APPID_AUTHENTICATION_PATH = "app-id";
|
||||
|
||||
private final String path;
|
||||
|
||||
private final String appId;
|
||||
|
||||
private final AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
private AppIdAuthenticationOptions(String path, String appId, AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
this.path = path;
|
||||
this.appId = appId;
|
||||
this.userIdMechanism = userIdMechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public static AppIdAuthenticationOptionsBuilder builder() {
|
||||
return new AppIdAuthenticationOptionsBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mount path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the AppId.
|
||||
*/
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link AppIdUserIdMechanism}.
|
||||
*/
|
||||
public AppIdUserIdMechanism getUserIdMechanism() {
|
||||
return userIdMechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
public static class AppIdAuthenticationOptionsBuilder {
|
||||
|
||||
private String path = DEFAULT_APPID_AUTHENTICATION_PATH;
|
||||
private String appId;
|
||||
private AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
AppIdAuthenticationOptionsBuilder() {}
|
||||
|
||||
/**
|
||||
* Configures the mount path.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
* @see #DEFAULT_APPID_AUTHENTICATION_PATH
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder path(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the AppId.
|
||||
*
|
||||
* @param appId must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder appId(String appId) {
|
||||
|
||||
Assert.hasText(path, "AppId must not be empty");
|
||||
|
||||
this.appId = appId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link AppIdUserIdMechanism}.
|
||||
*
|
||||
* @param userIdMechanism must not be {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder userIdMechanism(AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
|
||||
|
||||
this.userIdMechanism = userIdMechanism;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new {@link AppIdAuthenticationOptions} instance. Requires {@link #userIdMechanism(AppIdUserIdMechanism)}
|
||||
* to be configured.
|
||||
*
|
||||
* @return a new {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
public AppIdAuthenticationOptions build() {
|
||||
|
||||
Assert.hasText(path, "AppId must not be empty");
|
||||
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
|
||||
|
||||
return new AppIdAuthenticationOptions(path, appId, userIdMechanism);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
/**
|
||||
* Interface to obtain a UserId for AppId authentication.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface AppIdUserIdMechanism {
|
||||
|
||||
/**
|
||||
* Creates a UserId for AppId authentication.
|
||||
*
|
||||
* @return the UserId.
|
||||
*/
|
||||
String createUserId();
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* AWS-EC2 login implementation. AWS-EC2 login uses the EC2 identity document and a nonce to login into Vault. AWS-EC2
|
||||
* login obtains the PKCS#7 signed EC2 identity document and generates a {@link #createNonce() nonce}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AwsEc2AuthenticationOptions
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/aws-ec2.html">Auth Backend: aws-ec2</a>
|
||||
*/
|
||||
public class AwsEc2Authentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AwsEc2Authentication.class);
|
||||
|
||||
private final AwsEc2AuthenticationOptions options;
|
||||
private final VaultClient vaultClient;
|
||||
private final RestTemplate restTemplate;
|
||||
private final AtomicReference<char[]> nonce = new AtomicReference<char[]>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link AwsEc2Authentication}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public AwsEc2Authentication(VaultClient vaultClient) {
|
||||
this(AwsEc2AuthenticationOptions.DEFAULT, vaultClient, vaultClient.getRestTemplate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AwsEc2Authentication} specifying {@link AwsEc2AuthenticationOptions}, {@link VaultClient} and
|
||||
* a {@link RestTemplate}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
*/
|
||||
public AwsEc2Authentication(AwsEc2AuthenticationOptions options, VaultClient vaultClient, RestTemplate restTemplate) {
|
||||
|
||||
Assert.notNull(options, "AwsEc2AuthenticationOptions must not be null");
|
||||
Assert.notNull(vaultClient, "VaultEndpoint must not be null");
|
||||
Assert.notNull(restTemplate, "RestTemplate must not be null");
|
||||
|
||||
this.options = options;
|
||||
this.vaultClient = vaultClient;
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() throws VaultException {
|
||||
return createTokenUsingAwsEc2();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private VaultToken createTokenUsingAwsEc2() {
|
||||
|
||||
String path = String.format("auth/%s/login", options.getPath());
|
||||
|
||||
Map<String, String> login = getEc2Login();
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = this.vaultClient.postForEntity(path, login, VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using AWS-EC2: %s", entity.getMessage()));
|
||||
}
|
||||
|
||||
VaultResponse body = entity.getBody();
|
||||
String token = (String) body.getAuth().get("client_token");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
if (body.getAuth().get("metadata") instanceof Map) {
|
||||
Map<Object, Object> metadata = (Map<Object, Object>) body.getAuth().get("metadata");
|
||||
logger.debug(String.format("Login successful using AWS-EC2 authentication for instance %s, AMI %s",
|
||||
metadata.get("instance_id"), metadata.get("instance_id")));
|
||||
} else {
|
||||
logger.debug("Login successful using AWS-EC2 authentication");
|
||||
}
|
||||
}
|
||||
|
||||
return VaultToken.of(token, body.getLeaseDuration());
|
||||
}
|
||||
|
||||
protected Map<String, String> getEc2Login() {
|
||||
|
||||
Map<String, String> login = new HashMap<String, String>();
|
||||
|
||||
if (StringUtils.hasText(options.getRole())) {
|
||||
login.put("role", options.getRole());
|
||||
}
|
||||
|
||||
if (this.nonce.get() == null) {
|
||||
this.nonce.compareAndSet(null, createNonce());
|
||||
}
|
||||
|
||||
login.put("nonce", new String(this.nonce.get()));
|
||||
|
||||
try {
|
||||
String pkcs7 = restTemplate.getForObject(options.getIdentityDocumentUri(), String.class);
|
||||
if (StringUtils.hasText(pkcs7)) {
|
||||
login.put("pkcs7", pkcs7.replaceAll("\\r", "").replace("\\n", ""));
|
||||
}
|
||||
|
||||
return login;
|
||||
} catch (RestClientException e) {
|
||||
throw new VaultException(
|
||||
String.format("Cannot obtain Identity Document from %s", options.getIdentityDocumentUri()), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected char[] createNonce() {
|
||||
return UUID.randomUUID().toString().toCharArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Authentication options for {@link AwsEc2Authentication}. Authentication options provide the path, the Identity
|
||||
* Document URI and an optional role. {@link AwsEc2AuthenticationOptions} can be constructed using {@link #builder()}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AwsEc2Authentication
|
||||
* @see #builder()
|
||||
*/
|
||||
public class AwsEc2AuthenticationOptions {
|
||||
|
||||
public final static URI DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI = URI
|
||||
.create("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7");
|
||||
|
||||
public final static String DEFAULT_AWS_AUTHENTICATION_PATH = "aws-ec2";
|
||||
|
||||
/**
|
||||
* Default {@link AwsEc2AuthenticationOptions} using {@link #DEFAULT_AWS_AUTHENTICATION_PATH} and
|
||||
* {@link #DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI}.
|
||||
*/
|
||||
public final static AwsEc2AuthenticationOptions DEFAULT = new AwsEc2AuthenticationOptions();
|
||||
|
||||
private final String path;
|
||||
|
||||
private final URI identityDocumentUri;
|
||||
|
||||
private final String role;
|
||||
|
||||
private AwsEc2AuthenticationOptions() {
|
||||
this(DEFAULT_AWS_AUTHENTICATION_PATH, DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI, "");
|
||||
}
|
||||
|
||||
private AwsEc2AuthenticationOptions(String path, URI identityDocumentUri, String role) {
|
||||
|
||||
this.path = path;
|
||||
this.identityDocumentUri = identityDocumentUri;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public static AwsEc2AuthenticationOptionsBuilder builder() {
|
||||
return new AwsEc2AuthenticationOptionsBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mount path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link URI} to the Identity Document.
|
||||
*/
|
||||
public URI getIdentityDocumentUri() {
|
||||
return identityDocumentUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the role, may be {@literal null}.
|
||||
*/
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public static class AwsEc2AuthenticationOptionsBuilder {
|
||||
|
||||
private String path = DEFAULT_AWS_AUTHENTICATION_PATH;
|
||||
private URI identityDocumentUri = DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI;
|
||||
private String role;
|
||||
|
||||
AwsEc2AuthenticationOptionsBuilder() {}
|
||||
|
||||
/**
|
||||
* Configures the mount path.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AwsEc2AuthenticationOptionsBuilder path(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Identity Document {@link URI}.
|
||||
*
|
||||
* @param identityDocumentUri must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
* @see #DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI
|
||||
*/
|
||||
public AwsEc2AuthenticationOptionsBuilder identityDocumentUri(URI identityDocumentUri) {
|
||||
this.identityDocumentUri = identityDocumentUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the name of the role against which the login is being attempted.If role is not specified, then the
|
||||
* login endpoint looks for a role bearing the name of the AMI ID of the EC2 instance that is trying to login.
|
||||
*
|
||||
* @param role may be empty or {@literal null}.
|
||||
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AwsEc2AuthenticationOptionsBuilder role(String role) {
|
||||
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new {@link AwsEc2AuthenticationOptions} instance.
|
||||
*
|
||||
* @return a new {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
public AwsEc2AuthenticationOptions build() {
|
||||
|
||||
Assert.hasText(path, "AppId must not be empty");
|
||||
Assert.notNull(identityDocumentUri, "IdentityDocumentUri must not be null");
|
||||
|
||||
return new AwsEc2AuthenticationOptions(path, identityDocumentUri, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* {@link ClientAuthentication} provides {@link VaultToken} to be used for authenticated Vault access. Implementing
|
||||
* classes usually use a login method to login and return a {@link VaultToken} when implementing {@link #login()}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ClientAuthentication {
|
||||
|
||||
/**
|
||||
* Return a {@link VaultToken}. This method can optionally log into Vault to obtain a {@link VaultToken token}.
|
||||
*
|
||||
* @return a {@link VaultToken}.
|
||||
*/
|
||||
public VaultToken login() throws VaultException;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* TLS Client Certificate {@link ClientAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientCertificateAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ClientCertificateAuthentication.class);
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientCertificateAuthentication} using {@link VaultClient}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public ClientCertificateAuthentication(VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
|
||||
this.vaultClient = vaultClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() {
|
||||
return createTokenUsingTlsCertAuthentication("cert");
|
||||
}
|
||||
|
||||
private VaultToken createTokenUsingTlsCertAuthentication(String path) {
|
||||
|
||||
VaultResponseEntity<VaultResponse> response = vaultClient.postForEntity(String.format("auth/%s/login", path),
|
||||
Collections.emptyMap(), VaultResponse.class);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using TLS certificates: %s", response.getMessage()));
|
||||
}
|
||||
|
||||
VaultResponse body = response.getBody();
|
||||
String token = (String) body.getAuth().get("client_token");
|
||||
|
||||
logger.debug("Login successful using TLS certificates");
|
||||
|
||||
return VaultToken.of(token, body.getLeaseDuration());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link SessionManager}.
|
||||
* <p>
|
||||
* Uses a synchronized login method to log into Vault and reuse the resulting {@link VaultToken} throughout session
|
||||
* lifetime.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see ClientAuthentication
|
||||
* @see VaultToken
|
||||
*/
|
||||
public class DefaultSessionManager implements SessionManager {
|
||||
|
||||
private final ClientAuthentication clientAuthentication;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
private volatile VaultToken token;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultSessionManager} using a {@link ClientAuthentication}.
|
||||
*
|
||||
* @param clientAuthentication must not be {@literal null}.
|
||||
*/
|
||||
public DefaultSessionManager(ClientAuthentication clientAuthentication) {
|
||||
this.clientAuthentication = clientAuthentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken getSessionToken() {
|
||||
|
||||
if (token == null) {
|
||||
synchronized (lock) {
|
||||
if (token == null) {
|
||||
token = clientAuthentication.login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a SHA-256 hashed and hex-encoded representation of the IP address. Can be calculated with
|
||||
* {@code echo -n 192.168.99.1 | sha256sum}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class IpAddressUserId implements AppIdUserIdMechanism {
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
try {
|
||||
return Sha256.toSha256(InetAddress.getLocalHost().getHostAddress());
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a UserId based on the Mac address. {@link MacAddressUserId} creates a hex-encoded
|
||||
* representation of the Mac address without any separators (0123456789AB). A network interface hint can be specified
|
||||
* optionally to select a network interface (index/name).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class MacAddressUserId implements AppIdUserIdMechanism {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(MacAddressUserId.class);
|
||||
|
||||
private final String networkInterfaceHint;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MacAddressUserId} using the {@link NetworkInterface} from the
|
||||
* {@link InetAddress#getLocalHost()}.
|
||||
*/
|
||||
public MacAddressUserId() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceIndex}. The index is applied to
|
||||
* {@link NetworkInterface#getNetworkInterfaces()} to obtain the desired network interface.
|
||||
*
|
||||
* @param networkInterfaceIndex must be greater or equal to zero.
|
||||
*/
|
||||
public MacAddressUserId(int networkInterfaceIndex) {
|
||||
|
||||
Assert.isTrue(networkInterfaceIndex >= 0, "NetworkInterfaceIndex must be greater or equal to 0");
|
||||
|
||||
this.networkInterfaceHint = "" + networkInterfaceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceName}. This name is compared with
|
||||
* {@link NetworkInterface#getName()} and {@link NetworkInterface#getDisplayName()} to obtain the desired network
|
||||
* interface.
|
||||
*
|
||||
* @param networkInterfaceName must not be {@literal null}.
|
||||
*/
|
||||
public MacAddressUserId(String networkInterfaceName) {
|
||||
|
||||
Assert.notNull(networkInterfaceName, "NetworkInterfaceName must not be null");
|
||||
|
||||
this.networkInterfaceHint = networkInterfaceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
|
||||
try {
|
||||
|
||||
NetworkInterface networkInterface = null;
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
if (StringUtils.hasText(networkInterfaceHint)) {
|
||||
|
||||
try {
|
||||
networkInterface = getNetworkInterface(Integer.parseInt(networkInterfaceHint), interfaces);
|
||||
} catch (NumberFormatException e) {
|
||||
networkInterface = getNetworkInterface((networkInterfaceHint), interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
if (networkInterface == null) {
|
||||
|
||||
if (StringUtils.hasText(networkInterfaceHint)) {
|
||||
log.warn(String.format("Did not find a NetworkInterface applying hint %s", networkInterfaceHint));
|
||||
}
|
||||
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
networkInterface = NetworkInterface.getByInetAddress(localHost);
|
||||
|
||||
if (networkInterface == null) {
|
||||
throw new IllegalStateException(String.format("Cannot determine NetworkInterface for %s", localHost));
|
||||
}
|
||||
}
|
||||
|
||||
byte[] mac = networkInterface.getHardwareAddress();
|
||||
if (mac == null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Network interface %s has no hardware address", networkInterface.getName()));
|
||||
}
|
||||
|
||||
return Sha256.toSha256(Sha256.toHexString(mac));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkInterface getNetworkInterface(Number hint, List<NetworkInterface> interfaces) {
|
||||
|
||||
if (interfaces.size() > hint.intValue() && hint.intValue() >= 0) {
|
||||
return interfaces.get(hint.intValue());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private NetworkInterface getNetworkInterface(String hint, List<NetworkInterface> interfaces) {
|
||||
|
||||
for (NetworkInterface anInterface : interfaces) {
|
||||
if (hint.equals(anInterface.getDisplayName()) || hint.equals(anInterface.getName())) {
|
||||
return anInterface;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Strategy interface that encapsulates the creation and management of Vault sessions based on {@link VaultToken}.
|
||||
* <p>
|
||||
* {@link SessionManager} is used by {@link org.springframework.vault.core.VaultTemplate} to initiate a session.
|
||||
* Implementing classes usually use {@link ClientAuthentication} to log into Vault and obtain tokens.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see DefaultSessionManager
|
||||
* @see ClientAuthentication
|
||||
*/
|
||||
public interface SessionManager {
|
||||
|
||||
/**
|
||||
* Obtain a session token.
|
||||
*
|
||||
* @return a session token.
|
||||
*/
|
||||
VaultToken getSessionToken();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility to generate a SHA 256 checksum.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class Sha256 {
|
||||
|
||||
private static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||
|
||||
/**
|
||||
* Generates a hex-encoded SHA256 checksum from the supplied {@code content}.
|
||||
*
|
||||
* @param content must not be {@literal null} and not empty.
|
||||
* @return hex-encoded SHA256 checksum
|
||||
*/
|
||||
public static String toSha256(String content) {
|
||||
|
||||
Assert.hasText(content, "Content must not be empty");
|
||||
|
||||
MessageDigest messageDigest = getMessageDigest("SHA-256");
|
||||
byte[] digest = messageDigest.digest(content.getBytes(US_ASCII));
|
||||
return toHexString(digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MessageDigest instance for the given algorithm. Throws an IllegalArgumentException if <i>algorithm</i> is
|
||||
* unknown
|
||||
*
|
||||
* @return MessageDigest instance
|
||||
* @throws IllegalArgumentException if NoSuchAlgorithmException is thrown
|
||||
*/
|
||||
private static MessageDigest getMessageDigest(String algorithm) throws IllegalArgumentException {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("No such algorithm [" + algorithm + "]");
|
||||
}
|
||||
}
|
||||
|
||||
static String toHexString(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
sb.append(String.format("%X", bytes[i]));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A static UserId.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class StaticUserId implements AppIdUserIdMechanism {
|
||||
|
||||
private final String userId;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StaticUserId} for a given {@code userId}.
|
||||
*
|
||||
* @param userId must not be empty or {@literal null}.
|
||||
*/
|
||||
public StaticUserId(String userId) {
|
||||
|
||||
Assert.hasText(userId, "UserId must not be empty");
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Static Token-based {@link ClientAuthentication} method.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultToken
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">Auth Backend: Token</a>
|
||||
*/
|
||||
public class TokenAuthentication implements ClientAuthentication {
|
||||
|
||||
private final VaultToken token;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TokenAuthentication} with a static {@code token}.
|
||||
*
|
||||
* @param token the Vault token, must not be empty or {@literal null}.
|
||||
*/
|
||||
public TokenAuthentication(String token) {
|
||||
|
||||
Assert.hasText(token, "Token must not be empty");
|
||||
this.token = VaultToken.of(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TokenAuthentication} with a static {@code token}.
|
||||
*
|
||||
* @param token the Vault token, must not be {@literal null}.
|
||||
*/
|
||||
public TokenAuthentication(VaultToken token) {
|
||||
|
||||
Assert.notNull(token, "Token must not be null");
|
||||
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Support for authentication and session management.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for Vault accessing helpers, defining common properties such as the {@link RestTemplate} to operate on.
|
||||
* <p>
|
||||
* Not intended to be used directly. See {@link VaultClient}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public abstract class VaultAccessor {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* Create a {@link VaultAccessor} with a {@link RestTemplate}.
|
||||
*
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
*/
|
||||
protected VaultAccessor(RestTemplate restTemplate) {
|
||||
|
||||
Assert.notNull(restTemplate, "RestTemplate must not be null");
|
||||
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a {@link RestTemplateCallback} in the scope of the {@link RestTemplate}.
|
||||
*
|
||||
* @param uri must not be {@literal null}.
|
||||
* @param callback must not be {@literal null}.
|
||||
* @param <T> return type
|
||||
* @return the {@link RestTemplateCallback} return value.
|
||||
*/
|
||||
protected <T> T doWithRestTemplate(URI uri, RestTemplateCallback<T> callback) {
|
||||
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
Assert.notNull(callback, "RestTemplateCallback must not be null");
|
||||
|
||||
return callback.doWithRestTemplate(uri, getRestTemplate());
|
||||
}
|
||||
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri, HttpMethod httpMethod, HttpEntity<?> httpEntity,
|
||||
Class<T> returnType) {
|
||||
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
Assert.notNull(httpMethod, "HttpMethod must not be null");
|
||||
Assert.notNull(returnType, "Return type must not be null");
|
||||
|
||||
try {
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod, httpEntity, returnType);
|
||||
|
||||
return new VaultResponseEntity<S>((S) response.getBody(), response.getStatusCode(), uri,
|
||||
response.getStatusCode().getReasonPhrase());
|
||||
} catch (HttpStatusCodeException e) {
|
||||
return handleCodeException(uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri, HttpMethod httpMethod, HttpEntity<?> httpEntity,
|
||||
ParameterizedTypeReference<T> returnType) {
|
||||
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
Assert.notNull(httpMethod, "HttpMethod must not be null");
|
||||
Assert.notNull(returnType, "Return type must not be null");
|
||||
|
||||
try {
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod, httpEntity, returnType);
|
||||
|
||||
return new VaultResponseEntity<S>((S) response.getBody(), response.getStatusCode(), uri,
|
||||
response.getStatusCode().getReasonPhrase());
|
||||
} catch (HttpStatusCodeException e) {
|
||||
return handleCodeException(uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> VaultResponseEntity<T> handleCodeException(URI uri, HttpStatusCodeException e) {
|
||||
|
||||
String message = e.getResponseBodyAsString();
|
||||
|
||||
if (MediaType.APPLICATION_JSON.includes(e.getResponseHeaders().getContentType())) {
|
||||
message = VaultErrorMessage.getError(message);
|
||||
}
|
||||
|
||||
return new VaultResponseEntity<T>(null, e.getStatusCode(), uri, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the underlying {@link RestTemplate}.
|
||||
*/
|
||||
public RestTemplate getRestTemplate() {
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback for executing arbitrary operations on the {@link RestTemplate}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface RestTemplateCallback<T> {
|
||||
|
||||
/**
|
||||
* @param uri must not be {@literal null}.
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
* @return a result object or null if none.
|
||||
*/
|
||||
T doWithRestTemplate(URI uri, RestTemplate restTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Implementation of the low-level Vault client. This client uses the Vault HTTP API to issue requests using different
|
||||
* {@link HttpMethod HTTP methods}. {@link VaultClient} is configured with an {@link VaultEndpoint} and
|
||||
* {@link RestTemplate}. It does not maintain any session or token state. See {@link VaultTemplate} and
|
||||
* {@link org.springframework.vault.authentication.SessionManager} for authenticated and stateful Vault access.
|
||||
* <p>
|
||||
* {@link VaultClient} encapsulates base URI and path construction and uses {@link VaultAccessor} for request and error
|
||||
* handling by returning {@link VaultResponseEntity} for requests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultResponseEntity
|
||||
* @see VaultTemplate
|
||||
*/
|
||||
public class VaultClient extends VaultAccessor {
|
||||
|
||||
public static final String VAULT_TOKEN = "X-Vault-Token";
|
||||
|
||||
private final VaultEndpoint endpoint;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultClient} with a default a {@link RestTemplate} and {@link VaultEndpoint}.
|
||||
*
|
||||
* @see VaultEndpoint
|
||||
*/
|
||||
public VaultClient() {
|
||||
this(new RestTemplate(), new VaultEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultClient} for a {@link RestTemplate} and {@link VaultEndpoint}.
|
||||
*
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
* @param endpoint must not be {@literal null}.
|
||||
*/
|
||||
public VaultClient(RestTemplate restTemplate, VaultEndpoint endpoint) {
|
||||
|
||||
super(restTemplate);
|
||||
|
||||
Assert.notNull(endpoint, "VaultEndpoint must not be null");
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, VaultToken vaultToken,
|
||||
Class<T> responseType) {
|
||||
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null, createHeaders(vaultToken)), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be POSTed, may be {@code null}.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
* @param request the Object to be POSTed, may be {@code null}.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, VaultToken vaultToken, Object request,
|
||||
Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be PUT.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
* @param request the Object to be PUT.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, VaultToken vaultToken, Object request,
|
||||
Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a resource by DELETEing from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, VaultToken vaultToken,
|
||||
Class<T> responseType) {
|
||||
|
||||
return exchange(path, HttpMethod.DELETE, new HttpEntity<Object>(null, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns the
|
||||
* response as {@link VaultResponseEntity}.
|
||||
* <p>
|
||||
* URI Template variables are using the given URI variables, if any.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return exchange(uri, method, requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given path template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}. The given {@link ParameterizedTypeReference} is used to pass generic
|
||||
* type information:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
* ResponseEntity<List<MyBean>> response = client.exchange("http://example.com", HttpMethod.GET, null, myBean, null);
|
||||
* </pre>
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables)
|
||||
throws RestClientException {
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return exchange(uri, method, requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a {@link RestTemplateCallback}. Allows to interact with the underlying {@link RestTemplate} and benefit
|
||||
* from optional parameter expansion.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @param callback the request.
|
||||
* @return the {@link RestTemplateCallback} return value.
|
||||
*/
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables, RestTemplateCallback<T> callback) {
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return super.doWithRestTemplate(uri, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configured {@link VaultEndpoint}.
|
||||
*/
|
||||
public VaultEndpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Vault {@link URI} based on the given {@link VaultEndpoint} and {@code pathTemplate}. URI template
|
||||
* variables will be expanded using {@code uriVariables}.
|
||||
*
|
||||
* @param pathTemplate must not be empty or {@literal null}.
|
||||
* @param uriVariables must not be {@literal null}.
|
||||
* @see org.springframework.web.util.UriComponentsBuilder
|
||||
* @return
|
||||
*/
|
||||
protected URI buildUri(String pathTemplate, Map<String, ?> uriVariables) {
|
||||
|
||||
Assert.hasText(pathTemplate, "Path must not be empty");
|
||||
|
||||
return getRestTemplate().getUriTemplateHandler().expand(getEndpoint().createUriString(pathTemplate), uriVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create {@link HttpHeaders} for a {@link VaultToken}.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
* @return {@link HttpHeaders} for a {@link VaultToken}.
|
||||
*/
|
||||
public static HttpHeaders createHeaders(VaultToken vaultToken) {
|
||||
|
||||
Assert.notNull(vaultToken, "Vault Token must not be null");
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(VAULT_TOKEN, vaultToken.getToken());
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* Value object that defines Vault connection coordinates.
|
||||
* <p>
|
||||
* A {@link VaultEndpoint} defines the hostname, TCP port and the protocol scheme (HTTP or HTTPS).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class VaultEndpoint implements Serializable {
|
||||
|
||||
public static final String API_VERSION = "v1";
|
||||
|
||||
/**
|
||||
* Vault server host.
|
||||
*/
|
||||
private String host = "localhost";
|
||||
|
||||
/**
|
||||
* Vault server port.
|
||||
*/
|
||||
private int port = 8200;
|
||||
|
||||
/**
|
||||
* Protocol scheme. Can be either "http" or "https".
|
||||
*/
|
||||
private String scheme = "https";
|
||||
|
||||
/**
|
||||
* @return the hostname.
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hostname.
|
||||
*
|
||||
* @param host must not be empty or {@literal null}.
|
||||
*/
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port.
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param port must be a valid port in the range of 1-65535
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
|
||||
Assert.isTrue(port >= 1 && port <= 65535, "Port must be a valid port in the range between 1 and 65535");
|
||||
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the protocol scheme.
|
||||
*/
|
||||
public String getScheme() {
|
||||
return scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scheme must be {@literal http} or {@literal https}.
|
||||
*/
|
||||
public void setScheme(String scheme) {
|
||||
|
||||
Assert.isTrue("http".equals(scheme) || "https".equals(scheme), "Scheme must be http or https");
|
||||
|
||||
this.scheme = scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Vault {@link URI} based on the given {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return constructed {@link URI}.
|
||||
*/
|
||||
public URI createUri(String path) {
|
||||
return URI.create(createUriString(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Vault URI string based on the given {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return constructed URI String.
|
||||
*/
|
||||
public String createUriString(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
return String.format("%s://%s:%s/%s/%s", getScheme(), getHost(), getPort(), API_VERSION, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%://%:%d", scheme, host, port);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Utility to obtain a Vault error message.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class VaultErrorMessage {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Obtain the error message from a JSON response.
|
||||
*
|
||||
* @param json
|
||||
* @return
|
||||
*/
|
||||
static String getError(String json) {
|
||||
|
||||
if (json.contains("\"errors\":")) {
|
||||
|
||||
try {
|
||||
Map<String, Object> map = OBJECT_MAPPER.readValue(json.getBytes(),
|
||||
Map.class);
|
||||
if (map.containsKey("errors")) {
|
||||
|
||||
Collection<String> errors = (Collection<String>) map.get("errors");
|
||||
if (errors.size() == 1) {
|
||||
return errors.iterator().next();
|
||||
}
|
||||
return errors.toString();
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException o_O) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* The Spring Vault specific {@link NestedRuntimeException} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class VaultException extends NestedRuntimeException {
|
||||
|
||||
/**
|
||||
* Creates a {@code VaultException} with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public VaultException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code NestedRuntimeException} with the specified detail message and nested exception.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
*/
|
||||
public VaultException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* Encapsulates the client response used in {@link VaultAccessor}. Consists of the body, status code the location and a
|
||||
* message. The {@code body} is empty for all non-successful results. This class is immutable.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultResponseEntity<T> {
|
||||
|
||||
private final T body;
|
||||
|
||||
private final HttpStatus statusCode;
|
||||
|
||||
private final URI uri;
|
||||
|
||||
private final String message;
|
||||
|
||||
VaultResponseEntity(T body, HttpStatus statusCode, URI uri, String message) {
|
||||
this.body = body;
|
||||
this.statusCode = statusCode;
|
||||
this.uri = uri;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the request was completed successfully.
|
||||
*/
|
||||
public boolean isSuccessful() {
|
||||
return statusCode.is2xxSuccessful();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the request returned a body.
|
||||
*/
|
||||
public boolean hasBody() {
|
||||
return body != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the body of this entity.
|
||||
*/
|
||||
public T getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link HttpStatus} of this entity.
|
||||
*/
|
||||
public HttpStatus getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the request {@link URI} of this entity.
|
||||
*/
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message of this entity. {@literal null} for successful responses but provided usually when the response
|
||||
* yielded an error.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Spring Vault Client abstraction.
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.DefaultSessionManager;
|
||||
import org.springframework.vault.authentication.SessionManager;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.core.DefaultVaultClientFactory;
|
||||
import org.springframework.vault.core.VaultClientFactory;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for Spring Vault configuration using JavaConfig.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractVaultConfiguration {
|
||||
|
||||
/**
|
||||
* @return Vault endpoint coordinates for HTTP/HTTPS communication, must not be {@literal null}.
|
||||
*/
|
||||
public abstract VaultEndpoint vaultEndpoint();
|
||||
|
||||
/**
|
||||
* Annotate with {@link Bean} in case you want to expose a {@link ClientAuthentication} instance to the
|
||||
* {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return the {@link ClientAuthentication} to use. Must not be {@literal null}.
|
||||
*/
|
||||
public abstract ClientAuthentication clientAuthentication();
|
||||
|
||||
/**
|
||||
* Annotate with {@link Bean} in case you want to expose a {@link SessionManager} instance to the
|
||||
* {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return the {@link SessionManager} for Vault session management.
|
||||
* @see SessionManager
|
||||
* @see DefaultSessionManager
|
||||
*/
|
||||
public SessionManager sessionManager() {
|
||||
|
||||
ClientAuthentication clientAuthentication = clientAuthentication();
|
||||
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
|
||||
|
||||
return new DefaultSessionManager(clientAuthentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link ClientOptions} to configure communication parameters.
|
||||
* @see ClientOptions
|
||||
*/
|
||||
public ClientOptions clientOptions() {
|
||||
return new ClientOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SSL configuration options. Defaults to {@link SslConfiguration#NONE}.
|
||||
* @see SslConfiguration
|
||||
* @see SslConfiguration#NONE
|
||||
*/
|
||||
public SslConfiguration sslConfiguration() {
|
||||
return SslConfiguration.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientFactoryWrapper} containing a {@link ClientHttpRequestFactory}.
|
||||
* {@link ClientHttpRequestFactory} is not exposed as root bean because {@link ClientHttpRequestFactory} is configured
|
||||
* with {@link ClientOptions} and {@link SslConfiguration} which are not necessarily applicable for the whole
|
||||
* application.
|
||||
*
|
||||
* @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory} instance.
|
||||
* @see #clientOptions()
|
||||
* @see #sslConfiguration()
|
||||
*/
|
||||
@Bean
|
||||
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
|
||||
return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory.create(clientOptions(), sslConfiguration()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link VaultClient}
|
||||
* @see #clientHttpRequestFactoryWrapper()
|
||||
* @see #vaultEndpoint()
|
||||
*/
|
||||
@Bean
|
||||
public VaultClient vaultClient() {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactoryWrapper().getClientHttpRequestFactory());
|
||||
|
||||
return new VaultClient(restTemplate, vaultEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link VaultClientFactory} to be used with {@link VaultTemplate}. Uses by default
|
||||
* {@link DefaultVaultClientFactory} with the configured {@link #vaultClient()} instance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public VaultClientFactory vaultClientFactory() {
|
||||
return new DefaultVaultClientFactory(vaultClient());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link VaultTemplate}.
|
||||
*
|
||||
* @return
|
||||
* @see #vaultClientFactory()
|
||||
* @see #sessionManager()
|
||||
*/
|
||||
@Bean
|
||||
public VaultTemplate vaultTemplate() {
|
||||
return new VaultTemplate(vaultClientFactory(), sessionManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link ClientHttpRequestFactory} to not expose the bean globally.
|
||||
*/
|
||||
public static class ClientFactoryWrapper implements InitializingBean, DisposableBean {
|
||||
|
||||
private final ClientHttpRequestFactory clientHttpRequestFactory;
|
||||
|
||||
public ClientFactoryWrapper(ClientHttpRequestFactory clientHttpRequestFactory) {
|
||||
this.clientHttpRequestFactory = clientHttpRequestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (clientHttpRequestFactory instanceof DisposableBean) {
|
||||
((DisposableBean) clientHttpRequestFactory).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (clientHttpRequestFactory instanceof InitializingBean) {
|
||||
((InitializingBean) clientHttpRequestFactory).afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
public ClientHttpRequestFactory getClientHttpRequestFactory() {
|
||||
return clientHttpRequestFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.OkHttpClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components, OkHttp, Netty and the JDK HTTP
|
||||
* client (in that order). This factory configures a {@link ClientHttpRequestFactory} depending on the available
|
||||
* dependencies.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientHttpRequestFactoryFactory {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClientHttpRequestFactoryFactory.class);
|
||||
|
||||
private static final boolean HTTP_COMPONENTS_PRESENT = ClassUtils.isPresent("org.apache.http.client.HttpClient",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
private static final boolean OKHTTP_PRESENT = ClassUtils.isPresent("com.squareup.okhttp.OkHttpClient",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
private static final boolean NETTY_PRESENT = ClassUtils.isPresent("io.netty.channel.nio.NioEventLoopGroup",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and {@link SslConfiguration}.
|
||||
*
|
||||
* @param options must not be {@literal null}
|
||||
* @param sslConfiguration must not be {@literal null}
|
||||
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized after obtaining.
|
||||
*/
|
||||
public static ClientHttpRequestFactory create(ClientOptions options, SslConfiguration sslConfiguration) {
|
||||
|
||||
Assert.notNull(options, "ClientOptions must not be null");
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
|
||||
|
||||
try {
|
||||
|
||||
if (HTTP_COMPONENTS_PRESENT) {
|
||||
return HttpComponents.usingHttpComponents(options, sslConfiguration);
|
||||
}
|
||||
|
||||
if (OKHTTP_PRESENT) {
|
||||
return OkHttp.usingOkHttp(options, sslConfiguration);
|
||||
}
|
||||
|
||||
if (NETTY_PRESENT) {
|
||||
return Netty.usingNetty(options, sslConfiguration);
|
||||
}
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
logger.warn("VaultProperties has SSL configured but the SSL configuration "
|
||||
+ "must be applied outside the Vault Client to use the JDK HTTP client");
|
||||
}
|
||||
|
||||
return new SimpleClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
private static SSLContext getSSLContext(SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyManager[] keyManagers = sslConfiguration.getKeyStore() != null
|
||||
? createKeyManagerFactory(sslConfiguration.getKeyStore(), sslConfiguration.getKeyStorePassword())
|
||||
.getKeyManagers()
|
||||
: null;
|
||||
|
||||
TrustManager[] trustManagers = sslConfiguration.getTrustStore() != null
|
||||
? createTrustManagerFactory(sslConfiguration.getTrustStore(), sslConfiguration.getTrustStorePassword())
|
||||
.getTrustManagers()
|
||||
: null;
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(keyManagers, trustManagers, null);
|
||||
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
private static KeyManagerFactory createKeyManagerFactory(Resource keystoreFile, String storePassword)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
|
||||
loadKeyStore(keystoreFile, storePassword, keyStore);
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keyStore, StringUtils.hasText(storePassword) ? storePassword.toCharArray() : new char[0]);
|
||||
|
||||
return keyManagerFactory;
|
||||
}
|
||||
|
||||
private static TrustManagerFactory createTrustManagerFactory(Resource trustFile, String storePassword)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
|
||||
loadKeyStore(trustFile, storePassword, trustStore);
|
||||
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory
|
||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init(trustStore);
|
||||
|
||||
return trustManagerFactory;
|
||||
}
|
||||
|
||||
private static void loadKeyStore(Resource keyStoreResource, String storePassword, KeyStore keyStore)
|
||||
throws IOException, NoSuchAlgorithmException, CertificateException {
|
||||
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = keyStoreResource.getInputStream();
|
||||
keyStore.load(inputStream, StringUtils.hasText(storePassword) ? storePassword.toCharArray() : null);
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasSslConfiguration(SslConfiguration sslConfiguration) {
|
||||
return sslConfiguration.getTrustStore() != null || sslConfiguration.getKeyStore() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for Apache Http Components.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class HttpComponents {
|
||||
|
||||
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
|
||||
SSLContext sslContext = getSSLContext(sslConfiguration);
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
httpClientBuilder.setSSLContext(sslContext);
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom() //
|
||||
.setConnectTimeout(options.getConnectionTimeout()) //
|
||||
.setSocketTimeout(options.getReadTimeout()) //
|
||||
.setAuthenticationEnabled(true) //
|
||||
.build();
|
||||
|
||||
httpClientBuilder.setDefaultRequestConfig(requestConfig);
|
||||
|
||||
return new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for the {@link OkHttpClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class OkHttp {
|
||||
|
||||
static ClientHttpRequestFactory usingOkHttp(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
final OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(okHttpClient) {
|
||||
|
||||
@Override
|
||||
public void destroy() throws IOException {
|
||||
|
||||
if (okHttpClient.getCache() != null) {
|
||||
okHttpClient.getCache().close();
|
||||
}
|
||||
|
||||
okHttpClient.getDispatcher().getExecutorService().shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
okHttpClient.setSslSocketFactory(getSSLContext(sslConfiguration).getSocketFactory());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(options.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(options.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for Netty.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class Netty {
|
||||
|
||||
static ClientHttpRequestFactory usingNetty(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
|
||||
SslContextBuilder sslContextBuilder = SslContextBuilder //
|
||||
.forClient();
|
||||
|
||||
if (sslConfiguration.getTrustStore() != null) {
|
||||
sslContextBuilder.trustManager(
|
||||
createTrustManagerFactory(sslConfiguration.getTrustStore(), sslConfiguration.getTrustStorePassword()));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getKeyStore() != null) {
|
||||
sslContextBuilder.keyManager(
|
||||
createKeyManagerFactory(sslConfiguration.getKeyStore(), sslConfiguration.getKeyStorePassword()));
|
||||
}
|
||||
|
||||
requestFactory.setSslContext(sslContextBuilder.sslProvider(SslProvider.JDK).build());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(options.getConnectionTimeout());
|
||||
requestFactory.setReadTimeout(options.getReadTimeout());
|
||||
|
||||
return requestFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Spring configuration for Vault.
|
||||
*/
|
||||
package org.springframework.vault.config;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultClientFactory}. Returns the provided {@link VaultClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DefaultVaultClientFactory implements VaultClientFactory {
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultVaultClientFactory} returning always the same {@link VaultClient}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public DefaultVaultClientFactory(VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
|
||||
this.vaultClient = vaultClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultVaultClientFactory} using a default {@link VaultClient} and {@link VaultEndpoint}. Will
|
||||
* use Vault at {@code https://localhost:8200} .
|
||||
*
|
||||
* @see VaultClient
|
||||
* @see VaultEndpoint
|
||||
*/
|
||||
public DefaultVaultClientFactory() {
|
||||
this(new VaultClient(new RestTemplate(), new VaultEndpoint()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultClient getVaultClient() {
|
||||
return vaultClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
|
||||
/**
|
||||
* The strategy to produce a {@link VaultClient} instance(s).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface VaultClientFactory {
|
||||
|
||||
/**
|
||||
* @return a {@link VaultClient}.
|
||||
*/
|
||||
VaultClient getVaultClient();
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of Vault operations, implemented by {@link VaultTemplate}. This is the main
|
||||
* entry point to interact with Vault in an authenticated and unauthenticated context with configured
|
||||
* {@link VaultClient} instances.
|
||||
* <p>
|
||||
* {@link VaultOperations} resolves {@link VaultClient} instances and allows execution of callback methods on various
|
||||
* levels. Callbacks can execute requests within a {@link #doWithVault(SessionCallback) session}, the
|
||||
* {@link #doWithVault(ClientCallback) client (without requiring a session)} and a
|
||||
* {@link #doWithRestTemplate(String, Map, RestTemplateCallback) low-level}
|
||||
* {@link org.springframework.web.client.RestTemplate} level.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see #doWithVault(ClientCallback)
|
||||
* @see #doWithVault(SessionCallback)
|
||||
* @see #doWithRestTemplate(String, Map, RestTemplateCallback)
|
||||
* @see VaultClient
|
||||
* @see VaultTemplate
|
||||
* @see VaultTokenOperations
|
||||
* @see org.springframework.vault.authentication.SessionManager
|
||||
*/
|
||||
public interface VaultOperations {
|
||||
|
||||
/**
|
||||
* @return the operations interface administrative Vault access.
|
||||
*/
|
||||
VaultSysOperations opsForSys();
|
||||
|
||||
/**
|
||||
* @return the operations interface to interact with Vault token.
|
||||
*/
|
||||
VaultTokenOperations opsForToken();
|
||||
|
||||
/**
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret backends that do not require a
|
||||
* request body.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return the data. May be {@literal null} if the path does not exist.
|
||||
*/
|
||||
VaultResponse read(String path);
|
||||
|
||||
/**
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret backends that do not require a
|
||||
* request body.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @param responseType must not be {@literal null}.
|
||||
* @return the data. May be {@literal null} if the path does not exist.
|
||||
*/
|
||||
<T> VaultResponseSupport<T> read(String path, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Enumerate keys from a secret backend.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return the data. May be {@literal null} if the path does not exist.
|
||||
*/
|
||||
List<String> list(String path);
|
||||
|
||||
/**
|
||||
* Write to a secret backend.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return the configuration data. May be empty but never {@literal null}.
|
||||
*/
|
||||
VaultResponse write(String path, Object body);
|
||||
|
||||
/**
|
||||
* Delete a path in the secret backend.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
*/
|
||||
void delete(String path);
|
||||
|
||||
/**
|
||||
* Executes a Vault {@link ClientCallback}. Allows to interact with Vault using {@link VaultClient} without requiring a session.
|
||||
*
|
||||
* @param clientCallback the request.
|
||||
* @return the {@link ClientCallback} return value.
|
||||
*/
|
||||
<T> T doWithVault(ClientCallback<T> clientCallback);
|
||||
|
||||
/**
|
||||
* Executes a Vault {@link SessionCallback}. Allows to interact with Vault in an authenticated session.
|
||||
*
|
||||
* @param sessionCallback the request.
|
||||
* @return the {@link SessionCallback} return value.
|
||||
*/
|
||||
<T> T doWithVault(SessionCallback<T> sessionCallback);
|
||||
|
||||
/**
|
||||
* Executes {@link RestTemplateCallback}. Expands the {@code pathTemplate} to an {@link java.net.URI} and allows
|
||||
* low-level interaction with the underlying {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @param pathTemplate the path of the resource, e.g. {@code transit/{key}/foo}, must not be empty or {@literal null}.
|
||||
* @param variables the variables for expansion of the {@code pathTemplate}, must not be {@literal null}.
|
||||
* @param callback the request callback.
|
||||
* @return the {@link RestTemplateCallback} return value.
|
||||
*/
|
||||
<T> T doWithRestTemplate(String pathTemplate, Map<String, ?> variables, RestTemplateCallback<T> callback);
|
||||
|
||||
/**
|
||||
* A callback for executing arbitrary operations on the {@link VaultClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ClientCallback<T> {
|
||||
|
||||
/**
|
||||
* Callback method.
|
||||
*
|
||||
* @param client session to use, must not be {@literal null}.
|
||||
* @return a result object or null if none.
|
||||
*/
|
||||
T doWithVault(VaultClient client);
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback for executing arbitrary operations on the {@link VaultSession}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface SessionCallback<T> {
|
||||
|
||||
/**
|
||||
* Callback method.
|
||||
*
|
||||
* @param session session to use, must not be {@literal null}.
|
||||
* @return a result object or null if none.
|
||||
*/
|
||||
T doWithVault(VaultSession session);
|
||||
}
|
||||
|
||||
/**
|
||||
* An authenticated Vault session. {@link VaultSession} exposes request accessor methods to be executed in an
|
||||
* authenticated context.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface VaultSession {
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be POSTed, may be {@code null}.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be PUT.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Delete a resource by DELETEing from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}.
|
||||
* <p>
|
||||
* URI Template variables are using the given URI variables, if any.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables);
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given path template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}. The given {@link ParameterizedTypeReference} is used to pass generic
|
||||
* type information:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
* ResponseEntity<List<MyBean>> response = session.exchange("http://example.com", HttpMethod.GET, null, myBean,
|
||||
* null);
|
||||
* </pre>
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultHealthResponse;
|
||||
import org.springframework.vault.support.VaultInitializationRequest;
|
||||
import org.springframework.vault.support.VaultInitializationResponse;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
|
||||
/**
|
||||
* Interface that specified a basic set of Vault operations, implemented by {@link VaultTemplate}. Request errors are
|
||||
* wrapped within {@link VaultException}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface VaultSysOperations {
|
||||
|
||||
/**
|
||||
* @return {@literal true} if Vault is initialized.
|
||||
*/
|
||||
boolean isInitialized() throws VaultException;
|
||||
|
||||
/**
|
||||
* Initializes Vault with a {@link VaultInitializationRequest}.
|
||||
*
|
||||
* @param vaultInitializationRequest must not be {@literal null}.
|
||||
* @return the {@link VaultInitializationResponse}.
|
||||
*/
|
||||
VaultInitializationResponse initialize(VaultInitializationRequest vaultInitializationRequest) throws VaultException;
|
||||
|
||||
/**
|
||||
* Seals vault.
|
||||
*/
|
||||
void seal() throws VaultException;
|
||||
|
||||
/**
|
||||
* Unseal vault. See {@link VaultUnsealStatus#getProgress()} for progress.
|
||||
*
|
||||
* @param keyShare must not be empty and not {@literal null}.
|
||||
* @return the {@link VaultUnsealStatus}.
|
||||
*/
|
||||
VaultUnsealStatus unseal(String keyShare) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return the {@link VaultUnsealStatus}.
|
||||
*/
|
||||
VaultUnsealStatus getUnsealStatus() throws VaultException;
|
||||
|
||||
/**
|
||||
* Mounts a secret backend {@link VaultMount} to {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @param vaultMount must not be {@literal null}.
|
||||
*/
|
||||
void mount(String path, VaultMount vaultMount) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return {@link Map} of all secret backend {@link VaultMount mounts}.
|
||||
*/
|
||||
Map<String, VaultMount> getMounts() throws VaultException;
|
||||
|
||||
/**
|
||||
* Unmounts the secret backend mount at {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
*/
|
||||
void unmount(String path) throws VaultException;
|
||||
|
||||
/**
|
||||
* Mounts an auth backend {@link VaultMount} to {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @param vaultMount must not be {@literal null}.
|
||||
*/
|
||||
void authMount(String path, VaultMount vaultMount) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return {@link Map} of all auth backend {@link VaultMount mounts}.
|
||||
*/
|
||||
Map<String, VaultMount> getAuthMounts() throws VaultException;
|
||||
|
||||
/**
|
||||
* Unmounts the auth backend mount at {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
*/
|
||||
void authUnmount(String path) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return the {@link VaultHealthResponse}.
|
||||
*/
|
||||
VaultHealthResponse health() throws VaultException;
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.client.VaultAccessor;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.core.VaultOperations.ClientCallback;
|
||||
import org.springframework.vault.core.VaultOperations.SessionCallback;
|
||||
import org.springframework.vault.support.VaultHealthResponse;
|
||||
import org.springframework.vault.support.VaultInitializationRequest;
|
||||
import org.springframework.vault.support.VaultInitializationResponse;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultSysOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
private static final GetUnsealStatus GET_UNSEAL_STATUS = new GetUnsealStatus();
|
||||
|
||||
private static final Seal SEAL = new Seal();
|
||||
|
||||
private static final GetMounts GET_MOUNTS = new GetMounts("sys/mounts");
|
||||
|
||||
private static final GetMounts GET_AUTH_MOUNTS = new GetMounts("sys/auth");
|
||||
|
||||
private static final Health HEALTH = new Health();
|
||||
|
||||
private final VaultOperations vaultOperations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultSysTemplate} with the given {@link VaultOperations}.
|
||||
*
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
*/
|
||||
public VaultSysTemplate(VaultOperations vaultOperations) {
|
||||
|
||||
Assert.notNull(vaultOperations);
|
||||
|
||||
this.vaultOperations = vaultOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
|
||||
return vaultOperations.doWithVault(new ClientCallback<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<Map<String, Boolean>> response = client.getForEntity("sys/init", Map.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody().get("initialized");
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultInitializationResponse initialize(final VaultInitializationRequest vaultInitializationRequest) {
|
||||
|
||||
Assert.notNull(vaultInitializationRequest, "VaultInitialization must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new ClientCallback<VaultInitializationResponse>() {
|
||||
|
||||
@Override
|
||||
public VaultInitializationResponse doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultInitializationResponse> response = client.putForEntity("sys/init",
|
||||
vaultInitializationRequest, VaultInitializationResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seal() {
|
||||
vaultOperations.doWithVault(SEAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultUnsealStatus unseal(final String keyShare) {
|
||||
|
||||
return vaultOperations.doWithVault(new ClientCallback<VaultUnsealStatus>() {
|
||||
|
||||
@Override
|
||||
public VaultUnsealStatus doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultUnsealStatus> response = client.putForEntity("sys/unseal",
|
||||
Collections.singletonMap("key", keyShare), VaultUnsealStatus.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultUnsealStatus getUnsealStatus() {
|
||||
return vaultOperations.doWithVault(GET_UNSEAL_STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mount(final String path, final VaultMount vaultMount) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
Assert.notNull(vaultMount, "VaultMount must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new SessionCallback<Void>() {
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map<?, ?>> response = session.exchange("sys/mounts/{mount}", HttpMethod.PUT,
|
||||
new HttpEntity<VaultMount>(vaultMount), Map.class, Collections.singletonMap("mount", path));
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, VaultMount> getMounts() {
|
||||
return vaultOperations.doWithVault(GET_MOUNTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmount(final String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
vaultOperations.doWithVault(new SessionCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map<?, ?>> response = session.exchange("sys/mounts/{mount}", HttpMethod.DELETE, null,
|
||||
Map.class, Collections.singletonMap("mount", path));
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authMount(final String path, final VaultMount vaultMount) throws VaultException {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
Assert.notNull(vaultMount, "VaultMount must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new SessionCallback<Void>() {
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map<?, ?>> response = session.exchange("sys/auth/{mount}", HttpMethod.PUT,
|
||||
new HttpEntity<VaultMount>(vaultMount), Map.class, Collections.singletonMap("mount", path));
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, VaultMount> getAuthMounts() throws VaultException {
|
||||
return vaultOperations.doWithVault(GET_AUTH_MOUNTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authUnmount(final String path) throws VaultException {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
vaultOperations.doWithVault(new SessionCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map<?, ?>> response = session.exchange("sys/auth/{mount}", HttpMethod.DELETE, null,
|
||||
Map.class, Collections.singletonMap("mount", path));
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultHealthResponse health() {
|
||||
return vaultOperations.doWithRestTemplate("sys/health", Collections.<String, Object> emptyMap(), HEALTH);
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
}
|
||||
|
||||
private static class GetUnsealStatus implements ClientCallback<VaultUnsealStatus> {
|
||||
|
||||
@Override
|
||||
public VaultUnsealStatus doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultUnsealStatus> response = client.getForEntity("sys/seal-status", VaultUnsealStatus.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Seal implements SessionCallback<Void> {
|
||||
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map> response = session.putForEntity("sys/seal", null, Map.class);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class GetMounts implements SessionCallback<Map<String, VaultMount>> {
|
||||
|
||||
private static final ParameterizedTypeReference<VaultResponseSupport<Map<String, VaultMount>>> MOUNT_TYPE_REF = new ParameterizedTypeReference<VaultResponseSupport<Map<String, VaultMount>>>() {
|
||||
};
|
||||
|
||||
private final String path;
|
||||
|
||||
public GetMounts(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, VaultMount> doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultResponseSupport<Map<String, VaultMount>>> response = session.exchange(path, HttpMethod.GET, null,
|
||||
MOUNT_TYPE_REF, Collections.<String, Object>emptyMap());
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody().getData();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Health implements VaultAccessor.RestTemplateCallback<VaultHealthResponse> {
|
||||
|
||||
@Override
|
||||
public VaultHealthResponse doWithRestTemplate(URI uri, RestTemplate restTemplate) {
|
||||
|
||||
try {
|
||||
|
||||
ResponseEntity<VaultHealthResponse> healthResponse = restTemplate.exchange(uri, HttpMethod.GET, null,
|
||||
VaultHealthResponse.class);
|
||||
return healthResponse.getBody();
|
||||
} catch (HttpStatusCodeException responseError) {
|
||||
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.readValue(responseError.getResponseBodyAsString(), VaultHealthResponse.class);
|
||||
} catch (Exception jsonError) {
|
||||
throw responseError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.DefaultSessionManager;
|
||||
import org.springframework.vault.authentication.SessionManager;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* This class encapsulates main Vault interaction. {@link VaultTemplate} will log into Vault on initialization and use
|
||||
* the token throughout the whole lifetime.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultClientFactory
|
||||
* @see SessionManager
|
||||
*/
|
||||
public class VaultTemplate implements InitializingBean, VaultOperations {
|
||||
|
||||
private VaultClientFactory vaultClientFactory;
|
||||
|
||||
private SessionManager sessionManager;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} without setting {@link VaultClientFactory} and {@link SessionManager}.
|
||||
*/
|
||||
public VaultTemplate() {}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClient} and {@link ClientAuthentication}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
* @param clientAuthentication must not be {@literal null}.
|
||||
*/
|
||||
public VaultTemplate(VaultClient vaultClient, ClientAuthentication clientAuthentication) {
|
||||
|
||||
Assert.notNull(vaultClient, "VaultClientFactory must not be null");
|
||||
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
|
||||
|
||||
this.vaultClientFactory = new DefaultVaultClientFactory(vaultClient);
|
||||
this.sessionManager = new DefaultSessionManager(clientAuthentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClientFactory} and {@link SessionManager}.
|
||||
*
|
||||
* @param vaultClientFactory must not be {@literal null}.
|
||||
* @param sessionManager must not be {@literal null}.
|
||||
*/
|
||||
public VaultTemplate(VaultClientFactory vaultClientFactory, SessionManager sessionManager) {
|
||||
|
||||
Assert.notNull(vaultClientFactory, "VaultClientFactory must not be null");
|
||||
Assert.notNull(sessionManager, "SessionManager must not be null");
|
||||
|
||||
this.vaultClientFactory = vaultClientFactory;
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link VaultClientFactory}.
|
||||
*
|
||||
* @param vaultClientFactory must not be {@literal null}.
|
||||
*/
|
||||
public void setVaultClientFactory(VaultClientFactory vaultClientFactory) {
|
||||
|
||||
Assert.notNull(vaultClientFactory, "VaultClientFactory must not be null");
|
||||
|
||||
this.vaultClientFactory = vaultClientFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link SessionManager}.
|
||||
*
|
||||
* @param sessionManager must not be {@literal null}.
|
||||
*/
|
||||
public void setSessionManager(SessionManager sessionManager) {
|
||||
|
||||
Assert.notNull(sessionManager, "SessionManager must not be null");
|
||||
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
Assert.notNull(vaultClientFactory, "VaultClientFactory must not be null");
|
||||
Assert.notNull(sessionManager, "SessionManager must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenOperations opsForToken() {
|
||||
return new VaultTokenTemplate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultSysOperations opsForSys() {
|
||||
return new VaultSysTemplate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T doWithVault(ClientCallback<T> clientCallback) {
|
||||
|
||||
Assert.notNull(clientCallback, "ClientCallback must not be null!");
|
||||
Assert.state(vaultClientFactory != null, "VaultClientFactory must not be null");
|
||||
Assert.state(sessionManager != null, "SessionManager must not be null");
|
||||
|
||||
return clientCallback.doWithVault(vaultClientFactory.getVaultClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T doWithVault(SessionCallback<T> sessionCallback) {
|
||||
|
||||
Assert.notNull(sessionCallback, "SessionCallback must not be null!");
|
||||
Assert.state(vaultClientFactory != null, "VaultClientFactory must not be null");
|
||||
Assert.state(sessionManager != null, "SessionManager must not be null");
|
||||
|
||||
VaultClient vaultClient = vaultClientFactory.getVaultClient();
|
||||
|
||||
return sessionCallback.doWithVault(new DefaultVaultSession(sessionManager, vaultClient));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables, RestTemplateCallback<T> callback) {
|
||||
|
||||
Assert.notNull(callback, "RestTemplateCallback must not be null!");
|
||||
Assert.state(vaultClientFactory != null, "VaultClientFactory must not be null");
|
||||
|
||||
return vaultClientFactory.getVaultClient().doWithRestTemplate(pathTemplate, uriVariables, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultResponse read(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
return doRead(path, VaultResponse.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> VaultResponseSupport<T> read(final String path, final Class<T> responseType) {
|
||||
|
||||
final ParameterizedTypeReference<VaultResponseSupport<T>> ref = getTypeReference(responseType);
|
||||
|
||||
return doWithVault(new SessionCallback<VaultResponseSupport<T>>() {
|
||||
|
||||
@Override
|
||||
public VaultResponseSupport<T> doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultResponseSupport<T>> entity = session.exchange(path, HttpMethod.GET, null, ref, null);
|
||||
|
||||
if (entity.isSuccessful() && entity.hasBody()) {
|
||||
return entity.getBody();
|
||||
}
|
||||
|
||||
if (entity.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(entity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> list(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
VaultListResponse read = doRead(String.format("%s?list=true", path.endsWith("/") ? path : (path + "/")),
|
||||
VaultListResponse.class);
|
||||
if (read == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return (List) read.getData().get("keys");
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultResponse write(final String path, final Object body) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
return doWithVault(new SessionCallback<VaultResponse>() {
|
||||
|
||||
@Override
|
||||
public VaultResponse doWithVault(VaultSession session) {
|
||||
VaultResponseEntity<VaultResponse> entity = session.postForEntity(path, body, VaultResponse.class);
|
||||
|
||||
if (entity.isSuccessful()) {
|
||||
if (entity.hasBody()) {
|
||||
return entity.getBody();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(entity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(final String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
doWithVault(new SessionCallback<VaultResponse>() {
|
||||
|
||||
@Override
|
||||
public VaultResponse doWithVault(VaultSession session) {
|
||||
VaultResponseEntity<VaultResponse> entity = session.deleteForEntity(path, VaultResponse.class);
|
||||
|
||||
if (entity.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(entity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> ParameterizedTypeReference<VaultResponseSupport<T>> getTypeReference(final Class<T> responseType) {
|
||||
final Type supportType = new ParameterizedType() {
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return new Type[] { responseType };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return VaultResponseSupport.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return VaultResponseSupport.class;
|
||||
}
|
||||
};
|
||||
|
||||
return new ParameterizedTypeReference<VaultResponseSupport<T>>() {
|
||||
@Override
|
||||
public Type getType() {
|
||||
return supportType;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private <T> T doRead(final String path, final Class<T> responseType) {
|
||||
|
||||
return doWithVault(new SessionCallback<T>() {
|
||||
|
||||
@Override
|
||||
public T doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<T> entity = session.getForEntity(path, responseType);
|
||||
|
||||
if (entity.isSuccessful() && entity.hasBody()) {
|
||||
return entity.getBody();
|
||||
}
|
||||
|
||||
if (entity.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(entity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
}
|
||||
|
||||
private static class DefaultVaultSession implements VaultSession {
|
||||
|
||||
private final SessionManager sessionManager;
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
DefaultVaultSession(SessionManager sessionManager, VaultClient vaultClient) {
|
||||
this.sessionManager = sessionManager;
|
||||
this.vaultClient = vaultClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType) {
|
||||
return vaultClient.getForEntity(path, sessionManager.getSessionToken(), responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType) {
|
||||
return vaultClient.putForEntity(path, sessionManager.getSessionToken(), request, responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType) {
|
||||
return vaultClient.postForEntity(path, sessionManager.getSessionToken(), request, responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, Class<T> responseType) {
|
||||
return vaultClient.deleteForEntity(path, sessionManager.getSessionToken(), responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
|
||||
|
||||
HttpEntity<?> requestEntityToUse = getHttpEntity(requestEntity);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse, responseType, uriVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) {
|
||||
|
||||
HttpEntity<?> requestEntityToUse = getHttpEntity(requestEntity);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse, responseType, uriVariables);
|
||||
}
|
||||
|
||||
private HttpEntity<?> getHttpEntity(HttpEntity<?> requestEntity) {
|
||||
HttpHeaders httpHeaders = VaultClient.createHeaders(sessionManager.getSessionToken());
|
||||
|
||||
HttpEntity<?> requestEntityToUse = requestEntity;
|
||||
if (requestEntityToUse != null) {
|
||||
requestEntityToUse = new HttpEntity<Object>(requestEntityToUse.getBody(), httpHeaders);
|
||||
} else {
|
||||
requestEntityToUse = new HttpEntity<Object>(httpHeaders);
|
||||
}
|
||||
return requestEntityToUse;
|
||||
}
|
||||
}
|
||||
|
||||
private static class VaultListResponse extends VaultResponseSupport<Map<String, Object>> {}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.support.VaultTokenResponse;
|
||||
|
||||
/**
|
||||
* Interface that specifies token-related operations.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface VaultTokenOperations {
|
||||
|
||||
/**
|
||||
* Creates a new token.
|
||||
*
|
||||
* @return a {@link VaultTokenResponse}
|
||||
*/
|
||||
VaultTokenResponse create() throws VaultException;
|
||||
|
||||
/**
|
||||
* Creates a new token for the given {@link VaultTokenRequest}.
|
||||
*
|
||||
* @param request must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
*/
|
||||
VaultTokenResponse create(VaultTokenRequest request) throws VaultException;
|
||||
|
||||
/**
|
||||
* Creates a new orphan token.
|
||||
*
|
||||
* @return a {@link VaultTokenResponse}
|
||||
*/
|
||||
VaultTokenResponse createOrphan();
|
||||
|
||||
/**
|
||||
* Creates a new orphan token for the given {@link VaultTokenRequest}.
|
||||
*
|
||||
* @param request must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
*/
|
||||
VaultTokenResponse createOrphan(VaultTokenRequest request);
|
||||
|
||||
/**
|
||||
* Renews a {@link VaultToken}.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
*/
|
||||
VaultTokenResponse renew(VaultToken vaultToken);
|
||||
|
||||
/**
|
||||
* Revokes a {@link VaultToken}.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
*/
|
||||
void revoke(VaultToken vaultToken);
|
||||
|
||||
/**
|
||||
* Revokes a {@link VaultToken} but not its child tokens.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
*/
|
||||
void revokeOrphan(VaultToken vaultToken);
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.core.VaultOperations.SessionCallback;
|
||||
import org.springframework.vault.core.VaultOperations.VaultSession;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.support.VaultTokenResponse;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultTokenOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
|
||||
private final VaultOperations vaultOperations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTokenTemplate} with the given {@link VaultOperations}.
|
||||
*
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
*/
|
||||
public VaultTokenTemplate(VaultOperations vaultOperations) {
|
||||
|
||||
Assert.notNull(vaultOperations);
|
||||
|
||||
this.vaultOperations = vaultOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse create() {
|
||||
return create(new VaultTokenRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse create(VaultTokenRequest request) {
|
||||
|
||||
Assert.notNull(request, "VaultTokenRequest must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new CreateToken("auth/token/create", request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse createOrphan() {
|
||||
return createOrphan(new VaultTokenRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse createOrphan(VaultTokenRequest request) {
|
||||
|
||||
Assert.notNull(request, "VaultTokenRequest must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new CreateToken("auth/token/create-orphan", request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse renew(VaultToken vaultToken) {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new RenewToken(String.format("auth/token/renew/%s", vaultToken.getToken())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revoke(VaultToken vaultToken) {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format("auth/token/revoke/%s", vaultToken.getToken())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeOrphan(VaultToken vaultToken) {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format("auth/token/revoke-orphan/%s", vaultToken.getToken())));
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
}
|
||||
|
||||
private static class CreateToken implements SessionCallback<VaultTokenResponse> {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final VaultTokenRequest request;
|
||||
|
||||
public CreateToken(String path, VaultTokenRequest request) {
|
||||
this.path = path;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, request, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
|
||||
private static class RevokeToken implements SessionCallback<Void> {
|
||||
|
||||
private final String path;
|
||||
|
||||
RevokeToken(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, null, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
|
||||
private static class RenewToken implements SessionCallback<VaultTokenResponse> {
|
||||
|
||||
private final String path;
|
||||
|
||||
RenewToken(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultTokenResponse doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, null, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Vault core support.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Spring support for <a href="https://vaultproject.io">Hashicorp Vault</a>.
|
||||
*/
|
||||
package org.springframework.vault;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Client options for Vault.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientOptions {
|
||||
|
||||
/**
|
||||
* Connection timeout;
|
||||
*/
|
||||
private final int connectionTimeout;
|
||||
|
||||
/**
|
||||
* Read timeout;
|
||||
*/
|
||||
private final int readTimeout;
|
||||
|
||||
/**
|
||||
* Creates new {@link ClientOptions} with default timeouts of {@literal 5} {@link TimeUnit#SECONDS} connection timeout
|
||||
* and {@literal 15} {@link TimeUnit#SECONDS} read timeout.
|
||||
*/
|
||||
public ClientOptions() {
|
||||
this((int) TimeUnit.SECONDS.toMillis(5), (int) TimeUnit.SECONDS.toMillis(15));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ClientOptions}.
|
||||
*
|
||||
* @param connectionTimeout connection timeout in {@link TimeUnit#MILLISECONDS}, must be greater {@literal 0}.
|
||||
* @param readTimeout read timeout in {@link TimeUnit#MILLISECONDS}, must be greater {@literal 0}.
|
||||
*/
|
||||
public ClientOptions(int connectionTimeout, int readTimeout) {
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the connection timeout in {@link TimeUnit#MILLISECONDS}.
|
||||
*/
|
||||
public int getConnectionTimeout() {
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the read timeout in {@link TimeUnit#MILLISECONDS}.
|
||||
*/
|
||||
public int getReadTimeout() {
|
||||
return readTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* SSL configuration.
|
||||
* <p>
|
||||
* Provides configuration for a key store and trust store for TLS certificate verification. Key store and trust store
|
||||
* may be left unconfigured if the JDK trust store contains all necessary certificates to verify TLS certificates. The
|
||||
* key store is used for Client Certificate authentication.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see Resource
|
||||
* @see java.security.KeyStore
|
||||
* @see org.springframework.vault.authentication.ClientCertificateAuthentication
|
||||
*/
|
||||
public class SslConfiguration {
|
||||
|
||||
/**
|
||||
* Default {@link SslConfiguration} without a KeyStore/TrustStore configured.
|
||||
*/
|
||||
public static final SslConfiguration NONE = new SslConfiguration(null, null, null, null);
|
||||
|
||||
/**
|
||||
* Trust store that holds certificates and private keys.
|
||||
*/
|
||||
private final Resource keyStore;
|
||||
|
||||
/**
|
||||
* Password used to access the key store.
|
||||
*/
|
||||
private final String keyStorePassword;
|
||||
|
||||
/**
|
||||
* Trust store that holds SSL certificates.
|
||||
*/
|
||||
private final Resource trustStore;
|
||||
|
||||
/**
|
||||
* Password used to access the trust store.
|
||||
*/
|
||||
private final String trustStorePassword;
|
||||
|
||||
public SslConfiguration(Resource keyStore, String keyStorePassword, Resource trustStore, String trustStorePassword) {
|
||||
|
||||
this.keyStore = keyStore;
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
this.trustStore = trustStore;
|
||||
this.trustStorePassword = trustStorePassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given trust store.
|
||||
*
|
||||
* @param trustStore resource pointing to an existing trust store, must not be {@literal null}.
|
||||
* @param trustStorePassword may be {@literal null}.
|
||||
* @see java.security.KeyStore
|
||||
*/
|
||||
public static SslConfiguration forTrustStore(Resource trustStore, String trustStorePassword) {
|
||||
|
||||
Assert.notNull(trustStore, "TrustStore must not be null");
|
||||
Assert.notNull(trustStore.exists(), String.format("TrustStore %s does not exist", trustStore));
|
||||
|
||||
return new SslConfiguration(null, null, trustStore, trustStorePassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given key store.
|
||||
*
|
||||
* @param keyStore resource pointing to an existing key store, must not be {@literal null}.
|
||||
* @param keyStorePassword may be {@literal null}.
|
||||
* @see java.security.KeyStore
|
||||
*/
|
||||
public static SslConfiguration forKeyStore(Resource keyStore, String keyStorePassword) {
|
||||
|
||||
Assert.notNull(keyStore, "KeyStore must not be null");
|
||||
Assert.notNull(keyStore.exists(), String.format("KeyStore %s does not exist", keyStore));
|
||||
|
||||
return new SslConfiguration(keyStore, keyStorePassword, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given truststore.
|
||||
*
|
||||
* @param keyStore resource pointing to an existing keystore, must not be {@literal null}.
|
||||
* @param keyStorePassword may be {@literal null}.
|
||||
* @see java.security.KeyStore
|
||||
*/
|
||||
public SslConfiguration create(Resource keyStore, String keyStorePassword, Resource trustStore,
|
||||
String trustStorePassword) {
|
||||
|
||||
Assert.notNull(keyStore, "KeyStore must not be null");
|
||||
Assert.notNull(keyStore.exists(), String.format("KeyStore %s does not exist", trustStore));
|
||||
|
||||
Assert.notNull(trustStore, "TrustStore must not be null");
|
||||
Assert.notNull(trustStore.exists(), String.format("TrustStore %s does not exist", trustStore));
|
||||
|
||||
return new SslConfiguration(keyStore, keyStorePassword, trustStore, trustStorePassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if not configured.
|
||||
*/
|
||||
public Resource getKeyStore() {
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key store password or {@literal null} if not configured.
|
||||
*/
|
||||
public String getKeyStorePassword() {
|
||||
return keyStorePassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if not configured.
|
||||
*/
|
||||
public Resource getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the trust store password or {@literal null} if not configured.
|
||||
*/
|
||||
public String getTrustStorePassword() {
|
||||
return trustStorePassword;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind HTTP API responses for sys/health.
|
||||
*
|
||||
* @author Stuart Ingram
|
||||
* @author Bill Koch
|
||||
*/
|
||||
public class VaultHealthResponse {
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private boolean sealed;
|
||||
|
||||
private boolean standby;
|
||||
|
||||
@JsonProperty("server_time_utc") private int serverTimeUtc;
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
public void setInitialized(boolean initialized) {
|
||||
this.initialized = initialized;
|
||||
}
|
||||
|
||||
public boolean isSealed() {
|
||||
return sealed;
|
||||
}
|
||||
|
||||
public void setSealed(boolean sealed) {
|
||||
this.sealed = sealed;
|
||||
}
|
||||
|
||||
public boolean isStandby() {
|
||||
return standby;
|
||||
}
|
||||
|
||||
public void setStandby(boolean standby) {
|
||||
this.standby = standby;
|
||||
}
|
||||
|
||||
public int getServerTimeUtc() {
|
||||
return serverTimeUtc;
|
||||
}
|
||||
|
||||
public void setServerTimeUtc(int serverTimeUtc) {
|
||||
this.serverTimeUtc = serverTimeUtc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Initialization API requests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultInitializationRequest {
|
||||
|
||||
@JsonProperty("secret_shares") private int secretShares;
|
||||
|
||||
@JsonProperty("secret_threshold") private int secretThreshold;
|
||||
|
||||
public VaultInitializationRequest() {}
|
||||
|
||||
public VaultInitializationRequest(int secretShares, int secretThreshold) {
|
||||
this.secretShares = secretShares;
|
||||
this.secretThreshold = secretThreshold;
|
||||
}
|
||||
|
||||
public int getSecretShares() {
|
||||
return secretShares;
|
||||
}
|
||||
|
||||
public void setSecretShares(int secretShares) {
|
||||
this.secretShares = secretShares;
|
||||
}
|
||||
|
||||
public int getSecretThreshold() {
|
||||
return secretThreshold;
|
||||
}
|
||||
|
||||
public void setSecretThreshold(int secretThreshold) {
|
||||
this.secretThreshold = secretThreshold;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Initialization API responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultInitializationResponse {
|
||||
|
||||
private List<String> keys = new ArrayList<String>();
|
||||
|
||||
@JsonProperty("root_token") private String rootToken;
|
||||
|
||||
public VaultInitializationResponse() {}
|
||||
|
||||
public List<String> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public void setKeys(List<String> keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public String getRootToken() {
|
||||
return rootToken;
|
||||
}
|
||||
|
||||
public void setRootToken(String rootToken) {
|
||||
this.rootToken = rootToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Mount API requests/responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultMount {
|
||||
|
||||
private String type;
|
||||
|
||||
private String description;
|
||||
|
||||
private Map<String, Object> config;
|
||||
|
||||
public VaultMount() {}
|
||||
|
||||
public VaultMount(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Map<String, Object> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, Object> config) {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Value object to bind generic Vault HTTP API responses.
|
||||
* <p>
|
||||
* This class binds the data element to a {@link Map} for generic response handling.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = false)
|
||||
public class VaultResponse extends VaultResponseSupport<Map<String, Object>> {}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind generic Vault HTTP API responses.
|
||||
*
|
||||
* @param <T>
|
||||
* @author Spencer Gibb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class VaultResponseSupport<T> {
|
||||
|
||||
private Map<String, Object> auth;
|
||||
|
||||
private T data;
|
||||
|
||||
private Map<String, String> metadata;
|
||||
|
||||
@JsonProperty("wrap_info") private Map<String, String> wrapInfo;
|
||||
|
||||
@JsonProperty("lease_duration") private long leaseDuration;
|
||||
|
||||
@JsonProperty("lease_id") private String leaseId;
|
||||
|
||||
@JsonProperty("request_id") private String requestId;
|
||||
|
||||
private boolean renewable;
|
||||
|
||||
public Map<String, Object> getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(Map<String, Object> auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Map<String, String> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public long getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
public void setLeaseDuration(long leaseDuration) {
|
||||
this.leaseDuration = leaseDuration;
|
||||
}
|
||||
|
||||
public String getLeaseId() {
|
||||
return leaseId;
|
||||
}
|
||||
|
||||
public void setLeaseId(String leaseId) {
|
||||
this.leaseId = leaseId;
|
||||
}
|
||||
|
||||
public boolean isRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
|
||||
public void setRenewable(boolean renewable) {
|
||||
this.renewable = renewable;
|
||||
}
|
||||
|
||||
public Map<String, String> getWrapInfo() {
|
||||
return wrapInfo;
|
||||
}
|
||||
|
||||
public void setWrapInfo(Map<String, String> wrapInfo) {
|
||||
this.wrapInfo = wrapInfo;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public void setRequestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* Value object for a Vault token.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class VaultToken {
|
||||
|
||||
private final String token;
|
||||
|
||||
private final long leaseDuration;
|
||||
|
||||
private VaultToken(String token, long leaseDuration) {
|
||||
this.token = token;
|
||||
this.leaseDuration = leaseDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultToken}.
|
||||
*
|
||||
* @param token must not be {@literal null}.
|
||||
* @return the created {@link VaultToken}
|
||||
*/
|
||||
public static VaultToken of(String token) {
|
||||
return of(token, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultToken} with a {@code leaseDuration}.
|
||||
*
|
||||
* @param token must not be {@literal null}.
|
||||
* @return the created {@link VaultToken}
|
||||
*/
|
||||
public static VaultToken of(String token, long leaseDuration) {
|
||||
|
||||
Assert.hasText(token, "Token must not be empty");
|
||||
|
||||
return new VaultToken(token, leaseDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the token value.
|
||||
*/
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lease duration. May be {@literal 0} if none.
|
||||
*/
|
||||
public long getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Token API requests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultTokenRequest {
|
||||
|
||||
private String id;
|
||||
|
||||
private List<String> policies;
|
||||
|
||||
private Map<String, String> meta;
|
||||
|
||||
@JsonProperty("no_parent") private Boolean noParent;
|
||||
|
||||
@JsonProperty("no_default_policy") private Boolean noDefaultPolicy;
|
||||
|
||||
private Boolean renewable;
|
||||
|
||||
private String ttl;
|
||||
|
||||
@JsonProperty("explicit_max_ttl") private String explicitMaxTtl;
|
||||
|
||||
@JsonProperty("display_name") private String displayName;
|
||||
|
||||
@JsonProperty("num_uses") private Integer numUses;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
public void setPolicies(List<String> policies) {
|
||||
this.policies = policies;
|
||||
}
|
||||
|
||||
public Map<String, String> getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
public void setMeta(Map<String, String> meta) {
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
public Boolean getNoParent() {
|
||||
return noParent;
|
||||
}
|
||||
|
||||
public void setNoParent(Boolean noParent) {
|
||||
this.noParent = noParent;
|
||||
}
|
||||
|
||||
public Boolean getNoDefaultPolicy() {
|
||||
return noDefaultPolicy;
|
||||
}
|
||||
|
||||
public void setNoDefaultPolicy(Boolean noDefaultPolicy) {
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
}
|
||||
|
||||
public Boolean getRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
|
||||
public void setRenewable(Boolean renewable) {
|
||||
this.renewable = renewable;
|
||||
}
|
||||
|
||||
public String getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public void setTtl(String ttl) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
public String getExplicitMaxTtl() {
|
||||
return explicitMaxTtl;
|
||||
}
|
||||
|
||||
public void setExplicitMaxTtl(String explicitMaxTtl) {
|
||||
this.explicitMaxTtl = explicitMaxTtl;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
public void setNumUses(Integer numUses) {
|
||||
this.numUses = numUses;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Token API responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultTokenResponse extends VaultResponse {
|
||||
|
||||
/**
|
||||
* Returns a {@link VaultToken} from the {@link VaultResponse}.
|
||||
*
|
||||
* @return the {@link VaultToken}.
|
||||
*/
|
||||
public VaultToken getToken() {
|
||||
return VaultToken.of((String) getAuth().get("client_token"),
|
||||
((Number) getAuth().get("lease_duration")).longValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Unseal API responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultUnsealStatus {
|
||||
|
||||
private boolean sealed;
|
||||
|
||||
@JsonProperty("t") private int secretThreshold;
|
||||
|
||||
@JsonProperty("n") private int secretShares;
|
||||
|
||||
private int progress;
|
||||
|
||||
public VaultUnsealStatus() {}
|
||||
|
||||
public int getSecretShares() {
|
||||
return secretShares;
|
||||
}
|
||||
|
||||
public void setSecretShares(int secretShares) {
|
||||
this.secretShares = secretShares;
|
||||
}
|
||||
|
||||
public int getSecretThreshold() {
|
||||
return secretThreshold;
|
||||
}
|
||||
|
||||
public void setSecretThreshold(int secretThreshold) {
|
||||
this.secretThreshold = secretThreshold;
|
||||
}
|
||||
|
||||
public boolean isSealed() {
|
||||
return sealed;
|
||||
}
|
||||
|
||||
public void setSealed(boolean sealed) {
|
||||
this.sealed = sealed;
|
||||
}
|
||||
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Classes supporting the Vault packages, such as value objects.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.vault.util.TestRestTemplateFactory;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class AppIdAuthenticationIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
if (!prepare().hasAuth("app-id")) {
|
||||
prepare().mountAuth("app-id");
|
||||
}
|
||||
|
||||
prepare().getVaultOperations().doWithVault(new VaultOperations.SessionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
Map<String, String> appIdData = new HashMap<String, String>();
|
||||
appIdData.put("value", "dummy"); // policy
|
||||
appIdData.put("display_name", "this is my test application");
|
||||
|
||||
session.postForEntity("auth/app-id/map/app-id/myapp", appIdData, Map.class);
|
||||
|
||||
Map<String, String> userIdData = new HashMap<String, String>();
|
||||
userIdData.put("value", "myapp"); // name of the app-id
|
||||
userIdData.put("cidr_block", "0.0.0.0/0");
|
||||
|
||||
session.postForEntity("auth/app-id/map/user-id/static-userid-value", userIdData, Map.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLoginSuccessfully() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("myapp") //
|
||||
.userIdMechanism(new StaticUserId("static-userid-value")) //
|
||||
.build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, vaultClient);
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
assertThat(login.getToken()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("wrong") //
|
||||
.userIdMechanism(new StaticUserId("wrong")) //
|
||||
.build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
|
||||
new AppIdAuthentication(options, vaultClient).login();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class AppIdAuthenticationUnitTests {
|
||||
|
||||
private VaultClient vaultClient;
|
||||
private MockRestServiceServer mockRest;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
mockRest = MockRestServiceServer.createServer(restTemplate);
|
||||
vaultClient = new VaultClient(restTemplate, new VaultEndpoint());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginShouldObtainTokenWithStaticUserId() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/app-id/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.app_id").value("hello")) //
|
||||
.andExpect(jsonPath("$.user_id").value("world")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, vaultClient);
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
assertThat(login.getToken()).isEqualTo("my-token");
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/app-id/login")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
new AppIdAuthentication(options, vaultClient).login();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AwsEc2Authentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class AwsEc2AuthenticationUnitTests {
|
||||
|
||||
private VaultClient vaultClient;
|
||||
private MockRestServiceServer mockRest;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
mockRest = MockRestServiceServer.createServer(restTemplate);
|
||||
vaultClient = new VaultClient(restTemplate, new VaultEndpoint());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldObtainIdentityDocument() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andRespond(withSuccess().body("Hello, world"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(vaultClient);
|
||||
|
||||
assertThat(authentication.getEc2Login()).containsEntry("pkcs7", "Hello, world").containsKey("nonce").hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainRole() throws Exception {
|
||||
|
||||
AwsEc2AuthenticationOptions options = AwsEc2AuthenticationOptions.builder().role("ami").build();
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andRespond(withSuccess().body("Hello, world"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(options, vaultClient, vaultClient.getRestTemplate());
|
||||
|
||||
assertThat(authentication.getEc2Login()) //
|
||||
.containsEntry("pkcs7", "Hello, world") //
|
||||
.containsEntry("role", "ami") //
|
||||
.containsKey("nonce").hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLogin() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/aws-ec2/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.pkcs7").value("value")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(vaultClient) {
|
||||
@Override
|
||||
protected Map<String, String> getEc2Login() {
|
||||
return Collections.singletonMap("pkcs7", "value");
|
||||
}
|
||||
};
|
||||
|
||||
VaultToken vaultToken = authentication.login();
|
||||
|
||||
assertThat(vaultToken.getToken()).isEqualTo("my-token");
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFailWhileObtainingIdentityDocument() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
new AwsEc2Authentication(vaultClient).login();
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/aws-ec2/login")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
new AwsEc2Authentication(vaultClient) {
|
||||
@Override
|
||||
protected Map<String, String> getEc2Login() {
|
||||
return Collections.singletonMap("pkcs7", "value");
|
||||
}
|
||||
}.login();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.vault.util.Settings.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.assertj.core.util.Files;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.config.ClientHttpRequestFactoryFactory;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientCertificateAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientCertificateAuthenticationIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
if (!prepare().hasAuth("cert")) {
|
||||
prepare().mountAuth("cert");
|
||||
}
|
||||
|
||||
prepare().getVaultOperations().doWithVault(new VaultOperations.SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
File workDir = findWorkDir();
|
||||
|
||||
String certificate = Files.contentOf(new File(workDir, "ca/certs/client.cert.pem"),
|
||||
Charset.forName("US-ASCII"));
|
||||
|
||||
session.postForEntity("auth/cert/certs/my-role", Collections.singletonMap("certificate", certificate),
|
||||
Map.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLoginSuccessfully() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory.create(new ClientOptions(),
|
||||
prepareCertAuthenticationMethod());
|
||||
VaultClient vaultClient = new VaultClient(new RestTemplate(clientHttpRequestFactory), new VaultEndpoint());
|
||||
|
||||
ClientCertificateAuthentication authentication = new ClientCertificateAuthentication(vaultClient);
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
assertThat(login.getToken()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory.create(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
VaultClient vaultClient = new VaultClient(new RestTemplate(clientHttpRequestFactory), new VaultEndpoint());
|
||||
|
||||
new ClientCertificateAuthentication(vaultClient).login();
|
||||
}
|
||||
|
||||
private SslConfiguration prepareCertAuthenticationMethod() {
|
||||
|
||||
SslConfiguration original = createSslConfiguration();
|
||||
|
||||
SslConfiguration sslConfiguration = new SslConfiguration(
|
||||
new FileSystemResource(new File(findWorkDir(), "client-cert.jks")), "changeit", original.getTrustStore(),
|
||||
original.getTrustStorePassword());
|
||||
|
||||
return sslConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ClientCertificateAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientCertificateAuthenticationUnitTests {
|
||||
|
||||
private VaultClient vaultClient;
|
||||
private MockRestServiceServer mockRest;
|
||||
|
||||
private AppIdAuthentication sut;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
mockRest = MockRestServiceServer.createServer(restTemplate);
|
||||
vaultClient = new VaultClient(restTemplate, new VaultEndpoint());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginShouldObtainToken() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/cert/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
ClientCertificateAuthentication sut = new ClientCertificateAuthentication(vaultClient);
|
||||
|
||||
VaultToken login = sut.login();
|
||||
assertThat(login.getToken()).isEqualTo("my-token");
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/cert/login")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
new ClientCertificateAuthentication(vaultClient).login();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IpAddressUserId}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class IpAddressUserIdTests {
|
||||
|
||||
@Test
|
||||
public void shouldGenerateUppercaseSha256HexString() throws Exception {
|
||||
|
||||
String userId = new IpAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MacAddressUserId}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MacAddressUserIdUnitTests {
|
||||
|
||||
@Test
|
||||
public void shouldGenerateUppercaseSha256HexString() throws Exception {
|
||||
|
||||
String userId = new MacAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGenerateUserIdFromNetworkInterfaceIndex() throws Exception {
|
||||
|
||||
int index = getValidNetworkInterfaceIndex();
|
||||
assumeTrue(index != -1);
|
||||
|
||||
String userId = new MacAddressUserId(index).createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain index for {@link NetworkInterface} with a HardwareAddress.
|
||||
*
|
||||
* @return -1 if none, otherwise index.
|
||||
* @throws SocketException
|
||||
*/
|
||||
private int getValidNetworkInterfaceIndex() throws SocketException {
|
||||
|
||||
NetworkInterface[] networkInterfaces = CollectionUtils.toArray(NetworkInterface.getNetworkInterfaces(),
|
||||
new NetworkInterface[0]);
|
||||
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < networkInterfaces.length; i++) {
|
||||
if (networkInterfaces[i].getHardwareAddress() != null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.OkHttpClientHttpRequestFactory;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.config.ClientHttpRequestFactoryFactory.HttpComponents;
|
||||
import org.springframework.vault.config.ClientHttpRequestFactoryFactory.Netty;
|
||||
import org.springframework.vault.config.ClientHttpRequestFactoryFactory.OkHttp;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientHttpRequestFactory}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
|
||||
private final String url = new VaultEndpoint().createUriString("sys/health");
|
||||
|
||||
@Test
|
||||
public void httpComponentsClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = HttpComponents.usingHttpComponents(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nettyClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = Netty.usingNetty(new ClientOptions(), Settings.createSslConfiguration());
|
||||
((InitializingBean) factory).afterPropertiesSet();
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(Netty4ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void okHttpClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = OkHttp.usingOkHttp(new ClientOptions(), Settings.createSslConfiguration());
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(OkHttpClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
private String request(RestTemplate template) {
|
||||
|
||||
// Uninitialized and sealed can cause status 500
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = template.exchange(url, HttpMethod.GET, null, String.class);
|
||||
return responseEntity.getBody();
|
||||
} catch (HttpStatusCodeException e) {
|
||||
return e.getResponseBodyAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.DefaultSessionManager;
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.config.AbstractVaultConfiguration;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.util.Settings;
|
||||
|
||||
/**
|
||||
* Test configuration for Vault integration tests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
class VaultIntegrationTestConfiguration extends AbstractVaultConfiguration {
|
||||
|
||||
@Override
|
||||
public VaultEndpoint vaultEndpoint() {
|
||||
return new VaultEndpoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
return new TokenAuthentication(Settings.token());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SslConfiguration sslConfiguration() {
|
||||
return Settings.createSslConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
class test {
|
||||
|
||||
@Bean
|
||||
public VaultTemplate vaultTemplate() {
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate();
|
||||
vaultTemplate.setSessionManager(sessionManager());
|
||||
vaultTemplate.setVaultClientFactory(clientFactory());
|
||||
|
||||
return vaultTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultVaultClientFactory clientFactory() {
|
||||
return new DefaultVaultClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultSessionManager sessionManager() {
|
||||
return new DefaultSessionManager(new TokenAuthentication("…"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultSysTemplate} through {@link VaultSysOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultSysTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
private VaultSysOperations adminOperations;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
adminOperations = vaultOperations.opsForSys();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMountsShouldContainSecretBackend() {
|
||||
|
||||
Map<String, VaultMount> mounts = adminOperations.getMounts();
|
||||
|
||||
assertThat(mounts).containsKey("secret/");
|
||||
|
||||
VaultMount secret = mounts.get("secret/");
|
||||
assertThat(secret.getDescription()).isEqualTo("generic secret storage");
|
||||
assertThat(secret.getType()).isEqualTo("generic");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mountShouldMountGenericSecret() {
|
||||
|
||||
if (adminOperations.getMounts().containsKey("other/")) {
|
||||
adminOperations.unmount("other");
|
||||
}
|
||||
|
||||
VaultMount mount = new VaultMount("generic");
|
||||
mount.setConfig(Collections.singletonMap("default_lease_ttl", (Object) "1h"));
|
||||
mount.setDescription("hello, world");
|
||||
|
||||
adminOperations.mount("other", mount);
|
||||
|
||||
Map<String, VaultMount> mounts = adminOperations.getMounts();
|
||||
|
||||
assertThat(mounts).containsKey("other/");
|
||||
|
||||
VaultMount secret = mounts.get("other/");
|
||||
assertThat(secret.getDescription()).isEqualTo(mount.getDescription());
|
||||
assertThat(secret.getConfig()).containsEntry("default_lease_ttl", 3600);
|
||||
assertThat(secret.getType()).isEqualTo("generic");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAuthMountsShouldContainSecretBackend() {
|
||||
|
||||
Map<String, VaultMount> mounts = adminOperations.getAuthMounts();
|
||||
|
||||
assertThat(mounts).containsKey("token/");
|
||||
|
||||
VaultMount secret = mounts.get("token/");
|
||||
assertThat(secret.getDescription()).isEqualTo("token based credentials");
|
||||
assertThat(secret.getType()).isEqualTo("token");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authMountShouldMountGenericSecret() {
|
||||
|
||||
if (adminOperations.getAuthMounts().containsKey("other/")) {
|
||||
adminOperations.authUnmount("other");
|
||||
}
|
||||
|
||||
VaultMount mount = new VaultMount("userpass");
|
||||
mount.setDescription("hello, world");
|
||||
|
||||
adminOperations.authMount("other", mount);
|
||||
|
||||
Map<String, VaultMount> mounts = adminOperations.getAuthMounts();
|
||||
|
||||
assertThat(mounts).containsKey("other/");
|
||||
|
||||
VaultMount secret = mounts.get("other/");
|
||||
assertThat(secret.getDescription()).isEqualTo(mount.getDescription());
|
||||
assertThat(secret.getType()).isEqualTo("userpass");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInitializedShouldReturnTrue() {
|
||||
assertThat(adminOperations.isInitialized()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUnsealStatusShouldReturnStatus() {
|
||||
|
||||
VaultUnsealStatus unsealStatus = adminOperations.getUnsealStatus();
|
||||
assertThat(unsealStatus.isSealed()).isFalse();
|
||||
assertThat(unsealStatus.getProgress()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTemplate} using the {@code generic} backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTemplateGenericIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
|
||||
@Test
|
||||
public void readShouldReturnAbsentKey() throws Exception {
|
||||
|
||||
VaultResponse read = vaultOperations.read("secret/absent");
|
||||
|
||||
assertThat(read).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readShouldReturnExistingKey() throws Exception {
|
||||
|
||||
vaultOperations.write("secret/mykey", Collections.singletonMap("hello", "world"));
|
||||
|
||||
VaultResponse read = vaultOperations.read("secret/mykey");
|
||||
assertThat(read).isNotNull();
|
||||
assertThat(read.getData()).containsEntry("hello", "world");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readObjectShouldReadDomainClass() throws Exception {
|
||||
|
||||
Map<String, String> data = new HashMap<String, String>();
|
||||
data.put("firstname", "Walter");
|
||||
data.put("password", "Secret");
|
||||
|
||||
vaultOperations.write("secret/mykey", data);
|
||||
|
||||
VaultResponseSupport<Person> read = vaultOperations.read("secret/mykey", Person.class);
|
||||
assertThat(read).isNotNull();
|
||||
|
||||
Person person = read.getData();
|
||||
assertThat(person.getFirstname()).isEqualTo("Walter");
|
||||
assertThat(person.getPassword()).isEqualTo("Secret");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listShouldReturnExistingKey() throws Exception {
|
||||
|
||||
vaultOperations.write("secret/mykey", Collections.singletonMap("hello", "world"));
|
||||
|
||||
List<String> keys = vaultOperations.list("secret");
|
||||
assertThat(keys).contains("mykey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteShouldRemoveKey() throws Exception {
|
||||
|
||||
vaultOperations.write("secret/mykey", Collections.singletonMap("hello", "world"));
|
||||
|
||||
vaultOperations.delete("secret/mykey");
|
||||
|
||||
VaultResponse read = vaultOperations.read("secret/mykey");
|
||||
assertThat(read).isNull();
|
||||
}
|
||||
|
||||
static class Person {
|
||||
|
||||
String firstname;
|
||||
String password;
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTemplate} using the {@code transit} backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
VaultSysOperations adminOperations = vaultOperations.opsForSys();
|
||||
|
||||
if (!adminOperations.getMounts().containsKey("transit/")) {
|
||||
adminOperations.mount("transit", new VaultMount("transit"));
|
||||
|
||||
vaultOperations.write("transit/keys/mykey", null);
|
||||
vaultOperations.write("transit/keys/derived", Collections.singletonMap("derived", true));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncrypt() throws Exception {
|
||||
|
||||
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext", Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
|
||||
assertThat((String) response.getData().get("ciphertext")).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncryptAndDecrypt() throws Exception {
|
||||
|
||||
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext", Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
|
||||
VaultResponse decrypted = vaultOperations.write("transit/decrypt/mykey",
|
||||
Collections.singletonMap("ciphertext", response.getData().get("ciphertext")));
|
||||
|
||||
assertThat((String) decrypted.getData().get("plaintext")).isEqualTo(Base64.encodeBase64String("that message is secret".getBytes()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.support.VaultTokenResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTokenTemplate} through {@link VaultTokenOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
private VaultTokenOperations tokenOperations;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
tokenOperations = vaultOperations.opsForToken();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTokenShouldCreateANewToken() {
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.create();
|
||||
assertThat(tokenResponse.getAuth()).containsKey("client_token");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTokenShouldCreateACustomizedToken() {
|
||||
|
||||
VaultTokenRequest tokenRequest = new VaultTokenRequest();
|
||||
tokenRequest.setDisplayName("display");
|
||||
tokenRequest.setExplicitMaxTtl("1h");
|
||||
tokenRequest.setTtl("30m");
|
||||
tokenRequest.setPolicies(Collections.singletonList("root"));
|
||||
tokenRequest.setNumUses(2);
|
||||
tokenRequest.setRenewable(true);
|
||||
tokenRequest.setId("HELLO-WORLD");
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.create(tokenRequest);
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token", tokenRequest.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createOrphanTokenShouldCreateAToken() {
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.createOrphan();
|
||||
assertThat(tokenResponse.getAuth()).containsKey("client_token");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createOrphanTokenShouldCreateACustomizedToken() {
|
||||
|
||||
VaultTokenRequest tokenRequest = new VaultTokenRequest();
|
||||
tokenRequest.setDisplayName("display");
|
||||
tokenRequest.setExplicitMaxTtl("1h");
|
||||
tokenRequest.setTtl("30m");
|
||||
tokenRequest.setPolicies(Collections.singletonList("root"));
|
||||
tokenRequest.setNumUses(2);
|
||||
tokenRequest.setRenewable(true);
|
||||
tokenRequest.setId("HELLO-WORLD");
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.createOrphan(tokenRequest);
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token", tokenRequest.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renewShouldRenewToken() {
|
||||
|
||||
VaultTokenRequest tokenRequest = new VaultTokenRequest();
|
||||
tokenRequest.setDisplayName("display");
|
||||
tokenRequest.setExplicitMaxTtl("1h");
|
||||
tokenRequest.setTtl("30m");
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.create(tokenRequest);
|
||||
VaultTokenResponse renew = tokenOperations.renew(tokenResponse.getToken());
|
||||
|
||||
assertThat(renew.getAuth()).containsKey("client_token");
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
public void renewShouldFailForNonRenewableRenewTokens() {
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.create();
|
||||
VaultTokenResponse renew = tokenOperations.renew(tokenResponse.getToken());
|
||||
|
||||
assertThat(renew.getAuth()).containsKey("client_token");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revokeShouldRevokeToken() {
|
||||
|
||||
final VaultTokenResponse tokenResponse = tokenOperations.create();
|
||||
tokenOperations.revoke(tokenResponse.getToken());
|
||||
|
||||
VaultResponseEntity<String> response = lookupSelf(tokenResponse);
|
||||
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
|
||||
assertThat(response.getMessage()).isEqualTo("permission denied");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createdTokenShouldBeUsableWithVaultClient() {
|
||||
|
||||
final VaultTokenResponse tokenResponse = tokenOperations.create();
|
||||
|
||||
VaultResponseEntity<String> response = lookupSelf(tokenResponse);
|
||||
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
private VaultResponseEntity<String> lookupSelf(final VaultTokenResponse tokenResponse) {
|
||||
|
||||
return vaultOperations.doWithVault(new VaultOperations.ClientCallback<VaultResponseEntity<String>>() {
|
||||
@Override
|
||||
public VaultResponseEntity<String> doWithVault(VaultClient client) {
|
||||
return client.getForEntity("/auth/token/lookup-self", tokenResponse.getToken(), String.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.demo;
|
||||
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate(new VaultClient(),
|
||||
new TokenAuthentication("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
Secrets secrets = new Secrets();
|
||||
secrets.username = "hello";
|
||||
secrets.password = "world";
|
||||
|
||||
vaultTemplate.write("secret/myapp", secrets);
|
||||
|
||||
VaultResponseSupport<Secrets> response = vaultTemplate.read("secret/myapp", Secrets.class);
|
||||
System.out.println(response.getData().getUsername());
|
||||
|
||||
vaultTemplate.delete("secret/myapp");
|
||||
}
|
||||
|
||||
public static class Secrets {
|
||||
|
||||
String username;
|
||||
String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Helper to check whether a TCP connection can be established.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CanConnect {
|
||||
|
||||
/**
|
||||
* Performs a check whether a connection can be established to the
|
||||
* {@code socketAddress}.
|
||||
*
|
||||
* @param socketAddress the address to test, must not be {@literal null}.
|
||||
* @return {@literal true}, if a connection can be established
|
||||
*/
|
||||
public static boolean to(SocketAddress socketAddress) {
|
||||
|
||||
Socket socket = new Socket();
|
||||
try {
|
||||
|
||||
socket.connect(socketAddress, (int) TimeUnit.SECONDS.toMillis(1));
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException o_O) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import org.junit.Rule;
|
||||
|
||||
/**
|
||||
* Base class for integration tests using Vault.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public abstract class IntegrationTestSupport {
|
||||
|
||||
@Rule public final VaultRule vaultRule = new VaultRule();
|
||||
|
||||
public final PrepareVault prepare() {
|
||||
return vaultRule.prepare();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.core.VaultSysOperations;
|
||||
import org.springframework.vault.support.VaultInitializationRequest;
|
||||
import org.springframework.vault.support.VaultInitializationResponse;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.support.VaultTokenResponse;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PrepareVault {
|
||||
|
||||
private final VaultOperations vaultOperations;
|
||||
private final VaultSysOperations adminOperations;
|
||||
|
||||
public PrepareVault(VaultOperations vaultOperations) {
|
||||
|
||||
this.vaultOperations = vaultOperations;
|
||||
this.adminOperations = vaultOperations.opsForSys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Vault and unseal the vault.
|
||||
*
|
||||
* @return the root token.
|
||||
*/
|
||||
public VaultToken initializeVault() {
|
||||
|
||||
int createKeys = 2;
|
||||
int requiredKeys = 2;
|
||||
|
||||
VaultInitializationResponse initialized = vaultOperations.opsForSys()
|
||||
.initialize(new VaultInitializationRequest(createKeys, requiredKeys));
|
||||
|
||||
for (int i = 0; i < requiredKeys; i++) {
|
||||
|
||||
VaultUnsealStatus unsealStatus = vaultOperations.opsForSys().unseal(initialized.getKeys().get(i));
|
||||
|
||||
if (!unsealStatus.isSealed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return VaultToken.of(initialized.getRootToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a token for the given {@code tokenId} and {@code policy}.
|
||||
*
|
||||
* @param tokenId
|
||||
* @param policy
|
||||
* @return
|
||||
*/
|
||||
public VaultToken createToken(String tokenId, String policy) {
|
||||
|
||||
VaultTokenRequest tokenRequest = new VaultTokenRequest();
|
||||
|
||||
tokenRequest.setId(tokenId);
|
||||
if (policy != null) {
|
||||
tokenRequest.setPolicies(Collections.singletonList(policy));
|
||||
}
|
||||
|
||||
VaultTokenResponse vaultTokenResponse = vaultOperations.opsForToken().create(tokenRequest);
|
||||
return vaultTokenResponse.getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether Vault is available (vault created and unsealed).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isAvailable() {
|
||||
return adminOperations.isInitialized() && !adminOperations.health().isSealed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mount an auth backend.
|
||||
*
|
||||
* @param authBackend
|
||||
*/
|
||||
public void mountAuth(String authBackend) {
|
||||
|
||||
Assert.hasText(authBackend, "AuthBackend must not be empty");
|
||||
|
||||
adminOperations.authMount(authBackend, new VaultMount(authBackend));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a auth-backend is enabled.
|
||||
*
|
||||
* @param authBackend
|
||||
* @return
|
||||
*/
|
||||
public boolean hasAuth(String authBackend) {
|
||||
|
||||
Assert.hasText(authBackend, "AuthBackend must not be empty");
|
||||
|
||||
return adminOperations.getAuthMounts().containsKey(authBackend + "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Mount an secret backend.
|
||||
*
|
||||
* @param secretBackend
|
||||
*/
|
||||
public void mountSecret(String secretBackend) {
|
||||
|
||||
Assert.hasText(secretBackend, "SecretBackend must not be empty");
|
||||
|
||||
adminOperations.mount(secretBackend, new VaultMount(secretBackend));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a auth-backend is enabled.
|
||||
*
|
||||
* @param secretBackend
|
||||
* @return
|
||||
*/
|
||||
public boolean hasSecret(String secretBackend) {
|
||||
|
||||
Assert.hasText(secretBackend, "SecretBackend must not be empty");
|
||||
return adminOperations.getMounts().containsKey(secretBackend);
|
||||
}
|
||||
|
||||
public VaultOperations getVaultOperations() {
|
||||
return vaultOperations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
|
||||
/**
|
||||
* Utility to retrieve settings during test.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class Settings {
|
||||
|
||||
/**
|
||||
* @return the vault properties.
|
||||
*/
|
||||
public static SslConfiguration createSslConfiguration() {
|
||||
|
||||
File workDir = findWorkDir();
|
||||
|
||||
return SslConfiguration.forTrustStore(new FileSystemResource(new File(workDir, "keystore.jks")), "changeit");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@code work} directory, starting at the {@code user.dir} directory. Search
|
||||
* is performed by walking the parent directories.
|
||||
* @return the {@link File} pointing to the {@code work} directory
|
||||
* @throws IllegalStateException If the {@code work} directory cannot be found.
|
||||
*/
|
||||
public static File findWorkDir() {
|
||||
return findWorkDir(new File(System.getProperty("user.dir")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@code work} directory, starting at the given {@code directory}. Search
|
||||
* is performed by walking the parent directories.
|
||||
* @return the {@link File} pointing to the {@code work} directory
|
||||
* @throws IllegalStateException If the {@code work} directory cannot be found.
|
||||
*/
|
||||
public static File findWorkDir(File directory) {
|
||||
|
||||
File searchLevel = directory;
|
||||
while (searchLevel.getParentFile() != null
|
||||
&& searchLevel.getParentFile() != searchLevel) {
|
||||
|
||||
File work = new File(searchLevel, "work");
|
||||
if (work.isDirectory() && work.exists()) {
|
||||
return work;
|
||||
}
|
||||
|
||||
searchLevel = searchLevel.getParentFile();
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format(
|
||||
"Cannot find work directory in %s or any parent directories",
|
||||
directory.getAbsoluteFile()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the token to use during tests.
|
||||
*/
|
||||
public static VaultToken token() {
|
||||
return VaultToken.of(System.getProperty("vault.token",
|
||||
"00000000-0000-0000-0000-000000000000"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.config.ClientHttpRequestFactoryFactory;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Factory for {@link RestTemplate}. The template caches the {@link ClientHttpRequestFactory} once it was initialized.
|
||||
* Changes to timeouts or the SSL configuration won't be applied once a {@link ClientHttpRequestFactory} was created for
|
||||
* the first time.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class TestRestTemplateFactory {
|
||||
|
||||
private static final AtomicReference<ClientHttpRequestFactory> factoryCache = new AtomicReference<ClientHttpRequestFactory>();
|
||||
|
||||
/**
|
||||
* Create a new {@link RestTemplate} using the {@link SslConfiguration}. The underlying
|
||||
* {@link ClientHttpRequestFactory} is cached. See {@link #create(ClientHttpRequestFactory)} to create
|
||||
* {@link RestTemplate} for a given {@link ClientHttpRequestFactory}.
|
||||
*
|
||||
* @param sslConfiguration must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static RestTemplate create(SslConfiguration sslConfiguration) {
|
||||
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null!");
|
||||
|
||||
try {
|
||||
initializeClientHttpRequestFactory(sslConfiguration);
|
||||
return create(factoryCache.get());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RestTemplate} using the {@link ClientHttpRequestFactory}. The {@link RestTemplate} will throw
|
||||
* {@link org.springframework.web.client.HttpStatusCodeException exceptions} in error cases and behave in that aspect
|
||||
* like the regular {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @param requestFactory must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static RestTemplate create(ClientHttpRequestFactory requestFactory) {
|
||||
|
||||
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null!");
|
||||
|
||||
RestTemplate RestTemplate = new RestTemplate();
|
||||
RestTemplate.setErrorHandler(new DefaultResponseErrorHandler());
|
||||
RestTemplate.setRequestFactory(requestFactory);
|
||||
|
||||
return RestTemplate;
|
||||
}
|
||||
|
||||
private static void initializeClientHttpRequestFactory(SslConfiguration sslConfiguration) throws Exception {
|
||||
|
||||
if (factoryCache.get() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory
|
||||
.create(new ClientOptions(), sslConfiguration);
|
||||
|
||||
if (factoryCache.compareAndSet(null, clientHttpRequestFactory)) {
|
||||
|
||||
if (clientHttpRequestFactory instanceof InitializingBean) {
|
||||
((InitializingBean) clientHttpRequestFactory).afterPropertiesSet();
|
||||
}
|
||||
|
||||
if (clientHttpRequestFactory instanceof DisposableBean) {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread("ClientHttpRequestFactory Shutdown Hook") {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
((DisposableBean) clientHttpRequestFactory).destroy();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.authentication.SessionManager;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.core.DefaultVaultClientFactory;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Vault rule to ensure a running and prepared Vault.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultRule extends ExternalResource {
|
||||
|
||||
private final VaultEndpoint vaultEndpoint;
|
||||
private final PrepareVault prepareVault;
|
||||
|
||||
private VaultToken token;
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultRule} with default SSL configuration and endpoint.
|
||||
*
|
||||
* @see Settings#createSslConfiguration()
|
||||
* @see VaultEndpoint
|
||||
*/
|
||||
public VaultRule() {
|
||||
this(Settings.createSslConfiguration(), new VaultEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultRule} with the given {@link SslConfiguration} and {@link VaultEndpoint}.
|
||||
*
|
||||
* @param sslConfiguration must not be {@literal null}.
|
||||
* @param vaultEndpoint must not be {@literal null}.
|
||||
*/
|
||||
public VaultRule(SslConfiguration sslConfiguration, VaultEndpoint vaultEndpoint) {
|
||||
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
|
||||
Assert.notNull(vaultEndpoint, "VaultEndpoint must not be null");
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(sslConfiguration), vaultEndpoint);
|
||||
DefaultVaultClientFactory clientFactory = new DefaultVaultClientFactory(vaultClient);
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate(clientFactory, new PreparingSessionManager());
|
||||
|
||||
this.token = Settings.token();
|
||||
this.prepareVault = new PrepareVault(vaultTemplate);
|
||||
this.vaultEndpoint = vaultEndpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void before() {
|
||||
|
||||
Socket socket = null;
|
||||
try {
|
||||
|
||||
socket = new Socket();
|
||||
|
||||
socket.connect(new InetSocketAddress(InetAddress.getByName("localhost"), vaultEndpoint.getPort()));
|
||||
socket.close();
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Vault is not running on localhost:%d which is required to run a test using @Rule %s",
|
||||
vaultEndpoint.getPort(), getClass().getSimpleName()));
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.prepareVault.isAvailable()) {
|
||||
this.token = prepareVault.initializeVault();
|
||||
this.prepareVault.createToken(Settings.token().getToken(), "root");
|
||||
this.token = Settings.token();
|
||||
}
|
||||
}
|
||||
|
||||
public PrepareVault prepare() {
|
||||
return prepareVault;
|
||||
}
|
||||
|
||||
private class PreparingSessionManager implements SessionManager {
|
||||
|
||||
@Override
|
||||
public VaultToken getSessionToken() {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
spring-vault-core/src/test/resources/logback.xml
Normal file
18
spring-vault-core/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
1
spring-vault-core/src/test/resources/logging.properties
Normal file
1
spring-vault-core/src/test/resources/logging.properties
Normal file
@@ -0,0 +1 @@
|
||||
handlers = org.slf4j.bridge.SLF4JBridgeHandler
|
||||
143
spring-vault-dependencies/pom.xml
Normal file
143
spring-vault-dependencies/pom.xml
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-dependencies</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>spring-vault-dependencies</name>
|
||||
<description>Spring Vault Dependencies</description>
|
||||
|
||||
<properties>
|
||||
<spring.version>4.3.2.RELEASE</spring.version>
|
||||
<httpclient.version>4.5.2</httpclient.version>
|
||||
<httpcore.version>4.4.4</httpcore.version>
|
||||
<netty.version>4.1.4.Final</netty.version>
|
||||
<okhttp.version>2.7.5</okhttp.version>
|
||||
<jackson.version>2.8.2</jackson.version>
|
||||
<slf4j.version>1.7.21</slf4j.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring Vault -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-vault-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Framework -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- HTTP Client Libraries -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${httpcore.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
41
spring-vault-distribution/pom.xml
Normal file
41
spring-vault-distribution/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-vault-distribution</artifactId>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Vault - Distribution</name>
|
||||
<description>Distribution build for Spring Vault</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
26
src/main/asciidoc/index.adoc
Normal file
26
src/main/asciidoc/index.adoc
Normal file
@@ -0,0 +1,26 @@
|
||||
= Spring Vault - Reference Documentation
|
||||
Mark Paluch;
|
||||
:revnumber: {version}
|
||||
:revdate: {localdate}
|
||||
:toc:
|
||||
:toc-placement!:
|
||||
|
||||
(C) 2016 The original authors.
|
||||
|
||||
NOTE: _Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically._
|
||||
|
||||
toc::[]
|
||||
|
||||
:leveloffset: +1
|
||||
include::preface.adoc[]
|
||||
include::new-features.adoc[]
|
||||
:leveloffset: -1
|
||||
|
||||
[[reference]]
|
||||
= Reference Documentation
|
||||
|
||||
:leveloffset: +1
|
||||
include::reference/introduction.adoc[]
|
||||
include::reference/vault.adoc[]
|
||||
:leveloffset: -1
|
||||
|
||||
8
src/main/asciidoc/new-features.adoc
Normal file
8
src/main/asciidoc/new-features.adoc
Normal file
@@ -0,0 +1,8 @@
|
||||
[[new-features]]
|
||||
= New & Noteworthy
|
||||
|
||||
[[new-features.1-0-0]]
|
||||
== What's new in Spring Vault 1.0
|
||||
|
||||
* Initial Vault support.
|
||||
|
||||
62
src/main/asciidoc/preface.adoc
Normal file
62
src/main/asciidoc/preface.adoc
Normal file
@@ -0,0 +1,62 @@
|
||||
[[preface]]
|
||||
= Preface
|
||||
|
||||
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.
|
||||
|
||||
This document is the reference guide for Spring Vault. It explains Vault concepts and semantics and the syntax.
|
||||
|
||||
This section provides some basic introduction to Spring and Vault. The rest of the document refers only to Spring Vault features and assumes the user is familiar with Hashicorp Vault as well as Spring concepts.
|
||||
|
||||
[[get-started:first-steps:spring]]
|
||||
== Knowing Spring
|
||||
Spring Vault uses Spring framework's http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/spring-core.html[core] functionality, such as the http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/beans.html[IoC] container, http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/validation.html#core-convert[type conversion system], http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/expressions.html[expression language], http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/jmx.html[JMX integration], and portable http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/html/dao.html#dao-exceptions[DAO exception hierarchy]. 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.
|
||||
|
||||
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 `RestTemplate` 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.
|
||||
|
||||
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 http://spring.io/docs[home page ] for more information.
|
||||
|
||||
[[get-started:first-steps:vault]]
|
||||
== Knowing Vault
|
||||
|
||||
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.
|
||||
|
||||
The jumping off ground for learning about Vault is www.vaultproject.io. Here is a list of useful resources:
|
||||
|
||||
* The manual introduces Vault and contains links to getting started guides, reference documentation and tutorials.
|
||||
|
||||
* The online shell provides a convenient way to interact with a Vault instance in combination with the online tutorial.
|
||||
|
||||
* https://www.vaultproject.io/intro/index.html[Hashicorp Vault Introduction]
|
||||
|
||||
* https://www.vaultproject.io/docs/index.html[Hashicorp Vault Documentation]
|
||||
|
||||
[[requirements]]
|
||||
== Requirements
|
||||
|
||||
Spring Vault 1.x binaries requires JDK level 6.0 and above, and http://spring.io/docs[Spring Framework] {springVersion} and above.
|
||||
|
||||
In terms of Vault, https://www.vaultproject.io/[Vault] at least 0.5.
|
||||
|
||||
== Additional Help Resources
|
||||
|
||||
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:
|
||||
|
||||
[[get-started:help]]
|
||||
=== Support
|
||||
|
||||
There are a few support options available:
|
||||
|
||||
[[get-started:help:community]]
|
||||
==== Community Forum
|
||||
|
||||
Spring Vault on Stackoverflow http://stackoverflow.com/questions/tagged/spring-vault[Stackoverflow] is a tag for all Spring Vault users to share information and help each other. Note that registration is needed *only* for posting.
|
||||
|
||||
[[get-started:help:professional]]
|
||||
==== Professional Support
|
||||
|
||||
Professional, from-the-source support, with guaranteed response time, is available from http://pivotal.io/[Pivotal Sofware, Inc.], the company behind Spring Vault and Spring.
|
||||
|
||||
[[get-started:up-to-date]]
|
||||
=== Following Development
|
||||
|
||||
For information on the Spring Vault source code repository, nightly builds and snapshot artifacts please see the http://projects.spring.io/spring-vault/[Spring Vault homepage]. You can help make Spring Vault best serve the needs of the Spring community by interacting with developers through the Community on http://stackoverflow.com/questions/tagged/spring-vault[Stackoverflow]. If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Vault issue https://github.com/spring-projects/spring-vault/issues[tracker]. To stay up to date with the latest news and announcements in the Spring ecosystem, subscribe to the Spring Community http://spring.io[Portal]. Lastly, you can follow the Spring http://spring.io/blog[blog ]or the project team on Twitter (http://twitter.com/springcentral[SpringCentral]).
|
||||
13
src/main/asciidoc/reference/introduction.adoc
Normal file
13
src/main/asciidoc/reference/introduction.adoc
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
[[introduction]]
|
||||
= Introduction
|
||||
|
||||
== Document Structure
|
||||
|
||||
This part of the reference documentation explains the core functionality offered by Spring Vault.
|
||||
|
||||
<<vault.core>> introduces the Vault module feature set.
|
||||
|
||||
Spring Vault provides client-side support for accessing, storing and revoking secrets.
|
||||
With https://www.vaultproject.io[Hashicorp's Vault] you have a central place to manage external secret data for applications across all environments.
|
||||
Vault can manage static and dynamic secrets such as application data, username/password for remote applications/resources and provide credentials for external services such as MySQL, PostgreSQL, Apache Cassandra, Consul, AWS and more.
|
||||
547
src/main/asciidoc/reference/vault.adoc
Normal file
547
src/main/asciidoc/reference/vault.adoc
Normal file
@@ -0,0 +1,547 @@
|
||||
[[vault.core]]
|
||||
= Vault support
|
||||
|
||||
The Vault support contains a wide range of features which are summarized below.
|
||||
|
||||
* Spring configuration support using Java based @Configuration classes
|
||||
* `VaultTemplate` helper class that increases productivity performing common
|
||||
Vault operations. Includes integrated object mapping between Vault responses and POJOs.
|
||||
|
||||
For most tasks, you will find yourself using `VaultTemplate` that leverages the
|
||||
rich communication functionality. `VaultTemplate` is the place to look for
|
||||
accessing functionality such as reading data from Vault or issuing administrative commands. `VaultTemplate` also provides callback methods so that it is easy for you to
|
||||
get a hold of the low-level API artifacts such as `RestTemplate` to communicate
|
||||
directly with Vault.
|
||||
|
||||
[[vault.core.getting-started]]
|
||||
== Getting Started
|
||||
|
||||
Spring Vault support requires Vault 0.5 or higher and Java SE 6 or higher.
|
||||
An easy way to bootstrap setting up a working environment is to create a Spring based project in http://spring.io/tools/sts[STS].
|
||||
|
||||
First you need to set up a running Vault server. Refer to the https://www.vaultproject.io/intro/[Vault] for an explanation on how to startup a Vault instance.
|
||||
|
||||
To create a Spring project in STS go to File -> New -> Spring Template Project -> Simple Spring Utility Project -> press Yes when prompted. Then enter a project and a package name such as org.spring.vault.example.
|
||||
|
||||
Then add the following to pom.xml dependencies section.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<dependencies>
|
||||
|
||||
<!-- other dependency elements omitted -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
<artifactId>spring-vault-core</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
----
|
||||
|
||||
Also change the version of Spring in the pom.xml to be
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<spring.framework.version>{springVersion}</spring.framework.version>
|
||||
----
|
||||
|
||||
You will also need to add the location of the Spring Milestone repository for maven to your pom.xml which is at the same level of your <dependencies/> element
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Maven MILESTONE Repository</name>
|
||||
<url>http://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
|
||||
The repository is also http://repo.spring.io/milestone/org/springframework/data/[browseable here].
|
||||
|
||||
You may also want to set the logging level to `DEBUG` to see some additional information, edit the log4j.properties file to have
|
||||
|
||||
[source]
|
||||
----
|
||||
log4j.category.org.springframework.vault=DEBUG
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
----
|
||||
Create a simple `Secrets` class to persist:
|
||||
|
||||
.Mapped data object
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
package org.spring.vault.example;
|
||||
|
||||
public class Secrets {
|
||||
|
||||
String username;
|
||||
String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
And a main application to run
|
||||
|
||||
.Example application using Spring Vault
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
package org.springframework.vault.example;
|
||||
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
public class VaultApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate(new VaultClient(),
|
||||
new TokenAuthentication("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
Secrets secrets = new Secrets();
|
||||
secrets.username = "hello";
|
||||
secrets.password = "world";
|
||||
|
||||
vaultTemplate.write("secret/myapp", secrets);
|
||||
|
||||
VaultResponseSupport<Secrets> response = vaultTemplate.read("secret/myapp", Secrets.class);
|
||||
System.out.println(response.getData().getUsername());
|
||||
|
||||
vaultTemplate.delete("secret/myapp");
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Even in this simple example, there are few things to take notice of
|
||||
|
||||
* You can instantiate the central helper class of Spring Vault,
|
||||
<<vault-template,`VaultTemplate`>>, using the `org.springframework.vault.client.VaultClient`
|
||||
object and the `ClientAuthentication`.
|
||||
* The mapper works against standard POJO objects without the need for any
|
||||
additional metadata (though you can optionally provide that information).
|
||||
* Mapping conventions can use field access. Notice the `Secrets` class has only getters.
|
||||
* If the constructor argument names match the field names of the stored document,
|
||||
they will be used to instantiate the object
|
||||
|
||||
[[vault.core.connection]]
|
||||
== Connecting to Vault with Spring
|
||||
|
||||
One of the first tasks when using Vault and Spring is to create a `org.springframework.vault.client.VaultClient` object using the IoC container.
|
||||
|
||||
[[vault.core.vault-java-config]]
|
||||
=== Registering a Vault instance using Java based metadata
|
||||
|
||||
An example of using Java based bean metadata to register common Vault support classes.
|
||||
|
||||
.Registering a Spring Vault objects using Java based bean metadata
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
/**
|
||||
* Specify an endpoint for connecting to Vault.
|
||||
*/
|
||||
@Override
|
||||
public VaultEndpoint vaultEndpoint() {
|
||||
return new VaultEndpoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a client authentication.
|
||||
* Please consider a more secure authentication method
|
||||
* for production use.
|
||||
*/
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
return new TokenAuthentication("…");
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
[[vault.core.template]]
|
||||
== Introduction to VaultTemplate
|
||||
|
||||
The class `VaultTemplate`, located in the package `org.springframework.vault.core`,
|
||||
is the central class of the Spring's Vault support providing a rich feature set to
|
||||
interact with Vault. The template offers convenience operations to read, write and
|
||||
delete data in Vault and provides a mapping between your domain objects and Vault data.
|
||||
|
||||
NOTE: Once configured, `VaultTemplate` is thread-safe and can be reused across multiple instances.
|
||||
|
||||
The mapping between Vault documents and domain classes is done by delegating to
|
||||
`RestTemplate`. Spring Web support provides the mapping infrastructure.
|
||||
|
||||
The `VaultTemplate` class implements the interface `VaultOperations`.
|
||||
In as much as possible, the methods on `VaultOperations` are named after methods
|
||||
available on the Vault API to make the API familiar to existing Vault developers
|
||||
who are used to the API and CLI. For example, you will find methods such as
|
||||
"write", "delete", "read", and "revoke".
|
||||
The design goal was to make it as easy as possible to transition between
|
||||
the use of the Vault API and `VaultOperations`. A major difference in between
|
||||
the two APIs is that `VaultOperations` can be passed domain objects instead of JSON Key-Value pairs.
|
||||
|
||||
NOTE: The preferred way to reference the operations on `VaultTemplate` instance is via its interface `VaultOperations`.
|
||||
|
||||
While there are many convenience methods on `VaultTemplate` to help you easily
|
||||
perform common tasks if you should need to access the Vault API directly to access
|
||||
functionality not explicitly exposed by the `VaultTemplate` you can use one of
|
||||
several execute callback methods to access underlying APIs. The execute callbacks
|
||||
will give you a reference to either a `RestTemplate` or a `VaultClient` object. Please see the section <<vault.core.executioncallback,Execution Callbacks>> for more information.
|
||||
|
||||
Now let's look at a examples of how to work with the `VaultTemplate` in the context of the Spring container.
|
||||
|
||||
[[vault.core.template.instantiating]]
|
||||
=== Instantiating VaultTemplate
|
||||
|
||||
You can use Java to create and register an instance of `VaultTemplate` as shown below.
|
||||
|
||||
.Registering a `VaultTemplate` object
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig {
|
||||
|
||||
@Bean
|
||||
public VaultTemplate vaultTemplate() {
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate();
|
||||
vaultTemplate.setSessionManager(sessionManager());
|
||||
vaultTemplate.setVaultClientFactory(clientFactory());
|
||||
|
||||
return vaultTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultVaultClientFactory clientFactory() {
|
||||
return new DefaultVaultClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultSessionManager sessionManager() {
|
||||
return new DefaultSessionManager(new TokenAuthentication("…"));
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
There are several overloaded constructors of `VaultTemplate`. These are
|
||||
|
||||
* `VaultTemplate(VaultClient, ClientAuthentication)` - takes the `VaultClient` object and client authentication
|
||||
* `VaultTemplate(VaultClientFactory, SessionManager)` - takes a client factory for resource management and a `SessionManager`.
|
||||
|
||||
[[vault.core.clients]]
|
||||
=== Client support
|
||||
|
||||
|
||||
[[vault.core.authentication]]
|
||||
== Vault authentication
|
||||
|
||||
Different organizations have different requirements for security
|
||||
and authentication. Vault reflects that need by shipping multiple authentication
|
||||
methods. Spring Vault supports multiple authentications mechanisms.
|
||||
|
||||
=== Token authentication
|
||||
|
||||
Tokens are the core method for authentication within Vault.
|
||||
Token authentication requires a static token to be provided.
|
||||
|
||||
NOTE: Token authentication is the default authentication method.
|
||||
If a token is disclosed an unintended party, it gains access to Vault and
|
||||
can access secrets for the intended client.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
return new TokenAuthentication("…");
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
See also: https://www.vaultproject.io/docs/concepts/tokens.html[Vault Documentation: Tokens]
|
||||
|
||||
=== AppId authentication
|
||||
|
||||
Vault supports https://www.vaultproject.io/docs/auth/app-id.html[AppId]
|
||||
authentication that consists of two hard to guess tokens. The AppId
|
||||
defaults to `spring.application.name` that is statically configured.
|
||||
The second token is the UserId which is a part determined by the application,
|
||||
usually related to the runtime environment. IP address, Mac address or a
|
||||
Docker container name are good examples. Spring Vault supports
|
||||
IP address, Mac address and static UserId's (e.g. supplied via System properties).
|
||||
The IP and Mac address are represented as Hex-encoded SHA256 hash.
|
||||
|
||||
IP address-based UserId's use the local host's IP address.
|
||||
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("myapp") //
|
||||
.userIdMechanism(new IpAddressUserId()) //
|
||||
.build();
|
||||
|
||||
return new AppIdAuthentication(options, vaultClient());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The corresponding command to generate the IP address UserId from a command line is:
|
||||
|
||||
----
|
||||
$ echo -n 192.168.99.1 | sha256sum
|
||||
----
|
||||
|
||||
NOTE: Including the line break of `echo` leads to a different hash value
|
||||
so make sure to include the `-n` flag.
|
||||
|
||||
Mac address-based UserId's obtain their network device from the
|
||||
localhost-bound device. The configuration also allows specifying
|
||||
a `network-interface` hint to pick the right device. The value of
|
||||
`network-interface` is optional and can be either an interface
|
||||
name or interface index (0-based).
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("myapp") //
|
||||
.userIdMechanism(new MacAddressUserId()) //
|
||||
.build();
|
||||
|
||||
return new AppIdAuthentication(options, vaultClient());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The corresponding command to generate the IP address UserId from a command line is:
|
||||
|
||||
----
|
||||
$ echo -n 0AFEDE1234AC | sha256sum
|
||||
----
|
||||
|
||||
NOTE: The Mac address is specified uppercase and without colons.
|
||||
Including the line break of `echo` leads to a different hash value
|
||||
so make sure to include the `-n` flag.
|
||||
|
||||
==== Custom UserId
|
||||
|
||||
A more advanced approach lets you implementing your own `AppIdUserIdMechanism`.
|
||||
This class must be on your classpath and must implement
|
||||
the `org.springframework.vault.authentication.AppIdUserIdMechanism` interface
|
||||
and the `createUserId` method. Spring Vault will obtain the UserId
|
||||
by calling `createUserId` each time it authenticates using AppId to
|
||||
obtain a token.
|
||||
|
||||
|
||||
[source,java]
|
||||
.MyUserIdMechanism.java
|
||||
----
|
||||
public class MyUserIdMechanism implements AppIdUserIdMechanism {
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
String userId = ...
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
See also: https://www.vaultproject.io/docs/auth/app-id.html[Vault Documentation: Using the App ID auth backend]
|
||||
|
||||
=== AWS-EC2 authentication
|
||||
|
||||
The https://www.vaultproject.io/docs/auth/aws-ec2.html[aws-ec2]
|
||||
auth backend provides a secure introduction mechanism
|
||||
for AWS EC2 instances, allowing automated retrieval of a Vault
|
||||
token. Unlike most Vault authentication backends, this backend
|
||||
does not require first-deploying, or provisioning security-sensitive
|
||||
credentials (tokens, username/password, client certificates, etc.).
|
||||
Instead, it treats AWS as a Trusted Third Party and uses the
|
||||
cryptographically signed dynamic metadata information that uniquely
|
||||
represents each EC2 instance.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
return new AwsEc2Authentication(vaultClient());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
AWS-EC2 authentication enables nonce by default to follow
|
||||
the Trust On First Use (TOFU) principle. Any unintended party that
|
||||
gains access to the PKCS#7 identity metadata can authenticate
|
||||
against Vault.
|
||||
|
||||
During the first login, Spring Vault generates a nonce
|
||||
that is stored in the auth backend aside the instance Id.
|
||||
Re-authentication requires the same nonce to be sent. Any other
|
||||
party does not have the nonce and can raise an alert in Vault for
|
||||
further investigation.
|
||||
|
||||
The nonce is kept in memory and is lost during application restart.
|
||||
|
||||
AWS-EC2 authentication roles are optional and default to the AMI.
|
||||
You can configure the authentication role by setting
|
||||
it in `AwsEc2AuthenticationOptions`.
|
||||
|
||||
See also: https://www.vaultproject.io/docs/auth/aws-ec2.html[Vault Documentation: Using the aws-ec2 auth backend]
|
||||
|
||||
=== TLS certificate authentication
|
||||
|
||||
The `cert` auth backend allows authentication using SSL/TLS client
|
||||
certificates that are either signed by a CA or self-signed.
|
||||
|
||||
To enable `cert` authentication you need to:
|
||||
|
||||
1. Use SSL, see <<vault.client-ssl>>
|
||||
2. Configure a Java `Keystore` that contains the client
|
||||
certificate and the private key
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
return new ClientCertificateAuthentication(options, vaultClient());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
See also: https://www.vaultproject.io/docs/auth/cert.html[Vault Documentation: Using the cert auth backend]
|
||||
|
||||
[[vault.client-ssl]]
|
||||
== Vault Client SSL configuration
|
||||
|
||||
SSL can be configured using `SslConfiguration` by setting various properties.
|
||||
You can set either `javax.net.ssl.trustStore` to configure
|
||||
JVM-wide SSL settings or configure `SslConfiguration`
|
||||
to set SSL settings only for Spring Vault.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
|
||||
SslConfiguration sslConfiguration = new SslConfiguration( <1>
|
||||
new FileSystemResource("client-cert.jks"), "changeit",
|
||||
new FileSystemResource("truststore.jks"), "changeit");
|
||||
|
||||
SslConfiguration.forTrustStore(new FileSystemResource("keystore.jks"), <2>
|
||||
"changeit")
|
||||
|
||||
SslConfiguration.forKeyStore(new FileSystemResource("keystore.jks"), <3>
|
||||
"changeit")
|
||||
|
||||
----
|
||||
<1> Full configuration.
|
||||
<2> Configuring only trust store settings.
|
||||
<3> Configuring only key store settings.
|
||||
====
|
||||
|
||||
Please note that providing `SslConfiguration` can be only
|
||||
applied when either Apache Http Components or the OkHttp client
|
||||
is on your class-path.
|
||||
|
||||
[[vault.core.executioncallback]]
|
||||
== Execution callbacks
|
||||
|
||||
One common design feature of all Spring template classes is that all functionality is routed into one of the templates execute callback methods. This helps ensure that exceptions and any resource management that maybe required are performed consistency. While this was of much greater need in the case of JDBC and JMS than with Vault, it still offers a single spot for access and logging to occur. As such, using the execute callback is the preferred way to access the Vault API to perform uncommon operations that we've not exposed as methods on `VaultTemplate`.
|
||||
|
||||
Here is a list of execute callback methods.
|
||||
|
||||
* `<T> T` *doWithVault* `(ClientCallback<T> clientCallback)` Executes the given `ClientCallback`, allows to interact with Vault using `VaultClient` without requiring a session.
|
||||
|
||||
* `<T> T` *doWithVault* `(SessionCallback<T> sessionCallback)` Executes the given `SessionCallback`, allows to interact with Vault in an authenticated session..
|
||||
|
||||
* `<T> T` *doWithRestTemplate* `(String pathTemplate, Map<String, ?> variables, RestTemplateCallback<T> callback)` Expands the `pathTemplate` to an `java.net.URI` and allows low-level interaction with the underlying `org.springframework.web.client.RestTemplate`.
|
||||
|
||||
|
||||
Here is an example that uses the `ClientCallback` to initialize Vault:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
return vaultTemplate.doWithVault(new ClientCallback<VaultInitializationResponse>() {
|
||||
|
||||
@Override
|
||||
public VaultInitializationResponse doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultInitializationResponse> response = client.putForEntity("sys/init",
|
||||
vaultInitializationRequest, VaultInitializationResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
return null.
|
||||
}
|
||||
});
|
||||
----
|
||||
====
|
||||
5
src/main/resources/changelog.txt
Normal file
5
src/main/resources/changelog.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Spring Vault Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 1.0.0.M1 (?)
|
||||
-----------------------------------------
|
||||
216
src/main/resources/license.txt
Normal file
216
src/main/resources/license.txt
Normal file
@@ -0,0 +1,216 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
=======================================================================
|
||||
|
||||
To the extent any open source subcomponents are licensed under the EPL and/or other
|
||||
similar licenses that require the source code and/or modifications to
|
||||
source code to be made available (as would be noted above), you may obtain a
|
||||
copy of the source code corresponding to the binaries for such open source
|
||||
components and modifications thereto, if any, (the "Source Files"), by
|
||||
downloading the Source Files from http://www.springsource.org/download,
|
||||
or by sending a request, with your name and address to: VMware, Inc., 3401 Hillview
|
||||
Avenue, Palo Alto, CA 94304, United States of America or email info@vmware.com. All
|
||||
such requests should clearly specify: OPEN SOURCE FILES REQUEST, Attention General
|
||||
Counsel. VMware shall mail a copy of the Source Files to you on a CD or equivalent
|
||||
physical medium. This offer to obtain a copy of the Source Files is valid for three
|
||||
years from the date you acquired this Software product.
|
||||
10
src/main/resources/notice.txt
Normal file
10
src/main/resources/notice.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Spring Vault 1.10 M1
|
||||
Copyright (c) [2016] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
You may not use this product except in compliance with the License.
|
||||
|
||||
This product may include a number of subcomponents with
|
||||
separate copyright notices and license terms. Your use of the source
|
||||
code for the these subcomponents is subject to the terms and
|
||||
conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
103
src/test/bash/create_certificates.sh
Executable file
103
src/test/bash/create_certificates.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
CA_DIR=work/ca
|
||||
KEYSTORE_FILE=work/keystore.jks
|
||||
CLIENT_CERT_KEYSTORE=work/client-cert.jks
|
||||
if [[ -d work/ca ]] ; then
|
||||
rm -Rf ${CA_DIR}
|
||||
fi
|
||||
|
||||
if [[ -f ${KEYSTORE_FILE} ]] ; then
|
||||
rm -Rf ${KEYSTORE_FILE}
|
||||
fi
|
||||
|
||||
if [[ -f ${CLIENT_CERT_KEYSTORE} ]] ; then
|
||||
rm -Rf ${CLIENT_CERT_KEYSTORE}
|
||||
fi
|
||||
|
||||
mkdir -p ${CA_DIR}/private ${CA_DIR}/certs ${CA_DIR}/crl ${CA_DIR}/csr ${CA_DIR}/newcerts ${CA_DIR}/intermediate
|
||||
|
||||
echo "[INFO] Generating CA private key"
|
||||
# Less bits = less secure = faster to generate
|
||||
openssl genrsa -passout pass:changeit -aes256 -out ${CA_DIR}/private/ca.key.pem 2048
|
||||
|
||||
chmod 400 ${CA_DIR}/private/ca.key.pem
|
||||
|
||||
echo "[INFO] Generating CA certificate"
|
||||
openssl req -config ${DIR}/openssl.cnf \
|
||||
-key ${CA_DIR}/private/ca.key.pem \
|
||||
-new -x509 -days 7300 -sha256 -extensions v3_ca \
|
||||
-out ${CA_DIR}/certs/ca.cert.pem \
|
||||
-passin pass:changeit \
|
||||
-subj "/C=NN/ST=Unknown/L=Unknown/O=spring-cloud-vault-config/CN=CA Certificate"
|
||||
|
||||
echo "[INFO] Prepare CA database"
|
||||
echo 1000 > ${CA_DIR}/serial
|
||||
touch ${CA_DIR}/index.txt
|
||||
|
||||
echo "[INFO] Generating server private key"
|
||||
openssl genrsa -aes256 \
|
||||
-passout pass:changeit \
|
||||
-out ${CA_DIR}/private/localhost.key.pem 2048
|
||||
|
||||
openssl rsa -in ${CA_DIR}/private/localhost.key.pem \
|
||||
-out ${CA_DIR}/private/localhost.decrypted.key.pem \
|
||||
-passin pass:changeit
|
||||
|
||||
chmod 400 ${CA_DIR}/private/localhost.key.pem
|
||||
|
||||
echo "[INFO] Generating server certificate request"
|
||||
openssl req -config ${DIR}/openssl.cnf \
|
||||
-key ${CA_DIR}/private/localhost.key.pem \
|
||||
-passin pass:changeit \
|
||||
-new -sha256 -out ${CA_DIR}/csr/localhost.csr.pem \
|
||||
-subj "/C=NN/ST=Unknown/L=Unknown/O=spring-cloud-vault-config/CN=localhost"
|
||||
|
||||
echo "[INFO] Signing certificate request"
|
||||
openssl ca -config ${DIR}/openssl.cnf \
|
||||
-extensions server_cert -days 375 -notext -md sha256 \
|
||||
-passin pass:changeit \
|
||||
-batch \
|
||||
-in ${CA_DIR}/csr/localhost.csr.pem \
|
||||
-out ${CA_DIR}/certs/localhost.cert.pem
|
||||
|
||||
|
||||
echo "[INFO] Generating client auth private key"
|
||||
openssl genrsa -aes256 \
|
||||
-passout pass:changeit \
|
||||
-out ${CA_DIR}/private/client.key.pem 2048
|
||||
|
||||
openssl rsa -in ${CA_DIR}/private/client.key.pem \
|
||||
-out ${CA_DIR}/private/client.decrypted.key.pem \
|
||||
-passin pass:changeit
|
||||
|
||||
chmod 400 ${CA_DIR}/private/client.key.pem
|
||||
|
||||
echo "[INFO] Generating client certificate request"
|
||||
openssl req -config ${DIR}/openssl.cnf \
|
||||
-key ${CA_DIR}/private/client.key.pem \
|
||||
-passin pass:changeit \
|
||||
-new -sha256 -out ${CA_DIR}/csr/client.csr.pem \
|
||||
-subj "/C=NN/ST=Unknown/L=Unknown/O=spring-cloud-vault-config/CN=client"
|
||||
|
||||
echo "[INFO] Signing certificate request"
|
||||
openssl ca -config ${DIR}/openssl.cnf \
|
||||
-extensions usr_cert -days 375 -notext -md sha256 \
|
||||
-passin pass:changeit \
|
||||
-batch \
|
||||
-in ${CA_DIR}/csr/client.csr.pem \
|
||||
-out ${CA_DIR}/certs/client.cert.pem
|
||||
|
||||
echo "[INFO] Creating PKCS12 file with client certificate"
|
||||
openssl pkcs12 -export -clcerts \
|
||||
-in ${CA_DIR}/certs/client.cert.pem \
|
||||
-inkey ${CA_DIR}/private/client.decrypted.key.pem \
|
||||
-passout pass:changeit \
|
||||
-out ${CA_DIR}/client.p12
|
||||
|
||||
${JAVA_HOME}/bin/keytool -importcert -keystore ${KEYSTORE_FILE} -file ${CA_DIR}/certs/ca.cert.pem -noprompt -storepass changeit
|
||||
${JAVA_HOME}/bin/keytool -importkeystore \
|
||||
-srckeystore ${CA_DIR}/client.p12 -srcstoretype PKCS12 -srcstorepass changeit\
|
||||
-destkeystore ${CLIENT_CERT_KEYSTORE} -deststoretype JKS \
|
||||
-noprompt -storepass changeit
|
||||
12
src/test/bash/env.sh
Executable file
12
src/test/bash/env.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
###########################################################################
|
||||
# Vault environment settings. Source this file. #
|
||||
###########################################################################
|
||||
|
||||
export VAULT_TOKEN=00000000-0000-0000-0000-000000000000
|
||||
export VAULT_ADDR=https://localhost:8200
|
||||
export VAULT_SKIP_VERIFY=false
|
||||
export VAULT_CAPATH=${DIR}/work/ca/certs/ca.cert.pem
|
||||
46
src/test/bash/install_vault.sh
Executable file
46
src/test/bash/install_vault.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
###########################################################################
|
||||
# Download and Install Vault #
|
||||
# This script is prepared for caching of the download directory #
|
||||
###########################################################################
|
||||
|
||||
|
||||
VAULT_VER="0.6.1"
|
||||
UNAME=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
VAULT_ZIP="vault_${VAULT_VER}_${UNAME}_amd64.zip"
|
||||
IGNORE_CERTS="${IGNORE_CERTS:-no}"
|
||||
|
||||
# cleanup
|
||||
mkdir -p vault
|
||||
mkdir -p download
|
||||
|
||||
if [[ ! -f "download/${VAULT_ZIP}" ]] ; then
|
||||
cd download
|
||||
# install Vault
|
||||
if [[ "${IGNORE_CERTS}" == "no" ]] ; then
|
||||
echo "Downloading Vault with certs verification"
|
||||
wget "https://releases.hashicorp.com/vault/${VAULT_VER}/${VAULT_ZIP}"
|
||||
else
|
||||
echo "WARNING... Downloading Vault WITHOUT certs verification"
|
||||
wget "https://releases.hashicorp.com/vault/${VAULT_VER}/${VAULT_ZIP}" --no-check-certificate
|
||||
fi
|
||||
|
||||
if [[ $? != 0 ]] ; then
|
||||
echo "Cannot download Vault"
|
||||
exit 1
|
||||
fi
|
||||
cd ..
|
||||
fi
|
||||
|
||||
cd vault
|
||||
|
||||
if [[ -f vault ]] ; then
|
||||
rm vault
|
||||
fi
|
||||
|
||||
unzip ../download/${VAULT_ZIP}
|
||||
chmod a+x vault
|
||||
|
||||
# check
|
||||
./vault --version
|
||||
11
src/test/bash/local_run_vault.sh
Executable file
11
src/test/bash/local_run_vault.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
###########################################################################
|
||||
# Start Vault on localhost:8200 #
|
||||
###########################################################################
|
||||
|
||||
BASEDIR=`dirname $0`/../../..
|
||||
|
||||
./vault/vault server -config=${BASEDIR}/src/test/bash/vault.conf
|
||||
|
||||
exit $?
|
||||
106
src/test/bash/openssl.cnf
Normal file
106
src/test/bash/openssl.cnf
Normal file
@@ -0,0 +1,106 @@
|
||||
[ ca ]
|
||||
# `man ca`
|
||||
default_ca = CA_default
|
||||
|
||||
[ CA_default ]
|
||||
# Directory and file locations.
|
||||
dir = work/ca
|
||||
certs = $dir/certs
|
||||
crl_dir = $dir/crl
|
||||
new_certs_dir = $dir/newcerts
|
||||
database = $dir/index.txt
|
||||
serial = $dir/serial
|
||||
RANDFILE = $dir/private/.rand
|
||||
|
||||
# The root key and root certificate.
|
||||
private_key = $dir/private/ca.key.pem
|
||||
certificate = $dir/certs/ca.cert.pem
|
||||
|
||||
# For certificate revocation lists.
|
||||
crlnumber = $dir/crlnumber
|
||||
crl = $dir/crl/ca.crl.pem
|
||||
crl_extensions = crl_ext
|
||||
default_crl_days = 30
|
||||
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
|
||||
name_opt = ca_default
|
||||
cert_opt = ca_default
|
||||
default_days = 375
|
||||
preserve = no
|
||||
policy = policy_strict
|
||||
|
||||
[ policy_strict ]
|
||||
# The root CA should only sign intermediate certificates that match.
|
||||
# See the POLICY FORMAT section of `man ca`.
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ req ]
|
||||
# Options for the `req` tool (`man req`).
|
||||
default_bits = 2048
|
||||
distinguished_name = req_distinguished_name
|
||||
string_mask = utf8only
|
||||
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
|
||||
# Extension to add when the -x509 option is used.
|
||||
x509_extensions = v3_ca
|
||||
|
||||
[ req_distinguished_name ]
|
||||
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
|
||||
countryName = Country Name (2 letter code)
|
||||
stateOrProvinceName = State or Province Name
|
||||
localityName = Locality Name
|
||||
0.organizationName = Organization Name
|
||||
organizationalUnitName = Organizational Unit Name
|
||||
commonName = Common Name
|
||||
emailAddress = Email Address
|
||||
|
||||
# Optionally, specify some defaults.
|
||||
countryName_default = NN
|
||||
stateOrProvinceName_default = Vault Test
|
||||
localityName_default =
|
||||
0.organizationName_default = spring-cloud-vault-config
|
||||
#organizationalUnitName_default =
|
||||
#emailAddress_default = info@spring-cloud-vault-config.dummy
|
||||
|
||||
[ v3_ca ]
|
||||
# Extensions for a typical CA (`man x509v3_config`).
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
basicConstraints = critical, CA:true
|
||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
||||
|
||||
[ v3_intermediate_ca ]
|
||||
# Extensions for a typical intermediate CA (`man x509v3_config`).
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
basicConstraints = critical, CA:true, pathlen:0
|
||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
||||
|
||||
[ usr_cert ]
|
||||
# Extensions for client certificates (`man x509v3_config`).
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = client, email
|
||||
nsComment = "OpenSSL Generated Client Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer
|
||||
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth, emailProtection
|
||||
|
||||
[ server_cert ]
|
||||
# Extensions for server certificates (`man x509v3_config`).
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = server
|
||||
nsComment = "OpenSSL Generated Server Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
keyUsage = critical, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
10
src/test/bash/vault.conf
Normal file
10
src/test/bash/vault.conf
Normal file
@@ -0,0 +1,10 @@
|
||||
backend "inmem" {
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_cert_file = "work/ca/certs/localhost.cert.pem"
|
||||
tls_key_file = "work/ca/private/localhost.decrypted.key.pem"
|
||||
}
|
||||
|
||||
disable_mlock = true
|
||||
Reference in New Issue
Block a user