Compare commits
129 Commits
Author | SHA1 | Date | |
---|---|---|---|
a9f1eb63c2 | |||
fd749b19e5 | |||
0cca2de1aa | |||
8b278f67fe | |||
8f3462b22a | |||
a394cb7f0d | |||
50d0b2fe56 | |||
e2bb09d50f | |||
4a2b40a4cf | |||
bed9c868f6 | |||
7a45af8856 | |||
4bafcec012 | |||
4ca150a0cb | |||
efb0aba7cd | |||
17f1ee79db | |||
d8b9c2b373 | |||
04d530a5ed | |||
b134b5a605 | |||
f8ff93fa6c | |||
5bd6a90f25 | |||
92cfc3a597 | |||
3f47da6134 | |||
3446d1590e | |||
a24ddf65a5 | |||
d6f422e0ec | |||
fbaa560551 | |||
42c2869675 | |||
eabc458176 | |||
dee7ec0b23 | |||
ab33325b8e | |||
e4cf8a1dde | |||
22a48d4a90 | |||
7020d3701c | |||
51e54d9870 | |||
b103d6e804 | |||
1aade2882b | |||
7909a6772d | |||
5f391286e5 | |||
068f961454 | |||
ad2986195d | |||
487070bcd2 | |||
646379a69a | |||
5e143e9f36 | |||
19f9a97422 | |||
aca5443bdd | |||
e59073cf00 | |||
7032bd4b2b | |||
263669362f | |||
3b2a3dd70a | |||
d1876c88aa | |||
c2bd54ca22 | |||
493bed55f0 | |||
e41a61f33b | |||
e3f2193df2 | |||
068a87d915 | |||
04e92626bd | |||
c8aeb1396d | |||
12083df14b | |||
2e0d79424f | |||
9caeac4cba | |||
c1ec929147 | |||
96fd377db2 | |||
46cb33fd7d | |||
384cc77de2 | |||
2ca4473481 | |||
b6d36fbc5c | |||
c869a640a9 | |||
874341ddf7 | |||
c111a6aff0 | |||
13793dc9ce | |||
44858edb76 | |||
8287be48b9 | |||
51d118786a | |||
0193bebf0b | |||
493e22e46b | |||
6b1211d90f | |||
ee9a6530d3 | |||
3db73a913a | |||
ce9cd9bbf1 | |||
9e50190c02 | |||
4dea8a1c5f | |||
47e7a3f4b0 | |||
a5a708895e | |||
810073cb3b | |||
bc1223e1a3 | |||
4d46f2c6d1 | |||
d2aaea1938 | |||
e996ff157a | |||
065f662b95 | |||
44c1a685a6 | |||
b02d06f1dd | |||
23fbc7a6d3 | |||
1a18f9f6b7 | |||
0c23f47bd5 | |||
aa2619b1b0 | |||
88d49bc9f7 | |||
27e7a2dffc | |||
41c15f285c | |||
5f419e3f9b | |||
9362e245ee | |||
b2082925d5 | |||
38a7d4952d | |||
23cea38da6 | |||
bf2da210ba | |||
91fb012acc | |||
61e1f3f745 | |||
50cd400ba3 | |||
470dcb48ba | |||
736f23c19a | |||
ed2b9d62a3 | |||
007b523295 | |||
061c1e9743 | |||
6904ed6817 | |||
1ed5d8d992 | |||
f70fc084be | |||
4b14ab3f4b | |||
29776f459e | |||
4ca8aa56d2 | |||
32ab9f4bb1 | |||
e002fc749a | |||
b9ad2d1551 | |||
35a8c2e0fa | |||
89f7581d17 | |||
43511dc20b | |||
05b44759c0 | |||
ba17286ab3 | |||
51e505313a | |||
a1784245a3 | |||
df7de5dd73 |
26
.drone.yml
Normal file
26
.drone.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: test-online
|
||||||
|
image: maven:3-jdk-11
|
||||||
|
environment:
|
||||||
|
VAULT_VERSION: 1.2.2
|
||||||
|
commands:
|
||||||
|
- curl -o vault_1.2.2_linux_amd64.zip https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_linux_amd64.zip
|
||||||
|
- curl -s https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||||
|
- unzip vault_1.2.2_linux_amd64.zip
|
||||||
|
- rm vault_1.2.2_linux_amd64.zip
|
||||||
|
- mv vault /bin/
|
||||||
|
- mvn clean test
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
- name: test-offline
|
||||||
|
image: maven:3-jdk-11
|
||||||
|
commands:
|
||||||
|
- mvn clean test -P offline-tests
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- develop
|
||||||
|
- feature/*
|
28
.travis.yml
28
.travis.yml
@ -1,10 +1,6 @@
|
|||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
language: java
|
language: java
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- openjdk11
|
||||||
dist: trusty
|
|
||||||
install: true
|
install: true
|
||||||
addons:
|
addons:
|
||||||
sonarcloud:
|
sonarcloud:
|
||||||
@ -12,14 +8,26 @@ addons:
|
|||||||
token:
|
token:
|
||||||
secure: "sM9OfX5jW764pn9cb2LSXArnXucKMws+eGeg5NnZxHRcGYt4hpBKLSregBSsBNzUoWVj0zNzPCpnh+UQvgxQzUerOqwEdjTBpy3SNPaxSn7UpoSg+Wz3aUmL9ugmx01b51/wMG4UCHEwTZt2tpgTPVtw8K6uSO78e0dSICCBHDnRcdQwOjMEQHIJJ/qHVRwuy/MzLCAP3W1JPZlsphZg9QsFyhB4hW97dE90joZezfocQIv2xI/r6k+BLz0pY6MxYCul0RiDumaiaej0CPvEJI/uSu//BAQjUdHw+mQgnKUYIbrn2ONOviwNfwdr94JyoZEN2B6zASUmNLjPf4AbIojDeyS+CrpQpm17EVm/Qk/Ds+Xra4PPPIcsZhiWzV0KoDUz9xLfXuRJ526VT5tDPiaeI7oETf0+8l+JIS1b399FyqHi7smzjpvC6GuKflQrbuHK4MuKzDh7WTHiqokGG4SS0wOQIaaHB3dfdwwQzPh6IM24e8CETxh3DjMeqUTU4DWmv5po55jZ934TtxVQvVN78bTG9O0zS9u+JmRY04OZ+OaXuFam6MfMUFQi0EPZzdGul/oWSibGUu3bNfVEBp60CnJwYNM/dKG6U7pJthLHvSwiQFOdKzHZ+l1jZJ4gPaXaIGqpwqVGr28ntqA/El1rytPixr2driE6bYMt5jw="
|
secure: "sM9OfX5jW764pn9cb2LSXArnXucKMws+eGeg5NnZxHRcGYt4hpBKLSregBSsBNzUoWVj0zNzPCpnh+UQvgxQzUerOqwEdjTBpy3SNPaxSn7UpoSg+Wz3aUmL9ugmx01b51/wMG4UCHEwTZt2tpgTPVtw8K6uSO78e0dSICCBHDnRcdQwOjMEQHIJJ/qHVRwuy/MzLCAP3W1JPZlsphZg9QsFyhB4hW97dE90joZezfocQIv2xI/r6k+BLz0pY6MxYCul0RiDumaiaej0CPvEJI/uSu//BAQjUdHw+mQgnKUYIbrn2ONOviwNfwdr94JyoZEN2B6zASUmNLjPf4AbIojDeyS+CrpQpm17EVm/Qk/Ds+Xra4PPPIcsZhiWzV0KoDUz9xLfXuRJ526VT5tDPiaeI7oETf0+8l+JIS1b399FyqHi7smzjpvC6GuKflQrbuHK4MuKzDh7WTHiqokGG4SS0wOQIaaHB3dfdwwQzPh6IM24e8CETxh3DjMeqUTU4DWmv5po55jZ934TtxVQvVN78bTG9O0zS9u+JmRY04OZ+OaXuFam6MfMUFQi0EPZzdGul/oWSibGUu3bNfVEBp60CnJwYNM/dKG6U7pJthLHvSwiQFOdKzHZ+l1jZJ4gPaXaIGqpwqVGr28ntqA/El1rytPixr2driE6bYMt5jw="
|
||||||
env:
|
env:
|
||||||
- PATH=$PATH:.
|
- PATH=$PATH:. VAULT_VERSION=1.2.2
|
||||||
before_script:
|
before_script:
|
||||||
- wget https://releases.hashicorp.com/vault/0.8.1/vault_0.8.1_linux_amd64.zip
|
- |
|
||||||
- unzip vault_0.8.1_linux_amd64.zip
|
if [ "$TRAVIS_BRANCH" = "master" ]; then
|
||||||
- rm vault_0.8.1_linux_amd64.zip
|
wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
||||||
|
wget -q -O - https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||||
|
unzip vault_${VAULT_VERSION}_linux_amd64.zip
|
||||||
|
rm vault_${VAULT_VERSION}_linux_amd64.zip
|
||||||
|
fi
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- '$HOME/.m2/repository'
|
- '$HOME/.m2/repository'
|
||||||
- '$HOME/.sonar/cache'
|
- '$HOME/.sonar/cache'
|
||||||
script:
|
script:
|
||||||
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
|
- |
|
||||||
|
if [ "$TRAVIS_BRANCH" = "master" ]; then
|
||||||
|
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
|
||||||
|
else
|
||||||
|
mvn clean test -P offline-tests
|
||||||
|
fi
|
||||||
|
notifications:
|
||||||
|
slack:
|
||||||
|
secure: "YyE5GePOLkCVTtCy8j507BRmQrtrWhtvmUt4kY0Z2/ptf0LzfuDEJQ4ZbCxO5ri5IDJrrvyPAedjft818+bMzdFfxvi1oviIL+LZNhyev8gfeIBF/U2pvSLGKCRX4g4aZ6NKN3Untjdm8lmiVTltOyZ59JizQVwXzAl3LiOpnJugyBqbhOx4EIqBzwW3gaYAofMqY2LczW5W/M+99HJCst8Mb8H06GstCPEHCizAq7VRaUS68PstlxQMV0Q6bsSYMLFbLWmhuXs96WHqOrT+nNsl07ikr3N8c4HafhFutt2Jyc1+8gXO417+eSvVM0iBpHGwTmfGFfCqx/4Pf62DTJuvh8dR4fLgLDiqEeDrBEcRRDOs9cvXVOO22NN1HuBBJY8VRiFcwNAvuVMXCtnC+1RJRAZB2zubsANiFe+ygk/ywj37cVXY+NpqlBwcSph6jPHo2hD6cIl2rTWn1EnZH519Rh38xTSv6MRzAO9kWNVrAlX+UtvYS8Sk7Owrc0tET9Lc4zj6aI5tsA1wYbN3Jk6EbMhsF6K/XF2npt2qg09pxkj8wmxoUoR6/rGuSv55aSxTdLDmH+en4ahEm3uc4h1lYoVCk0yrZoTAas3zS4WpBCKnl+mweuKNxaejyy0Wv6NR9ZCTaS3yFgibNOjvDpxZxTAPdNBL7hn+k4LwgN4="
|
||||||
|
193
CHANGELOG.md
193
CHANGELOG.md
@ -1,55 +1,164 @@
|
|||||||
|
## 0.8.1 (2019-08-16)
|
||||||
|
### Fixes
|
||||||
|
* Removed compile dependency to JUnit library (#30)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Updated ependencies
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 1.2.2
|
||||||
|
|
||||||
|
## 0.8.0 (2019-03-24)
|
||||||
|
### Breaking
|
||||||
|
* Moved Maven artifact to `de.stklcode.jvault:jvault-connector` (#28)
|
||||||
|
* Removed support for `HTTPVaultConnectorFactory#withSslContext()` in favor of `#withTrustedCA()` due to
|
||||||
|
|
||||||
|
### Features
|
||||||
|
* Support for KV version 2 secret engine (#16)
|
||||||
|
* Ability to pass custom mount point to KV v2 read/write methods (#25)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* refactoring of the internal SSL handling (#17)
|
||||||
|
* `VaultConnector` extends `java.io.Serializable` (#19)
|
||||||
|
* Added missing flags to `SealResponse` (#20)
|
||||||
|
* Added replication flags to `HealthResponse` (#21)
|
||||||
|
* Enforce TLS 1.2 by default with option to override (#22)
|
||||||
|
* Build environment and tests now compatible with Java 10
|
||||||
|
* Updated dependencies to fix vulnerabilities (i.e. CVE-2018-7489)
|
||||||
|
* New static method `Token.builder()` to get token builder instance
|
||||||
|
* New static method `AppRole.builder()` to get AppRole builder instance
|
||||||
|
|
||||||
|
### Deprecation
|
||||||
|
* `VaultConnectorFactory` is deprecated in favor of `VaultConnectorBuilder` with identical API (#18)
|
||||||
|
* `AppRoleBuilder#withBoundCidrList(List)` is deprecated in favor of `AppRoleBuilder#withSecretIdBoundCidrs(List)` (#24)
|
||||||
|
|
||||||
|
|
||||||
|
## 0.7.1 (2018-03-17)
|
||||||
|
### Improvements
|
||||||
|
* Added automatic module name for JPMS compatibility
|
||||||
|
* Minor dependency updates
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.9.5
|
||||||
|
|
||||||
|
|
||||||
|
## 0.7.0 (2017-10-03)
|
||||||
|
### Features
|
||||||
|
* Retrieval of health status via `getHealth()` (#15)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* `seal()`, `unseal()` are now `void` and throw Exception on error (#12)
|
||||||
|
* Adaptation to Vault 0.8 endpoints for `renew` and `revoke`, **breaking** 0.7 compatibility (#11)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* Removed deprecated `listAppRoleSecretss()` (use `listAppRoleSecrets()`) (#14)
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.8.3
|
||||||
|
|
||||||
|
|
||||||
## 0.6.2 [2017-08-19]
|
## 0.6.2 [2017-08-19]
|
||||||
* [fix] Prevent potential NPE on SecretResponse getter
|
### Fixes
|
||||||
* [fix] Removed stack traces on PUT request and response deserialization (#13)
|
* Prevent potential NPE on SecretResponse getter
|
||||||
* [improvement] Fields of InvalidResposneException made final
|
* Removed stack traces on PUT request and response deserialization (#13)
|
||||||
* [deprecation] `listAppRoleSecretss()` in favor of `listAppRoleSecrets()` (#14)
|
|
||||||
* [test] Tested against Vault 0.8.1, increased coverage
|
|
||||||
|
|
||||||
## 0.6.1 [2017-08-02]
|
### Improvements
|
||||||
* [fix] `TokenModel.getPassword()` returned username instead of password
|
* Fields of InvalidResposneException made final
|
||||||
* [fix] `TokenModel.getUsername()` and `getPassword()` could produce NPE in multithreaded environments
|
|
||||||
* [fix] `TokenData.getCreatinTtl()` renamed to `getCreationTtl()` (typo fix)
|
|
||||||
* [test] Tested against Vault 0.7.3
|
|
||||||
|
|
||||||
## 0.6.0 [2017-05-12]
|
### Deprecation
|
||||||
* [feature] Initialization from environment variables using `fromEnv()` in factory (#8)
|
* `listAppRoleSecretss()` in favor of `listAppRoleSecrets()` (#14)
|
||||||
* [feature] Automatic authentication with `buildAndAuth()`
|
|
||||||
* [feature] Custom timeout and number of retries (#9)
|
### Test
|
||||||
* [feature] Connector implements `AutoCloseable`
|
* Tested against Vault 0.8.1, increased coverage
|
||||||
* [fix] `SecretResponse` does not throw NPE on `get(key)` and `getData()`
|
|
||||||
* [test] Tested against Vault 0.7.2
|
|
||||||
|
## 0.6.1 (2017-08-02)
|
||||||
|
### Fixes
|
||||||
|
* `TokenModel.getPassword()` returned username instead of password
|
||||||
|
* `TokenModel.getUsername()` and `getPassword()` could produce NPE in multithreaded environments
|
||||||
|
* `TokenData.getCreatinTtl()` renamed to `getCreationTtl()` (typo fix)
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.7.3
|
||||||
|
|
||||||
|
|
||||||
|
## 0.6.0 (2017-05-12)
|
||||||
|
### Features
|
||||||
|
* Initialization from environment variables using `fromEnv()` in factory (#8)
|
||||||
|
* Automatic authentication with `buildAndAuth()`
|
||||||
|
* Custom timeout and number of retries (#9)
|
||||||
|
* Connector implements `AutoCloseable`
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* `SecretResponse` does not throw NPE on `get(key)` and `getData()`
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.7.2
|
||||||
|
|
||||||
|
|
||||||
|
## 0.5.0 (2017-03-18)
|
||||||
|
### Features
|
||||||
|
* Convenience methods for DB credentials (#7)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Minor bugfix in TokenBuilder
|
||||||
|
|
||||||
|
### Deprecation
|
||||||
|
* `SecretResponse.getValue()` deprecated
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.7.0
|
||||||
|
|
||||||
## 0.5.0 [2017-03-18]
|
|
||||||
* [feature] Convenience methods for DB credentials (#7)
|
|
||||||
* [fix] Minor bugfix in TokenBuilder
|
|
||||||
* [deprecation] `SecretResponse.getValue()` deprecated
|
|
||||||
* [test] Tested against Vault 0.7.0
|
|
||||||
|
|
||||||
## 0.4.1 [2016-12-24]
|
## 0.4.1 [2016-12-24]
|
||||||
* [fix] Factory Null-tolerant for trusted certificate (#6)
|
### Fixes
|
||||||
* [test] StackTraces tested for secret leaks
|
* Factory Null-tolerant for trusted certificate (#6)
|
||||||
* [test] Tested against Vault 0.6.4
|
|
||||||
|
|
||||||
## 0.4.0 [2016-11-06]
|
### Test
|
||||||
* [feature] Option to provide a trusted CA certificate (#2)
|
* StackTraces tested for secret leaks
|
||||||
* [feature] Deletion, revocation and renewal of secrets (#3)
|
* Tested against Vault 0.6.4
|
||||||
* [feature] Token creation (#4)
|
|
||||||
* [feature] AppRole auth backend supported (#5)
|
|
||||||
* [improvement] Support for complex secrets
|
|
||||||
* [deprecation] App-ID backend marked as deprecated
|
|
||||||
|
|
||||||
## 0.3.0 [2016-10-07]
|
|
||||||
* [feature] Retrieval of JSON objects (#1)
|
|
||||||
* [test] Tested against Vault 0.6.2
|
|
||||||
|
|
||||||
## 0.2.0 [2016-09-01]
|
## 0.4.0 (2016-11-06)
|
||||||
|
### Features
|
||||||
|
* Option to provide a trusted CA certificate (#2)
|
||||||
|
* Deletion, revocation and renewal of secrets (#3)
|
||||||
|
* Token creation (#4)
|
||||||
|
* AppRole auth backend supported (#5)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Support for complex secrets
|
||||||
|
|
||||||
|
### Deprecation
|
||||||
|
* App-ID backend marked as deprecated
|
||||||
|
|
||||||
|
|
||||||
|
## 0.3.0 (2016-10-07)
|
||||||
|
### Features
|
||||||
|
* Retrieval of JSON objects (#1)
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.6.2
|
||||||
|
|
||||||
|
|
||||||
|
## 0.2.0 (2016-09-01)
|
||||||
|
### Improvements
|
||||||
* Dependecies updated and CommonsIO removed
|
* Dependecies updated and CommonsIO removed
|
||||||
* [fix] Fixed auth backend detection for Vault 0.6.1
|
|
||||||
* [test] Tested against Vault 0.6.1
|
|
||||||
|
|
||||||
## 0.1.1 [2016-06-20]
|
### Fixes
|
||||||
* [fix] Check for "permission denied" without status code 400 instead of 403
|
* Fixed auth backend detection for Vault 0.6.1
|
||||||
* [test] Tested against Vault 0.6.0
|
|
||||||
|
|
||||||
## 0.1.0 [2016-03-29]
|
### Test
|
||||||
|
* Tested against Vault 0.6.1
|
||||||
|
|
||||||
|
|
||||||
|
## 0.1.1 (2016-06-20)
|
||||||
|
### Fixes
|
||||||
|
* Check for "permission denied" without status code 400 instead of 403
|
||||||
|
|
||||||
|
### Test
|
||||||
|
* Tested against Vault 0.6.0
|
||||||
|
|
||||||
|
|
||||||
|
## 0.1.0 (2016-03-29)
|
||||||
* First release
|
* First release
|
||||||
|
55
README.md
55
README.md
@ -1,9 +1,9 @@
|
|||||||
# Java Vault Connector
|
# Java Vault Connector
|
||||||
|
|
||||||
[](https://travis-ci.org/stklcode/jvaultconnector)
|
[](https://travis-ci.org/stklcode/jvaultconnector)
|
||||||
[](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Aconnector)
|
[](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Aconnector)
|
||||||
[](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
|
[](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
|
||||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22connector%22)
|
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22jvault-connector%22)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -17,8 +17,8 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
|||||||
* Authorization methods
|
* Authorization methods
|
||||||
* Token
|
* Token
|
||||||
* Username/Password
|
* Username/Password
|
||||||
* AppID (register and authenticate) [_deprecated_]
|
|
||||||
* AppRole (register and authenticate)
|
* AppRole (register and authenticate)
|
||||||
|
* AppID (register and authenticate) [_deprecated_]
|
||||||
* Tokens
|
* Tokens
|
||||||
* Creation and lookup of tokens
|
* Creation and lookup of tokens
|
||||||
* TokenBuilder for speaking creation of complex configuraitons
|
* TokenBuilder for speaking creation of complex configuraitons
|
||||||
@ -30,16 +30,17 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
|||||||
* Renew/revoke leases
|
* Renew/revoke leases
|
||||||
* Raw secret content or JSON decoding
|
* Raw secret content or JSON decoding
|
||||||
* SQL secret handling
|
* SQL secret handling
|
||||||
|
* KV v1 and v2 support
|
||||||
* Connector Factory with builder pattern
|
* Connector Factory with builder pattern
|
||||||
* Tested against Vault 0.8.1
|
* Tested against Vault 1.2.2
|
||||||
|
|
||||||
|
|
||||||
## Maven Artifact
|
## Maven Artifact
|
||||||
```
|
```xml
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.stklcode.jvault</groupId>
|
<groupId>de.stklcode.jvault</groupId>
|
||||||
<artifactId>connector</artifactId>
|
<artifactId>jvault-connector</artifactId>
|
||||||
<version>0.6.2</version>
|
<version>0.8.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -49,21 +50,21 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
// Instantiate using builder pattern style factory (TLS enabled by default)
|
// Instantiate using builder pattern style factory (TLS enabled by default)
|
||||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
VaultConnector vault = VaultConnectorBuilder.http()
|
||||||
.withHost("127.0.0.1")
|
.withHost("127.0.0.1")
|
||||||
.withPort(8200)
|
.withPort(8200)
|
||||||
.withTLS()
|
.withTLS()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Instantiate with custom SSL context
|
// Instantiate with custom SSL context
|
||||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
VaultConnector vault = VaultConnectorBuilder.http()
|
||||||
.withHost("example.com")
|
.withHost("example.com")
|
||||||
.withPort(8200)
|
.withPort(8200)
|
||||||
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Initialization from environment variables
|
// Initialization from environment variables
|
||||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
VaultConnector vault = VaultConnectorBuilder.http()
|
||||||
.fromEnv()
|
.fromEnv()
|
||||||
.build();
|
.build();
|
||||||
```
|
```
|
||||||
@ -71,33 +72,33 @@ VaultConnector vault = VaultConnectorFactory.httpFactory()
|
|||||||
### Authentication
|
### Authentication
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Authenticate with token
|
// Authenticate with token.
|
||||||
vault.authToken("01234567-89ab-cdef-0123-456789abcdef");
|
vault.authToken("01234567-89ab-cdef-0123-456789abcdef");
|
||||||
|
|
||||||
// Authenticate with username and password
|
// Authenticate with username and password.
|
||||||
vault.authUserPass("username", "p4ssw0rd");
|
vault.authUserPass("username", "p4ssw0rd");
|
||||||
|
|
||||||
// Authenticate with AppID (secret - 2nd argument - is optional)
|
// Authenticate with AppRole (secret - 2nd argument - is optional).
|
||||||
vault.authAppId("01234567-89ab-cdef-0123-456789abcdef", "fedcba98-7654-3210-fedc-ba9876543210");
|
vault.authAppRole("01234567-89ab-cdef-0123-456789abcdef", "fedcba98-7654-3210-fedc-ba9876543210");
|
||||||
```
|
```
|
||||||
|
|
||||||
### Secret read & write
|
### Secret read & write
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Retrieve secret (prefix "secret/" assumed, use read() to read arbitrary paths)
|
// Retrieve secret (prefix "secret/" assumed, use read() to read arbitrary paths)
|
||||||
String secret = vault.readSecret("some/secret/key").getValue();
|
String secret = vault.readSecret("some/secret/key").get("value", String.class);
|
||||||
|
|
||||||
// Complex secret
|
// Complex secret.
|
||||||
Map<String, Object> secretData = vault.readSecret("another/secret/key").getData();
|
Map<String, Object> secretData = vault.readSecret("another/secret/key").getData();
|
||||||
|
|
||||||
// Write simple secret
|
// Write simple secret.
|
||||||
vault.writeSecret("new/secret/key", "secret value");
|
vault.writeSecret("new/secret/key", "secret value");
|
||||||
|
|
||||||
// Write complex data to arbitraty path
|
// Write complex data to arbitraty path.
|
||||||
Map<String, Object> map = [...]
|
Map<String, Object> map = ...;
|
||||||
vault.write("any/path/to/write", map);
|
vault.write("any/path/to/write", map);
|
||||||
|
|
||||||
// Delete secret
|
// Delete secret.
|
||||||
vault.delete("any/path/to/write");
|
vault.delete("any/path/to/write");
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -105,10 +106,11 @@ vault.delete("any/path/to/write");
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
// Create token using TokenBuilder
|
// Create token using TokenBuilder
|
||||||
Token token = new TokenBuilder().withId("token id")
|
Token token = Token.builder()
|
||||||
.withDisplayName("new test token")
|
.withId("token id")
|
||||||
.withPolicies("pol1", "pol2")
|
.withDisplayName("new test token")
|
||||||
.build();
|
.withPolicies("pol1", "pol2")
|
||||||
|
.build();
|
||||||
vault.createToken(token);
|
vault.createToken(token);
|
||||||
|
|
||||||
// Create AppRole credentials
|
// Create AppRole credentials
|
||||||
@ -122,11 +124,6 @@ AppRoleSecretResponse secret = vault.createAppRoleSecret("testrole");
|
|||||||
|
|
||||||
[JavaDoc API](http://jvault.stklcode.de/apidocs/)
|
[JavaDoc API](http://jvault.stklcode.de/apidocs/)
|
||||||
|
|
||||||
## Planned features
|
|
||||||
|
|
||||||
* Creation and modification of policies
|
|
||||||
* Implement more authentication methods
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
BIN
assets/logo.png
BIN
assets/logo.png
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
@ -2,11 +2,11 @@
|
|||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128">
|
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128">
|
||||||
<path d="M4,12 l60,104 l60,-104 z" stroke="none" fill="#000000" />
|
<path d="M4,12 l60,104 l60,-104 z" stroke="none" fill="#000000" />
|
||||||
<circle cx="78" cy="24" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="74" y="20" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="78" cy="38" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="74" y="34" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="78" cy="52" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="74" y="48" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="78" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="74" y="62" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="72" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="68" y="74" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="58" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="54" y="74" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
<circle cx="52" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
<rect x="48" y="62" width="8" height="8" stroke="none" fill="#00abe0" />
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 837 B |
176
pom.xml
176
pom.xml
@ -3,14 +3,15 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>de.stklcode.jvault</groupId>
|
<groupId>de.stklcode.jvault</groupId>
|
||||||
<artifactId>connector</artifactId>
|
<artifactId>jvault-connector</artifactId>
|
||||||
<version>0.6.2</version>
|
<version>0.8.1</version>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>jVaultConnector</name>
|
<name>jVaultConnector</name>
|
||||||
<description>Connector artifact for Hashicorp's Vault secret management</description>
|
<description>Connector artifact for Hashicorp's Vault secret management</description>
|
||||||
<url>https://jvault.stklcode.de</url>
|
<url>https://jvault.stklcode.de</url>
|
||||||
|
<inceptionYear>2016</inceptionYear>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
@ -24,46 +25,110 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Stefan Kalscheuer</name>
|
||||||
|
<email>stefan@stklcode.de</email>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git://github.com/stklcode/jvaultconnector.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:stklcode/jvaultconnector.git</developerConnection>
|
||||||
|
<url>https://github.com/stklcode/jvaultconnector</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub Issues</system>
|
||||||
|
<url>https://github.com/stklcode/jvaultconnector/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.6.1</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestEntries>
|
||||||
|
<Automatic-Module-Name>de.stklcode.jvault.connector</Automatic-Module-Name>
|
||||||
|
</manifestEntries>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-install-plugin</artifactId>
|
||||||
|
<version>2.5.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
<configuration>
|
||||||
|
<reuseForks>false</reuseForks>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpcore</artifactId>
|
<artifactId>httpcore</artifactId>
|
||||||
<version>4.4.6</version>
|
<version>4.4.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
<version>4.5.3</version>
|
<version>4.5.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
<version>2.9.0</version>
|
<version>2.9.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>2.9.0</version>
|
<version>2.9.9.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
<version>4.12</version>
|
<version>5.5.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-migrationsupport</artifactId>
|
||||||
|
<version>5.5.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -75,8 +140,97 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.stefanbirkner</groupId>
|
<groupId>com.github.stefanbirkner</groupId>
|
||||||
<artifactId>system-rules</artifactId>
|
<artifactId>system-rules</artifactId>
|
||||||
<version>1.16.1</version>
|
<version>1.17.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>sources</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>javadoc</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>offline-tests</id>
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludedGroups>online</excludedGroups>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,7 +21,11 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
|||||||
import de.stklcode.jvault.connector.model.*;
|
import de.stklcode.jvault.connector.model.*;
|
||||||
import de.stklcode.jvault.connector.model.response.*;
|
import de.stklcode.jvault.connector.model.response.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vault Connector interface.
|
* Vault Connector interface.
|
||||||
@ -30,7 +34,10 @@ import java.util.*;
|
|||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
*/
|
*/
|
||||||
public interface VaultConnector extends AutoCloseable {
|
public interface VaultConnector extends AutoCloseable, Serializable {
|
||||||
|
/**
|
||||||
|
* Default sub-path for Vault secrets.
|
||||||
|
*/
|
||||||
String PATH_SECRET = "secret";
|
String PATH_SECRET = "secret";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,35 +49,47 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* Retrieve status of vault seal.
|
* Retrieve status of vault seal.
|
||||||
*
|
*
|
||||||
* @return Seal status
|
* @return Seal status
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
SealResponse sealStatus();
|
SealResponse sealStatus() throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seal vault.
|
* Seal vault.
|
||||||
*
|
*
|
||||||
* @return TRUE on success
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
boolean seal();
|
void seal() throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unseal vault.
|
* Unseal vault.
|
||||||
*
|
*
|
||||||
* @param key A single master share key
|
* @param key A single master share key
|
||||||
* @param reset Discard previously provided keys (optional)
|
* @param reset Discard previously provided keys (optional)
|
||||||
* @return TRUE on success
|
* @return Response with seal status
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
SealResponse unseal(final String key, final Boolean reset);
|
SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unseal vault.
|
* Unseal vault.
|
||||||
*
|
*
|
||||||
* @param key A single master share key
|
* @param key A single master share key
|
||||||
* @return TRUE on success
|
* @return Response with seal status
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
default SealResponse unseal(final String key) {
|
default SealResponse unseal(final String key) throws VaultConnectorException {
|
||||||
return unseal(key, null);
|
return unseal(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query server health information.
|
||||||
|
*
|
||||||
|
* @return Health information.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.7.0
|
||||||
|
*/
|
||||||
|
HealthResponse getHealth() throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all availale authentication backends.
|
* Get all availale authentication backends.
|
||||||
*
|
*
|
||||||
@ -103,7 +122,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param appID The App ID
|
* @param appID The App ID
|
||||||
* @param userID The User ID
|
* @param userID The User ID
|
||||||
* @return TRUE on success
|
* @return The {@link AuthResponse}
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||||
*/
|
*/
|
||||||
@ -114,7 +133,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* Authorize to Vault using AppRole method without secret ID.
|
* Authorize to Vault using AppRole method without secret ID.
|
||||||
*
|
*
|
||||||
* @param roleID The role ID
|
* @param roleID The role ID
|
||||||
* @return TRUE on success
|
* @return The {@link AuthResponse}
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -127,7 +146,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param roleID The role ID
|
* @param roleID The role ID
|
||||||
* @param secretID The secret ID
|
* @param secretID The secret ID
|
||||||
* @return TRUE on success
|
* @return The {@link AuthResponse}
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -139,7 +158,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* @param appID The unique App-ID
|
* @param appID The unique App-ID
|
||||||
* @param policy The policy to associate with
|
* @param policy The policy to associate with
|
||||||
* @param displayName Arbitrary name to display
|
* @param displayName Arbitrary name to display
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||||
*/
|
*/
|
||||||
@ -151,7 +170,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* Register a new AppRole role from given metamodel.
|
* Register a new AppRole role from given metamodel.
|
||||||
*
|
*
|
||||||
* @param role The role
|
* @param role The role
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -161,7 +180,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* Register new AppRole role with default policy.
|
* Register new AppRole role with default policy.
|
||||||
*
|
*
|
||||||
* @param roleName The role name
|
* @param roleName The role name
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -174,7 +193,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param roleName The role name
|
* @param roleName The role name
|
||||||
* @param policies The policies to associate with
|
* @param policies The policies to associate with
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -187,7 +206,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param roleName The role name
|
* @param roleName The role name
|
||||||
* @param roleID A custom role ID
|
* @param roleID A custom role ID
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -201,7 +220,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* @param roleName The role name
|
* @param roleName The role name
|
||||||
* @param policies The policies to associate with
|
* @param policies The policies to associate with
|
||||||
* @param roleID A custom role ID
|
* @param roleID A custom role ID
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -214,7 +233,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* Delete AppRole role from Vault.
|
* Delete AppRole role from Vault.
|
||||||
*
|
*
|
||||||
* @param roleName The role anme
|
* @param roleName The role anme
|
||||||
* @return TRUE on succevss
|
* @return {@code true} on succevss
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
|
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
|
||||||
@ -244,7 +263,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param roleName The role name
|
* @param roleName The role name
|
||||||
* @param roleID The role ID
|
* @param roleID The role ID
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
@ -319,19 +338,6 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
List<String> listAppRoles() throws VaultConnectorException;
|
List<String> listAppRoles() throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
|
||||||
* List existing (accessible) secret IDs for AppRole role.
|
|
||||||
*
|
|
||||||
* @param roleName The role name
|
|
||||||
* @return List of roles
|
|
||||||
* @throws VaultConnectorException on error
|
|
||||||
* @deprecated Use {@link #listAppRoleSecrets(String)}}. Will be removed in 0.7.0!
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException {
|
|
||||||
return listAppRoleSecrets(roleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List existing (accessible) secret IDs for AppRole role.
|
* List existing (accessible) secret IDs for AppRole role.
|
||||||
*
|
*
|
||||||
@ -346,10 +352,10 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*
|
*
|
||||||
* @param appID The App-ID
|
* @param appID The App-ID
|
||||||
* @param userID The User-ID
|
* @param userID The User-ID
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||||
* Consider using {@link #createAppRoleSecret} instead.
|
* Consider using {@link #createAppRoleSecret} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||||
@ -361,7 +367,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* @param policy The policy to associate with
|
* @param policy The policy to associate with
|
||||||
* @param displayName Arbitrary name to display
|
* @param displayName Arbitrary name to display
|
||||||
* @param userID The User-ID
|
* @param userID The User-ID
|
||||||
* @return TRUE on success
|
* @return {@code true} on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||||
*/
|
*/
|
||||||
@ -392,7 +398,8 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve secret from Vault.
|
* Retrieve secret from Vault.
|
||||||
* Prefix "secret/" is automatically added to key.
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to key.
|
||||||
*
|
*
|
||||||
* @param key Secret identifier
|
* @param key Secret identifier
|
||||||
* @return Secret response
|
* @return Secret response
|
||||||
@ -402,6 +409,176 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
return read(PATH_SECRET + "/" + key);
|
return read(PATH_SECRET + "/" + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the latest secret data for specific version from Vault.
|
||||||
|
* <br>
|
||||||
|
* Prefix "secret/data" is automatically added to key.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @return Secret response
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default SecretResponse readSecretData(final String key) throws VaultConnectorException {
|
||||||
|
return readSecretVersion(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the latest secret data for specific version from Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/data/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @return Secret response
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default SecretResponse readSecretData(final String mount, final String key) throws VaultConnectorException {
|
||||||
|
return readSecretVersion(mount, key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write secret to Vault.
|
||||||
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param key Secret identifier.
|
||||||
|
* @param data Secret content. Value must be be JSON serializable.
|
||||||
|
* @return Metadata for the created/updated secret.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default SecretVersionResponse writeSecretData(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||||
|
return writeSecretData(PATH_SECRET, key, data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write secret to Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/data/<key>} is written here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param data Secret content. Value must be be JSON serializable.
|
||||||
|
* @return Metadata for the created/updated secret.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||||
|
return writeSecretData(mount, key, data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write secret to Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/data/<key>} is written here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param data Secret content. Value must be be JSON serializable.
|
||||||
|
* @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value.
|
||||||
|
* @return Metadata for the created/updated secret.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data, final Integer cas) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve secret data from Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/data/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
|
||||||
|
* @return Secret response
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default SecretResponse readSecretVersion(final String key, final Integer version) throws VaultConnectorException {
|
||||||
|
return readSecretVersion(PATH_SECRET, key, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve secret data from Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/data/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
|
||||||
|
* @return Secret responsef
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
SecretResponse readSecretVersion(final String mount, final String key, final Integer version) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve secret metadata from Vault.
|
||||||
|
* Path {@code secret/metadata/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @return Metadata response
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default MetadataResponse readSecretMetadata(final String key) throws VaultConnectorException {
|
||||||
|
return readSecretMetadata(PATH_SECRET, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update secret metadata.
|
||||||
|
* <br>
|
||||||
|
* Path {@code secret/metadata/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param maxVersions Maximum number of versions (fallback to backend default if {@code null})
|
||||||
|
* @param casRequired Specify if Check-And-Set is required for this secret.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void updateSecretMetadata(final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException {
|
||||||
|
updateSecretMetadata(PATH_SECRET, key, maxVersions, casRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve secret metadata from Vault.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/metadata/<key>} is read here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @return Metadata response
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
MetadataResponse readSecretMetadata(final String mount, final String key) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update secret metadata.
|
||||||
|
* <br>
|
||||||
|
* Path {@code <mount>/metadata/<key>} is written here.
|
||||||
|
* Only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret identifier
|
||||||
|
* @param maxVersions Maximum number of versions (fallback to backend default if {@code null})
|
||||||
|
* @param casRequired Specify if Check-And-Set is required for this secret.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void updateSecretMetadata(final String mount, final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List available nodes from Vault.
|
* List available nodes from Vault.
|
||||||
*
|
*
|
||||||
@ -414,7 +591,8 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* List available secrets from Vault.
|
* List available secrets from Vault.
|
||||||
* Prefix "secret/" is automatically added to path.
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
*
|
*
|
||||||
* @param path Root path to search
|
* @param path Root path to search
|
||||||
* @return List of secret keys
|
* @return List of secret keys
|
||||||
@ -446,11 +624,25 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
*/
|
*/
|
||||||
void write(final String key, final Map<String, Object> data) throws VaultConnectorException;
|
default void write(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||||
|
write(key, data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write value to Vault.
|
||||||
|
*
|
||||||
|
* @param key Secret path
|
||||||
|
* @param data Secret content. Value must be be JSON serializable.
|
||||||
|
* @param options Secret options (optional).
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8 {@code options} parameter added
|
||||||
|
*/
|
||||||
|
void write(final String key, final Map<String, Object> data, final Map<String, Object> options) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write secret to Vault.
|
* Write secret to Vault.
|
||||||
* Prefix "secret/" is automatically added to path.
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
*
|
*
|
||||||
* @param key Secret path
|
* @param key Secret path
|
||||||
* @param value Secret value
|
* @param value Secret value
|
||||||
@ -464,7 +656,8 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Write secret to Vault.
|
* Write secret to Vault.
|
||||||
* Prefix "secret/" is automatically added to path.
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
*
|
*
|
||||||
* @param key Secret path
|
* @param key Secret path
|
||||||
* @param data Secret content. Value must be be JSON serializable.
|
* @param data Secret content. Value must be be JSON serializable.
|
||||||
@ -472,8 +665,9 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
*/
|
*/
|
||||||
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||||
if (key == null || key.isEmpty())
|
if (key == null || key.isEmpty()) {
|
||||||
throw new InvalidRequestException("Secret path must not be empty.");
|
throw new InvalidRequestException("Secret path must not be empty.");
|
||||||
|
}
|
||||||
write(PATH_SECRET + "/" + key, data);
|
write(PATH_SECRET + "/" + key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +682,8 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete secret from Vault.
|
* Delete secret from Vault.
|
||||||
* Prefix "secret/" is automatically added to path.
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
*
|
*
|
||||||
* @param key Secret path
|
* @param key Secret path
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
@ -497,6 +692,135 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
delete(PATH_SECRET + "/" + key);
|
delete(PATH_SECRET + "/" + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete latest version of a secret from Vault.
|
||||||
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path. Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param key Secret path.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void deleteLatestSecretVersion(final String key) throws VaultConnectorException {
|
||||||
|
deleteLatestSecretVersion(PATH_SECRET, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete latest version of a secret from Vault.
|
||||||
|
* <br>
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret path.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete latest version of a secret from Vault.
|
||||||
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param key Secret path.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void deleteAllSecretVersions(final String key) throws VaultConnectorException {
|
||||||
|
deleteAllSecretVersions(PATH_SECRET, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete latest version of a secret from Vault.
|
||||||
|
* <br>
|
||||||
|
* Prefix {@code secret/} is automatically added to path.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret path.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete secret versions from Vault.
|
||||||
|
* <br>
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to delete.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void deleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||||
|
deleteSecretVersions(PATH_SECRET, key, versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete secret versions from Vault.
|
||||||
|
* <br>
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to delete.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void deleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undelete (restore) secret versions from Vault.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to undelete.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void undeleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||||
|
undeleteSecretVersions(PATH_SECRET, key, versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undelete (restore) secret versions from Vault.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to undelete.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void undeleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy secret versions from Vault.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to destroy.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
default void destroySecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||||
|
destroySecretVersions(PATH_SECRET, key, versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy secret versions from Vault.
|
||||||
|
* Only available for KV v2 stores.
|
||||||
|
*
|
||||||
|
* @param mount Secret store mountpoint (without leading or trailing slash).
|
||||||
|
* @param key Secret path.
|
||||||
|
* @param versions Versions of the secret to destroy.
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
void destroySecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke given lease immediately.
|
* Revoke given lease immediately.
|
||||||
*
|
*
|
||||||
@ -564,10 +888,12 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
TokenResponse lookupToken(final String token) throws VaultConnectorException;
|
TokenResponse lookupToken(final String token) throws VaultConnectorException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read credentials for MySQL backend at default mount point.
|
* Read credentials for MySQL backend at default mount point.
|
||||||
*
|
*
|
||||||
* @param role the role name
|
* @param role the role name
|
||||||
* @return the credentials response
|
* @return the credentials response
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
@ -579,7 +905,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
/**
|
/**
|
||||||
* Read credentials for PostgreSQL backend at default mount point.
|
* Read credentials for PostgreSQL backend at default mount point.
|
||||||
*
|
*
|
||||||
* @param role the role name
|
* @param role the role name
|
||||||
* @return the credentials response
|
* @return the credentials response
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
@ -591,7 +917,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
/**
|
/**
|
||||||
* Read credentials for MSSQL backend at default mount point.
|
* Read credentials for MSSQL backend at default mount point.
|
||||||
*
|
*
|
||||||
* @param role the role name
|
* @param role the role name
|
||||||
* @return the credentials response
|
* @return the credentials response
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
@ -603,7 +929,7 @@ public interface VaultConnector extends AutoCloseable {
|
|||||||
/**
|
/**
|
||||||
* Read credentials for MSSQL backend at default mount point.
|
* Read credentials for MSSQL backend at default mount point.
|
||||||
*
|
*
|
||||||
* @param role the role name
|
* @param role the role name
|
||||||
* @return the credentials response
|
* @return the credentials response
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.5.0
|
* @since 0.5.0
|
||||||
|
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.builder;
|
||||||
|
|
||||||
|
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||||
|
import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||||
|
import de.stklcode.jvault.connector.exception.TlsException;
|
||||||
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault Connector Factory implementation for HTTP Vault connectors.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||||
|
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
|
||||||
|
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
|
||||||
|
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
|
||||||
|
private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES";
|
||||||
|
|
||||||
|
public static final String DEFAULT_HOST = "127.0.0.1";
|
||||||
|
public static final Integer DEFAULT_PORT = 8200;
|
||||||
|
public static final boolean DEFAULT_TLS = true;
|
||||||
|
public static final String DEFAULT_TLS_VERSION = "TLSv1.2";
|
||||||
|
public static final String DEFAULT_PREFIX = "/v1/";
|
||||||
|
public static final int DEFAULT_NUMBER_OF_RETRIES = 0;
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
private Integer port;
|
||||||
|
private boolean tls;
|
||||||
|
private String tlsVersion;
|
||||||
|
private String prefix;
|
||||||
|
private X509Certificate trustedCA;
|
||||||
|
private int numberOfRetries;
|
||||||
|
private Integer timeout;
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default empty constructor.
|
||||||
|
* Initializes factory with default values.
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder() {
|
||||||
|
host = DEFAULT_HOST;
|
||||||
|
port = DEFAULT_PORT;
|
||||||
|
tls = DEFAULT_TLS;
|
||||||
|
tlsVersion = DEFAULT_TLS_VERSION;
|
||||||
|
prefix = DEFAULT_PREFIX;
|
||||||
|
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set hostname (default: 127.0.0.1).
|
||||||
|
*
|
||||||
|
* @param host Hostname or IP address
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withHost(final String host) {
|
||||||
|
this.host = host;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set port (default: 8200).
|
||||||
|
*
|
||||||
|
* @param port Vault TCP port
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withPort(final Integer port) {
|
||||||
|
this.port = port;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set TLS usage (default: TRUE).
|
||||||
|
*
|
||||||
|
* @param useTLS use TLS or not
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS) {
|
||||||
|
this.tls = useTLS;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set TLS usage (default: TRUE).
|
||||||
|
*
|
||||||
|
* @param useTLS Use TLS or not.
|
||||||
|
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
|
||||||
|
* @return self
|
||||||
|
* @since 0.8 Added version parameter (#22).
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS, final String version) {
|
||||||
|
this.tls = useTLS;
|
||||||
|
this.tlsVersion = version;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience Method for TLS usage (enabled by default).
|
||||||
|
*
|
||||||
|
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
|
||||||
|
* @return self
|
||||||
|
* @since 0.8 Added version parameter (#22).
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTLS(final String version) {
|
||||||
|
return withTLS(true, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience Method for TLS usage (enabled by default).
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTLS() {
|
||||||
|
return withTLS(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience Method for NOT using TLS.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withoutTLS() {
|
||||||
|
return withTLS(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
|
||||||
|
*
|
||||||
|
* @param prefix Vault API prefix (default: "/v1/"
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withPrefix(final String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a trusted CA certifiate for HTTPS connections.
|
||||||
|
*
|
||||||
|
* @param cert path to certificate file
|
||||||
|
* @return self
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
|
* @since 0.4.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||||
|
if (cert != null) {
|
||||||
|
return withTrustedCA(certificateFromFile(cert));
|
||||||
|
} else {
|
||||||
|
this.trustedCA = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a trusted CA certifiate for HTTPS connections.
|
||||||
|
*
|
||||||
|
* @param cert path to certificate file
|
||||||
|
* @return self
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTrustedCA(final X509Certificate cert) {
|
||||||
|
this.trustedCA = cert;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set token for automatic authentication, using {@link #buildAndAuth()}.
|
||||||
|
*
|
||||||
|
* @param token Vault token
|
||||||
|
* @return self
|
||||||
|
* @since 0.6.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withToken(final String token) {
|
||||||
|
this.token = token;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
* @throws VaultConnectorException if Vault address from environment variables is malformed
|
||||||
|
* @since 0.6.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder fromEnv() throws VaultConnectorException {
|
||||||
|
/* Parse URL from environment variable */
|
||||||
|
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
|
||||||
|
this.host = url.getHost();
|
||||||
|
this.port = url.getPort();
|
||||||
|
this.tls = url.getProtocol().equals("https");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new ConnectionException("URL provided in environment variable malformed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read number of retries */
|
||||||
|
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
|
||||||
|
try {
|
||||||
|
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
/* Ignore malformed values. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read token */
|
||||||
|
token = System.getenv(ENV_VAULT_TOKEN);
|
||||||
|
|
||||||
|
/* Parse certificate, if set */
|
||||||
|
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
|
||||||
|
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the number of retries to attempt on 5xx errors.
|
||||||
|
*
|
||||||
|
* @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0)
|
||||||
|
* @return self
|
||||||
|
* @since 0.6.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withNumberOfRetries(final int numberOfRetries) {
|
||||||
|
this.numberOfRetries = numberOfRetries;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a custom timeout for the HTTP connection.
|
||||||
|
*
|
||||||
|
* @param milliseconds Timeout value in milliseconds.
|
||||||
|
* @return self
|
||||||
|
* @since 0.6.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorBuilder withTimeout(final int milliseconds) {
|
||||||
|
this.timeout = milliseconds;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HTTPVaultConnector build() {
|
||||||
|
return new HTTPVaultConnector(host, tls, tlsVersion, port, prefix, trustedCA, numberOfRetries, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||||
|
if (token == null) {
|
||||||
|
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
||||||
|
}
|
||||||
|
HTTPVaultConnector con = build();
|
||||||
|
con.authToken(token);
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read given certificate file to X.509 certificate.
|
||||||
|
*
|
||||||
|
* @param certFile Path to certificate file
|
||||||
|
* @return X.509 Certificate object
|
||||||
|
* @throws TlsException on error
|
||||||
|
* @since 0.4.0
|
||||||
|
*/
|
||||||
|
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
|
||||||
|
try (InputStream is = Files.newInputStream(certFile)) {
|
||||||
|
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||||
|
} catch (IOException | CertificateException e) {
|
||||||
|
throw new TlsException("Unable to read certificate.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.builder;
|
||||||
|
|
||||||
|
import de.stklcode.jvault.connector.VaultConnector;
|
||||||
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Vault Connector Builder interface.
|
||||||
|
* Provides builder style for Vault connectors.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public interface VaultConnectorBuilder {
|
||||||
|
/**
|
||||||
|
* Get Factory implementation for HTTP Vault Connector.
|
||||||
|
*
|
||||||
|
* @return HTTP Connector Factory
|
||||||
|
*/
|
||||||
|
static HTTPVaultConnectorBuilder http() {
|
||||||
|
return new HTTPVaultConnectorBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build command, produces connector after initialization.
|
||||||
|
*
|
||||||
|
* @return Vault Connector instance.
|
||||||
|
*/
|
||||||
|
VaultConnector build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build connector and authenticate with token set in factory or from environment.
|
||||||
|
*
|
||||||
|
* @return Authenticated Vault connector instance.
|
||||||
|
* @throws VaultConnectorException if authentication failed
|
||||||
|
* @since 0.6.0
|
||||||
|
*/
|
||||||
|
VaultConnector buildAndAuth() throws VaultConnectorException;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This package contains the {@link de.stklcode.jvault.connector.builder.VaultConnectorBuilder} to initialize a
|
||||||
|
* connector instance.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.builder;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -38,7 +38,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new exception with the specified detail message.
|
* Constructs a new exception with the specified detail message.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final String message) {
|
public InvalidResponseException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
@ -49,7 +49,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new exception with the specified cause.
|
* Constructs a new exception with the specified cause.
|
||||||
*
|
*
|
||||||
* @param cause the cause
|
* @param cause The cause
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final Throwable cause) {
|
public InvalidResponseException(final Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
@ -60,8 +60,8 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new exception with the specified detail message and cause.
|
* Constructs a new exception with the specified detail message and cause.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
* @param cause the cause
|
* @param cause The cause
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final String message, final Throwable cause) {
|
public InvalidResponseException(final String message, final Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
@ -74,8 +74,8 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
* <p>
|
* <p>
|
||||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
* @param statusCode status code of the HTTP response
|
* @param statusCode Status code of the HTTP response
|
||||||
* @since 0.6.2
|
* @since 0.6.2
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final String message, final Integer statusCode) {
|
public InvalidResponseException(final String message, final Integer statusCode) {
|
||||||
@ -89,9 +89,9 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
* <p>
|
* <p>
|
||||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
* @param statusCode status code of the HTTP response
|
* @param statusCode Status code of the HTTP response
|
||||||
* @param cause the cause
|
* @param cause The cause
|
||||||
* @since 0.6.2
|
* @since 0.6.2
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final String message, final Integer statusCode, final Throwable cause) {
|
public InvalidResponseException(final String message, final Integer statusCode, final Throwable cause) {
|
||||||
@ -103,8 +103,8 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
* <p>
|
* <p>
|
||||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
* @param statusCode status code of the HTTP response
|
* @param statusCode Status code of the HTTP response
|
||||||
* @param response HTTP response string
|
* @param response HTTP response string
|
||||||
* @since 0.6.2
|
* @since 0.6.2
|
||||||
*/
|
*/
|
||||||
@ -121,10 +121,10 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
* <p>
|
* <p>
|
||||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message The detail message
|
||||||
* @param statusCode status code of the HTTP response
|
* @param statusCode Status code of the HTTP response
|
||||||
* @param response HTTP response string
|
* @param response HTTP response string
|
||||||
* @param cause the cause
|
* @param cause The cause
|
||||||
* @since 0.6.2
|
* @since 0.6.2
|
||||||
*/
|
*/
|
||||||
public InvalidResponseException(final String message,
|
public InvalidResponseException(final String message,
|
||||||
@ -139,7 +139,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Specify the HTTP status code. Can be retrieved by {@link #getStatusCode()} later.
|
* Specify the HTTP status code. Can be retrieved by {@link #getStatusCode()} later.
|
||||||
*
|
*
|
||||||
* @param statusCode the status code
|
* @param statusCode The status code
|
||||||
* @return self
|
* @return self
|
||||||
* @deprecated as of 0.6.2, use constructor with status code argument instead
|
* @deprecated as of 0.6.2, use constructor with status code argument instead
|
||||||
*/
|
*/
|
||||||
@ -151,7 +151,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Specify the response string. Can be retrieved by {@link #getResponse()} later.
|
* Specify the response string. Can be retrieved by {@link #getResponse()} later.
|
||||||
*
|
*
|
||||||
* @param response response text
|
* @param response Response text
|
||||||
* @return self
|
* @return self
|
||||||
* @deprecated use constructor with response argument instead
|
* @deprecated use constructor with response argument instead
|
||||||
*/
|
*/
|
||||||
@ -163,7 +163,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Retrieve the HTTP status code.
|
* Retrieve the HTTP status code.
|
||||||
*
|
*
|
||||||
* @return the status code or {@code null} if none specified.
|
* @return The status code or {@code null} if none specified.
|
||||||
*/
|
*/
|
||||||
public Integer getStatusCode() {
|
public Integer getStatusCode() {
|
||||||
return statusCode;
|
return statusCode;
|
||||||
@ -172,7 +172,7 @@ public final class InvalidResponseException extends VaultConnectorException {
|
|||||||
/**
|
/**
|
||||||
* Retrieve the response text.
|
* Retrieve the response text.
|
||||||
*
|
*
|
||||||
* @return the response text or {@code null} if none specified.
|
* @return The response text or {@code null} if none specified.
|
||||||
*/
|
*/
|
||||||
public String getResponse() {
|
public String getResponse() {
|
||||||
return response;
|
return response;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some custom exceptions for error handling.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.exception;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,23 +17,11 @@
|
|||||||
package de.stklcode.jvault.connector.factory;
|
package de.stklcode.jvault.connector.factory;
|
||||||
|
|
||||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||||
import de.stklcode.jvault.connector.exception.ConnectionException;
|
import de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder;
|
||||||
import de.stklcode.jvault.connector.exception.TlsException;
|
|
||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.*;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,38 +29,19 @@ import java.security.cert.X509Certificate;
|
|||||||
*
|
*
|
||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
|
* @deprecated As of 0.8.0 please refer to {@link de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder} with identical API.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||||
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
|
|
||||||
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
|
|
||||||
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
|
|
||||||
private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES";
|
|
||||||
|
|
||||||
public static final String DEFAULT_HOST = "127.0.0.1";
|
private final HTTPVaultConnectorBuilder delegate;
|
||||||
public static final Integer DEFAULT_PORT = 8200;
|
|
||||||
public static final boolean DEFAULT_TLS = true;
|
|
||||||
public static final String DEFAULT_PREFIX = "/v1/";
|
|
||||||
public static final int DEFAULT_NUMBER_OF_RETRIES = 0;
|
|
||||||
|
|
||||||
private String host;
|
|
||||||
private Integer port;
|
|
||||||
private boolean tls;
|
|
||||||
private String prefix;
|
|
||||||
private SSLContext sslContext;
|
|
||||||
private int numberOfRetries;
|
|
||||||
private Integer timeout;
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default empty constructor.
|
* Default empty constructor.
|
||||||
* Initializes factory with default values.
|
* Initializes factory with default values.
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory() {
|
public HTTPVaultConnectorFactory() {
|
||||||
host = DEFAULT_HOST;
|
delegate = new HTTPVaultConnectorBuilder();
|
||||||
port = DEFAULT_PORT;
|
|
||||||
tls = DEFAULT_TLS;
|
|
||||||
prefix = DEFAULT_PREFIX;
|
|
||||||
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,7 +51,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withHost(final String host) {
|
public HTTPVaultConnectorFactory withHost(final String host) {
|
||||||
this.host = host;
|
delegate.withHost(host);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +62,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withPort(final Integer port) {
|
public HTTPVaultConnectorFactory withPort(final Integer port) {
|
||||||
this.port = port;
|
delegate.withPort(port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +73,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withTLS(final boolean useTLS) {
|
public HTTPVaultConnectorFactory withTLS(final boolean useTLS) {
|
||||||
this.tls = useTLS;
|
delegate.withTLS(useTLS);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +102,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withPrefix(final String prefix) {
|
public HTTPVaultConnectorFactory withPrefix(final String prefix) {
|
||||||
this.prefix = prefix;
|
delegate.withPrefix(prefix);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,8 +115,19 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||||
if (cert != null)
|
delegate.withTrustedCA(cert);
|
||||||
return withSslContext(createSslContext(cert));
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a trusted CA certifiate for HTTPS connections.
|
||||||
|
*
|
||||||
|
* @param cert path to certificate file
|
||||||
|
* @return self
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public HTTPVaultConnectorFactory withTrustedCA(final X509Certificate cert) {
|
||||||
|
delegate.withTrustedCA(cert);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,10 +138,10 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @param sslContext the SSL context
|
* @param sslContext the SSL context
|
||||||
* @return self
|
* @return self
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
|
* @deprecated As of 0.8.0 this is no longer supported, please use {@link #withTrustedCA(Path)} or {@link #withTrustedCA(X509Certificate)}.
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
||||||
this.sslContext = sslContext;
|
throw new UnsupportedOperationException("Use of deprecated method, please switch to withTrustedCA()");
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,7 +152,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.6.0
|
* @since 0.6.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withToken(final String token) {
|
public HTTPVaultConnectorFactory withToken(final String token) {
|
||||||
this.token = token;
|
delegate.withToken(token);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,33 +164,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.6.0
|
* @since 0.6.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException {
|
public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException {
|
||||||
/* Parse URL from environment variable */
|
delegate.fromEnv();
|
||||||
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
|
|
||||||
try {
|
|
||||||
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
|
|
||||||
this.host = url.getHost();
|
|
||||||
this.port = url.getPort();
|
|
||||||
this.tls = url.getProtocol().equals("https");
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
throw new ConnectionException("URL provided in environment variable malformed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read number of retries */
|
|
||||||
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
|
|
||||||
try {
|
|
||||||
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read token */
|
|
||||||
token = System.getenv(ENV_VAULT_TOKEN);
|
|
||||||
|
|
||||||
/* Parse certificate, if set */
|
|
||||||
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
|
|
||||||
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +176,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.6.0
|
* @since 0.6.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) {
|
public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) {
|
||||||
this.numberOfRetries = numberOfRetries;
|
delegate.withNumberOfRetries(numberOfRetries);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,78 +188,17 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.6.0
|
* @since 0.6.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withTimeout(final int milliseconds) {
|
public HTTPVaultConnectorFactory withTimeout(final int milliseconds) {
|
||||||
this.timeout = milliseconds;
|
delegate.withTimeout(milliseconds);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HTTPVaultConnector build() {
|
public HTTPVaultConnector build() {
|
||||||
return new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
return delegate.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||||
if (token == null)
|
return delegate.buildAndAuth();
|
||||||
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
|
||||||
HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
|
||||||
con.authToken(token);
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create SSL Context trusting only provided certificate.
|
|
||||||
*
|
|
||||||
* @param trustedCert Path to trusted CA certificate
|
|
||||||
* @return SSL context
|
|
||||||
* @throws TlsException on errors
|
|
||||||
* @since 0.4.0
|
|
||||||
*/
|
|
||||||
private SSLContext createSslContext(final Path trustedCert) throws TlsException {
|
|
||||||
try {
|
|
||||||
SSLContext context = SSLContext.getInstance("TLS");
|
|
||||||
context.init(null, createTrustManager(trustedCert), new SecureRandom());
|
|
||||||
return context;
|
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
|
||||||
throw new TlsException("Unable to intialize SSLContext", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a custom TrustManager for given CA certificate file.
|
|
||||||
*
|
|
||||||
* @param trustedCert Path to trusted CA certificate
|
|
||||||
* @return TrustManger
|
|
||||||
* @throws TlsException on error
|
|
||||||
* @since 0.4.0
|
|
||||||
*/
|
|
||||||
private TrustManager[] createTrustManager(final Path trustedCert) throws TlsException {
|
|
||||||
try {
|
|
||||||
/* Create Keystore with trusted certificate */
|
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
keyStore.load(null, null);
|
|
||||||
keyStore.setCertificateEntry("trustedCert", certificateFromFile(trustedCert));
|
|
||||||
/* Initialize TrustManager */
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
tmf.init(keyStore);
|
|
||||||
return tmf.getTrustManagers();
|
|
||||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
|
|
||||||
throw new TlsException("Unable to initialize TrustManager", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read given certificate file to X.509 certificate.
|
|
||||||
*
|
|
||||||
* @param certFile Path to certificate file
|
|
||||||
* @return X.509 Certificate object
|
|
||||||
* @throws TlsException on error
|
|
||||||
* @since 0.4.0
|
|
||||||
*/
|
|
||||||
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
|
|
||||||
try (InputStream is = Files.newInputStream(certFile)) {
|
|
||||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
|
||||||
} catch (IOException | CertificateException e) {
|
|
||||||
throw new TlsException("Unable to read certificate.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
package de.stklcode.jvault.connector.factory;
|
package de.stklcode.jvault.connector.factory;
|
||||||
|
|
||||||
import de.stklcode.jvault.connector.VaultConnector;
|
import de.stklcode.jvault.connector.builder.VaultConnectorBuilder;
|
||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract Vault Connector Factory interface.
|
* Abstract Vault Connector Factory interface.
|
||||||
@ -25,30 +24,19 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
|||||||
*
|
*
|
||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
|
* @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder} with identical API.
|
||||||
*/
|
*/
|
||||||
public abstract class VaultConnectorFactory {
|
@Deprecated
|
||||||
|
public abstract class VaultConnectorFactory implements VaultConnectorBuilder {
|
||||||
/**
|
/**
|
||||||
* Get Factory implementation for HTTP Vault Connector.
|
* Get Factory implementation for HTTP Vault Connector.
|
||||||
*
|
*
|
||||||
* @return HTTP Connector Factory
|
* @return HTTP Connector Factory
|
||||||
|
* @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder#http()}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static HTTPVaultConnectorFactory httpFactory() {
|
public static HTTPVaultConnectorFactory httpFactory() {
|
||||||
return new HTTPVaultConnectorFactory();
|
return new HTTPVaultConnectorFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build command, produces connector after initialization.
|
|
||||||
*
|
|
||||||
* @return Vault Connector instance.
|
|
||||||
*/
|
|
||||||
public abstract VaultConnector build();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build connector and authenticate with token set in factory or from environment.
|
|
||||||
*
|
|
||||||
* @return Authenticated Vault connector instance.
|
|
||||||
* @throws VaultConnectorException if authentication failed
|
|
||||||
* @since 0.6.0
|
|
||||||
*/
|
|
||||||
public abstract VaultConnector buildAndAuth() throws VaultConnectorException;
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This package contains the {@link de.stklcode.jvault.connector.factory.VaultConnectorFactory} to initialize a
|
||||||
|
* connector instance.
|
||||||
|
*
|
||||||
|
* @deprecated As of v0.8.0 please refer to {@link de.stklcode.jvault.connector.builder}.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.factory;
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.internal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to bundle common error messages.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8 Extracted from static inner class.
|
||||||
|
*/
|
||||||
|
final class Error {
|
||||||
|
static final String READ_RESPONSE = "Unable to read response";
|
||||||
|
static final String PARSE_RESPONSE = "Unable to parse response";
|
||||||
|
static final String UNEXPECTED_RESPONSE = "Received response where none was expected";
|
||||||
|
static final String URI_FORMAT = "Invalid URI format";
|
||||||
|
static final String RESPONSE_CODE = "Invalid response code";
|
||||||
|
static final String INIT_SSL_CONTEXT = "Unable to intialize SSLContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor hidden, this class should not be instantiated.
|
||||||
|
*/
|
||||||
|
private Error() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,433 @@
|
|||||||
|
package de.stklcode.jvault.connector.internal;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import de.stklcode.jvault.connector.exception.*;
|
||||||
|
import de.stklcode.jvault.connector.model.response.ErrorResponse;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.methods.*;
|
||||||
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to bundle Vault HTTP requests.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8 Extracted methods from {@link de.stklcode.jvault.connector.HTTPVaultConnector}.
|
||||||
|
*/
|
||||||
|
public final class RequestHelper implements Serializable {
|
||||||
|
private static final String HEADER_VAULT_TOKEN = "X-Vault-Token";
|
||||||
|
|
||||||
|
private final String baseURL; // Base URL of Vault.
|
||||||
|
private final Integer timeout; // Timeout in milliseconds.
|
||||||
|
private final int retries; // Number of retries on 5xx errors.
|
||||||
|
private final String tlsVersion; // TLS version (#22).
|
||||||
|
private final X509Certificate trustedCaCert; // Trusted CA certificate.
|
||||||
|
private final ObjectMapper jsonMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the request helper.
|
||||||
|
*
|
||||||
|
* @param baseURL The URL
|
||||||
|
* @param retries Number of retries on 5xx errors
|
||||||
|
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||||
|
* @param tlsVersion TLS Version.
|
||||||
|
* @param trustedCaCert Trusted CA certificate
|
||||||
|
*/
|
||||||
|
public RequestHelper(final String baseURL,
|
||||||
|
final int retries,
|
||||||
|
final Integer timeout,
|
||||||
|
final String tlsVersion,
|
||||||
|
final X509Certificate trustedCaCert) {
|
||||||
|
this.baseURL = baseURL;
|
||||||
|
this.retries = retries;
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.tlsVersion = tlsVersion;
|
||||||
|
this.trustedCaCert = trustedCaCert;
|
||||||
|
this.jsonMapper = new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using POST method.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8 Added {@code token} parameter.
|
||||||
|
*/
|
||||||
|
public String post(final String path, final Object payload, final String token) throws VaultConnectorException {
|
||||||
|
/* Initialize post */
|
||||||
|
HttpPost post = new HttpPost(baseURL + path);
|
||||||
|
|
||||||
|
/* generate JSON from payload */
|
||||||
|
StringEntity input;
|
||||||
|
try {
|
||||||
|
input = new StringEntity(jsonMapper.writeValueAsString(payload), StandardCharsets.UTF_8);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new InvalidRequestException(Error.PARSE_RESPONSE, e);
|
||||||
|
}
|
||||||
|
input.setContentEncoding("UTF-8");
|
||||||
|
input.setContentType("application/json");
|
||||||
|
post.setEntity(input);
|
||||||
|
|
||||||
|
/* Set X-Vault-Token header */
|
||||||
|
if (token != null) {
|
||||||
|
post.addHeader(HEADER_VAULT_TOKEN, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request(post, retries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using POST method and parse JSON result.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @param target Target class.
|
||||||
|
* @param <T> Target type.
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public <T> T post(final String path, final Object payload, final String token, final Class<T> target)
|
||||||
|
throws VaultConnectorException {
|
||||||
|
try {
|
||||||
|
String response = post(path, payload, token);
|
||||||
|
return jsonMapper.readValue(response, target);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException(Error.PARSE_RESPONSE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using POST method and expect empty (204) response.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public void postWithoutResponse(final String path, final Object payload, final String token) throws VaultConnectorException {
|
||||||
|
if (!post(path, payload, token).isEmpty()) {
|
||||||
|
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using PUT method.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8 Added {@code token} parameter.
|
||||||
|
*/
|
||||||
|
public String put(final String path, final Map<String, String> payload, final String token) throws VaultConnectorException {
|
||||||
|
/* Initialize put */
|
||||||
|
HttpPut put = new HttpPut(baseURL + path);
|
||||||
|
|
||||||
|
/* generate JSON from payload */
|
||||||
|
StringEntity entity = null;
|
||||||
|
try {
|
||||||
|
entity = new StringEntity(jsonMapper.writeValueAsString(payload));
|
||||||
|
} catch (UnsupportedEncodingException | JsonProcessingException e) {
|
||||||
|
throw new InvalidRequestException("Payload serialization failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse parameters */
|
||||||
|
put.setEntity(entity);
|
||||||
|
|
||||||
|
/* Set X-Vault-Token header */
|
||||||
|
if (token != null) {
|
||||||
|
put.addHeader(HEADER_VAULT_TOKEN, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request(put, retries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using PUT method and parse JSON result.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @param target Target class.
|
||||||
|
* @param <T> Target type.
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public <T> T put(final String path, final Map<String, String> payload, final String token, final Class<T> target)
|
||||||
|
throws VaultConnectorException {
|
||||||
|
try {
|
||||||
|
String response = put(path, payload, token);
|
||||||
|
return jsonMapper.readValue(response, target);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException(Error.PARSE_RESPONSE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using PUT method and expect empty (204) response.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public void putWithoutResponse(final String path, final Map<String, String> payload, final String token)
|
||||||
|
throws VaultConnectorException {
|
||||||
|
if (!put(path, payload, token).isEmpty()) {
|
||||||
|
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using DELETE method.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8 Added {@code token} parameter.
|
||||||
|
*/
|
||||||
|
public String delete(final String path, final String token) throws VaultConnectorException {
|
||||||
|
/* Initialize delete */
|
||||||
|
HttpDelete delete = new HttpDelete(baseURL + path);
|
||||||
|
|
||||||
|
/* Set X-Vault-Token header */
|
||||||
|
if (token != null) {
|
||||||
|
delete.addHeader(HEADER_VAULT_TOKEN, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request(delete, retries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using DELETE method and expect empty (204) response.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public void deleteWithoutResponse(final String path, final String token) throws VaultConnectorException {
|
||||||
|
if (!delete(path, token).isEmpty()) {
|
||||||
|
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using GET method.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8 Added {@code token} parameter.
|
||||||
|
*/
|
||||||
|
public String get(final String path, final Map<String, String> payload, final String token)
|
||||||
|
throws VaultConnectorException {
|
||||||
|
HttpGet get;
|
||||||
|
try {
|
||||||
|
/* Add parameters to URI */
|
||||||
|
URIBuilder uriBuilder = new URIBuilder(baseURL + path);
|
||||||
|
payload.forEach(uriBuilder::addParameter);
|
||||||
|
|
||||||
|
/* Initialize request */
|
||||||
|
get = new HttpGet(uriBuilder.build());
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
/* this should never occur and may leak sensible information */
|
||||||
|
throw new InvalidRequestException(Error.URI_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set X-Vault-Token header */
|
||||||
|
if (token != null) {
|
||||||
|
get.addHeader(HEADER_VAULT_TOKEN, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request(get, retries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request using GET method and parse JSON result to target class.
|
||||||
|
*
|
||||||
|
* @param path URL path (relative to base).
|
||||||
|
* @param payload Map of payload values (will be converted to JSON).
|
||||||
|
* @param token Vault token (may be {@code null}).
|
||||||
|
* @param target Target class.
|
||||||
|
* @param <T> Target type.
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public <T> T get(final String path, final Map<String, String> payload, final String token, final Class<T> target)
|
||||||
|
throws VaultConnectorException {
|
||||||
|
try {
|
||||||
|
String response = get(path, payload, token);
|
||||||
|
return jsonMapper.readValue(response, target);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException(Error.PARSE_RESPONSE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute prepared HTTP request and return result.
|
||||||
|
*
|
||||||
|
* @param base Prepares Request
|
||||||
|
* @param retries number of retries
|
||||||
|
* @return HTTP response
|
||||||
|
* @throws VaultConnectorException on connection error
|
||||||
|
*/
|
||||||
|
private String request(final HttpRequestBase base, final int retries) throws VaultConnectorException {
|
||||||
|
/* Set JSON Header */
|
||||||
|
base.addHeader("accept", "application/json");
|
||||||
|
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
|
||||||
|
try (CloseableHttpClient httpClient = HttpClientBuilder.create()
|
||||||
|
.setSSLSocketFactory(createSSLSocketFactory())
|
||||||
|
.build()) {
|
||||||
|
/* Set custom timeout, if defined */
|
||||||
|
if (this.timeout != null) {
|
||||||
|
base.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(timeout).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute request */
|
||||||
|
response = httpClient.execute(base);
|
||||||
|
|
||||||
|
/* Check if response is valid */
|
||||||
|
if (response == null) {
|
||||||
|
throw new InvalidResponseException("Response unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (response.getStatusLine().getStatusCode()) {
|
||||||
|
case 200:
|
||||||
|
return handleResult(response);
|
||||||
|
case 204:
|
||||||
|
return "";
|
||||||
|
case 403:
|
||||||
|
throw new PermissionDeniedException();
|
||||||
|
default:
|
||||||
|
if (response.getStatusLine().getStatusCode() >= 500
|
||||||
|
&& response.getStatusLine().getStatusCode() < 600 && retries > 0) {
|
||||||
|
/* Retry on 5xx errors */
|
||||||
|
return request(base, retries - 1);
|
||||||
|
} else {
|
||||||
|
/* Fail on different error code and/or no retries left */
|
||||||
|
handleError(response);
|
||||||
|
|
||||||
|
/* Throw exception withoud details, if response entity is empty. */
|
||||||
|
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
||||||
|
response.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException(Error.READ_RESPONSE, e);
|
||||||
|
} finally {
|
||||||
|
if (response != null && response.getEntity() != null) {
|
||||||
|
try {
|
||||||
|
EntityUtils.consume(response.getEntity());
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// Exception ignored.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a custom socket factory from trusted CA certificate.
|
||||||
|
*
|
||||||
|
* @return The factory.
|
||||||
|
* @throws TlsException An error occured during initialization of the SSL context.
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
private SSLConnectionSocketFactory createSSLSocketFactory() throws TlsException {
|
||||||
|
try {
|
||||||
|
// Create Keystore with trusted certificate.
|
||||||
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
|
keyStore.load(null, null);
|
||||||
|
keyStore.setCertificateEntry("trustedCert", trustedCaCert);
|
||||||
|
|
||||||
|
// Initialize TrustManager.
|
||||||
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
tmf.init(keyStore);
|
||||||
|
|
||||||
|
// Create context usint this TrustManager.
|
||||||
|
SSLContext context = SSLContext.getInstance(tlsVersion);
|
||||||
|
context.init(null, tmf.getTrustManagers(), new SecureRandom());
|
||||||
|
|
||||||
|
return new SSLConnectionSocketFactory(
|
||||||
|
context,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
|
||||||
|
);
|
||||||
|
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
|
||||||
|
throw new TlsException(Error.INIT_SSL_CONTEXT, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle successful result.
|
||||||
|
*
|
||||||
|
* @param response The raw HTTP response (assuming status code 200)
|
||||||
|
* @return Complete response body as String
|
||||||
|
* @throws InvalidResponseException on reading errors
|
||||||
|
*/
|
||||||
|
private String handleResult(final HttpResponse response) throws InvalidResponseException {
|
||||||
|
try (BufferedReader br = new BufferedReader(
|
||||||
|
new InputStreamReader(response.getEntity().getContent()))) {
|
||||||
|
return br.lines().collect(Collectors.joining("\n"));
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
throw new InvalidResponseException(Error.READ_RESPONSE, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle unsuccessful response. Throw detailed exception if possible.
|
||||||
|
*
|
||||||
|
* @param response The raw HTTP response (assuming status code 5xx)
|
||||||
|
* @throws VaultConnectorException Expected exception with details to throw
|
||||||
|
*/
|
||||||
|
private void handleError(final HttpResponse response) throws VaultConnectorException {
|
||||||
|
if (response.getEntity() != null) {
|
||||||
|
try (BufferedReader br = new BufferedReader(
|
||||||
|
new InputStreamReader(response.getEntity().getContent()))) {
|
||||||
|
String responseString = br.lines().collect(Collectors.joining("\n"));
|
||||||
|
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
|
||||||
|
/* Check for "permission denied" response */
|
||||||
|
if (!er.getErrors().isEmpty() && er.getErrors().get(0).equals("permission denied")) {
|
||||||
|
throw new PermissionDeniedException();
|
||||||
|
}
|
||||||
|
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
||||||
|
response.getStatusLine().getStatusCode(), er.toString());
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// Exception ignored.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,6 +28,17 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public final class AppRole {
|
public final class AppRole {
|
||||||
|
/**
|
||||||
|
* Get {@link AppRoleBuilder} instance.
|
||||||
|
*
|
||||||
|
* @param name Role name.
|
||||||
|
* @return AppRole Builder.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public static AppRoleBuilder builder(final String name) {
|
||||||
|
return new AppRoleBuilder(name);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty("role_name")
|
@JsonProperty("role_name")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ -41,6 +52,8 @@ public final class AppRole {
|
|||||||
|
|
||||||
private List<String> boundCidrList;
|
private List<String> boundCidrList;
|
||||||
|
|
||||||
|
private List<String> secretIdBoundCidrs;
|
||||||
|
|
||||||
private List<String> policies;
|
private List<String> policies;
|
||||||
|
|
||||||
@JsonProperty("secret_id_num_uses")
|
@JsonProperty("secret_id_num_uses")
|
||||||
@ -73,24 +86,57 @@ public final class AppRole {
|
|||||||
/**
|
/**
|
||||||
* Construct complete {@link AppRole} object.
|
* Construct complete {@link AppRole} object.
|
||||||
*
|
*
|
||||||
* @param name Role name (required)
|
* @param name Role name (required)
|
||||||
* @param id Role ID (optional)
|
* @param id Role ID (optional)
|
||||||
* @param bindSecretId Bind secret ID (optional)
|
* @param bindSecretId Bind secret ID (optional)
|
||||||
* @param boundCidrList Whitelist of subnets in CIDR notation (optional)
|
* @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional)
|
||||||
* @param policies List of policies (optional)
|
* @param policies List of policies (optional)
|
||||||
* @param secretIdNumUses Maximum number of uses per secret (optional)
|
* @param secretIdNumUses Maximum number of uses per secret (optional)
|
||||||
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
|
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
|
||||||
* @param tokenTtl Token TTL in seconds (optional)
|
* @param tokenTtl Token TTL in seconds (optional)
|
||||||
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
|
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
|
||||||
* @param period Duration in seconds, if set the token is a periodic token (optional)
|
* @param period Duration in seconds, if set the token is a periodic token (optional)
|
||||||
*/
|
*/
|
||||||
public AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> boundCidrList,
|
public AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> secretIdBoundCidrs,
|
||||||
final List<String> policies, final Integer secretIdNumUses, final Integer secretIdTtl,
|
final List<String> policies, final Integer secretIdNumUses, final Integer secretIdTtl,
|
||||||
final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) {
|
final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.bindSecretId = bindSecretId;
|
this.bindSecretId = bindSecretId;
|
||||||
|
this.secretIdBoundCidrs = secretIdBoundCidrs;
|
||||||
|
this.policies = policies;
|
||||||
|
this.secretIdNumUses = secretIdNumUses;
|
||||||
|
this.secretIdTtl = secretIdTtl;
|
||||||
|
this.tokenTtl = tokenTtl;
|
||||||
|
this.tokenMaxTtl = tokenMaxTtl;
|
||||||
|
this.period = period;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct complete {@link AppRole} object.
|
||||||
|
* <p>
|
||||||
|
* This constructor is used for transition from {@code bound_cidr_list} to {@code secret_id_bound_cidrs} only.
|
||||||
|
*
|
||||||
|
* @param name Role name (required)
|
||||||
|
* @param id Role ID (optional)
|
||||||
|
* @param bindSecretId Bind secret ID (optional)
|
||||||
|
* @param boundCidrList Whitelist of subnets in CIDR notation (optional)
|
||||||
|
* @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional)
|
||||||
|
* @param policies List of policies (optional)
|
||||||
|
* @param secretIdNumUses Maximum number of uses per secret (optional)
|
||||||
|
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
|
||||||
|
* @param tokenTtl Token TTL in seconds (optional)
|
||||||
|
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
|
||||||
|
* @param period Duration in seconds, if set the token is a periodic token (optional)
|
||||||
|
*/
|
||||||
|
AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> boundCidrList,
|
||||||
|
final List<String> secretIdBoundCidrs, final List<String> policies, final Integer secretIdNumUses,
|
||||||
|
final Integer secretIdTtl, final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) {
|
||||||
|
this.name = name;
|
||||||
|
this.id = id;
|
||||||
|
this.bindSecretId = bindSecretId;
|
||||||
this.boundCidrList = boundCidrList;
|
this.boundCidrList = boundCidrList;
|
||||||
|
this.secretIdBoundCidrs = secretIdBoundCidrs;
|
||||||
this.policies = policies;
|
this.policies = policies;
|
||||||
this.secretIdNumUses = secretIdNumUses;
|
this.secretIdNumUses = secretIdNumUses;
|
||||||
this.secretIdTtl = secretIdTtl;
|
this.secretIdTtl = secretIdTtl;
|
||||||
@ -122,14 +168,18 @@ public final class AppRole {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of bound CIDR subnets
|
* @return list of bound CIDR subnets
|
||||||
|
* @deprecated Use {@link #getSecretIdBoundCidrs()} instead, as this parameter is deprecated in Vault.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public List<String> getBoundCidrList() {
|
public List<String> getBoundCidrList() {
|
||||||
return boundCidrList;
|
return boundCidrList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boundCidrList list of subnets in CIDR notation to bind role to
|
* @param boundCidrList list of subnets in CIDR notation to bind role to
|
||||||
|
* @deprecated Use {@link #setSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@JsonSetter("bound_cidr_list")
|
@JsonSetter("bound_cidr_list")
|
||||||
public void setBoundCidrList(final List<String> boundCidrList) {
|
public void setBoundCidrList(final List<String> boundCidrList) {
|
||||||
this.boundCidrList = boundCidrList;
|
this.boundCidrList = boundCidrList;
|
||||||
@ -137,15 +187,48 @@ public final class AppRole {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of subnets in CIDR notation as comma-separated {@link String}
|
* @return list of subnets in CIDR notation as comma-separated {@link String}
|
||||||
|
* @deprecated Use {@link #getSecretIdBoundCidrsString()} instead, as this parameter is deprecated in Vault.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@JsonGetter("bound_cidr_list")
|
@JsonGetter("bound_cidr_list")
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
public String getBoundCidrListString() {
|
public String getBoundCidrListString() {
|
||||||
if (boundCidrList == null || boundCidrList.isEmpty())
|
if (boundCidrList == null || boundCidrList.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
return String.join(",", boundCidrList);
|
return String.join(",", boundCidrList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list of bound CIDR subnets
|
||||||
|
* @since 0.8 replaces {@link #getBoundCidrList()}
|
||||||
|
*/
|
||||||
|
public List<String> getSecretIdBoundCidrs() {
|
||||||
|
return secretIdBoundCidrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secretIdBoundCidrs List of subnets in CIDR notation to bind secrets of this role to.
|
||||||
|
* @since 0.8 replaces {@link #setBoundCidrList(List)}
|
||||||
|
*/
|
||||||
|
@JsonSetter("secret_id_bound_cidrs")
|
||||||
|
public void setSecretIdBoundCidrs(final List<String> secretIdBoundCidrs) {
|
||||||
|
this.secretIdBoundCidrs = secretIdBoundCidrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of subnets in CIDR notation as comma-separated {@link String}
|
||||||
|
* @since 0.8 replaces {@link #getBoundCidrListString()} ()}
|
||||||
|
*/
|
||||||
|
@JsonGetter("secret_id_bound_cidrs")
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public String getSecretIdBoundCidrsString() {
|
||||||
|
if (secretIdBoundCidrs == null || secretIdBoundCidrs.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return String.join(",", secretIdBoundCidrs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of policies
|
* @return list of policies
|
||||||
*/
|
*/
|
||||||
@ -167,8 +250,9 @@ public final class AppRole {
|
|||||||
@JsonGetter("policies")
|
@JsonGetter("policies")
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
public String getPoliciesString() {
|
public String getPoliciesString() {
|
||||||
if (policies == null || policies.isEmpty())
|
if (policies == null || policies.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
return String.join(",", policies);
|
return String.join(",", policies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -30,6 +30,7 @@ public final class AppRoleBuilder {
|
|||||||
private String id;
|
private String id;
|
||||||
private Boolean bindSecretId;
|
private Boolean bindSecretId;
|
||||||
private List<String> boundCidrList;
|
private List<String> boundCidrList;
|
||||||
|
private List<String> secretIdBoundCidrs;
|
||||||
private List<String> policies;
|
private List<String> policies;
|
||||||
private Integer secretIdNumUses;
|
private Integer secretIdNumUses;
|
||||||
private Integer secretIdTtl;
|
private Integer secretIdTtl;
|
||||||
@ -93,12 +94,26 @@ public final class AppRoleBuilder {
|
|||||||
*
|
*
|
||||||
* @param boundCidrList List of CIDR blocks which can perform login
|
* @param boundCidrList List of CIDR blocks which can perform login
|
||||||
* @return self
|
* @return self
|
||||||
|
* @deprecated Use {@link #withSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public AppRoleBuilder withBoundCidrList(final List<String> boundCidrList) {
|
public AppRoleBuilder withBoundCidrList(final List<String> boundCidrList) {
|
||||||
this.boundCidrList = boundCidrList;
|
this.boundCidrList = boundCidrList;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bound CIDR blocks.
|
||||||
|
*
|
||||||
|
* @param secretIdBoundCidrs List of CIDR blocks which can perform login
|
||||||
|
* @return self
|
||||||
|
* @since 0.8 replaces {@link #withBoundCidrList(List)}
|
||||||
|
*/
|
||||||
|
public AppRoleBuilder withSecretIdBoundCidrs(final List<String> secretIdBoundCidrs) {
|
||||||
|
this.secretIdBoundCidrs = secretIdBoundCidrs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a CIDR block to list of bound blocks.
|
* Add a CIDR block to list of bound blocks.
|
||||||
*
|
*
|
||||||
@ -106,9 +121,15 @@ public final class AppRoleBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public AppRoleBuilder withCidrBlock(final String cidrBlock) {
|
public AppRoleBuilder withCidrBlock(final String cidrBlock) {
|
||||||
if (boundCidrList == null)
|
if (boundCidrList == null) {
|
||||||
boundCidrList = new ArrayList<>();
|
boundCidrList = new ArrayList<>();
|
||||||
|
}
|
||||||
boundCidrList.add(cidrBlock);
|
boundCidrList.add(cidrBlock);
|
||||||
|
|
||||||
|
if (secretIdBoundCidrs == null) {
|
||||||
|
secretIdBoundCidrs = new ArrayList<>();
|
||||||
|
}
|
||||||
|
secretIdBoundCidrs.add(cidrBlock);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,8 +140,9 @@ public final class AppRoleBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public AppRoleBuilder withPolicies(final List<String> policies) {
|
public AppRoleBuilder withPolicies(final List<String> policies) {
|
||||||
if (this.policies == null)
|
if (this.policies == null) {
|
||||||
this.policies = new ArrayList<>();
|
this.policies = new ArrayList<>();
|
||||||
|
}
|
||||||
this.policies.addAll(policies);
|
this.policies.addAll(policies);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -132,8 +154,9 @@ public final class AppRoleBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public AppRoleBuilder withPolicy(final String policy) {
|
public AppRoleBuilder withPolicy(final String policy) {
|
||||||
if (this.policies == null)
|
if (this.policies == null) {
|
||||||
this.policies = new ArrayList<>();
|
this.policies = new ArrayList<>();
|
||||||
|
}
|
||||||
policies.add(policy);
|
policies.add(policy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -204,6 +227,7 @@ public final class AppRoleBuilder {
|
|||||||
id,
|
id,
|
||||||
bindSecretId,
|
bindSecretId,
|
||||||
boundCidrList,
|
boundCidrList,
|
||||||
|
secretIdBoundCidrs,
|
||||||
policies,
|
policies,
|
||||||
secretIdNumUses,
|
secretIdNumUses,
|
||||||
secretIdTtl,
|
secretIdTtl,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -126,8 +126,9 @@ public final class AppRoleSecret {
|
|||||||
*/
|
*/
|
||||||
@JsonGetter("cidr_list")
|
@JsonGetter("cidr_list")
|
||||||
public String getCidrListString() {
|
public String getCidrListString() {
|
||||||
if (cidrList == null || cidrList.isEmpty())
|
if (cidrList == null || cidrList.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
return String.join(",", cidrList);
|
return String.join(",", cidrList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -48,9 +48,11 @@ public enum AuthBackend {
|
|||||||
* @return Auth backend value
|
* @return Auth backend value
|
||||||
*/
|
*/
|
||||||
public static AuthBackend forType(final String type) {
|
public static AuthBackend forType(final String type) {
|
||||||
for (AuthBackend v : values())
|
for (AuthBackend v : values()) {
|
||||||
if (v.type.equalsIgnoreCase(type))
|
if (v.type.equalsIgnoreCase(type)) {
|
||||||
return v;
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -31,6 +31,16 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public final class Token {
|
public final class Token {
|
||||||
|
/**
|
||||||
|
* Get {@link TokenBuilder} instance.
|
||||||
|
*
|
||||||
|
* @return Token Builder.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public static TokenBuilder builder() {
|
||||||
|
return new TokenBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
@JsonProperty("id")
|
@JsonProperty("id")
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
private String id;
|
private String id;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -159,8 +159,9 @@ public final class TokenBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public TokenBuilder withPolicies(final List<String> policies) {
|
public TokenBuilder withPolicies(final List<String> policies) {
|
||||||
if (this.policies == null)
|
if (this.policies == null) {
|
||||||
this.policies = new ArrayList<>();
|
this.policies = new ArrayList<>();
|
||||||
|
}
|
||||||
this.policies.addAll(policies);
|
this.policies.addAll(policies);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -172,8 +173,9 @@ public final class TokenBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public TokenBuilder withPolicy(final String policy) {
|
public TokenBuilder withPolicy(final String policy) {
|
||||||
if (this.policies == null)
|
if (this.policies == null) {
|
||||||
this.policies = new ArrayList<>();
|
this.policies = new ArrayList<>();
|
||||||
|
}
|
||||||
policies.add(policy);
|
policies.add(policy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -185,8 +187,9 @@ public final class TokenBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public TokenBuilder withMeta(final Map<String, String> meta) {
|
public TokenBuilder withMeta(final Map<String, String> meta) {
|
||||||
if (this.meta == null)
|
if (this.meta == null) {
|
||||||
this.meta = new HashMap<>();
|
this.meta = new HashMap<>();
|
||||||
|
}
|
||||||
this.meta.putAll(meta);
|
this.meta.putAll(meta);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -199,8 +202,9 @@ public final class TokenBuilder {
|
|||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public TokenBuilder withMeta(final String key, final String value) {
|
public TokenBuilder withMeta(final String key, final String value) {
|
||||||
if (this.meta == null)
|
if (this.meta == null) {
|
||||||
this.meta = new HashMap<>();
|
this.meta = new HashMap<>();
|
||||||
|
}
|
||||||
this.meta.put(key, value);
|
this.meta.put(key, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model classes for communication with the Vault API.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.model;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -42,7 +42,9 @@ public final class AppRoleResponse extends VaultDataResponse {
|
|||||||
/* null empty strings on list objects */
|
/* null empty strings on list objects */
|
||||||
Map<String, Object> filteredData = new HashMap<>();
|
Map<String, Object> filteredData = new HashMap<>();
|
||||||
data.forEach((k, v) -> {
|
data.forEach((k, v) -> {
|
||||||
if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k, v);
|
if (!(v instanceof String && ((String) v).isEmpty())) {
|
||||||
|
filteredData.put(k, v);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
|
this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -42,7 +42,9 @@ public final class AppRoleSecretResponse extends VaultDataResponse {
|
|||||||
/* null empty strings on list objects */
|
/* null empty strings on list objects */
|
||||||
Map<String, Object> filteredData = new HashMap<>();
|
Map<String, Object> filteredData = new HashMap<>();
|
||||||
data.forEach((k, v) -> {
|
data.forEach((k, v) -> {
|
||||||
if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k, v);
|
if (!(v instanceof String && ((String) v).isEmpty())) {
|
||||||
|
filteredData.put(k, v);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
|
this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -32,8 +32,9 @@ public final class CredentialsResponse extends SecretResponse {
|
|||||||
*/
|
*/
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
Object username = get("username");
|
Object username = get("username");
|
||||||
if (username != null)
|
if (username != null) {
|
||||||
return username.toString();
|
return username.toString();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,8 +43,9 @@ public final class CredentialsResponse extends SecretResponse {
|
|||||||
*/
|
*/
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
Object password = get("password");
|
Object password = get("password");
|
||||||
if (password != null)
|
if (password != null) {
|
||||||
return password.toString();
|
return password.toString();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -38,4 +38,13 @@ public final class ErrorResponse implements VaultResponse {
|
|||||||
public List<String> getErrors() {
|
public List<String> getErrors() {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (errors == null || errors.isEmpty()) {
|
||||||
|
return "error response";
|
||||||
|
} else {
|
||||||
|
return errors.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault response for health query.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.7.0
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public final class HealthResponse implements VaultResponse {
|
||||||
|
@JsonProperty("cluster_id")
|
||||||
|
private String clusterID;
|
||||||
|
|
||||||
|
@JsonProperty("cluster_name")
|
||||||
|
private String clusterName;
|
||||||
|
|
||||||
|
@JsonProperty("version")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
@JsonProperty("server_time_utc")
|
||||||
|
private Long serverTimeUTC;
|
||||||
|
|
||||||
|
@JsonProperty("standby")
|
||||||
|
private Boolean standby;
|
||||||
|
|
||||||
|
@JsonProperty("sealed")
|
||||||
|
private Boolean sealed;
|
||||||
|
|
||||||
|
@JsonProperty("initialized")
|
||||||
|
private Boolean initialized;
|
||||||
|
|
||||||
|
@JsonProperty("replication_perf_mode")
|
||||||
|
private String replicationPerfMode;
|
||||||
|
|
||||||
|
@JsonProperty("replication_dr_mode")
|
||||||
|
private String replicationDrMode;
|
||||||
|
|
||||||
|
@JsonProperty("performance_standby")
|
||||||
|
private Boolean performanceStandby;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Cluster ID.
|
||||||
|
*/
|
||||||
|
public String getClusterID() {
|
||||||
|
return clusterID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Cluster name.
|
||||||
|
*/
|
||||||
|
public String getClusterName() {
|
||||||
|
return clusterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vault version.
|
||||||
|
*/
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server time UTC (timestamp).
|
||||||
|
*/
|
||||||
|
public Long getServerTimeUTC() {
|
||||||
|
return serverTimeUTC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server standby status.
|
||||||
|
*/
|
||||||
|
public Boolean isStandby() {
|
||||||
|
return standby;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server seal status.
|
||||||
|
*/
|
||||||
|
public Boolean isSealed() {
|
||||||
|
return sealed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server initialization status.
|
||||||
|
*/
|
||||||
|
public Boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Replication performance mode of the active node (since Vault 0.9.2).
|
||||||
|
* @since 0.8 (#21)
|
||||||
|
*/
|
||||||
|
public String getReplicationPerfMode() {
|
||||||
|
return replicationPerfMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Replication DR mode of the active node (since Vault 0.9.2).
|
||||||
|
* @since 0.8 (#21)
|
||||||
|
*/
|
||||||
|
public String getReplicationDrMode() {
|
||||||
|
return replicationDrMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Performance standby status.
|
||||||
|
* @since 0.8 (#21)
|
||||||
|
*/
|
||||||
|
public Boolean isPerformanceStandby() {
|
||||||
|
return performanceStandby;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import de.stklcode.jvault.connector.model.response.embedded.SecretMetadata;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault response for secret metadata (KV v2).
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class MetadataResponse extends VaultDataResponse {
|
||||||
|
|
||||||
|
private SecretMetadata metadata;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
this.metadata = mapper.readValue(mapper.writeValueAsString(data), SecretMetadata.class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException("Failed deserializing response", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actual metadata.
|
||||||
|
*
|
||||||
|
* @return Metadata.
|
||||||
|
*/
|
||||||
|
public SecretMetadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,14 +22,20 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
/**
|
/**
|
||||||
* Vault response for seal status or unseal request.
|
* Vault response for seal status or unseal request.
|
||||||
*
|
*
|
||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
*/
|
*/
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public final class SealResponse implements VaultResponse {
|
public final class SealResponse implements VaultResponse {
|
||||||
|
@JsonProperty("type")
|
||||||
|
private String type;
|
||||||
|
|
||||||
@JsonProperty("sealed")
|
@JsonProperty("sealed")
|
||||||
private boolean sealed;
|
private boolean sealed;
|
||||||
|
|
||||||
|
@JsonProperty("initialized")
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
@JsonProperty("t")
|
@JsonProperty("t")
|
||||||
private Integer threshold;
|
private Integer threshold;
|
||||||
|
|
||||||
@ -39,6 +45,26 @@ public final class SealResponse implements VaultResponse {
|
|||||||
@JsonProperty("progress")
|
@JsonProperty("progress")
|
||||||
private Integer progress;
|
private Integer progress;
|
||||||
|
|
||||||
|
@JsonProperty("version")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
@JsonProperty("nonce")
|
||||||
|
private String nonce;
|
||||||
|
|
||||||
|
@JsonProperty("cluster_name")
|
||||||
|
private String clusterName;
|
||||||
|
|
||||||
|
@JsonProperty("cluster_id")
|
||||||
|
private String clusterId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Seal type.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Seal status
|
* @return Seal status
|
||||||
*/
|
*/
|
||||||
@ -46,6 +72,14 @@ public final class SealResponse implements VaultResponse {
|
|||||||
return sealed;
|
return sealed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vault initialization status (since Vault 0.11.2).
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Required threshold of secret shares
|
* @return Required threshold of secret shares
|
||||||
*/
|
*/
|
||||||
@ -66,4 +100,36 @@ public final class SealResponse implements VaultResponse {
|
|||||||
public Integer getProgress() {
|
public Integer getProgress() {
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vault version.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A random nonce.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public String getNonce() {
|
||||||
|
return nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vault cluster name (only if unsealed).
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public String getClusterName() {
|
||||||
|
return clusterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vault cluster ID (only if unsealed).
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public String getClusterId() {
|
||||||
|
return clusterId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -32,11 +33,29 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class SecretResponse extends VaultDataResponse {
|
public class SecretResponse extends VaultDataResponse {
|
||||||
|
private static final String KEY_DATA = "data";
|
||||||
|
private static final String KEY_METADATA = "metadata";
|
||||||
|
|
||||||
private Map<String, Object> data;
|
private Map<String, Object> data;
|
||||||
|
private VersionMetadata metadata;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||||
this.data = data;
|
if (data.size() == 2
|
||||||
|
&& data.containsKey(KEY_DATA) && data.get(KEY_DATA) instanceof Map
|
||||||
|
&& data.containsKey(KEY_METADATA) && data.get(KEY_METADATA) instanceof Map) {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
// This is apparently a KV v2 value.
|
||||||
|
this.data = (Map<String, Object>) data.get(KEY_DATA);
|
||||||
|
this.metadata = mapper.readValue(mapper.writeValueAsString(data.get(KEY_METADATA)), VersionMetadata.class);
|
||||||
|
} catch (ClassCastException | IOException e) {
|
||||||
|
throw new InvalidResponseException("Failed deserializing response", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For KV v1 without metadata just store the data map.
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,11 +65,22 @@ public class SecretResponse extends VaultDataResponse {
|
|||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
public final Map<String, Object> getData() {
|
public final Map<String, Object> getData() {
|
||||||
if (data == null)
|
if (data == null) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get secret metadata. This is only available for KV v2 secrets.
|
||||||
|
*
|
||||||
|
* @return Metadata of the secret.
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public final VersionMetadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single value for given key.
|
* Get a single value for given key.
|
||||||
*
|
*
|
||||||
@ -59,8 +89,9 @@ public class SecretResponse extends VaultDataResponse {
|
|||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
public final Object get(final String key) {
|
public final Object get(final String key) {
|
||||||
if (data == null)
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return getData().get(key);
|
return getData().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,8 +105,9 @@ public class SecretResponse extends VaultDataResponse {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public final String getValue() {
|
public final String getValue() {
|
||||||
Object value = get("value");
|
Object value = get("value");
|
||||||
if (value == null)
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +129,7 @@ public class SecretResponse extends VaultDataResponse {
|
|||||||
/**
|
/**
|
||||||
* Get response parsed as JSON.
|
* Get response parsed as JSON.
|
||||||
*
|
*
|
||||||
* @param key the key
|
* @param key the key
|
||||||
* @param type Class to parse response
|
* @param type Class to parse response
|
||||||
* @param <T> Class to parse response
|
* @param <T> Class to parse response
|
||||||
* @return Parsed object or {@code null} if absent
|
* @return Parsed object or {@code null} if absent
|
||||||
@ -107,8 +139,9 @@ public class SecretResponse extends VaultDataResponse {
|
|||||||
public final <T> T get(final String key, final Class<T> type) throws InvalidResponseException {
|
public final <T> T get(final String key, final Class<T> type) throws InvalidResponseException {
|
||||||
try {
|
try {
|
||||||
Object rawValue = get(key);
|
Object rawValue = get(key);
|
||||||
if (rawValue == null)
|
if (rawValue == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return new ObjectMapper().readValue(rawValue.toString(), type);
|
return new ObjectMapper().readValue(rawValue.toString(), type);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
|
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vault response for a single secret version metatada, i.e. after update (KV v2).
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class SecretVersionResponse extends VaultDataResponse {
|
||||||
|
|
||||||
|
private VersionMetadata metadata;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
this.metadata = mapper.readValue(mapper.writeValueAsString(data), VersionMetadata.class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidResponseException("Failed deserializing response", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actual metadata.
|
||||||
|
*
|
||||||
|
* @return Metadata.
|
||||||
|
*/
|
||||||
|
public VersionMetadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response.embedded;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embedded metadata for Key-Value v2 secrets.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public final class SecretMetadata {
|
||||||
|
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX");
|
||||||
|
|
||||||
|
@JsonProperty("created_time")
|
||||||
|
private String createdTimeString;
|
||||||
|
|
||||||
|
@JsonProperty("current_version")
|
||||||
|
private Integer currentVersion;
|
||||||
|
|
||||||
|
@JsonProperty("max_versions")
|
||||||
|
private Integer maxVersions;
|
||||||
|
|
||||||
|
@JsonProperty("oldest_version")
|
||||||
|
private Integer oldestVersion;
|
||||||
|
|
||||||
|
@JsonProperty("updated_time")
|
||||||
|
private String updatedTime;
|
||||||
|
|
||||||
|
@JsonProperty("versions")
|
||||||
|
private Map<Integer, VersionMetadata> versions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret creation as raw string representation.
|
||||||
|
*/
|
||||||
|
public String getCreatedTimeString() {
|
||||||
|
return createdTimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret creation.
|
||||||
|
*/
|
||||||
|
public ZonedDateTime getCreatedTime() {
|
||||||
|
if (createdTimeString != null && !createdTimeString.isEmpty()) {
|
||||||
|
try {
|
||||||
|
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Current version number.
|
||||||
|
*/
|
||||||
|
public Integer getCurrentVersion() {
|
||||||
|
return currentVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Maximum number of versions.
|
||||||
|
*/
|
||||||
|
public Integer getMaxVersions() {
|
||||||
|
return maxVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Oldest available version number.
|
||||||
|
*/
|
||||||
|
public Integer getOldestVersion() {
|
||||||
|
return oldestVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret update as raw string representation.
|
||||||
|
*/
|
||||||
|
public String getUpdatedTimeString() {
|
||||||
|
return updatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret update..
|
||||||
|
*/
|
||||||
|
public ZonedDateTime getUpdatedTime() {
|
||||||
|
if (updatedTime != null && !updatedTime.isEmpty()) {
|
||||||
|
try {
|
||||||
|
return ZonedDateTime.parse(updatedTime, TIME_FORMAT);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Version of the entry.
|
||||||
|
*/
|
||||||
|
public Map<Integer, VersionMetadata> getVersions() {
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response.embedded;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embedded metadata for a single Key-Value v2 version.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public final class VersionMetadata {
|
||||||
|
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX");
|
||||||
|
|
||||||
|
@JsonProperty("created_time")
|
||||||
|
private String createdTimeString;
|
||||||
|
|
||||||
|
@JsonProperty("deletion_time")
|
||||||
|
private String deletionTimeString;
|
||||||
|
|
||||||
|
@JsonProperty("destroyed")
|
||||||
|
private boolean destroyed;
|
||||||
|
|
||||||
|
@JsonProperty("version")
|
||||||
|
private Integer version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret creation as raw string representation.
|
||||||
|
*/
|
||||||
|
public String getCreatedTimeString() {
|
||||||
|
return createdTimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time of secret creation.
|
||||||
|
*/
|
||||||
|
public ZonedDateTime getCreatedTime() {
|
||||||
|
if (createdTimeString != null && !createdTimeString.isEmpty()) {
|
||||||
|
try {
|
||||||
|
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time for secret deletion as raw string representation.
|
||||||
|
*/
|
||||||
|
public String getDeletionTimeString() {
|
||||||
|
return deletionTimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Time for secret deletion.
|
||||||
|
*/
|
||||||
|
public ZonedDateTime getDeletionTime() {
|
||||||
|
if (deletionTimeString != null && !deletionTimeString.isEmpty()) {
|
||||||
|
try {
|
||||||
|
return ZonedDateTime.parse(deletionTimeString, TIME_FORMAT);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether the secret is destroyed.
|
||||||
|
*/
|
||||||
|
public boolean isDestroyed() {
|
||||||
|
return destroyed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Version of the entry.
|
||||||
|
*/
|
||||||
|
public Integer getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embedded data classes for responses from the Vault API.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.model.response.embedded;
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model classes for responses from the Vault API.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector.model.response;
|
21
src/main/java/de/stklcode/jvault/connector/package-info.java
Normal file
21
src/main/java/de/stklcode/jvault/connector/package-info.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java Vault Connector base package - contains {@link de.stklcode.jvault.connector.VaultConnector} interface and
|
||||||
|
* default implementation.
|
||||||
|
*/
|
||||||
|
package de.stklcode.jvault.connector;
|
13
src/main/javadoc/overview.html
Normal file
13
src/main/javadoc/overview.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>API Overview</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Java Vault Connector is a connector library for Vault by Hashicorp written in Java.</p>
|
||||||
|
<p>The connector allows simple usage of Vault's secret store in own applications.</p>
|
||||||
|
<p>It features a default implementation for the HTTP(S) interface and supports various authorization methods including
|
||||||
|
AppRole, token and secret handling.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,504 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector;
|
||||||
|
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
|
||||||
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||||
|
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||||
|
import org.apache.http.ProtocolVersion;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static net.bytebuddy.implementation.MethodDelegation.to;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit test for HTTP Vault connector.
|
||||||
|
* This test suite contains tests that do not require connection to an actual Vault instance.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.7.0
|
||||||
|
*/
|
||||||
|
public class HTTPVaultConnectorOfflineTest {
|
||||||
|
private static final String INVALID_URL = "foo:/\\1nv4l1d_UrL";
|
||||||
|
|
||||||
|
private static CloseableHttpClient httpMock = mock(CloseableHttpClient.class);
|
||||||
|
private CloseableHttpResponse responseMock = mock(CloseableHttpResponse.class);
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void initByteBuddy() {
|
||||||
|
// Install ByteBuddy Agent.
|
||||||
|
ByteBuddyAgent.install();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for redefinition of {@link HttpClientBuilder#create()} from {@link #initHttpMock()}.
|
||||||
|
*
|
||||||
|
* @return Mocked HTTP client builder.
|
||||||
|
*/
|
||||||
|
public static HttpClientBuilder create() {
|
||||||
|
return new MockedHttpClientBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void initHttpMock() {
|
||||||
|
// Redefine static method to return Mock on HttpClientBuilder creation.
|
||||||
|
new ByteBuddy().redefine(HttpClientBuilder.class)
|
||||||
|
.method(named("create"))
|
||||||
|
.intercept(to(HTTPVaultConnectorOfflineTest.class))
|
||||||
|
.make()
|
||||||
|
.load(HttpClientBuilder.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||||
|
|
||||||
|
// Re-initialize HTTP mock to ensure fresh (empty) results.
|
||||||
|
httpMock = mock(CloseableHttpClient.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test exceptions thrown during request.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void requestExceptionTest() throws IOException {
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector("http://127.0.0.1", null, 0, 250);
|
||||||
|
|
||||||
|
// Test invalid response code.
|
||||||
|
final int responseCode = 400;
|
||||||
|
mockResponse(responseCode, "", ContentType.APPLICATION_JSON);
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("Querying health status succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Invalid response code"));
|
||||||
|
assertThat("Unexpected status code in exception", ((InvalidResponseException) e).getStatusCode(), is(responseCode));
|
||||||
|
assertThat("Response message where none was expected", ((InvalidResponseException) e).getResponse(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate permission denied response.
|
||||||
|
mockResponse(responseCode, "{\"errors\":[\"permission denied\"]}", ContentType.APPLICATION_JSON);
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("Querying health status succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(PermissionDeniedException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test exception thrown during request.
|
||||||
|
when(httpMock.execute(any())).thenThrow(new IOException("Test Exception"));
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("Querying health status succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Unable to read response"));
|
||||||
|
assertThat("Unexpected cause", e.getCause(), instanceOf(IOException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now simulate a failing request that succeeds on second try.
|
||||||
|
connector = new HTTPVaultConnector("https://127.0.0.1", null, 1, 250);
|
||||||
|
doReturn(responseMock).doReturn(responseMock).when(httpMock).execute(any());
|
||||||
|
doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||||
|
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||||
|
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||||
|
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, ""))
|
||||||
|
.when(responseMock).getStatusLine();
|
||||||
|
when(responseMock.getEntity()).thenReturn(new StringEntity("{}", ContentType.APPLICATION_JSON));
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("Request failed unexpectedly: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test constductors of the {@link HTTPVaultConnector} class.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void constructorTest() throws IOException, CertificateException {
|
||||||
|
final String url = "https://vault.example.net/test/";
|
||||||
|
final String hostname = "vault.example.com";
|
||||||
|
final Integer port = 1337;
|
||||||
|
final String prefix = "/custom/prefix/";
|
||||||
|
final int retries = 42;
|
||||||
|
final String expectedNoTls = "http://" + hostname + "/v1/";
|
||||||
|
final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/";
|
||||||
|
final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix;
|
||||||
|
X509Certificate trustedCaCert;
|
||||||
|
|
||||||
|
try (InputStream is = getClass().getResourceAsStream("/tls/ca.pem")) {
|
||||||
|
trustedCaCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Most basic constructor expects complete URL.
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector(url);
|
||||||
|
assertThat("Unexpected base URL", getRequestHelperPrivate(connector, "baseURL"), is(url));
|
||||||
|
|
||||||
|
// Now override TLS usage.
|
||||||
|
connector = new HTTPVaultConnector(hostname, false);
|
||||||
|
assertThat("Unexpected base URL with TLS disabled", getRequestHelperPrivate(connector, "baseURL"), is(expectedNoTls));
|
||||||
|
|
||||||
|
// Specify custom port.
|
||||||
|
connector = new HTTPVaultConnector(hostname, true, port);
|
||||||
|
assertThat("Unexpected base URL with custom port", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPort));
|
||||||
|
|
||||||
|
// Specify custom prefix.
|
||||||
|
connector = new HTTPVaultConnector(hostname, true, port, prefix);
|
||||||
|
assertThat("Unexpected base URL with custom prefix", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||||
|
assertThat("Trusted CA cert set, but not specified", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
|
|
||||||
|
// Provide custom SSL context.
|
||||||
|
connector = new HTTPVaultConnector(hostname, true, port, prefix, trustedCaCert);
|
||||||
|
assertThat("Unexpected base URL with custom prefix", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||||
|
assertThat("Trusted CA cert not filled correctly", getRequestHelperPrivate(connector, "trustedCaCert"), is(trustedCaCert));
|
||||||
|
|
||||||
|
// Specify number of retries.
|
||||||
|
connector = new HTTPVaultConnector(url, trustedCaCert, retries);
|
||||||
|
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(retries));
|
||||||
|
|
||||||
|
// Test TLS version (#22).
|
||||||
|
assertThat("TLS version should be 1.2 if not specified", getRequestHelperPrivate(connector, "tlsVersion"), is("TLSv1.2"));
|
||||||
|
// Now override.
|
||||||
|
connector = new HTTPVaultConnector(url, trustedCaCert, retries, null, "TLSv1.1");
|
||||||
|
assertThat("Overridden TLS version 1.1 not correct", getRequestHelperPrivate(connector, "tlsVersion"), is("TLSv1.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void sealExceptionTest() throws IOException {
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
|
||||||
|
try {
|
||||||
|
connector.sealStatus();
|
||||||
|
fail("Querying seal status succeeded on invalid URL");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidRequestException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||||
|
|
||||||
|
// Simulate NULL response (mock not supplied with data).
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.sealStatus();
|
||||||
|
fail("Querying seal status succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void healthExceptionTest() throws IOException {
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("Querying health status succeeded on invalid URL");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidRequestException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||||
|
|
||||||
|
// Simulate NULL response (mock not supplied with data).
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("Querying health status succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test behavior on unparsable responses.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void parseExceptionTest() throws IOException {
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||||
|
// Mock authorization.
|
||||||
|
setPrivate(connector, "authorized", true);
|
||||||
|
// Mock response.
|
||||||
|
mockResponse(200, "invalid", ContentType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
// Now test the methods.
|
||||||
|
try {
|
||||||
|
connector.sealStatus();
|
||||||
|
fail("sealStatus() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.unseal("key");
|
||||||
|
fail("unseal() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.getHealth();
|
||||||
|
fail("getHealth() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.getAuthBackends();
|
||||||
|
fail("getAuthBackends() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.authToken("token");
|
||||||
|
fail("authToken() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.lookupAppRole("roleName");
|
||||||
|
fail("lookupAppRole() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.getAppRoleID("roleName");
|
||||||
|
fail("getAppRoleID() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.createAppRoleSecret("roleName");
|
||||||
|
fail("createAppRoleSecret() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.lookupAppRoleSecret("roleName", "secretID");
|
||||||
|
fail("lookupAppRoleSecret() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.listAppRoles();
|
||||||
|
fail("listAppRoles() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.listAppRoleSecrets("roleName");
|
||||||
|
fail("listAppRoleSecrets() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.read("key");
|
||||||
|
fail("read() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.list("path");
|
||||||
|
fail("list() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.renew("leaseID");
|
||||||
|
fail("renew() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.lookupToken("token");
|
||||||
|
fail("lookupToken() succeeded on invalid instance");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertParseError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertParseError(Exception e) {
|
||||||
|
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||||
|
assertThat("Unexpected exception message", e.getMessage(), is("Unable to parse response"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test requests that expect an empty response with code 204, but receive a 200 body.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void nonEmpty204ResponseTest() throws IOException {
|
||||||
|
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||||
|
// Mock authorization.
|
||||||
|
setPrivate(connector, "authorized", true);
|
||||||
|
// Mock response.
|
||||||
|
mockResponse(200, "{}", ContentType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
// Now test the methods expecting a 204.
|
||||||
|
try {
|
||||||
|
connector.registerAppId("appID", "policy", "displayName");
|
||||||
|
fail("registerAppId() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.registerUserId("appID", "userID");
|
||||||
|
fail("registerUserId() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.createAppRole("appID", Collections.singletonList("policy"));
|
||||||
|
fail("createAppRole() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.deleteAppRole("roleName");
|
||||||
|
fail("deleteAppRole() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.setAppRoleID("roleName", "roleID");
|
||||||
|
fail("setAppRoleID() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.destroyAppRoleSecret("roleName", "secretID");
|
||||||
|
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.destroyAppRoleSecret("roleName", "secretUD");
|
||||||
|
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.delete("key");
|
||||||
|
fail("delete() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connector.revoke("leaseID");
|
||||||
|
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) {
|
||||||
|
try {
|
||||||
|
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
|
if (field.isAccessible()) {
|
||||||
|
return field.get(target);
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object value = field.get(target);
|
||||||
|
field.setAccessible(false);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPrivate(Object target, String fieldName, Object value) {
|
||||||
|
try {
|
||||||
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
|
boolean accessible = field.isAccessible();
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(target, value);
|
||||||
|
field.setAccessible(accessible);
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
// Should not occur, to be taken care of in test code.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mockResponse(int status, String body, ContentType type) throws IOException {
|
||||||
|
when(httpMock.execute(any())).thenReturn(responseMock);
|
||||||
|
when(responseMock.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), status, ""));
|
||||||
|
when(responseMock.getEntity()).thenReturn(new StringEntity(body, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocked {@link HttpClientBuilder} that always returns the mocked client.
|
||||||
|
*/
|
||||||
|
private static class MockedHttpClientBuilder extends HttpClientBuilder {
|
||||||
|
@Override
|
||||||
|
public CloseableHttpClient build() {
|
||||||
|
return httpMock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.builder;
|
||||||
|
|
||||||
|
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||||
|
import de.stklcode.jvault.connector.exception.TlsException;
|
||||||
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.contrib.java.lang.system.EnvironmentVariables;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.nio.file.NoSuchFileException;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit test for HTTP Vault connector factory
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
@EnableRuleMigrationSupport
|
||||||
|
public class HTTPVaultConnectorBuilderTest {
|
||||||
|
private static final String VAULT_ADDR = "https://localhost:8201";
|
||||||
|
private static final Integer VAULT_MAX_RETRIES = 13;
|
||||||
|
private static final String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
File tempDir;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final EnvironmentVariables environment = new EnvironmentVariables();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test building from environment variables
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testFromEnv() throws NoSuchFieldException, IllegalAccessException, IOException {
|
||||||
|
/* Provide address only should be enough */
|
||||||
|
setenv(VAULT_ADDR, null, null, null);
|
||||||
|
|
||||||
|
HTTPVaultConnectorBuilder factory = null;
|
||||||
|
HTTPVaultConnector connector;
|
||||||
|
try {
|
||||||
|
factory = VaultConnectorBuilder.http().fromEnv();
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
fail("Factory creation from minimal environment failed");
|
||||||
|
}
|
||||||
|
connector = factory.build();
|
||||||
|
|
||||||
|
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
|
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
|
assertThat("Non-default number of retries, when none set", getRequestHelperPrivate(connector, "retries"), is(0));
|
||||||
|
|
||||||
|
/* Provide address and number of retries */
|
||||||
|
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory = VaultConnectorBuilder.http().fromEnv();
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
fail("Factory creation from environment failed");
|
||||||
|
}
|
||||||
|
connector = factory.build();
|
||||||
|
|
||||||
|
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
|
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
|
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||||
|
|
||||||
|
/* Provide CA certificate */
|
||||||
|
String VAULT_CACERT = tempDir.toString() + "/doesnotexist";
|
||||||
|
setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
VaultConnectorBuilder.http().fromEnv();
|
||||||
|
fail("Creation with unknown cert path failed.");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat(e, is(instanceOf(TlsException.class)));
|
||||||
|
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
||||||
|
assertThat(((NoSuchFileException) e.getCause()).getFile(), is(VAULT_CACERT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Automatic authentication */
|
||||||
|
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory = VaultConnectorBuilder.http().fromEnv();
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
fail("Factory creation from minimal environment failed");
|
||||||
|
}
|
||||||
|
assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
|
||||||
|
environment.set("VAULT_ADDR", vault_addr);
|
||||||
|
environment.set("VAULT_CACERT", vault_cacert);
|
||||||
|
environment.set("VAULT_MAX_RETRIES", vault_max_retries);
|
||||||
|
environment.set("VAULT_TOKEN", vault_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
|
if (field.isAccessible()) {
|
||||||
|
return field.get(target);
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object value = field.get(target);
|
||||||
|
field.setAccessible(false);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
package de.stklcode.jvault.connector.exception;
|
package de.stklcode.jvault.connector.exception;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.hamcrest.core.Is.is;
|
import static org.hamcrest.core.Is.is;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common JUnit test for Exceptions extending {@link VaultConnectorException}.
|
* Common JUnit test for Exceptions extending {@link VaultConnectorException}.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,18 +19,20 @@ package de.stklcode.jvault.connector.factory;
|
|||||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||||
import de.stklcode.jvault.connector.exception.TlsException;
|
import de.stklcode.jvault.connector.exception.TlsException;
|
||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.contrib.java.lang.system.EnvironmentVariables;
|
import org.junit.contrib.java.lang.system.EnvironmentVariables;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit test for HTTP Vault connector factory
|
* JUnit test for HTTP Vault connector factory
|
||||||
@ -38,13 +40,14 @@ import static org.junit.Assert.*;
|
|||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.6.0
|
* @since 0.6.0
|
||||||
*/
|
*/
|
||||||
|
@EnableRuleMigrationSupport
|
||||||
public class HTTPVaultConnectorFactoryTest {
|
public class HTTPVaultConnectorFactoryTest {
|
||||||
private static String VAULT_ADDR = "https://localhost:8201";
|
private static String VAULT_ADDR = "https://localhost:8201";
|
||||||
private static Integer VAULT_MAX_RETRIES = 13;
|
private static Integer VAULT_MAX_RETRIES = 13;
|
||||||
private static String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
private static String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||||
|
|
||||||
@Rule
|
@TempDir
|
||||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
File tempDir;
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final EnvironmentVariables environment = new EnvironmentVariables();
|
public final EnvironmentVariables environment = new EnvironmentVariables();
|
||||||
@ -66,9 +69,9 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
}
|
}
|
||||||
connector = factory.build();
|
connector = factory.build();
|
||||||
|
|
||||||
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
assertThat("Non-default number of retries, when none set", getPrivate(connector, "retries"), is(0));
|
assertThat("Non-default number of retries, when none set", getRequestHelperPrivate(connector, "retries"), is(0));
|
||||||
|
|
||||||
/* Provide address and number of retries */
|
/* Provide address and number of retries */
|
||||||
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
|
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
|
||||||
@ -80,12 +83,12 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
}
|
}
|
||||||
connector = factory.build();
|
connector = factory.build();
|
||||||
|
|
||||||
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||||
|
|
||||||
/* Provide CA certificate */
|
/* Provide CA certificate */
|
||||||
String VAULT_CACERT = tmpDir.newFolder().toString() + "/doesnotexist";
|
String VAULT_CACERT = tempDir.toString() + "/doesnotexist";
|
||||||
setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null);
|
setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -94,7 +97,7 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, is(instanceOf(TlsException.class)));
|
assertThat(e, is(instanceOf(TlsException.class)));
|
||||||
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
||||||
assertThat(((NoSuchFileException)e.getCause()).getFile(), is(VAULT_CACERT));
|
assertThat(((NoSuchFileException) e.getCause()).getFile(), is(VAULT_CACERT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Automatic authentication */
|
/* Automatic authentication */
|
||||||
@ -105,7 +108,7 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Factory creation from minimal environment failed");
|
fail("Factory creation from minimal environment failed");
|
||||||
}
|
}
|
||||||
assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN)));
|
assertThat("Token nor set correctly", getPrivate(getPrivate(factory, "delegate"), "token"), is(equalTo(VAULT_TOKEN)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
|
private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
|
||||||
@ -115,10 +118,15 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
environment.set("VAULT_TOKEN", vault_token);
|
environment.set("VAULT_TOKEN", vault_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Field field = target.getClass().getDeclaredField(fieldName);
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
if (field.isAccessible())
|
if (field.isAccessible()) {
|
||||||
return field.get(target);
|
return field.get(target);
|
||||||
|
}
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
Object value = field.get(target);
|
Object value = field.get(target);
|
||||||
field.setAccessible(false);
|
field.setAccessible(false);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,13 +18,14 @@ package de.stklcode.jvault.connector.model;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for AppRole Builder.
|
* JUnit Test for AppRole Builder.
|
||||||
@ -50,10 +51,10 @@ public class AppRoleBuilderTest {
|
|||||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||||
private static final Integer PERIOD = 1234;
|
private static final Integer PERIOD = 1234;
|
||||||
private static final String JSON_MIN = "{\"role_name\":\"" + NAME + "\"}";
|
private static final String JSON_MIN = "{\"role_name\":\"" + NAME + "\"}";
|
||||||
private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"bound_cidr_list\":\"%s\",\"policies\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"token_ttl\":%d,\"token_max_ttl\":%d,\"period\":%d}",
|
private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"bound_cidr_list\":\"%s\",\"secret_id_bound_cidrs\":\"%s\",\"policies\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"token_ttl\":%d,\"token_max_ttl\":%d,\"period\":%d}",
|
||||||
NAME, ID, BIND_SECRET_ID, CIDR_1, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD);
|
NAME, ID, BIND_SECRET_ID, CIDR_1, CIDR_1, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD);
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeAll
|
||||||
public static void init() {
|
public static void init() {
|
||||||
BOUND_CIDR_LIST.add(CIDR_1);
|
BOUND_CIDR_LIST.add(CIDR_1);
|
||||||
POLICIES.add(POLICY);
|
POLICIES.add(POLICY);
|
||||||
@ -68,6 +69,7 @@ public class AppRoleBuilderTest {
|
|||||||
assertThat(role.getId(), is(nullValue()));
|
assertThat(role.getId(), is(nullValue()));
|
||||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||||
assertThat(role.getBoundCidrList(), is(nullValue()));
|
assertThat(role.getBoundCidrList(), is(nullValue()));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), is(nullValue()));
|
||||||
assertThat(role.getPolicies(), is(nullValue()));
|
assertThat(role.getPolicies(), is(nullValue()));
|
||||||
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
||||||
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
||||||
@ -88,6 +90,7 @@ public class AppRoleBuilderTest {
|
|||||||
.withId(ID)
|
.withId(ID)
|
||||||
.withBindSecretID(BIND_SECRET_ID)
|
.withBindSecretID(BIND_SECRET_ID)
|
||||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
.withBoundCidrList(BOUND_CIDR_LIST)
|
||||||
|
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||||
.withPolicies(POLICIES)
|
.withPolicies(POLICIES)
|
||||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||||
.withSecretIdTtl(SECRET_ID_TTL)
|
.withSecretIdTtl(SECRET_ID_TTL)
|
||||||
@ -99,6 +102,7 @@ public class AppRoleBuilderTest {
|
|||||||
assertThat(role.getId(), is(ID));
|
assertThat(role.getId(), is(ID));
|
||||||
assertThat(role.getBindSecretId(), is(BIND_SECRET_ID));
|
assertThat(role.getBindSecretId(), is(BIND_SECRET_ID));
|
||||||
assertThat(role.getBoundCidrList(), is(BOUND_CIDR_LIST));
|
assertThat(role.getBoundCidrList(), is(BOUND_CIDR_LIST));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST));
|
||||||
assertThat(role.getPolicies(), is(POLICIES));
|
assertThat(role.getPolicies(), is(POLICIES));
|
||||||
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
||||||
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
||||||
@ -127,12 +131,16 @@ public class AppRoleBuilderTest {
|
|||||||
role = new AppRoleBuilder(NAME).withCidrBlock(CIDR_2).build();
|
role = new AppRoleBuilder(NAME).withCidrBlock(CIDR_2).build();
|
||||||
assertThat(role.getBoundCidrList(), hasSize(1));
|
assertThat(role.getBoundCidrList(), hasSize(1));
|
||||||
assertThat(role.getBoundCidrList(), contains(CIDR_2));
|
assertThat(role.getBoundCidrList(), contains(CIDR_2));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), hasSize(1));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_2));
|
||||||
role = new AppRoleBuilder(NAME)
|
role = new AppRoleBuilder(NAME)
|
||||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||||
.withCidrBlock(CIDR_2)
|
.withCidrBlock(CIDR_2)
|
||||||
.build();
|
.build();
|
||||||
assertThat(role.getBoundCidrList(), hasSize(2));
|
assertThat(role.getBoundCidrList(), hasSize(1));
|
||||||
assertThat(role.getBoundCidrList(), contains(CIDR_1, CIDR_2));
|
assertThat(role.getBoundCidrList(), contains(CIDR_2));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), hasSize(2));
|
||||||
|
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2));
|
||||||
|
|
||||||
/* Add single policy */
|
/* Add single policy */
|
||||||
role = new AppRoleBuilder(NAME).withPolicy(POLICY_2).build();
|
role = new AppRoleBuilder(NAME).withPolicy(POLICY_2).build();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,11 +16,9 @@
|
|||||||
|
|
||||||
package de.stklcode.jvault.connector.model;
|
package de.stklcode.jvault.connector.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -29,12 +27,11 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.emptyString;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
|
||||||
import static org.hamcrest.junit.MatcherAssume.assumeThat;
|
import static org.hamcrest.junit.MatcherAssume.assumeThat;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for AppRoleSecret model.
|
* JUnit Test for AppRoleSecret model.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package de.stklcode.jvault.connector.model;
|
package de.stklcode.jvault.connector.model;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for AuthBackend model.
|
* JUnit Test for AuthBackend model.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,16 +18,16 @@ package de.stklcode.jvault.connector.model;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for Token Builder.
|
* JUnit Test for Token Builder.
|
||||||
@ -55,7 +55,7 @@ public class TokenBuilderTest {
|
|||||||
private static final Boolean RENEWABLE = true;
|
private static final Boolean RENEWABLE = true;
|
||||||
private static final String JSON_FULL = "{\"id\":\"test-id\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}";
|
private static final String JSON_FULL = "{\"id\":\"test-id\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}";
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeAll
|
||||||
public static void init() {
|
public static void init() {
|
||||||
POLICIES.add(POLICY);
|
POLICIES.add(POLICY);
|
||||||
META.put(META_KEY, META_VALUE);
|
META.put(META_KEY, META_VALUE);
|
||||||
|
@ -1,17 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
package de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
import de.stklcode.jvault.connector.model.AppRole;
|
import de.stklcode.jvault.connector.model.AppRole;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for {@link AppRoleResponse} model.
|
* JUnit Test for {@link AppRoleResponse} model.
|
||||||
|
@ -1,20 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
package de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
|
||||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for {@link AuthMethodsResponse} model.
|
* JUnit Test for {@link AuthMethodsResponse} model.
|
||||||
|
@ -1,17 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
package de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for {@link AuthResponse} model.
|
* JUnit Test for {@link AuthResponse} model.
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link CredentialsResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public class CredentialsResponseTest {
|
||||||
|
private static final Map<String, Object> DATA = new HashMap<>();
|
||||||
|
private static final String VAL_USER = "testUserName";
|
||||||
|
private static final String VAL_PASS = "5up3r5ecr3tP455";
|
||||||
|
|
||||||
|
static {
|
||||||
|
DATA.put("username", VAL_USER);
|
||||||
|
DATA.put("password", VAL_PASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test getter, setter and get-methods for response data.
|
||||||
|
*
|
||||||
|
* @throws InvalidResponseException Should not occur
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void getCredentialsTest() throws InvalidResponseException {
|
||||||
|
// Create empty Object.
|
||||||
|
CredentialsResponse res = new CredentialsResponse();
|
||||||
|
assertThat("Username not present in data map should not return anything", res.getUsername(), is(nullValue()));
|
||||||
|
assertThat("Password not present in data map should not return anything", res.getPassword(), is(nullValue()));
|
||||||
|
|
||||||
|
// Fill data map.
|
||||||
|
res.setData(DATA);
|
||||||
|
assertThat("Incorrect username", res.getUsername(), is(VAL_USER));
|
||||||
|
assertThat("Incorrect password", res.getPassword(), is(VAL_PASS));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link AuthResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.7.0
|
||||||
|
*/
|
||||||
|
public class HealthResponseTest {
|
||||||
|
private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228";
|
||||||
|
private static final String CLUSTER_NAME = "vault-cluster-5515c810";
|
||||||
|
private static final String VERSION = "0.9.2";
|
||||||
|
private static final Long SERVER_TIME_UTC = 1469555798L;
|
||||||
|
private static final Boolean STANDBY = false;
|
||||||
|
private static final Boolean SEALED = false;
|
||||||
|
private static final Boolean INITIALIZED = true;
|
||||||
|
private static final Boolean PERF_STANDBY = false;
|
||||||
|
private static final String REPL_PERF_MODE = "disabled";
|
||||||
|
private static final String REPL_DR_MODE = "disabled";
|
||||||
|
|
||||||
|
private static final String RES_JSON = "{\n" +
|
||||||
|
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||||
|
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
|
||||||
|
" \"version\": \"" + VERSION + "\",\n" +
|
||||||
|
" \"server_time_utc\": " + SERVER_TIME_UTC + ",\n" +
|
||||||
|
" \"standby\": " + STANDBY + ",\n" +
|
||||||
|
" \"sealed\": " + SEALED + ",\n" +
|
||||||
|
" \"initialized\": " + INITIALIZED + ",\n" +
|
||||||
|
" \"replication_perf_mode\": \"" + REPL_PERF_MODE + "\",\n" +
|
||||||
|
" \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" +
|
||||||
|
" \"performance_standby\": " + PERF_STANDBY + "\n" +
|
||||||
|
"}";
|
||||||
|
/**
|
||||||
|
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void jsonRoundtrip() {
|
||||||
|
try {
|
||||||
|
HealthResponse res = new ObjectMapper().readValue(RES_JSON, HealthResponse.class);
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Incorrect cluster ID", res.getClusterID(), is(CLUSTER_ID));
|
||||||
|
assertThat("Incorrect cluster name", res.getClusterName(), is(CLUSTER_NAME));
|
||||||
|
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||||
|
assertThat("Incorrect server time", res.getServerTimeUTC(), is(SERVER_TIME_UTC));
|
||||||
|
assertThat("Incorrect standby state", res.isStandby(), is(STANDBY));
|
||||||
|
assertThat("Incorrect seal state", res.isSealed(), is(SEALED));
|
||||||
|
assertThat("Incorrect initialization state", res.isInitialized(), is(INITIALIZED));
|
||||||
|
assertThat("Incorrect performance standby state", res.isPerformanceStandby(), is(PERF_STANDBY));
|
||||||
|
assertThat("Incorrect replication perf mode", res.getReplicationPerfMode(), is(REPL_PERF_MODE));
|
||||||
|
assertThat("Incorrect replication DR mode", res.getReplicationDrMode(), is(REPL_DR_MODE));
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("Health deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link MetadataResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public class MetadataResponseTest {
|
||||||
|
private static final String V1_TIME = "2018-03-22T02:24:06.945319214Z";
|
||||||
|
private static final String V3_TIME = "2018-03-22T02:36:43.986212308Z";
|
||||||
|
private static final String V2_TIME = "2018-03-22T02:36:33.954880664Z";
|
||||||
|
private static final Integer CURRENT_VERSION = 3;
|
||||||
|
private static final Integer MAX_VERSIONS = 0;
|
||||||
|
private static final Integer OLDEST_VERSION = 1;
|
||||||
|
|
||||||
|
private static final String META_JSON = "{\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"created_time\": \"" + V1_TIME + "\",\n" +
|
||||||
|
" \"current_version\": " + CURRENT_VERSION + ",\n" +
|
||||||
|
" \"max_versions\": " + MAX_VERSIONS + ",\n" +
|
||||||
|
" \"oldest_version\": " + OLDEST_VERSION + ",\n" +
|
||||||
|
" \"updated_time\": \"" + V3_TIME + "\",\n" +
|
||||||
|
" \"versions\": {\n" +
|
||||||
|
" \"1\": {\n" +
|
||||||
|
" \"created_time\": \"" + V1_TIME + "\",\n" +
|
||||||
|
" \"deletion_time\": \"" + V2_TIME + "\",\n" +
|
||||||
|
" \"destroyed\": true\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"2\": {\n" +
|
||||||
|
" \"created_time\": \"" + V2_TIME + "\",\n" +
|
||||||
|
" \"deletion_time\": \"\",\n" +
|
||||||
|
" \"destroyed\": false\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"3\": {\n" +
|
||||||
|
" \"created_time\": \"" + V3_TIME + "\",\n" +
|
||||||
|
" \"deletion_time\": \"\",\n" +
|
||||||
|
" \"destroyed\": false\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void jsonRoundtrip() {
|
||||||
|
try {
|
||||||
|
MetadataResponse res = new ObjectMapper().readValue(META_JSON, MetadataResponse.class);
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Parsed metadatra is NULL", res.getMetadata(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(V1_TIME));
|
||||||
|
assertThat("Parting created time failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect current version", res.getMetadata().getCurrentVersion(), is(CURRENT_VERSION));
|
||||||
|
assertThat("Incorrect max versions", res.getMetadata().getMaxVersions(), is(MAX_VERSIONS));
|
||||||
|
assertThat("Incorrect oldest version", res.getMetadata().getOldestVersion(), is(OLDEST_VERSION));
|
||||||
|
assertThat("Incorrect updated time", res.getMetadata().getUpdatedTimeString(), is(V3_TIME));
|
||||||
|
assertThat("Parting updated time failed", res.getMetadata().getUpdatedTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect number of versions", res.getMetadata().getVersions().size(), is(3));
|
||||||
|
assertThat("Incorrect version 1 delete time", res.getMetadata().getVersions().get(1).getDeletionTimeString(), is(V2_TIME));
|
||||||
|
assertThat("Parsion version delete time failed", res.getMetadata().getVersions().get(1).getDeletionTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect version 1 destroyed state", res.getMetadata().getVersions().get(1).isDestroyed(), is(true));
|
||||||
|
assertThat("Incorrect version 2 created time", res.getMetadata().getVersions().get(2).getCreatedTimeString(), is(V2_TIME));
|
||||||
|
assertThat("Parsion version created failed", res.getMetadata().getVersions().get(2).getCreatedTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect version 3 destroyed state", res.getMetadata().getVersions().get(3).isDestroyed(), is(false));
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("MetadataResoponse deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link SealResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public class SealResponseTest {
|
||||||
|
private static final String TYPE = "shamir";
|
||||||
|
private static final Integer THRESHOLD = 3;
|
||||||
|
private static final Integer SHARES = 5;
|
||||||
|
private static final Integer PROGRESS_SEALED = 2;
|
||||||
|
private static final Integer PROGRESS_UNSEALED = 0;
|
||||||
|
private static final String VERSION = "0.11.2";
|
||||||
|
private static final String CLUSTER_NAME = "vault-cluster-d6ec3c7f";
|
||||||
|
private static final String CLUSTER_ID = "3e8b3fec-3749-e056-ba41-b62a63b997e8";
|
||||||
|
private static final String NONCE = "ef05d55d-4d2c-c594-a5e8-55bc88604c24";
|
||||||
|
|
||||||
|
private static final String RES_SEALED = "{\n" +
|
||||||
|
" \"type\": \"" + TYPE + "\",\n" +
|
||||||
|
" \"sealed\": true,\n" +
|
||||||
|
" \"initialized\": true,\n" +
|
||||||
|
" \"t\": " + THRESHOLD + ",\n" +
|
||||||
|
" \"n\": " + SHARES + ",\n" +
|
||||||
|
" \"progress\": " + PROGRESS_SEALED + ",\n" +
|
||||||
|
" \"nonce\": \"\",\n" +
|
||||||
|
" \"version\": \"" + VERSION + "\"\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
private static final String RES_UNSEALED = "{\n" +
|
||||||
|
" \"type\": \"" + TYPE + "\",\n" +
|
||||||
|
" \"sealed\": false,\n" +
|
||||||
|
" \"initialized\": true,\n" +
|
||||||
|
" \"t\": " + THRESHOLD + ",\n" +
|
||||||
|
" \"n\": " + SHARES + ",\n" +
|
||||||
|
" \"progress\": " + PROGRESS_UNSEALED + ",\n" +
|
||||||
|
" \"version\": \"" + VERSION + "\",\n" +
|
||||||
|
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
|
||||||
|
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||||
|
" \"nonce\": \"" + NONCE + "\"\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test creation from JSON value as returned by Vault when sealed (JSON example close to Vault documentation).
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void jsonRoundtripSealed() {
|
||||||
|
// First test sealed Vault's response.
|
||||||
|
try {
|
||||||
|
SealResponse res = new ObjectMapper().readValue(RES_SEALED, SealResponse.class);
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Incorrect seal type", res.getType(), is(TYPE));
|
||||||
|
assertThat("Incorrect seal status", res.isSealed(), is(true));
|
||||||
|
assertThat("Incorrect initialization status", res.isInitialized(), is(true));
|
||||||
|
assertThat("Incorrect threshold", res.getThreshold(), is(THRESHOLD));
|
||||||
|
assertThat("Incorrect number of shares", res.getNumberOfShares(), is(SHARES));
|
||||||
|
assertThat("Incorrect progress", res.getProgress(), is(PROGRESS_SEALED));
|
||||||
|
assertThat("Nonce not empty", res.getNonce(), is(""));
|
||||||
|
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||||
|
// And the fields, that should not be filled.
|
||||||
|
assertThat("Cluster name should not be populated", res.getClusterName(), is(nullValue()));
|
||||||
|
assertThat("Cluster ID should not be populated", res.getClusterId(), is(nullValue()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("TokenResponse deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Not test unsealed Vault's response.
|
||||||
|
try {
|
||||||
|
SealResponse res = new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class);
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Incorrect seal type", res.getType(), is(TYPE));
|
||||||
|
assertThat("Incorrect seal status", res.isSealed(), is(false));
|
||||||
|
assertThat("Incorrect initialization status", res.isInitialized(), is(true));
|
||||||
|
assertThat("Incorrect threshold", res.getThreshold(), is(THRESHOLD));
|
||||||
|
assertThat("Incorrect number of shares", res.getNumberOfShares(), is(SHARES));
|
||||||
|
assertThat("Incorrect progress", res.getProgress(), is(PROGRESS_UNSEALED));
|
||||||
|
assertThat("Incorrect nonce", res.getNonce(), is(NONCE));
|
||||||
|
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||||
|
assertThat("Incorrect cluster name", res.getClusterName(), is(CLUSTER_NAME));
|
||||||
|
assertThat("Incorrect cluster ID", res.getClusterId(), is(CLUSTER_ID));
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("TokenResponse deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link SecretListResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public class SecretListResponseTest {
|
||||||
|
private static final Map<String, Object> DATA = new HashMap<>();
|
||||||
|
private static final String KEY1 = "key1";
|
||||||
|
private static final String KEY2 = "key-2";
|
||||||
|
private static final List<String> KEYS = Arrays.asList(KEY1, KEY2);
|
||||||
|
|
||||||
|
static {
|
||||||
|
DATA.put("keys", KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test getter, setter and get-methods for response data.
|
||||||
|
*
|
||||||
|
* @throws InvalidResponseException Should not occur
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void getKeysTest() throws InvalidResponseException {
|
||||||
|
// Create empty Object.
|
||||||
|
SecretListResponse res = new SecretListResponse();
|
||||||
|
assertThat("Keys should be null without initialization", res.getKeys(), is(nullValue()));
|
||||||
|
|
||||||
|
// Provoke internal ClassCastException.
|
||||||
|
try {
|
||||||
|
Map<String, Object> invalidData = new HashMap<>();
|
||||||
|
invalidData.put("keys", "some string");
|
||||||
|
res.setData(invalidData);
|
||||||
|
fail("Setting incorrect class succeeded");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill correct data.
|
||||||
|
res.setData(DATA);
|
||||||
|
assertThat("Keys should be filled here", res.getKeys(), is(notNullValue()));
|
||||||
|
assertThat("Unexpected number of keys", res.getKeys(), hasSize(2));
|
||||||
|
assertThat("Unexpected keys", res.getKeys(), contains(KEY1, KEY2));
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
package de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for {@link SecretResponse} model.
|
* JUnit Test for {@link SecretResponse} model.
|
||||||
@ -37,6 +53,8 @@ public class SecretResponseTest {
|
|||||||
private static final String SECRET_DATA_V1 = "yes";
|
private static final String SECRET_DATA_V1 = "yes";
|
||||||
private static final String SECRET_DATA_K2 = "value";
|
private static final String SECRET_DATA_K2 = "value";
|
||||||
private static final String SECRET_DATA_V2 = "world";
|
private static final String SECRET_DATA_V2 = "world";
|
||||||
|
private static final String SECRET_META_CREATED = "2018-03-22T02:24:06.945319214Z";
|
||||||
|
private static final String SECRET_META_DELETED = "2018-03-23T03:25:07.056420325Z";
|
||||||
private static final List<String> SECRET_WARNINGS = null;
|
private static final List<String> SECRET_WARNINGS = null;
|
||||||
private static final String SECRET_JSON = "{\n" +
|
private static final String SECRET_JSON = "{\n" +
|
||||||
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
||||||
@ -49,6 +67,44 @@ public class SecretResponseTest {
|
|||||||
" },\n" +
|
" },\n" +
|
||||||
" \"warnings\": " + SECRET_WARNINGS + "\n" +
|
" \"warnings\": " + SECRET_WARNINGS + "\n" +
|
||||||
"}";
|
"}";
|
||||||
|
private static final String SECRET_JSON_V2 = "{\n" +
|
||||||
|
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
||||||
|
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
|
||||||
|
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
|
||||||
|
" \"renewable\": " + SECRET_RENEWABLE + ",\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
|
||||||
|
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"metadata\": {\n" +
|
||||||
|
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
|
||||||
|
" \"deletion_time\": \"\",\n" +
|
||||||
|
" \"destroyed\": false,\n" +
|
||||||
|
" \"version\": 1\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"warnings\": " + SECRET_WARNINGS + "\n" +
|
||||||
|
"}";
|
||||||
|
private static final String SECRET_JSON_V2_2 = "{\n" +
|
||||||
|
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
||||||
|
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
|
||||||
|
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
|
||||||
|
" \"renewable\": " + SECRET_RENEWABLE + ",\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
|
||||||
|
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"metadata\": {\n" +
|
||||||
|
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
|
||||||
|
" \"deletion_time\": \"" + SECRET_META_DELETED + "\",\n" +
|
||||||
|
" \"destroyed\": true,\n" +
|
||||||
|
" \"version\": 2\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"warnings\": " + SECRET_WARNINGS + "\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -102,16 +158,49 @@ public class SecretResponseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void jsonRoundtrip() {
|
public void jsonRoundtrip() {
|
||||||
try {
|
try {
|
||||||
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class);
|
assertSecretData(new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class));
|
||||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
} catch (IOException e) {
|
||||||
assertThat("Incorrect lease ID", res.getLeaseId(), is(SECRET_LEASE_ID));
|
fail("SecretResponse deserialization failed: " + e.getMessage());
|
||||||
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(SECRET_LEASE_DURATION));
|
}
|
||||||
assertThat("Incorrect renewable status", res.isRenewable(), is(SECRET_RENEWABLE));
|
|
||||||
assertThat("Incorrect warnings", res.getWarnings(), is(SECRET_WARNINGS));
|
// KV v2 secret.
|
||||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K1), is(SECRET_DATA_V1));
|
try {
|
||||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K2), is(SECRET_DATA_V2));
|
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON_V2, SecretResponse.class);
|
||||||
|
assertSecretData(res);
|
||||||
|
assertThat("SecretResponse does not contain metadata", res.getMetadata(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect creation date string", res.getMetadata().getCreatedTimeString(), is(SECRET_META_CREATED));
|
||||||
|
assertThat("Creation date parsing failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect deletion date string", res.getMetadata().getDeletionTimeString(), is(emptyString()));
|
||||||
|
assertThat("Incorrect deletion date", res.getMetadata().getDeletionTime(), is(nullValue()));
|
||||||
|
assertThat("Secret destroyed when not expected", res.getMetadata().isDestroyed(), is(false));
|
||||||
|
assertThat("Incorrect secret version", res.getMetadata().getVersion(), is(1));
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("SecretResponse deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleted KV v2 secret.
|
||||||
|
try {
|
||||||
|
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON_V2_2, SecretResponse.class);
|
||||||
|
assertSecretData(res);
|
||||||
|
assertThat("SecretResponse does not contain metadata", res.getMetadata(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect creation date string", res.getMetadata().getCreatedTimeString(), is(SECRET_META_CREATED));
|
||||||
|
assertThat("Creation date parsing failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect deletion date string", res.getMetadata().getDeletionTimeString(), is(SECRET_META_DELETED));
|
||||||
|
assertThat("Incorrect deletion date", res.getMetadata().getDeletionTime(), is(notNullValue()));
|
||||||
|
assertThat("Secret destroyed when not expected", res.getMetadata().isDestroyed(), is(true));
|
||||||
|
assertThat("Incorrect secret version", res.getMetadata().getVersion(), is(2));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail("SecretResponse deserialization failed: " + e.getMessage());
|
fail("SecretResponse deserialization failed: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertSecretData(SecretResponse res) {
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Incorrect lease ID", res.getLeaseId(), is(SECRET_LEASE_ID));
|
||||||
|
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(SECRET_LEASE_DURATION));
|
||||||
|
assertThat("Incorrect renewable status", res.isRenewable(), is(SECRET_RENEWABLE));
|
||||||
|
assertThat("Incorrect warnings", res.getWarnings(), is(SECRET_WARNINGS));
|
||||||
|
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K1), is(SECRET_DATA_V1));
|
||||||
|
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K2), is(SECRET_DATA_V2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Test for {@link SecretVersionResponse} model.
|
||||||
|
*
|
||||||
|
* @author Stefan Kalscheuer
|
||||||
|
* @since 0.8
|
||||||
|
*/
|
||||||
|
public class SecretVersionResponseTest {
|
||||||
|
private static final String CREATION_TIME = "2018-03-22T02:24:06.945319214Z";
|
||||||
|
private static final String DELETION_TIME = "2018-03-22T02:36:43.986212308Z";
|
||||||
|
private static final Integer VERSION = 42;
|
||||||
|
|
||||||
|
private static final String META_JSON = "{\n" +
|
||||||
|
" \"data\": {\n" +
|
||||||
|
" \"created_time\": \"" + CREATION_TIME + "\",\n" +
|
||||||
|
" \"deletion_time\": \"" + DELETION_TIME + "\",\n" +
|
||||||
|
" \"destroyed\": false,\n" +
|
||||||
|
" \"version\": " + VERSION + "\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void jsonRoundtrip() {
|
||||||
|
try {
|
||||||
|
SecretVersionResponse res = new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class);
|
||||||
|
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||||
|
assertThat("Parsed metadatra is NULL", res.getMetadata(), is(notNullValue()));
|
||||||
|
assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(CREATION_TIME));
|
||||||
|
assertThat("Incorrect deletion time", res.getMetadata().getDeletionTimeString(), is(DELETION_TIME));
|
||||||
|
assertThat("Incorrect destroyed state", res.getMetadata().isDestroyed(), is(false));
|
||||||
|
assertThat("Incorrect version", res.getMetadata().getVersion(), is(VERSION));
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("SecretVersionResponse deserialization failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
|
*
|
||||||
|
* 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 de.stklcode.jvault.connector.model.response;
|
package de.stklcode.jvault.connector.model.response;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
|
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit Test for {@link TokenResponse} model.
|
* JUnit Test for {@link TokenResponse} model.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2017 Stefan Kalscheuer
|
* Copyright 2016-2019 Stefan Kalscheuer
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -92,7 +92,7 @@ public class VaultConfiguration {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "backend \"file\" {\n" +
|
return "storage \"file\" {\n" +
|
||||||
" path = \"" + dataLocation + "\"\n" +
|
" path = \"" + dataLocation + "\"\n" +
|
||||||
"}\n" +
|
"}\n" +
|
||||||
"listener \"tcp\" {\n" +
|
"listener \"tcp\" {\n" +
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/20e9c2e6-5b1f-b9c9-5a99-21667e0a899d/salt","Value":"AAAAAQJUsuXXEpmdNY5aIh5HdzZRTFpOUIgyKLGiw65DBwSXW6yGAYe/zhN/Ow+vyRZxG4temgnTjN7RVGjyzXGG5yLY"}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/20e9c2e6-5b1f-b9c9-5a99-21667e0a899d/struct/map/app-id/19d90b9adcec2bf5088304034622a169a148ff43","Value":"AAAAAQJuuRcCRinyawQ05brruZQY7ypgs1mOsFHI16XLwYB4dzwJob71wW+74RjvK4FVL4qPfgyMPKEtV2uO9+4hr2mC6BrcN///Ksxv+ns8FMVlBOMJpQ=="}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/20e9c2e6-5b1f-b9c9-5a99-21667e0a899d/struct/map/user-id/55a852babe045b5980fc8ac4a13af27021dbbfd4","Value":"AAAAAQICaFIxG2xAq0AuJryVn1XghDulkVdQicXvhEL45K2S48aZcvMEsrDUXm9o427Bp6eMiq0Hw070nosnB9SWSQJEFUfPmM6I7Jhsou6CKmocs/AmocxY3Du4Lg=="}
|
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQINZKQEssY4IzHI/0k27nBtxSvnC6LkivYrqky6CblcjyAmQIg/4/cKQIBCXzmrWEv/SqMQbLw+4Lp63Xu1niF+U0NbyqDmFaPqnD2yfPs7meXvZr21+P9E/0APZMHQaSR7DIEY46zedHRjQ/pkhR2Axcjuy5gdfzBzC2XvUcNqdyR0pQwcDwGhAIdO0gxJfZCeBuvv8ceYS+aPs4gDHtIlA3szi+5qAQ8HvPBTDKQn1lHVYnzTdNbMS7v3mtzCyG8AeMkaUw=="}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQJiN0bHxM8aNJpY7aHGZ/p3qOhJbd7JIXwFMEI4LtKmO6pP5Oa4P5z+2LK+2qzZhhX/iDeM4u+nR+lxt/GsBPKf"}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQIZ5rvzLtBcBQvWqwwDoRADwUo6W0ECKgmcvXejbLKiYcbO0hP8fceCqB12J41wxcMViQ8vvWoIgyOX2HwcZS09GGCqQbjvyVfz/w+kyox9dJzr845f26tJjHVYlHX2YFsnxytwe5qCKdCsD5QP9kyz8J0="}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQJIKXgvJ2Prr92Fn7qZK/WZxb+Q+vJsXyjMo44en/+zqbbnLfs5m7uH7hEUOfDM/MjzTrhfkOWxf6qcrC4MR3ocrFJwtbJ6j+QrNLg61gVIiLBUVBkvh8ErqCFnSjNIqhaIMQhuZXWANsgGF9K2+HBGJerWGe26C1rdWRZV4J0M23HnxLBf8aYDlOfkHe24I30rHUqXIk9/BKEuekcnhETw9Tx4Fk7KxxxEdGmHPbg+4G14c27wVj8IrpWHBpyLmt55Qdb/y24i5RzFYv1FQ2kQZIO6TQiYkwAUxJ5cIdCiAsEDNt+rBJ9zX1MvkEfkVj/WvzC9pxB7ad+j5vYIJgCUD1o09t0w2ChjBojGoOAWDSvNAeY8kr5PDKwYk+gBY5M2JHDI6ELvOVu8gsW+sqk9St9V3VisShTfU3+qln7TOWw/LQ+fUzGvYrAWG6UyPVpIEYeNmN0iGCIM8rzjQYvVC3KcQMG96MwK3ZlSQzgPpvTGxNxFm2omTn3ue7QHn7Ni6+c/K6xVy0bbJ+jS4yyfl2wFBm1tF1l3BITLqw3TiP3LEw=="}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQIUt2iYYy9zOwkx1mtNMHt69RjdHbUmcN8zydVQTMGjhv1kjEW+d4AaBv1qE22rPTs0xL3pJ1AjIvkBXXVBAuc/FE63t5dE81Fa+MvSY4tBeMtl6i09ykkAYyQUeeV2HlbjRpMUwPyq2QIslYw3d4lc73yT0S82s5I3MfjodKmDpheWMOgg5hGes/wstBHN5HEZkKV8gOPRZ/BsTM7tMXH1piM/JT8sNfsDh6TAGD1OEsS+N2QlKvS4yImNzcKrH0EgdkXB4sRZ9e/SmMaEVaagB1n0M5LukC+pyExgC7eK4EU8o2Xye3iij3YMWBaGollDzJBJFP5aSO4E5u+NnRc5/ZbLRCbqgfQj8IY86WF9hya31aJxbc8Pg28Yfez8hbGRJZZws/ojIUgEz+VtH3OyaW2Wohnycop7i4fK8xlJ2gYOGvlw43czOH6Y6joTce+QBZWI7KR6ugB0dI8pnK2eFy14OZeww1NEew7r1u7PgD10Obg8okIJSD8cGkxUHu/oOLxvKKOAJBLSPfKnJfKEiKrqYED7EPkmgP/t7okvo4c95qeuWy1BLtKfxw5lkv0="}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQKv0Yr+QFSWxYe8o51TBwGz/yAhNYFmkNHPISEK6EbIVGkpEJMHFYvHWxTXUzF7f2/a"}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQKs2/ICwQPLv6siBGDbBnB52fBVo52BkSKGvm74p4oHrdMEvejJ4cJljOADYyDT2QYa"}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQIq05o3NmsucipTxPrcRbT1sXpAJ8w2PpiShnof74Kuzf/4kkHj3AZL5AObGFLAkYUvUrv3RRmYBIhw6Jk4FCbgdQyJAjPNVUTwBun/kQVyzP5sQ9hUFgHJwINomtVDiDgPkOc92zk8ydr1hfnMmTAtS71G3xloHDn6CF/1Y9WI1PkHdSkZ8d+yBNxr+qjGyewrV3QVmQvAfpY56uQ6AOztItD9NgiPrtNP+clbCczsieY6Y9Ce2FZawmuKFi9svMcBtnEcMILV/SGt4iCiMgFwkCJ9gQsGEdWPifu6ITPB92LgT4Ccw4gVRO31QVcPl6S+FG6iCeN6lk2yRXYjyhBuU+GklouEZIsA6SoxlIXPZuvauyS1MWwMxtSOQUFVYr3kvtXzCpcpEHDyBOEUdxPaYUZXHNdhGtMr/JuJCN50t0ng5mEAqfhjoJfJ/tBTqAjySj4zmEHuY0RnqYLPmsp203Q="}
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/6802ec63-11b0-0ccc-280a-982ad0a90621/user/validuser","Value":"AAAAAQJwFKMpgopAFjJaftTVY/iiawMw4Yj0S3pPDkzMPAfLxxaM3sCjOJt0q/07ozjTharT52wBv+s2ZEurPpr7VKDDzgy4xTMxFJbJs+0VkG3cjxRYEfW3bOIVAHhjLjmxZwYEATh0UUG7bQRNt56+/622bwR99ifWZ6e9zyRDGEwIn74JFN/3dY44qLQZmqfvDUrRQP5RfqDxqVdzbwse61s692Vy/QvlPsRFVRTkZHlNPqxT+OXd"}
|
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQK5U1GclNj+Tga7D4bQ5wExYfVu2y+djHlAlhiJ/JHOS1gS0G/kDrjR8gCdg/Aw2UunrObAq/mrKw0HEe1wo2qA"}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQLbvc+neI458Mqhl2WUUjY5HMC1Ast0KjZ5pslwW+5TtjVHcqdzls4whrrYHGUWv+nTg6wxJaS46j5+FER+4gsgWVJE1S33ZqvGtmmueCVpac5ZM0biBDXOvE/YFQ=="}
|
@ -0,0 +1 @@
|
|||||||
|
{"Value":"AAAAAQIK4FkvUHPiWUfHY7l9lGW1qf+sU2mAIWbjlfSvEIecbg94Mu4KAPxY3E2YLwOs7VyPZtWNZrZAZDMJJJzxM/pLux2o/IctJ5oXGtfPPjTjwNRRJ4U62wpRqBnBGX4="}
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/salt","Value":"AAAAAQKDLmmb/XlhfVJ45oKGyYwneS9s3tcQUenB8bTcxuDmAMUWnwG8oNNJFs0mSCF9Yv1KOq3Twxj4qPp05viFnP0z"}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/da42ddc9a483efd8ddeae4ab38428f73d42ad7f6320705f333555fed8593cbe2","Value":"AAAAAQLCu78fbRRgGWG++5XDCfaO/8NTg7LMAJL7aCsrn6c1WHJ5yrAAmWmSs1euhNd7yKUd0lQ0aknCKdPAZFBlAsqgOdnN8JLFe/H9lISaWdU6lRIfgTH9whEXWT0VK25FcS4r5yVe3Qoxg0DfT8FhjuzOa70="}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e83aed0dd0b867f09aa1dbc88b965eafba6030458d6555712e82c479cee3d2d7","Value":"AAAAAQL7t56z9Fr92ztubIfZPPkV3X1Aljnn95Y/tDXOxn8vjbjf21Fhyj3UnLwWyzK/9ip/6+x2DJBXikBOvXoCqKLXGegZ4JN9Z9UMiQ88aE9Z978r13E/rNbhIUa/PhT5NGwCbOl6vtK2hL06BHxKb+4+goM="}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e96c348451147331101ad48e157e8056ca1b039ee63a6aafd2d66446c94bcad8","Value":"AAAAAQIcvMn5QMtwELRDXZD9nNf7y/8O6z7u0NUZqyJrBb2OYDRvGpSuPS3CIareSxl8y5F4xtadvhyhunCGBUd289H9foMjfGbVVsM1mbM5i6FDTW0sFOPmXX44mQV29PVNMO+fcLuSWb0+qU4erqylpcvdLW8="}
|
|
@ -1 +0,0 @@
|
|||||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role/testrole1","Value":"AAAAAQLyV03lH8m3IYxoZKLf+/suZ+2wwKAyIHqrR3QeJZK+68wslLXy0XZ35bPrdc3jzAFhTizqILlgTBHVccdM/pydtTtbsvGHQlWstLaC79GUTM32gS/jwSrbwfa9j0q/Yrdo2LSa9IM5lw2tmYy+xR9c3ZKcm+VADZMZy3+6UmbQ1t0lniZ4uuVmqu2gl3y0732UtdMSxJepPWMjfvVq5+tynhgvEZNGgZCPc9lsV1fcBVFswtBUeATNnSJPmTnxQflXyhitPOpEM+5L+gnEsSNsyinRjv5cSbIHCP5yDzvpiWtwZ5Q0psVRSh/WJppBHcovwbJsTLK/tZ1wtFl1OgU9NLONEpgDJYiDyU0ACeFJ7r+DhjIDrQkr+WITnfBBwI+65wpOPYboqGgd4qZy84PE2s/VhWS5hjpxgpM="}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user