39 Commits

Author SHA1 Message Date
635cf19e54 prepare release v1.5.3
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 56s
CI / build-with-it (11, 1.20.3) (push) Successful in 1m12s
CI / build-with-it (17, 1.2.0) (push) Successful in 53s
CI / build-with-it (17, 1.20.3) (push) Successful in 1m6s
CI / build-with-it (21, 1.2.0) (push) Successful in 53s
CI / build-with-it (true, 21, 1.20.3) (push) Successful in 1m1s
2025-09-09 11:47:52 +02:00
f5e40ca032 test: run IT against Vault 1.20.3
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 54s
CI / build-with-it (11, 1.20.3) (push) Successful in 1m8s
CI / build-with-it (17, 1.2.0) (push) Successful in 50s
CI / build-with-it (17, 1.20.3) (push) Successful in 1m3s
CI / build-with-it (21, 1.2.0) (push) Successful in 49s
CI / build-with-it (true, 21, 1.20.3) (push) Successful in 58s
2025-09-09 11:39:32 +02:00
15f514f877 add token_bound_cidrs field to AppRoleSecret model (#110)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 54s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m9s
CI / build-with-it (17, 1.2.0) (push) Successful in 49s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m9s
CI / build-with-it (21, 1.2.0) (push) Successful in 51s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 56s
2025-09-08 10:25:39 +02:00
f79ed98986 encode user-provided URL parts (#109)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 50s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m4s
CI / build-with-it (17, 1.2.0) (push) Successful in 46s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m2s
CI / build-with-it (21, 1.2.0) (push) Successful in 46s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 54s
In various methods we use user-provided values like role names or lease
ids as parts of the API request path.

Apply URL encoding to these paths that are not expected to contain any
path separators or query args.
2025-09-05 09:46:48 +02:00
e96ece3385 build: update maven-wrapper to 3.3.3
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 49s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m6s
CI / build-with-it (21, 1.2.0) (push) Successful in 49s
CI / build-with-it (17, 1.2.0) (push) Successful in 48s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m5s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 59s
2025-09-02 13:27:29 +02:00
41eeae6687 refactor: extract API paths into a utility class (#108)
Some checks failed
CI / build-with-it (11, 1.2.0) (push) Successful in 50s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m8s
CI / build-with-it (17, 1.2.0) (push) Successful in 46s
CI / build-with-it (true, 21, 1.20.0) (push) Has been cancelled
CI / build-with-it (17, 1.20.0) (push) Has been cancelled
CI / build-with-it (21, 1.2.0) (push) Has been cancelled
Extract some static String constants from HTTPVaultConnector, which is
quite long already, into an internal utility class VaultApiPath.
We just reorganize some constants that should not change any behavior.
2025-08-30 09:53:46 +02:00
bac06c5d19 fix: prevent potential off-by-1 error in internal mapOf() helper (#107)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 43s
CI / build-with-it (11, 1.20.0) (push) Successful in 53s
CI / build-with-it (17, 1.2.0) (push) Successful in 40s
CI / build-with-it (17, 1.20.0) (push) Successful in 52s
CI / build-with-it (21, 1.2.0) (push) Successful in 41s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 45s
2025-08-30 09:41:09 +02:00
e30a3bd93a build: update sonar-maven-plugin to 5.2.0.4988
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 44s
CI / build-with-it (11, 1.20.0) (push) Successful in 51s
CI / build-with-it (17, 1.2.0) (push) Successful in 40s
CI / build-with-it (17, 1.20.0) (push) Successful in 49s
CI / build-with-it (21, 1.2.0) (push) Successful in 39s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 46s
2025-08-30 09:11:21 +02:00
8447b572b4 build: update maven-javadoc-plugin to 3.11.3 2025-08-30 09:10:26 +02:00
a95b05ba0e build: update GitHub actions 2025-08-30 09:08:30 +02:00
29517b9d78 deps: update jackson to 2.20.0 (#106)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 47s
CI / build-with-it (11, 1.20.0) (push) Successful in 54s
CI / build-with-it (17, 1.2.0) (push) Successful in 43s
CI / build-with-it (17, 1.20.0) (push) Successful in 53s
CI / build-with-it (21, 1.2.0) (push) Successful in 44s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 51s
2025-08-29 17:36:24 +02:00
1536c23cf0 test(deps): update mockito-core to 5.19.0
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 47s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m0s
CI / build-with-it (17, 1.2.0) (push) Successful in 46s
CI / build-with-it (17, 1.20.0) (push) Successful in 57s
CI / build-with-it (21, 1.2.0) (push) Successful in 46s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 54s
2025-08-16 10:23:36 +02:00
a7a435b420 test(deps): update junit-jupiter to 5.13.3
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 57s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m13s
CI / build-with-it (17, 1.2.0) (push) Successful in 52s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m11s
CI / build-with-it (21, 1.2.0) (push) Successful in 50s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m4s
2025-07-20 15:47:32 +02:00
d1b8b12ffe test(deps): update commons-io to 2.20.0 2025-07-20 15:47:31 +02:00
27c94870d3 deps: update jackson to 2.19.2 (#105) 2025-07-20 15:47:30 +02:00
12aee10741 prepare for next development iteration
All checks were successful
CI / build (11) (push) Successful in 38s
CI / build (17) (push) Successful in 39s
CI / build (true, 21) (push) Successful in 36s
CI / build-with-it (11, 1.2.0) (push) Successful in 54s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m8s
CI / build-with-it (17, 1.2.0) (push) Successful in 57s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m10s
CI / build-with-it (21, 1.2.0) (push) Successful in 1m10s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m13s
2025-07-16 18:36:24 +02:00
1803728256 prepare release v1.5.2
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 56s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m11s
CI / build-with-it (17, 1.2.0) (push) Successful in 58s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m10s
CI / build-with-it (21, 1.2.0) (push) Successful in 54s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m2s
2025-07-16 18:22:35 +02:00
9e7d8f50d3 build: update maven to 3.9.11
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 1m1s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m12s
CI / build-with-it (17, 1.2.0) (push) Successful in 56s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m8s
CI / build-with-it (21, 1.2.0) (push) Successful in 57s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m9s
2025-07-16 18:09:25 +02:00
08886a0c7c build: update maven-gpg-plugin to 3.2.8 2025-07-16 18:08:19 +02:00
eebe3f0ef6 build: update maven-enforcer-plugin to 3.6.1 2025-07-16 18:08:05 +02:00
5b9f1392d3 build: restore argLine to fix code coverage
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 49s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m6s
CI / build-with-it (17, 1.2.0) (push) Successful in 44s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m26s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m8s
CI / build-with-it (21, 1.2.0) (push) Successful in 51s
Partially reverts da4fffc823
2025-07-15 08:41:46 +02:00
da4fffc823 build remove unused test module access flags
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 40s
CI / build-with-it (11, 1.20.0) (push) Successful in 51s
CI / build-with-it (17, 1.2.0) (push) Successful in 39s
CI / build-with-it (17, 1.20.0) (push) Successful in 50s
CI / build-with-it (21, 1.2.0) (push) Successful in 41s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 48s
Remove redundant module opens directives and argLine property
inheritance, keeping only essential module access config for tests.
2025-07-13 18:38:47 +02:00
91276e1615 test: autoformat test code
All checks were successful
CI / build (11) (push) Successful in 34s
CI / build (17) (push) Successful in 32s
CI / build (true, 21) (push) Successful in 28s
CI / build-with-it (11, 1.2.0) (push) Successful in 50s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m7s
CI / build-with-it (17, 1.2.0) (push) Successful in 45s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m7s
CI / build-with-it (21, 1.2.0) (push) Successful in 48s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 59s
2025-07-13 18:19:56 +02:00
6d2313289c test: use Files.writeString() for config creation 2025-07-13 18:19:45 +02:00
bcbb3a0926 test: use assertDoesNotThrow instead of try-catch-fail for createFull() 2025-07-13 18:17:48 +02:00
f03c05bd5b fix: use Long for numeric TTL fields (#103) (#104)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 55s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m8s
CI / build-with-it (17, 1.2.0) (push) Successful in 43s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m3s
CI / build-with-it (21, 1.2.0) (push) Successful in 47s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 53s
Mapping these fields as Integer limits the possible maximum TTL value to
roughly 68 years. This may or may not be a reasonable value, but is
technically a valid number in the JSON response. Convert all TTL-related
fields to Long, so we can map such values.
2025-07-01 20:05:05 +02:00
afdad92ae6 test: run IT against Vault 1.20.0 (#102)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 59s
CI / build-with-it (11, 1.20.0) (push) Successful in 1m7s
CI / build-with-it (17, 1.2.0) (push) Successful in 56s
CI / build-with-it (17, 1.20.0) (push) Successful in 1m5s
CI / build-with-it (21, 1.2.0) (push) Successful in 54s
CI / build-with-it (true, 21, 1.20.0) (push) Successful in 1m0s
2025-06-26 18:17:23 +02:00
9fa360393d deps: update build and test dependencies 2025-06-26 18:12:42 +02:00
d28c189ec2 deps: update jackson to 2.19.1 (#101)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 1m1s
CI / build-with-it (11, 1.19.5) (push) Successful in 1m7s
CI / build-with-it (17, 1.2.0) (push) Successful in 1m3s
CI / build-with-it (17, 1.19.5) (push) Successful in 1m11s
CI / build-with-it (21, 1.2.0) (push) Successful in 1m1s
CI / build-with-it (true, 21, 1.19.5) (push) Successful in 1m9s
2025-06-20 20:28:52 +02:00
46fffcc711 prepare for next development iteration
All checks were successful
CI / build (11) (push) Successful in 39s
CI / build (17) (push) Successful in 39s
CI / build (true, 21) (push) Successful in 29s
CI / build-with-it (11, 1.2.0) (push) Successful in 57s
CI / build-with-it (11, 1.19.5) (push) Successful in 1m6s
CI / build-with-it (17, 1.19.5) (push) Successful in 1m3s
CI / build-with-it (17, 1.2.0) (push) Successful in 57s
CI / build-with-it (21, 1.2.0) (push) Successful in 51s
CI / build-with-it (true, 21, 1.19.5) (push) Successful in 1m1s
2025-06-02 16:59:30 +02:00
31d8f9b0aa prepare release v1.5.1
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 59s
CI / build-with-it (11, 1.19.5) (push) Successful in 1m8s
CI / build-with-it (17, 1.19.5) (push) Successful in 1m9s
CI / build-with-it (17, 1.2.0) (push) Successful in 1m2s
CI / build-with-it (21, 1.2.0) (push) Successful in 53s
CI / build-with-it (true, 21, 1.19.5) (push) Successful in 1m0s
2025-06-02 16:59:29 +02:00
505b360343 test: run IT against Vault 1.19.5
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 58s
CI / build-with-it (11, 1.19.5) (push) Successful in 1m6s
CI / build-with-it (17, 1.19.5) (push) Successful in 59s
CI / build-with-it (17, 1.2.0) (push) Successful in 53s
CI / build-with-it (21, 1.2.0) (push) Successful in 50s
CI / build-with-it (true, 21, 1.19.5) (push) Successful in 56s
2025-06-01 18:31:41 +02:00
51ab19cd8a deps: update test dependencies
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 52s
CI / build-with-it (11, 1.19.0) (push) Successful in 58s
CI / build-with-it (17, 1.2.0) (push) Successful in 50s
CI / build-with-it (17, 1.19.0) (push) Successful in 57s
CI / build-with-it (21, 1.2.0) (push) Successful in 47s
CI / build-with-it (true, 21, 1.19.0) (push) Successful in 53s
2025-05-29 15:49:32 +02:00
Lehel Balázs
c8f396a5df use lookup-self for token check instead of lookup (#98) (#99)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 54s
CI / build-with-it (11, 1.19.0) (push) Successful in 1m0s
CI / build-with-it (17, 1.2.0) (push) Successful in 53s
CI / build-with-it (17, 1.19.0) (push) Successful in 58s
CI / build-with-it (21, 1.2.0) (push) Successful in 48s
CI / build-with-it (true, 21, 1.19.0) (push) Successful in 55s
Using the /lookup-self to retrieve information about the current token
requires less permissions than the general /lookup API and yields the
same results, if accessible.
2025-05-28 18:09:08 +03:00
4bd6039827 deps: update jackson to 2.19.0 (#97)
All checks were successful
CI / build-with-it (11, 1.2.0) (push) Successful in 53s
CI / build-with-it (11, 1.19.0) (push) Successful in 1m0s
CI / build-with-it (17, 1.2.0) (push) Successful in 55s
CI / build-with-it (17, 1.19.0) (push) Successful in 1m0s
CI / build-with-it (21, 1.2.0) (push) Successful in 50s
CI / build-with-it (true, 21, 1.19.0) (push) Successful in 56s
2025-04-27 17:25:23 +02:00
80abbda46f docs: update version and features in README
All checks were successful
CI / build (11) (push) Successful in 39s
CI / build (17) (push) Successful in 39s
CI / build (true, 21) (push) Successful in 34s
CI / build-with-it (11, 1.2.0) (push) Successful in 55s
CI / build-with-it (11, 1.19.0) (push) Successful in 1m2s
CI / build-with-it (17, 1.2.0) (push) Successful in 54s
CI / build-with-it (17, 1.19.0) (push) Successful in 1m0s
CI / build-with-it (21, 1.2.0) (push) Successful in 52s
CI / build-with-it (true, 21, 1.19.0) (push) Successful in 59s
2025-04-24 18:36:36 +02:00
a8e85b88d1 test: use WireMockTest annotation 2025-04-24 18:30:32 +02:00
91baed4fe5 test: update wiremock to 3.13.0 2025-04-24 18:30:04 +02:00
2ea261d36a prepare for next development iteration
All checks were successful
CI / build (11) (push) Successful in 36s
CI / build (17) (push) Successful in 36s
CI / build (true, 21) (push) Successful in 28s
2025-04-13 12:25:18 +02:00
41 changed files with 1489 additions and 1464 deletions

View File

@@ -15,18 +15,18 @@ jobs:
strategy: strategy:
matrix: matrix:
jdk: [ 11, 17, 21 ] jdk: [ 11, 17, 21 ]
vault: [ '1.2.0', '1.19.0' ] vault: [ '1.2.0', '1.20.3' ]
include: include:
- jdk: 21 - jdk: 21
vault: '1.19.0' vault: '1.20.3'
analysis: true analysis: true
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v5
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Java - name: Set up Java
uses: actions/setup-java@v4 uses: actions/setup-java@v5
with: with:
java-version: ${{ matrix.jdk }} java-version: ${{ matrix.jdk }}
distribution: 'temurin' distribution: 'temurin'

View File

@@ -21,11 +21,11 @@ jobs:
analysis: true analysis: true
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v5
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Java - name: Set up Java
uses: actions/setup-java@v4 uses: actions/setup-java@v5
with: with:
java-version: ${{ matrix.jdk }} java-version: ${{ matrix.jdk }}
distribution: 'temurin' distribution: 'temurin'

View File

@@ -1,2 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip distributionType=only-script
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

View File

@@ -1,3 +1,38 @@
## 1.5.3 (2025-09-09)
### Dependencies
* Updated Jackson to 2.20.0 (#106)
### Improvements
* Extract API paths into a utility class (#108)
* Encode user-provided URL parts (#109)
* Add `token_bound_cidrs` field to `AppRoleSecret` model (#110)
### Fix
* Prevent potential off-by-1 error in internal `mapOf()` helper (#107)
## 1.5.2 (2025-07-16)
### Dependencies
* Updated Jackson to 2.19.1 (#101)
### Fix
* Use `Long` for numeric TTL fields (#103) (#104)
### Test
* Tested against Vault 1.2 to 1.20 (#102)
## 1.5.1 (2025-06-02)
### Improvements
* Use `lookup-self` for token check instead of `lookup` (#98) (#99)
### Dependencies
* Updated Jackson to 2.19.0 (#97)
## 1.5.0 (2025-04-13) ## 1.5.0 (2025-04-13)
### Deprecations ### Deprecations

View File

@@ -28,10 +28,11 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
* Delete secrets * Delete secrets
* Renew/revoke leases * Renew/revoke leases
* Raw secret content or JSON decoding * Raw secret content or JSON decoding
* SQL secret handling
* KV v1 and v2 support * KV v1 and v2 support
* Database secret handling
* Transit API support
* Connector Factory with builder pattern * Connector Factory with builder pattern
* Tested against Vault 1.2 to 1.19 * Tested against Vault 1.2 to 1.20
## Maven Artifact ## Maven Artifact
@@ -39,7 +40,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
<dependency> <dependency>
<groupId>de.stklcode.jvault</groupId> <groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId> <artifactId>jvault-connector</artifactId>
<version>1.4.0</version> <version>1.5.3</version>
</dependency> </dependency>
``` ```

493
mvnw vendored
View File

@@ -19,314 +19,277 @@
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2 # Apache Maven Wrapper startup batch script, version 3.3.3
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
# #
# Optional ENV vars # Optional ENV vars
# ----------------- # -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven # JAVA_HOME - location of a JDK home dir, required when download maven via java source
# e.g. to debug Maven itself, use # MVNW_REPOURL - repo url base for downloading maven distribution
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 # MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files # MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
if [ -f /usr/local/etc/mavenrc ]; then # OS specific support.
. /usr/local/etc/mavenrc native_path() { printf %s\\n "$1"; }
fi
if [ -f /etc/mavenrc ]; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ]; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false
darwin=false
mingw=false
case "$(uname)" in case "$(uname)" in
CYGWIN*) cygwin=true ;; CYGWIN* | MINGW*)
MINGW*) mingw=true ;; [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
Darwin*) native_path() { cygpath --path --windows "$1"; }
darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"
export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"
export JAVA_HOME
fi
fi
;; ;;
esac esac
if [ -z "$JAVA_HOME" ]; then # set JAVACMD and JAVACCMD
if [ -r /etc/gentoo-release ]; then set_java_home() {
JAVA_HOME=$(java-config --jre-home) # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
fi if [ -n "${JAVA_HOME-}" ]; then
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
[ -n "$JAVA_HOME" ] \
&& JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] \
&& CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \
&& JAVA_HOME="$(
cd "$JAVA_HOME" || (
echo "cannot cd into $JAVA_HOME." >&2
exit 1
)
pwd
)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin; then
javaHome="$(dirname "$javaExecutable")"
javaExecutable="$(cd "$javaHome" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "$javaExecutable")"
fi
javaHome="$(dirname "$javaExecutable")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ]; then
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi fi
else else
JAVACMD="$( JAVACMD="$(
\unset -f command 2>/dev/null 'set' +e
\command -v java 'unset' -f command 2>/dev/null
)" 'command' -v java
fi )" || :
fi JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "$JAVACMD" ]; then if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "Error: JAVA_HOME is not defined correctly." >&2 echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
echo " We cannot execute $JAVACMD" >&2 return 1
exit 1
fi
if [ -z "$JAVA_HOME" ]; then
echo "Warning: JAVA_HOME environment variable is not set." >&2
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]; then
echo "Path not specified to find_maven_basedir" >&2
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ]; do
if [ -d "$wdir"/.mvn ]; then
basedir=$wdir
break
fi fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc) fi
if [ -d "${wdir}" ]; then }
wdir=$(
cd "$wdir/.." || exit 1 # hash string like Java String::hashCode
pwd hash_string() {
) str="${1:-}" h=0
fi while [ -n "$str" ]; do
# end of workaround char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done done
printf '%s' "$( printf %x\\n $h
cd "$basedir" || exit 1
pwd
)"
} }
# concatenates all lines of a file verbose() { :; }
concat_lines() { [ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' <"$1"
fi
}
log() { die() {
if [ "$MVNW_VERBOSE" = true ]; then printf %s\\n "$1" >&2
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1 exit 1
fi }
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} trim() {
export MAVEN_PROJECTBASEDIR # MWRAPPER-139:
log "$MAVEN_PROJECTBASEDIR" # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
########################################################################################## scriptDir="$(dirname "$0")"
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central scriptName="$(basename "$0")"
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then # parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in wrapperUrl)
wrapperUrl="$safeValue"
break
;;
esac
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl >/dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do while IFS="=" read -r key value; do
case "$key" in wrapperSha256Sum) case "${key-}" in
wrapperSha256Sum=$value distributionUrl) distributionUrl=$(trim "${value-}") ;;
break distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;; ;;
esac esac
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
if [ -n "$wrapperSha256Sum" ]; then ;;
wrapperSha256Result=false maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
if command -v sha256sum >/dev/null; then *) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then esac
wrapperSha256Result=true
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi fi
elif command -v shasum >/dev/null; then elif command -v shasum >/dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
wrapperSha256Result=true distributionSha256Result=true
fi fi
else else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1 exit 1
fi fi
if [ $wrapperSha256Result = false ]; then if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1 exit 1
fi fi
fi fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # unzip and move
if command -v unzip >/dev/null; then
# For Cygwin, switch paths to Windows format before running java unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
if $cygwin; then else
[ -n "$JAVA_HOME" ] \ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
&& JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] \
&& CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] \
&& MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi fi
# Provide a "standardized" way to retrieve the CLI args that will # Find the actual extracted directory name (handles snapshots where filename != directory name)
# work with both Windows and non-Windows executions. actualDistributionDir=""
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain # First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# shellcheck disable=SC2086 # safe args # If not found, search for any directory with the Maven executable (for snapshots)
exec "$JAVACMD" \ if [ -z "$actualDistributionDir" ]; then
$MAVEN_OPTS \ # enable globbing to iterate over items
$MAVEN_DEBUG_OPTS \ set +f
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ for dir in "$TMP_DOWNLOAD_DIR"/*; do
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ if [ -d "$dir" ]; then
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

323
mvnw.cmd vendored
View File

@@ -1,3 +1,4 @@
<# : batch portion
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one @REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file @REM or more contributor license agreements. See the NOTICE file
@@ -18,189 +19,171 @@
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.2 @REM Apache Maven Wrapper startup batch script, version 3.3.3
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM @REM
@REM Optional ENV vars @REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands @REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' @IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@echo off @SET __MVNW_CMD__=
@REM set title of command window @SET __MVNW_ERROR__=
title %0 @SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' @SET PSModulePath=
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo. >&2
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo. >&2
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo. >&2
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo. >&2
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
) )
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central $ErrorActionPreference = "Stop"
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. if ($env:MVNW_VERBOSE -eq "true") {
if exist %WRAPPER_JAR% ( $VerbosePreference = "Continue"
if "%MVNW_VERBOSE%" == "true" ( }
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^ # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
"$webclient = new-object System.Net.WebClient;"^ $distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ if (!$distributionUrl) {
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
"}"^ }
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
SET WRAPPER_SHA_256_SUM="" "maven-mvnd-*" {
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( $USE_MVND = $true
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
) $MVN_CMD = "mvnd.cmd"
IF NOT %WRAPPER_SHA_256_SUM%=="" ( break
powershell -Command "&{"^ }
"Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ default {
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ $USE_MVND = $false
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ $MVN_CMD = $script -replace '^mvnw','mvn'
" Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ break
" Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ }
" Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ }
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will # apply MVNW_REPOURL and calculate MAVEN_HOME
@REM work with both Windows and non-Windows executions. # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
set MAVEN_CMD_LINE_ARGS=%* if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
%MAVEN_JAVA_EXE% ^ $MAVEN_M2_PATH = "$HOME/.m2"
%JVM_CONFIG_MAVEN_PROPS% ^ if ($env:MAVEN_USER_HOME) {
%MAVEN_OPTS% ^ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
%MAVEN_DEBUG_OPTS% ^ }
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
set ERROR_CODE=1 New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
:end $MAVEN_WRAPPER_DISTS = $null
@endlocal & set ERROR_CODE=%ERROR_CODE% if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost $MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
@REM check for post script, once with legacy .bat ending and once with .cmd ending $MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" $MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
if "%MAVEN_BATCH_PAUSE%"=="on" pause Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
cmd /C exit /B %ERROR_CODE% # prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

49
pom.xml
View File

@@ -1,10 +1,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.stklcode.jvault</groupId> <groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId> <artifactId>jvault-connector</artifactId>
<version>1.5.0</version> <version>1.5.3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -33,7 +32,7 @@
<connection>scm:git:git://github.com/stklcode/jvaultconnector.git</connection> <connection>scm:git:git://github.com/stklcode/jvaultconnector.git</connection>
<developerConnection>scm:git:git@github.com:stklcode/jvaultconnector.git</developerConnection> <developerConnection>scm:git:git@github.com:stklcode/jvaultconnector.git</developerConnection>
<url>https://github.com/stklcode/jvaultconnector</url> <url>https://github.com/stklcode/jvaultconnector</url>
<tag>v1.5.0</tag> <tag>v1.5.3</tag>
</scm> </scm>
<issueManagement> <issueManagement>
@@ -43,32 +42,32 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputTimestamp>2025-04-13T09:25:23Z</project.build.outputTimestamp> <project.build.outputTimestamp>2025-09-09T09:45:59Z</project.build.outputTimestamp>
<argLine></argLine> <argLine />
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.18.3</version> <version>2.20.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId> <artifactId>jackson-datatype-jsr310</artifactId>
<version>2.18.3</version> <version>2.20.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>5.12.1</version> <version>5.13.3</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>5.17.0</version> <version>5.19.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -80,19 +79,19 @@
<dependency> <dependency>
<groupId>org.wiremock</groupId> <groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId> <artifactId>wiremock</artifactId>
<version>3.12.1</version> <version>3.13.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.19.0</version> <version>2.20.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>nl.jqno.equalsverifier</groupId> <groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId> <artifactId>equalsverifier</artifactId>
<version>3.19.3</version> <version>3.19.4</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -117,7 +116,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.4.1</version> <version>3.5.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -131,7 +130,8 @@
<configuration> <configuration>
<argLine> <argLine>
@{argLine} @{argLine}
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind --add-opens
de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
</argLine> </argLine>
</configuration> </configuration>
</plugin> </plugin>
@@ -163,13 +163,6 @@
<argLine> <argLine>
@{argLine} @{argLine}
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.exception=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response.embedded=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.datatype.jsr310
</argLine> </argLine>
</configuration> </configuration>
</plugin> </plugin>
@@ -186,7 +179,7 @@
<plugin> <plugin>
<groupId>org.sonarsource.scanner.maven</groupId> <groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId> <artifactId>sonar-maven-plugin</artifactId>
<version>5.1.0.4751</version> <version>5.2.0.4988</version>
</plugin> </plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
@@ -195,7 +188,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version> <version>3.6.1</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@@ -252,7 +245,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.11.2</version> <version>3.11.3</version>
<configuration> <configuration>
<source>11</source> <source>11</source>
</configuration> </configuration>
@@ -299,7 +292,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>3.2.7</version> <version>3.2.8</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@@ -370,7 +363,7 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>12.1.1</version> <version>12.1.3</version>
<configuration> <configuration>
<nvdApiKey>${env.NVD_API_KEY}</nvdApiKey> <nvdApiKey>${env.NVD_API_KEY}</nvdApiKey>
<nvdDatafeedUrl>${env.NVD_DATAFEED_URL}</nvdDatafeedUrl> <nvdDatafeedUrl>${env.NVD_DATAFEED_URL}</nvdDatafeedUrl>
@@ -394,7 +387,7 @@
<plugin> <plugin>
<groupId>org.sonatype.central</groupId> <groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId> <artifactId>central-publishing-maven-plugin</artifactId>
<version>0.7.0</version> <version>0.8.0</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<publishingServerId>central</publishingServerId> <publishingServerId>central</publishingServerId>

View File

@@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static de.stklcode.jvault.connector.internal.RequestHelper.encode;
import static de.stklcode.jvault.connector.internal.VaultApiPath.*;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
@@ -41,38 +43,6 @@ import static java.util.Collections.singletonMap;
* @since 0.1 * @since 0.1
*/ */
public class HTTPVaultConnector implements VaultConnector { public class HTTPVaultConnector implements VaultConnector {
private static final String PATH_SYS = "sys";
private static final String PATH_SYS_AUTH = PATH_SYS + "/auth";
private static final String PATH_RENEW = PATH_SYS + "/leases/renew";
private static final String PATH_REVOKE = PATH_SYS + "/leases/revoke/";
private static final String PATH_HEALTH = PATH_SYS + "/health";
private static final String PATH_SEAL = PATH_SYS + "/seal";
private static final String PATH_SEAL_STATUS = PATH_SYS + "/seal-status";
private static final String PATH_UNSEAL = PATH_SYS + "/unseal";
private static final String PATH_AUTH = "auth";
private static final String PATH_AUTH_TOKEN = PATH_AUTH + "/token";
private static final String PATH_LOOKUP = "/lookup";
private static final String PATH_CREATE = "/create";
private static final String PATH_ROLES = "/roles";
private static final String PATH_CREATE_ORPHAN = "/create-orphan";
private static final String PATH_AUTH_USERPASS = PATH_AUTH + "/userpass/login/";
private static final String PATH_AUTH_APPROLE = PATH_AUTH + "/approle";
private static final String PATH_AUTH_APPROLE_ROLE = PATH_AUTH_APPROLE + "/role/%s%s";
private static final String PATH_DATA = "/data/";
private static final String PATH_METADATA = "/metadata/";
private static final String PATH_LOGIN = "/login";
private static final String PATH_DELETE = "/delete/";
private static final String PATH_UNDELETE = "/undelete/";
private static final String PATH_DESTROY = "/destroy/";
private static final String PATH_TRANSIT = "transit";
private static final String PATH_TRANSIT_ENCRYPT = PATH_TRANSIT + "/encrypt/";
private static final String PATH_TRANSIT_DECRYPT = PATH_TRANSIT + "/decrypt/";
private static final String PATH_TRANSIT_HASH = PATH_TRANSIT + "/hash/";
private final RequestHelper request; private final RequestHelper request;
private boolean authorized = false; // Authorization status. private boolean authorized = false; // Authorization status.
@@ -139,12 +109,12 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final SealResponse sealStatus() throws VaultConnectorException { public final SealResponse sealStatus() throws VaultConnectorException {
return request.get(PATH_SEAL_STATUS, emptyMap(), token, SealResponse.class); return request.get(SYS_SEAL_STATUS, emptyMap(), token, SealResponse.class);
} }
@Override @Override
public final void seal() throws VaultConnectorException { public final void seal() throws VaultConnectorException {
request.put(PATH_SEAL, emptyMap(), token); request.put(SYS_SEAL, emptyMap(), token);
} }
@Override @Override
@@ -154,14 +124,14 @@ public class HTTPVaultConnector implements VaultConnector {
"reset", reset "reset", reset
); );
return request.put(PATH_UNSEAL, param, token, SealResponse.class); return request.put(SYS_UNSEAL, param, token, SealResponse.class);
} }
@Override @Override
public HealthResponse getHealth() throws VaultConnectorException { public HealthResponse getHealth() throws VaultConnectorException {
return request.get( return request.get(
PATH_HEALTH, SYS_HEALTH,
// Force status code to be 200, so we don't need to modify the request sequence. // Force status code to be 200, so we don't need to modify the request sequence.
Map.of( Map.of(
"standbycode", "200", // Default: 429. "standbycode", "200", // Default: 429.
@@ -181,7 +151,7 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException { public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
/* Issue request and parse response */ /* Issue request and parse response */
AuthMethodsResponse amr = request.get(PATH_SYS_AUTH, emptyMap(), token, AuthMethodsResponse.class); AuthMethodsResponse amr = request.get(SYS_AUTH, emptyMap(), token, AuthMethodsResponse.class);
return amr.getSupportedMethods().values().stream().map(AuthMethod::getType).collect(Collectors.toList()); return amr.getSupportedMethods().values().stream().map(AuthMethod::getType).collect(Collectors.toList());
} }
@@ -191,7 +161,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* set token */ /* set token */
this.token = token; this.token = token;
this.tokenTTL = 0; this.tokenTTL = 0;
TokenResponse res = request.post(PATH_AUTH_TOKEN + PATH_LOOKUP, emptyMap(), token, TokenResponse.class); TokenResponse res = request.get(AUTH_TOKEN + TOKEN_LOOKUP_SELF, emptyMap(), token, TokenResponse.class);
authorized = true; authorized = true;
return res; return res;
@@ -201,7 +171,7 @@ public class HTTPVaultConnector implements VaultConnector {
public final AuthResponse authUserPass(final String username, final String password) public final AuthResponse authUserPass(final String username, final String password)
throws VaultConnectorException { throws VaultConnectorException {
final Map<String, String> payload = singletonMap("password", password); final Map<String, String> payload = singletonMap("password", password);
return queryAuth(PATH_AUTH_USERPASS + username, payload); return queryAuth(AUTH_USERPASS_LOGIN + encode(username), payload);
} }
@Override @Override
@@ -210,7 +180,7 @@ public class HTTPVaultConnector implements VaultConnector {
"role_id", roleID, "role_id", roleID,
"secret_id", secretID "secret_id", secretID
); );
return queryAuth(PATH_AUTH_APPROLE + PATH_LOGIN, payload); return queryAuth(AUTH_APPROLE + "login", payload);
} }
/** /**
@@ -238,7 +208,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.postWithoutResponse(String.format(PATH_AUTH_APPROLE_ROLE, role.getName(), ""), role, token); request.postWithoutResponse(AUTH_APPROLE_ROLE + encode(role.getName()), role, token);
/* Set custom ID if provided */ /* Set custom ID if provided */
return !(role.getId() != null && !role.getId().isEmpty()) || setAppRoleID(role.getName(), role.getId()); return !(role.getId() != null && !role.getId().isEmpty()) || setAppRoleID(role.getName(), role.getId());
@@ -249,7 +219,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
return request.get( return request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""), AUTH_APPROLE_ROLE + encode(roleName),
emptyMap(), emptyMap(),
token, token,
AppRoleResponse.class AppRoleResponse.class
@@ -261,7 +231,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.deleteWithoutResponse(String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""), token); request.deleteWithoutResponse(AUTH_APPROLE_ROLE + encode(roleName), token);
return true; return true;
} }
@@ -271,7 +241,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Issue request, parse response and extract Role ID */ /* Issue request, parse response and extract Role ID */
return request.get( return request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"), AUTH_APPROLE_ROLE + encode(roleName) + "/role-id",
emptyMap(), emptyMap(),
token, token,
RawDataResponse.class RawDataResponse.class
@@ -284,7 +254,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.postWithoutResponse( request.postWithoutResponse(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"), AUTH_APPROLE_ROLE + encode(roleName) + "/role-id",
singletonMap("role_id", roleID), singletonMap("role_id", roleID),
token token
); );
@@ -299,14 +269,14 @@ public class HTTPVaultConnector implements VaultConnector {
if (secret.getId() != null && !secret.getId().isEmpty()) { if (secret.getId() != null && !secret.getId().isEmpty()) {
return request.post( return request.post(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/custom-secret-id"), AUTH_APPROLE_ROLE + encode(roleName) + "/custom-secret-id",
secret, secret,
token, token,
AppRoleSecretResponse.class AppRoleSecretResponse.class
); );
} else { } else {
return request.post( return request.post(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id"), AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id",
secret, token, secret, token,
AppRoleSecretResponse.class AppRoleSecretResponse.class
); );
@@ -320,7 +290,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Issue request and parse secret response */ /* Issue request and parse secret response */
return request.post( return request.post(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/lookup"), AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id/lookup",
new AppRoleSecret(secretID), new AppRoleSecret(secretID),
token, token,
AppRoleSecretResponse.class AppRoleSecretResponse.class
@@ -334,7 +304,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.postWithoutResponse( request.postWithoutResponse(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/destroy"), AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id/destroy",
new AppRoleSecret(secretID), new AppRoleSecret(secretID),
token); token);
@@ -346,7 +316,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
SecretListResponse secrets = request.get( SecretListResponse secrets = request.get(
PATH_AUTH_APPROLE + "/role?list=true", AUTH_APPROLE + "role?list=true",
emptyMap(), emptyMap(),
token, token,
SecretListResponse.class SecretListResponse.class
@@ -360,7 +330,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
SecretListResponse secrets = request.get( SecretListResponse secrets = request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id?list=true"), AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id?list=true",
emptyMap(), emptyMap(),
token, token,
SecretListResponse.class SecretListResponse.class
@@ -383,7 +353,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Request HTTP response and parse secret metadata */ /* Request HTTP response and parse secret metadata */
Map<String, String> args = mapOfStrings("version", version); Map<String, String> args = mapOfStrings("version", version);
return request.get(mount + PATH_DATA + key, args, token, MetaSecretResponse.class); return request.get(mount + SECRET_DATA + key, args, token, MetaSecretResponse.class);
} }
@Override @Override
@@ -392,7 +362,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Request HTTP response and parse secret metadata */ /* Request HTTP response and parse secret metadata */
return request.get(mount + PATH_METADATA + key, emptyMap(), token, MetadataResponse.class); return request.get(mount + SECRET_METADATA + key, emptyMap(), token, MetadataResponse.class);
} }
@Override @Override
@@ -407,7 +377,7 @@ public class HTTPVaultConnector implements VaultConnector {
"cas_required", casRequired "cas_required", casRequired
); );
write(mount + PATH_METADATA + key, payload); write(mount + SECRET_METADATA + key, payload);
} }
@Override @Override
@@ -426,7 +396,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Issue request and parse metadata response */ /* Issue request and parse metadata response */
return request.post( return request.post(
mount + PATH_DATA + key, mount + SECRET_DATA + key,
Map.of( Map.of(
"data", data, "data", data,
"options", options "options", options
@@ -479,30 +449,30 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException { public final void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException {
delete(mount + PATH_DATA + key); delete(mount + SECRET_DATA + key);
} }
@Override @Override
public final void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException { public final void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException {
delete(mount + PATH_METADATA + key); delete(mount + SECRET_METADATA + key);
} }
@Override @Override
public final void deleteSecretVersions(final String mount, final String key, final int... versions) public final void deleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException { throws VaultConnectorException {
handleSecretVersions(mount, PATH_DELETE, key, versions); handleSecretVersions(mount, SECRET_DELETE, key, versions);
} }
@Override @Override
public final void undeleteSecretVersions(final String mount, final String key, final int... versions) public final void undeleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException { throws VaultConnectorException {
handleSecretVersions(mount, PATH_UNDELETE, key, versions); handleSecretVersions(mount, SECRET_UNDELETE, key, versions);
} }
@Override @Override
public final void destroySecretVersions(final String mount, final String key, final int... versions) public final void destroySecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException { throws VaultConnectorException {
handleSecretVersions(mount, PATH_DESTROY, key, versions); handleSecretVersions(mount, SECRET_DESTROY, key, versions);
} }
/** /**
@@ -533,7 +503,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.putWithoutResponse(PATH_REVOKE + leaseID, emptyMap(), token); request.putWithoutResponse(SYS_LEASES_REVOKE + encode(leaseID), emptyMap(), token);
} }
@Override @Override
@@ -546,17 +516,17 @@ public class HTTPVaultConnector implements VaultConnector {
); );
/* Issue request and parse secret response */ /* Issue request and parse secret response */
return request.put(PATH_RENEW, payload, token, SecretResponse.class); return request.put(SYS_LEASES_RENEW, payload, token, SecretResponse.class);
} }
@Override @Override
public final AuthResponse createToken(final Token token) throws VaultConnectorException { public final AuthResponse createToken(final Token token) throws VaultConnectorException {
return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_CREATE); return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE);
} }
@Override @Override
public final AuthResponse createToken(final Token token, final boolean orphan) throws VaultConnectorException { public final AuthResponse createToken(final Token token, final boolean orphan) throws VaultConnectorException {
return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_CREATE_ORPHAN); return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE_ORPHAN);
} }
@Override @Override
@@ -564,7 +534,7 @@ public class HTTPVaultConnector implements VaultConnector {
if (role == null || role.isEmpty()) { if (role == null || role.isEmpty()) {
throw new InvalidRequestException("No role name specified."); throw new InvalidRequestException("No role name specified.");
} }
return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_CREATE + "/" + role); return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE + "/" + encode(role));
} }
@Override @Override
@@ -599,7 +569,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
return request.get( return request.get(
PATH_AUTH_TOKEN + PATH_LOOKUP, AUTH_TOKEN + TOKEN_LOOKUP,
singletonMap("token", token), singletonMap("token", token),
token, token,
TokenResponse.class TokenResponse.class
@@ -617,7 +587,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
// Issue request and expect code 204 with empty response. // Issue request and expect code 204 with empty response.
request.postWithoutResponse(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, role, token); request.postWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), role, token);
return true; return true;
} }
@@ -627,14 +597,14 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
// Request HTTP response and parse response. // Request HTTP response and parse response.
return request.get(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, emptyMap(), token, TokenRoleResponse.class); return request.get(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), emptyMap(), token, TokenRoleResponse.class);
} }
@Override @Override
public List<String> listTokenRoles() throws VaultConnectorException { public List<String> listTokenRoles() throws VaultConnectorException {
requireAuth(); requireAuth();
return list(PATH_AUTH_TOKEN + PATH_ROLES); return list(AUTH_TOKEN + TOKEN_ROLES);
} }
@Override @Override
@@ -646,7 +616,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
// Issue request and expect code 204 with empty response. // Issue request and expect code 204 with empty response.
request.deleteWithoutResponse(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, token); request.deleteWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), token);
return true; return true;
} }
@@ -660,7 +630,7 @@ public class HTTPVaultConnector implements VaultConnector {
"plaintext", plaintext "plaintext", plaintext
); );
return request.post(PATH_TRANSIT_ENCRYPT + keyName, payload, token, TransitResponse.class); return request.post(TRANSIT_ENCRYPT + encode(keyName), payload, token, TransitResponse.class);
} }
@Override @Override
@@ -672,7 +642,7 @@ public class HTTPVaultConnector implements VaultConnector {
"ciphertext", ciphertext "ciphertext", ciphertext
); );
return request.post(PATH_TRANSIT_DECRYPT + keyName, payload, token, TransitResponse.class); return request.post(TRANSIT_DECRYPT + encode(keyName), payload, token, TransitResponse.class);
} }
@Override @Override
@@ -689,7 +659,7 @@ public class HTTPVaultConnector implements VaultConnector {
"format", format "format", format
); );
return request.post(PATH_TRANSIT_HASH + algorithm, payload, token, TransitResponse.class); return request.post(TRANSIT_HASH + encode(algorithm), payload, token, TransitResponse.class);
} }
/** /**
@@ -731,7 +701,7 @@ public class HTTPVaultConnector implements VaultConnector {
*/ */
private static Map<String, Object> mapOf(Object... keyValues) { private static Map<String, Object> mapOf(Object... keyValues) {
Map<String, Object> map = new HashMap<>(keyValues.length / 2, 1); Map<String, Object> map = new HashMap<>(keyValues.length / 2, 1);
for (int i = 0; i < keyValues.length; i = i + 2) { for (int i = 0; i < keyValues.length - 1; i = i + 2) {
Object key = keyValues[i]; Object key = keyValues[i];
Object val = keyValues[i + 1]; Object val = keyValues[i + 1];
if (key instanceof String && val != null) { if (key instanceof String && val != null) {

View File

@@ -25,6 +25,7 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.time.Duration; import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -263,9 +264,9 @@ public final class RequestHelper implements Serializable {
if (!payload.isEmpty()) { if (!payload.isEmpty()) {
uriBuilder.append("?").append( uriBuilder.append("?").append(
payload.entrySet().stream().map(par -> payload.entrySet().stream()
URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8) .map(par -> encode(par.getKey()) + "=" + encode(par.getValue()))
).collect(Collectors.joining("&")) .collect(Collectors.joining("&"))
); );
} }
@@ -307,6 +308,17 @@ public final class RequestHelper implements Serializable {
} }
} }
/**
* Encode URL part.
*
* @param part Path part to URL-encode and insert into the template
* @return Encoded URL part
* @since 1.5.3
*/
public static String encode(final String part) {
return URLEncoder.encode(Objects.requireNonNullElse(part, ""), UTF_8);
}
/** /**
* Execute prepared HTTP request and return result. * Execute prepared HTTP request and return result.
* *

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2016-2025 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;
/**
* Vault API path constants.
*
* @author Stefan Kalscheuer
* @since 1.5.3
*/
public final class VaultApiPath {
// Base paths
private static final String SYS = "sys";
private static final String AUTH = "auth";
private static final String TRANSIT = "transit";
// System paths
public static final String SYS_AUTH = SYS + "/auth";
public static final String SYS_LEASES_RENEW = SYS + "/leases/renew";
public static final String SYS_LEASES_REVOKE = SYS + "/leases/revoke/";
public static final String SYS_HEALTH = SYS + "/health";
public static final String SYS_SEAL = SYS + "/seal";
public static final String SYS_SEAL_STATUS = SYS + "/seal-status";
public static final String SYS_UNSEAL = SYS + "/unseal";
// Auth paths
public static final String AUTH_TOKEN = AUTH + "/token";
public static final String AUTH_USERPASS_LOGIN = AUTH + "/userpass/login/";
public static final String AUTH_APPROLE = AUTH + "/approle/";
public static final String AUTH_APPROLE_ROLE = AUTH_APPROLE + "role/";
// Token operations
public static final String TOKEN_LOOKUP = "/lookup";
public static final String TOKEN_LOOKUP_SELF = "/lookup-self";
public static final String TOKEN_CREATE = "/create";
public static final String TOKEN_CREATE_ORPHAN = "/create-orphan";
public static final String TOKEN_ROLES = "/roles";
// Secret engine paths
public static final String SECRET_DATA = "/data/";
public static final String SECRET_METADATA = "/metadata/";
public static final String SECRET_DELETE = "/delete/";
public static final String SECRET_UNDELETE = "/undelete/";
public static final String SECRET_DESTROY = "/destroy/";
// Transit engine paths
public static final String TRANSIT_ENCRYPT = TRANSIT + "/encrypt/";
public static final String TRANSIT_DECRYPT = TRANSIT + "/decrypt/";
public static final String TRANSIT_HASH = TRANSIT + "/hash/";
/**
* Private constructor to prevent instantiation.
*/
private VaultApiPath() {
// Utility class
}
}

View File

@@ -32,7 +32,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRole implements Serializable { public final class AppRole implements Serializable {
private static final long serialVersionUID = 693228837510483448L; private static final long serialVersionUID = 1546673231280751679L;
@JsonProperty("role_name") @JsonProperty("role_name")
private String name; private String name;
@@ -53,7 +53,7 @@ public final class AppRole implements Serializable {
@JsonProperty("secret_id_ttl") @JsonProperty("secret_id_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer secretIdTtl; private Long secretIdTtl;
@JsonProperty("local_secret_ids") @JsonProperty("local_secret_ids")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -61,11 +61,11 @@ public final class AppRole implements Serializable {
@JsonProperty("token_ttl") @JsonProperty("token_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenTtl; private Long tokenTtl;
@JsonProperty("token_max_ttl") @JsonProperty("token_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenMaxTtl; private Long tokenMaxTtl;
private List<String> tokenPolicies; private List<String> tokenPolicies;
@@ -75,7 +75,7 @@ public final class AppRole implements Serializable {
@JsonProperty("token_explicit_max_ttl") @JsonProperty("token_explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenExplicitMaxTtl; private Long tokenExplicitMaxTtl;
@JsonProperty("token_no_default_policy") @JsonProperty("token_no_default_policy")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -255,7 +255,7 @@ public final class AppRole implements Serializable {
/** /**
* @return maximum TTL in seconds for secrets * @return maximum TTL in seconds for secrets
*/ */
public Integer getSecretIdTtl() { public Long getSecretIdTtl() {
return secretIdTtl; return secretIdTtl;
} }
@@ -271,14 +271,14 @@ public final class AppRole implements Serializable {
/** /**
* @return token TTL in seconds * @return token TTL in seconds
*/ */
public Integer getTokenTtl() { public Long getTokenTtl() {
return tokenTtl; return tokenTtl;
} }
/** /**
* @return maximum token TTL in seconds, including renewals * @return maximum token TTL in seconds, including renewals
*/ */
public Integer getTokenMaxTtl() { public Long getTokenMaxTtl() {
return tokenMaxTtl; return tokenMaxTtl;
} }
@@ -286,7 +286,7 @@ public final class AppRole implements Serializable {
* @return explicit maximum token TTL in seconds, including renewals * @return explicit maximum token TTL in seconds, including renewals
* @since 0.9 * @since 0.9
*/ */
public Integer getTokenExplicitMaxTtl() { public Long getTokenExplicitMaxTtl() {
return tokenExplicitMaxTtl; return tokenExplicitMaxTtl;
} }
@@ -370,12 +370,12 @@ public final class AppRole implements Serializable {
private List<String> secretIdBoundCidrs; private List<String> secretIdBoundCidrs;
private List<String> tokenPolicies; private List<String> tokenPolicies;
private Integer secretIdNumUses; private Integer secretIdNumUses;
private Integer secretIdTtl; private Long secretIdTtl;
private Boolean localSecretIds; private Boolean localSecretIds;
private Integer tokenTtl; private Long tokenTtl;
private Integer tokenMaxTtl; private Long tokenMaxTtl;
private List<String> tokenBoundCidrs; private List<String> tokenBoundCidrs;
private Integer tokenExplicitMaxTtl; private Long tokenExplicitMaxTtl;
private Boolean tokenNoDefaultPolicy; private Boolean tokenNoDefaultPolicy;
private Integer tokenNumUses; private Integer tokenNumUses;
private Integer tokenPeriod; private Integer tokenPeriod;
@@ -520,7 +520,7 @@ public final class AppRole implements Serializable {
* @param secretIdTtl the TTL * @param secretIdTtl the TTL
* @return self * @return self
*/ */
public Builder withSecretIdTtl(final Integer secretIdTtl) { public Builder withSecretIdTtl(final Long secretIdTtl) {
this.secretIdTtl = secretIdTtl; this.secretIdTtl = secretIdTtl;
return this; return this;
} }
@@ -544,7 +544,7 @@ public final class AppRole implements Serializable {
* @param tokenTtl the TTL * @param tokenTtl the TTL
* @return self * @return self
*/ */
public Builder withTokenTtl(final Integer tokenTtl) { public Builder withTokenTtl(final Long tokenTtl) {
this.tokenTtl = tokenTtl; this.tokenTtl = tokenTtl;
return this; return this;
} }
@@ -555,7 +555,7 @@ public final class AppRole implements Serializable {
* @param tokenMaxTtl the TTL * @param tokenMaxTtl the TTL
* @return self * @return self
*/ */
public Builder withTokenMaxTtl(final Integer tokenMaxTtl) { public Builder withTokenMaxTtl(final Long tokenMaxTtl) {
this.tokenMaxTtl = tokenMaxTtl; this.tokenMaxTtl = tokenMaxTtl;
return this; return this;
} }
@@ -596,7 +596,7 @@ public final class AppRole implements Serializable {
* @param tokenExplicitMaxTtl the TTL * @param tokenExplicitMaxTtl the TTL
* @return self * @return self
*/ */
public Builder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) { public Builder withTokenExplicitMaxTtl(final Long tokenExplicitMaxTtl) {
this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; this.tokenExplicitMaxTtl = tokenExplicitMaxTtl;
return this; return this;
} }

View File

@@ -32,7 +32,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRoleSecret implements Serializable { public final class AppRoleSecret implements Serializable {
private static final long serialVersionUID = -3401074170145792641L; private static final long serialVersionUID = 3079272087137299819L;
@JsonProperty("secret_id") @JsonProperty("secret_id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -47,6 +47,8 @@ public final class AppRoleSecret implements Serializable {
private List<String> cidrList; private List<String> cidrList;
private List<String> tokenBoundCidrs;
@JsonProperty(value = "creation_time", access = JsonProperty.Access.WRITE_ONLY) @JsonProperty(value = "creation_time", access = JsonProperty.Access.WRITE_ONLY)
private String creationTime; private String creationTime;
@@ -137,6 +139,36 @@ public final class AppRoleSecret implements Serializable {
return String.join(",", cidrList); return String.join(",", cidrList);
} }
/**
* @return list of bound CIDR subnets of associated tokens
* @since 1.5.3
*/
public List<String> getTokenBoundCidrs() {
return tokenBoundCidrs;
}
/**
* @param boundCidrList list of subnets in CIDR notation to bind role to
* @since 1.5.3
*/
@JsonSetter("token_bound_cidrs")
public void setTokenBoundCidrs(final List<String> boundCidrList) {
this.tokenBoundCidrs = boundCidrList;
}
/**
* @return list of subnets in CIDR notation as comma-separated {@link String}
* @since 1.5.3
*/
@JsonGetter("token_bound_cidrs")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getTokenBoundCidrsString() {
if (tokenBoundCidrs == null || tokenBoundCidrs.isEmpty()) {
return "";
}
return String.join(",", tokenBoundCidrs);
}
/** /**
* @return Creation time * @return Creation time
*/ */
@@ -184,6 +216,7 @@ public final class AppRoleSecret implements Serializable {
Objects.equals(accessor, that.accessor) && Objects.equals(accessor, that.accessor) &&
Objects.equals(metadata, that.metadata) && Objects.equals(metadata, that.metadata) &&
Objects.equals(cidrList, that.cidrList) && Objects.equals(cidrList, that.cidrList) &&
Objects.equals(tokenBoundCidrs, that.tokenBoundCidrs) &&
Objects.equals(creationTime, that.creationTime) && Objects.equals(creationTime, that.creationTime) &&
Objects.equals(expirationTime, that.expirationTime) && Objects.equals(expirationTime, that.expirationTime) &&
Objects.equals(lastUpdatedTime, that.lastUpdatedTime) && Objects.equals(lastUpdatedTime, that.lastUpdatedTime) &&
@@ -193,7 +226,7 @@ public final class AppRoleSecret implements Serializable {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(id, accessor, metadata, cidrList, creationTime, expirationTime, lastUpdatedTime, numUses, return Objects.hash(id, accessor, metadata, cidrList, tokenBoundCidrs, creationTime, expirationTime,
ttl); lastUpdatedTime, numUses, ttl);
} }
} }

View File

@@ -32,7 +32,7 @@ import java.util.*;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class Token implements Serializable { public final class Token implements Serializable {
private static final long serialVersionUID = 5208508683665365287L; private static final long serialVersionUID = 7003016071684507115L;
@JsonProperty("id") @JsonProperty("id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -56,11 +56,11 @@ public final class Token implements Serializable {
@JsonProperty("ttl") @JsonProperty("ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer ttl; private Long ttl;
@JsonProperty("explicit_max_ttl") @JsonProperty("explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer explicitMaxTtl; private Long explicitMaxTtl;
@JsonProperty("num_uses") @JsonProperty("num_uses")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -162,7 +162,7 @@ public final class Token implements Serializable {
/** /**
* @return Time-to-live in seconds * @return Time-to-live in seconds
*/ */
public Integer getTtl() { public Long getTtl() {
return ttl; return ttl;
} }
@@ -170,7 +170,7 @@ public final class Token implements Serializable {
* @return Explicit maximum time-to-live in seconds * @return Explicit maximum time-to-live in seconds
* @since 0.9 * @since 0.9
*/ */
public Integer getExplicitMaxTtl() { public Long getExplicitMaxTtl() {
return explicitMaxTtl; return explicitMaxTtl;
} }
@@ -282,8 +282,8 @@ public final class Token implements Serializable {
private String displayName; private String displayName;
private Boolean noParent; private Boolean noParent;
private Boolean noDefaultPolicy; private Boolean noDefaultPolicy;
private Integer ttl; private Long ttl;
private Integer explicitMaxTtl; private Long explicitMaxTtl;
private Integer numUses; private Integer numUses;
private List<String> policies; private List<String> policies;
private Map<String, String> meta; private Map<String, String> meta;
@@ -331,7 +331,7 @@ public final class Token implements Serializable {
* @param ttl the ttl * @param ttl the ttl
* @return self * @return self
*/ */
public Builder withTtl(final Integer ttl) { public Builder withTtl(final Long ttl) {
this.ttl = ttl; this.ttl = ttl;
return this; return this;
} }
@@ -342,7 +342,7 @@ public final class Token implements Serializable {
* @param explicitMaxTtl the explicit max. TTL * @param explicitMaxTtl the explicit max. TTL
* @return self * @return self
*/ */
public Builder withExplicitMaxTtl(final Integer explicitMaxTtl) { public Builder withExplicitMaxTtl(final Long explicitMaxTtl) {
this.explicitMaxTtl = explicitMaxTtl; this.explicitMaxTtl = explicitMaxTtl;
return this; return this;
} }

View File

@@ -34,7 +34,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenRole implements Serializable { public final class TokenRole implements Serializable {
private static final long serialVersionUID = -3505215215838576321L; private static final long serialVersionUID = -4856948364869438439L;
@JsonProperty("name") @JsonProperty("name")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -78,7 +78,7 @@ public final class TokenRole implements Serializable {
@JsonProperty("token_explicit_max_ttl") @JsonProperty("token_explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenExplicitMaxTtl; private Long tokenExplicitMaxTtl;
@JsonProperty("token_no_default_policy") @JsonProperty("token_no_default_policy")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -204,7 +204,7 @@ public final class TokenRole implements Serializable {
/** /**
* @return Token explicit maximum TTL * @return Token explicit maximum TTL
*/ */
public Integer getTokenExplicitMaxTtl() { public Long getTokenExplicitMaxTtl() {
return tokenExplicitMaxTtl; return tokenExplicitMaxTtl;
} }
@@ -285,7 +285,7 @@ public final class TokenRole implements Serializable {
private String pathSuffix; private String pathSuffix;
private List<String> allowedEntityAliases; private List<String> allowedEntityAliases;
private List<String> tokenBoundCidrs; private List<String> tokenBoundCidrs;
private Integer tokenExplicitMaxTtl; private Long tokenExplicitMaxTtl;
private Boolean tokenNoDefaultPolicy; private Boolean tokenNoDefaultPolicy;
private Integer tokenNumUses; private Integer tokenNumUses;
private Integer tokenPeriod; private Integer tokenPeriod;
@@ -537,7 +537,7 @@ public final class TokenRole implements Serializable {
* @param tokenExplicitMaxTtl explicit maximum TTL * @param tokenExplicitMaxTtl explicit maximum TTL
* @return self * @return self
*/ */
public Builder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) { public Builder withTokenExplicitMaxTtl(final Long tokenExplicitMaxTtl) {
this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; this.tokenExplicitMaxTtl = tokenExplicitMaxTtl;
return this; return this;
} }

View File

@@ -15,13 +15,13 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class MountConfig implements Serializable { public class MountConfig implements Serializable {
private static final long serialVersionUID = -8653909672663717792L; private static final long serialVersionUID = 7241631159224756605L;
@JsonProperty("default_lease_ttl") @JsonProperty("default_lease_ttl")
private Integer defaultLeaseTtl; private Long defaultLeaseTtl;
@JsonProperty("max_lease_ttl") @JsonProperty("max_lease_ttl")
private Integer maxLeaseTtl; private Long maxLeaseTtl;
@JsonProperty("force_no_cache") @JsonProperty("force_no_cache")
private Boolean forceNoCache; private Boolean forceNoCache;
@@ -56,14 +56,14 @@ public class MountConfig implements Serializable {
/** /**
* @return Default lease TTL * @return Default lease TTL
*/ */
public Integer getDefaultLeaseTtl() { public Long getDefaultLeaseTtl() {
return defaultLeaseTtl; return defaultLeaseTtl;
} }
/** /**
* @return Maximum lease TTL * @return Maximum lease TTL
*/ */
public Integer getMaxLeaseTtl() { public Long getMaxLeaseTtl() {
return maxLeaseTtl; return maxLeaseTtl;
} }

View File

@@ -34,7 +34,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenData implements Serializable { public final class TokenData implements Serializable {
private static final long serialVersionUID = -5749716740973138916L; private static final long serialVersionUID = -4168046151053509784L;
@JsonProperty("accessor") @JsonProperty("accessor")
private String accessor; private String accessor;
@@ -43,7 +43,7 @@ public final class TokenData implements Serializable {
private Integer creationTime; private Integer creationTime;
@JsonProperty("creation_ttl") @JsonProperty("creation_ttl")
private Integer creationTtl; private Long creationTtl;
@JsonProperty("display_name") @JsonProperty("display_name")
private String name; private String name;
@@ -55,7 +55,7 @@ public final class TokenData implements Serializable {
private ZonedDateTime expireTime; private ZonedDateTime expireTime;
@JsonProperty("explicit_max_ttl") @JsonProperty("explicit_max_ttl")
private Integer explicitMaxTtl; private Long explicitMaxTtl;
@JsonProperty("id") @JsonProperty("id")
private String id; private String id;
@@ -82,7 +82,7 @@ public final class TokenData implements Serializable {
private boolean renewable; private boolean renewable;
@JsonProperty("ttl") @JsonProperty("ttl")
private Integer ttl; private Long ttl;
@JsonProperty("type") @JsonProperty("type")
private String type; private String type;
@@ -104,7 +104,7 @@ public final class TokenData implements Serializable {
/** /**
* @return Creation TTL (in seconds) * @return Creation TTL (in seconds)
*/ */
public Integer getCreationTtl() { public Long getCreationTtl() {
return creationTtl; return creationTtl;
} }
@@ -135,7 +135,7 @@ public final class TokenData implements Serializable {
* @return Explicit maximum TTL * @return Explicit maximum TTL
* @since 0.9 * @since 0.9
*/ */
public Integer getExplicitMaxTtl() { public Long getExplicitMaxTtl() {
return explicitMaxTtl; return explicitMaxTtl;
} }
@@ -202,7 +202,7 @@ public final class TokenData implements Serializable {
/** /**
* @return Token TTL (in seconds) * @return Token TTL (in seconds)
*/ */
public Integer getTtl() { public Long getTtl() {
return ttl; return ttl;
} }

View File

@@ -63,12 +63,12 @@ class HTTPVaultConnectorBuilderTest {
// Specify all options. // Specify all options.
HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder() HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder()
.withHost("vault2.example.com") .withHost("vault2.example.com")
.withoutTLS() .withoutTLS()
.withPort(1234) .withPort(1234)
.withPrefix("/foo/") .withPrefix("/foo/")
.withTimeout(5678) .withTimeout(5678)
.withNumberOfRetries(9); .withNumberOfRetries(9);
connector = builder.build(); connector = builder.build();
assertEquals("http://vault2.example.com:1234/foo/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly"); assertEquals("http://vault2.example.com:1234/foo/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
@@ -79,13 +79,13 @@ class HTTPVaultConnectorBuilderTest {
// Initialization from URL. // Initialization from URL.
assertThrows( assertThrows(
URISyntaxException.class, URISyntaxException.class,
() -> HTTPVaultConnector.builder().withBaseURL("foo:/\\1nv4l1d_UrL"), () -> HTTPVaultConnector.builder().withBaseURL("foo:/\\1nv4l1d_UrL"),
"Initialization from invalid URL should fail" "Initialization from invalid URL should fail"
); );
connector = assertDoesNotThrow( connector = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().withBaseURL("https://vault3.example.com:5678/bar/").build(), () -> HTTPVaultConnector.builder().withBaseURL("https://vault3.example.com:5678/bar/").build(),
"Initialization from valid URL should not fail" "Initialization from valid URL should not fail"
); );
assertEquals("https://vault3.example.com:5678/bar/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly"); assertEquals("https://vault3.example.com:5678/bar/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
@@ -106,8 +106,8 @@ class HTTPVaultConnectorBuilderTest {
// Provide address only should be enough. // Provide address only should be enough.
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> { withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed" "Factory creation from minimal environment failed"
); );
HTTPVaultConnector connector = builder.build(); HTTPVaultConnector connector = builder.build();
@@ -119,16 +119,16 @@ class HTTPVaultConnectorBuilderTest {
}); });
withVaultEnv(VAULT_ADDR_2, null, null, null).execute(() -> { withVaultEnv(VAULT_ADDR_2, null, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed" "Factory creation from minimal environment failed"
); );
assertEquals(VAULT_ADDR_2 + "/v1/", getRequestHelperPrivate(builder.build(), "baseURL"), "URL without port not set correctly"); assertEquals(VAULT_ADDR_2 + "/v1/", getRequestHelperPrivate(builder.build(), "baseURL"), "URL without port not set correctly");
return null; return null;
}); });
withVaultEnv(VAULT_ADDR_3, null, null, null).execute(() -> { withVaultEnv(VAULT_ADDR_3, null, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed" "Factory creation from minimal environment failed"
); );
assertEquals(VAULT_ADDR_3, getRequestHelperPrivate(builder.build(), "baseURL"), "URL with custom path not set correctly"); assertEquals(VAULT_ADDR_3, getRequestHelperPrivate(builder.build(), "baseURL"), "URL with custom path not set correctly");
return null; return null;
@@ -137,8 +137,8 @@ class HTTPVaultConnectorBuilderTest {
// Provide address and number of retries. // Provide address and number of retries.
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> { withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from environment failed" "Factory creation from environment failed"
); );
HTTPVaultConnector connector = builder.build(); HTTPVaultConnector connector = builder.build();
@@ -152,8 +152,8 @@ class HTTPVaultConnectorBuilderTest {
// Automatic authentication. // Automatic authentication.
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> { withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed" "Factory creation from minimal environment failed"
); );
assertEquals(VAULT_TOKEN, getPrivate(builder, "token"), "Token not set correctly"); assertEquals(VAULT_TOKEN, getPrivate(builder, "token"), "Token not set correctly");
@@ -163,9 +163,9 @@ class HTTPVaultConnectorBuilderTest {
// Invalid URL. // Invalid URL.
withVaultEnv("This is not a valid URL!", null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> { withVaultEnv("This is not a valid URL!", null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
assertThrows( assertThrows(
ConnectionException.class, ConnectionException.class,
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Invalid URL from environment should raise an exception" "Invalid URL from environment should raise an exception"
); );
return null; return null;
@@ -182,8 +182,8 @@ class HTTPVaultConnectorBuilderTest {
AtomicReference<Object> certFromPem = new AtomicReference<>(); AtomicReference<Object> certFromPem = new AtomicReference<>();
withVaultEnv(VAULT_ADDR, pem, null, null).execute(() -> { withVaultEnv(VAULT_ADDR, pem, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Builder with PEM certificate from environment failed" "Builder with PEM certificate from environment failed"
); );
HTTPVaultConnector connector = builder.build(); HTTPVaultConnector connector = builder.build();
@@ -198,8 +198,8 @@ class HTTPVaultConnectorBuilderTest {
AtomicReference<Object> certFromFile = new AtomicReference<>(); AtomicReference<Object> certFromFile = new AtomicReference<>();
withVaultEnv(VAULT_ADDR, file, null, null).execute(() -> { withVaultEnv(VAULT_ADDR, file, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow( HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Builder with certificate path from environment failed" "Builder with certificate path from environment failed"
); );
HTTPVaultConnector connector = builder.build(); HTTPVaultConnector connector = builder.build();
@@ -215,9 +215,9 @@ class HTTPVaultConnectorBuilderTest {
String doesNotExist = tempDir.toString() + "/doesnotexist"; String doesNotExist = tempDir.toString() + "/doesnotexist";
withVaultEnv(VAULT_ADDR, doesNotExist, VAULT_MAX_RETRIES.toString(), null).execute(() -> { withVaultEnv(VAULT_ADDR, doesNotExist, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
TlsException e = assertThrows( TlsException e = assertThrows(
TlsException.class, TlsException.class,
() -> HTTPVaultConnector.builder().fromEnv(), () -> HTTPVaultConnector.builder().fromEnv(),
"Creation with unknown cert path failed" "Creation with unknown cert path failed"
); );
assertEquals(doesNotExist, assertInstanceOf(NoSuchFileException.class, e.getCause()).getFile()); assertEquals(doesNotExist, assertInstanceOf(NoSuchFileException.class, e.getCause()).getFile());
@@ -227,9 +227,9 @@ class HTTPVaultConnectorBuilderTest {
private SystemLambda.WithEnvironmentVariables withVaultEnv(String vaultAddr, String vaultCacert, String vaultMaxRetries, String vaultToken) { private SystemLambda.WithEnvironmentVariables withVaultEnv(String vaultAddr, String vaultCacert, String vaultMaxRetries, String vaultToken) {
return withEnvironmentVariable("VAULT_ADDR", vaultAddr) return withEnvironmentVariable("VAULT_ADDR", vaultAddr)
.and("VAULT_CACERT", vaultCacert) .and("VAULT_CACERT", vaultCacert)
.and("VAULT_MAX_RETRIES", vaultMaxRetries) .and("VAULT_MAX_RETRIES", vaultMaxRetries)
.and("VAULT_TOKEN", vaultToken); .and("VAULT_TOKEN", vaultToken);
} }
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException { private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {

View File

@@ -52,7 +52,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
* @since 0.1 * @since 0.1
*/ */
class HTTPVaultConnectorIT { class HTTPVaultConnectorIT {
private static String VAULT_VERSION = "1.19.0"; // The vault version this test is supposed to run against. private static String VAULT_VERSION = "1.20.3"; // The vault version this test is supposed to run against.
private static final String KEY1 = "E38bkCm0VhUvpdCKGQpcohhD9XmcHJ/2hreOSY019Lho"; private static final String KEY1 = "E38bkCm0VhUvpdCKGQpcohhD9XmcHJ/2hreOSY019Lho";
private static final String KEY2 = "O5OHwDleY3IiPdgw61cgHlhsrEm6tVJkrxhF6QAnILd1"; private static final String KEY2 = "O5OHwDleY3IiPdgw61cgHlhsrEm6tVJkrxhF6QAnILd1";
private static final String KEY3 = "mw7Bm3nbt/UWa/juDjjL2EPQ04kiJ0saC5JEXwJvXYsB"; private static final String KEY3 = "mw7Bm3nbt/UWa/juDjjL2EPQ04kiJ0saC5JEXwJvXYsB";
@@ -86,9 +86,9 @@ class HTTPVaultConnectorIT {
// Initialize connector. // Initialize connector.
HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder() HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder()
.withHost(config.getHost()) .withHost(config.getHost())
.withPort(config.getPort()) .withPort(config.getPort())
.withTLS(isTls); .withTLS(isTls);
if (isTls) { if (isTls) {
builder.withTrustedCA(Paths.get(getClass().getResource("/tls/ca.pem").getPath())); builder.withTrustedCA(Paths.get(getClass().getResource("/tls/ca.pem").getPath()));
} }
@@ -134,9 +134,9 @@ class HTTPVaultConnectorIT {
final String invalidPath = "secret/invalid/path"; final String invalidPath = "secret/invalid/path";
VaultConnectorException e = assertThrows( VaultConnectorException e = assertThrows(
PermissionDeniedException.class, PermissionDeniedException.class,
() -> connector.read(invalidPath), () -> connector.read(invalidPath),
"Invalid secret path should raise an exception" "Invalid secret path should raise an exception"
); );
// Assert that the exception does not reveal secret or credentials. // Assert that the exception does not reveal secret or credentials.
@@ -147,15 +147,15 @@ class HTTPVaultConnectorIT {
// Try to read accessible path with known value. // Try to read accessible path with known value.
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/" + SECRET_KEY), () -> connector.read(SECRET_PATH + "/" + SECRET_KEY),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertEquals(SECRET_VALUE, res.get("value"), "Known secret returned invalid value"); assertEquals(SECRET_VALUE, res.get("value"), "Known secret returned invalid value");
// Try to read accessible path with JSON value. // Try to read accessible path with JSON value.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/" + SECRET_KEY_JSON), () -> connector.read(SECRET_PATH + "/" + SECRET_KEY_JSON),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertNotNull(res.get("value"), "Known secret returned null value"); assertNotNull(res.get("value"), "Known secret returned null value");
@@ -167,8 +167,8 @@ class HTTPVaultConnectorIT {
// Try to read accessible path with JSON value. // Try to read accessible path with JSON value.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/" + SECRET_KEY_JSON), () -> connector.read(SECRET_PATH + "/" + SECRET_KEY_JSON),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertNotNull(res.get("value"), "Known secret returned null value"); assertNotNull(res.get("value"), "Known secret returned null value");
@@ -180,8 +180,8 @@ class HTTPVaultConnectorIT {
// Try to read accessible complex secret. // Try to read accessible complex secret.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/" + SECRET_KEY_COMPLEX), () -> connector.read(SECRET_PATH + "/" + SECRET_KEY_COMPLEX),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertNotNull(res.getData(), "Known secret returned null value"); assertNotNull(res.getData(), "Known secret returned null value");
assertEquals(Map.of("key1", "value1", "key2", "value2"), res.getData(), "Unexpected data"); assertEquals(Map.of("key1", "value1", "key2", "value2"), res.getData(), "Unexpected data");
@@ -198,8 +198,8 @@ class HTTPVaultConnectorIT {
assumeTrue(connector.isAuthorized()); assumeTrue(connector.isAuthorized());
// Try to list secrets from valid path. // Try to list secrets from valid path.
List<String> secrets = assertDoesNotThrow( List<String> secrets = assertDoesNotThrow(
() -> connector.list(SECRET_PATH), () -> connector.list(SECRET_PATH),
"Secrets could not be listed" "Secrets could not be listed"
); );
assertNotEquals(0, secrets.size(), "Invalid number of secrets"); assertNotEquals(0, secrets.size(), "Invalid number of secrets");
assertTrue(secrets.contains(SECRET_KEY), "Known secret key not found"); assertTrue(secrets.contains(SECRET_KEY), "Known secret key not found");
@@ -217,33 +217,33 @@ class HTTPVaultConnectorIT {
// Try to write to null path. // Try to write to null path.
assertThrows( assertThrows(
InvalidRequestException.class, InvalidRequestException.class,
() -> connector.write(null, "someValue"), () -> connector.write(null, "someValue"),
"Secret written to null path" "Secret written to null path"
); );
// Try to write to invalid path. // Try to write to invalid path.
assertThrows( assertThrows(
InvalidRequestException.class, InvalidRequestException.class,
() -> connector.write("", "someValue"), () -> connector.write("", "someValue"),
"Secret written to invalid path" "Secret written to invalid path"
); );
// Try to write to a path the user has no access for. // Try to write to a path the user has no access for.
assertThrows( assertThrows(
PermissionDeniedException.class, PermissionDeniedException.class,
() -> connector.write("invalid/path", "someValue"), () -> connector.write("invalid/path", "someValue"),
"Secret written to inaccessible path" "Secret written to inaccessible path"
); );
// Perform a valid write/read roundtrip to valid path. Also check UTF8-encoding. // Perform a valid write/read roundtrip to valid path. Also check UTF8-encoding.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.write(SECRET_PATH + "/temp", "Abc123äöü,!"), () -> connector.write(SECRET_PATH + "/temp", "Abc123äöü,!"),
"Failed to write secret to accessible path" "Failed to write secret to accessible path"
); );
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/temp"), () -> connector.read(SECRET_PATH + "/temp"),
"Written secret could not be read" "Written secret could not be read"
); );
assertEquals("Abc123äöü,!", res.get("value")); assertEquals("Abc123äöü,!", res.get("value"));
} }
@@ -260,26 +260,26 @@ class HTTPVaultConnectorIT {
// Write a test secret to vault. // Write a test secret to vault.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.write(SECRET_PATH + "/toDelete", "secret content"), () -> connector.write(SECRET_PATH + "/toDelete", "secret content"),
"Secret written to inaccessible path" "Secret written to inaccessible path"
); );
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/toDelete"), () -> connector.read(SECRET_PATH + "/toDelete"),
"Written secret could not be read" "Written secret could not be read"
); );
assumeTrue(res != null); assumeTrue(res != null);
// Delete secret. // Delete secret.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.delete(SECRET_PATH + "/toDelete"), () -> connector.delete(SECRET_PATH + "/toDelete"),
"Revocation threw unexpected exception" "Revocation threw unexpected exception"
); );
// Try to read again. // Try to read again.
InvalidResponseException e = assertThrows( InvalidResponseException e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.read(SECRET_PATH + "/toDelete"), () -> connector.read(SECRET_PATH + "/toDelete"),
"Successfully read deleted secret" "Successfully read deleted secret"
); );
assertEquals(404, e.getStatusCode()); assertEquals(404, e.getStatusCode());
} }
@@ -296,19 +296,19 @@ class HTTPVaultConnectorIT {
// Write a test secret to vault. // Write a test secret to vault.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.write(SECRET_PATH + "/toRevoke", "secret content"), () -> connector.write(SECRET_PATH + "/toRevoke", "secret content"),
"Secret written to inaccessible path" "Secret written to inaccessible path"
); );
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> connector.read(SECRET_PATH + "/toRevoke"), () -> connector.read(SECRET_PATH + "/toRevoke"),
"Written secret could not be read" "Written secret could not be read"
); );
assumeTrue(res != null); assumeTrue(res != null);
// Revoke secret. // Revoke secret.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.revoke(SECRET_PATH + "/toRevoke"), () -> connector.revoke(SECRET_PATH + "/toRevoke"),
"Revocation threw unexpected exception" "Revocation threw unexpected exception"
); );
} }
} }
@@ -337,8 +337,8 @@ class HTTPVaultConnectorIT {
// Try to read accessible path with known value. // Try to read accessible path with known value.
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret"); assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret");
assertEquals(2, res.getMetadata().getVersion(), "Unexpected secret version"); assertEquals(2, res.getMetadata().getVersion(), "Unexpected secret version");
@@ -346,8 +346,8 @@ class HTTPVaultConnectorIT {
// Try to read different version of same secret. // Try to read different version of same secret.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.readSecretVersion(MOUNT_KV2, SECRET2_KEY, 1), () -> connector.readSecretVersion(MOUNT_KV2, SECRET2_KEY, 1),
"Valid secret version could not be read" "Valid secret version could not be read"
); );
assertEquals(1, res.getMetadata().getVersion(), "Unexpected secret version"); assertEquals(1, res.getMetadata().getVersion(), "Unexpected secret version");
assertEquals(SECRET2_VALUE1, res.get("value"), "Known secret returned invalid value"); assertEquals(SECRET2_VALUE1, res.get("value"), "Known secret returned invalid value");
@@ -365,8 +365,8 @@ class HTTPVaultConnectorIT {
// First get the current version of the secret. // First get the current version of the secret.
MetadataResponse res = assertDoesNotThrow( MetadataResponse res = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading secret metadata failed" "Reading secret metadata failed"
); );
int currentVersion = res.getMetadata().getCurrentVersion(); int currentVersion = res.getMetadata().getCurrentVersion();
@@ -374,25 +374,25 @@ class HTTPVaultConnectorIT {
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new HashMap<>();
data.put("value", SECRET2_VALUE3); data.put("value", SECRET2_VALUE3);
SecretVersionResponse res2 = assertDoesNotThrow( SecretVersionResponse res2 = assertDoesNotThrow(
() -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data), () -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data),
"Writing secret to KV v2 store failed" "Writing secret to KV v2 store failed"
); );
assertEquals(currentVersion + 1, res2.getMetadata().getVersion(), "Version not updated after writing secret"); assertEquals(currentVersion + 1, res2.getMetadata().getVersion(), "Version not updated after writing secret");
int currentVersion2 = res2.getMetadata().getVersion(); int currentVersion2 = res2.getMetadata().getVersion();
// Verify the content. // Verify the content.
SecretResponse res3 = assertDoesNotThrow( SecretResponse res3 = assertDoesNotThrow(
() -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY),
"Reading secret from KV v2 store failed" "Reading secret from KV v2 store failed"
); );
assertEquals(SECRET2_VALUE3, res3.get("value"), "Data not updated correctly"); assertEquals(SECRET2_VALUE3, res3.get("value"), "Data not updated correctly");
// Now try with explicit CAS value (invalid). // Now try with explicit CAS value (invalid).
Map<String, Object> data4 = singletonMap("value", SECRET2_VALUE4); Map<String, Object> data4 = singletonMap("value", SECRET2_VALUE4);
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data4, currentVersion2 - 1), () -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data4, currentVersion2 - 1),
"Writing secret to KV v2 with invalid CAS value succeeded" "Writing secret to KV v2 with invalid CAS value succeeded"
); );
// And finally with a correct CAS value. // And finally with a correct CAS value.
@@ -412,22 +412,22 @@ class HTTPVaultConnectorIT {
// Read current metadata first. // Read current metadata first.
MetadataResponse res = assertDoesNotThrow( MetadataResponse res = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading secret metadata failed" "Reading secret metadata failed"
); );
Integer maxVersions = res.getMetadata().getMaxVersions(); Integer maxVersions = res.getMetadata().getMaxVersions();
assumeTrue(10 == res.getMetadata().getMaxVersions(), "Unexpected maximum number of versions"); assumeTrue(10 == res.getMetadata().getMaxVersions(), "Unexpected maximum number of versions");
// Now update the metadata. // Now update the metadata.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.updateSecretMetadata(MOUNT_KV2, SECRET2_KEY, maxVersions + 1, true), () -> connector.updateSecretMetadata(MOUNT_KV2, SECRET2_KEY, maxVersions + 1, true),
"Updating secret metadata failed" "Updating secret metadata failed"
); );
// And verify the result. // And verify the result.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading secret metadata failed" "Reading secret metadata failed"
); );
assertEquals(maxVersions + 1, res.getMetadata().getMaxVersions(), "Unexpected maximum number of versions"); assertEquals(maxVersions + 1, res.getMetadata().getMaxVersions(), "Unexpected maximum number of versions");
} }
@@ -444,8 +444,8 @@ class HTTPVaultConnectorIT {
// Try to read accessible path with known value. // Try to read accessible path with known value.
MetadataResponse res = assertDoesNotThrow( MetadataResponse res = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Valid secret path could not be read" "Valid secret path could not be read"
); );
assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret"); assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret");
assertEquals(2, res.getMetadata().getCurrentVersion(), "Unexpected secret version"); assertEquals(2, res.getMetadata().getCurrentVersion(), "Unexpected secret version");
@@ -467,79 +467,79 @@ class HTTPVaultConnectorIT {
// Try to delete non-existing versions. // Try to delete non-existing versions.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 5, 42), () -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 5, 42),
"Revealed non-existence of secret versions" "Revealed non-existence of secret versions"
); );
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Revealed non-existence of secret versions" "Revealed non-existence of secret versions"
); );
// Now delete existing version and verify. // Now delete existing version and verify.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1), () -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
"Deleting existing version failed" "Deleting existing version failed"
); );
MetadataResponse meta = assertDoesNotThrow( MetadataResponse meta = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading deleted secret metadata failed" "Reading deleted secret metadata failed"
); );
assertNotNull( assertNotNull(
meta.getMetadata().getVersions().get(1).getDeletionTime(), meta.getMetadata().getVersions().get(1).getDeletionTime(),
"Expected deletion time for secret 1" "Expected deletion time for secret 1"
); );
// Undelete the just deleted version. // Undelete the just deleted version.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.undeleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1), () -> connector.undeleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
"Undeleting existing version failed" "Undeleting existing version failed"
); );
meta = assertDoesNotThrow( meta = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading deleted secret metadata failed" "Reading deleted secret metadata failed"
); );
assertNull( assertNull(
meta.getMetadata().getVersions().get(1).getDeletionTime(), meta.getMetadata().getVersions().get(1).getDeletionTime(),
"Expected deletion time for secret 1 to be reset" "Expected deletion time for secret 1 to be reset"
); );
// Now destroy it. // Now destroy it.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.destroySecretVersions(MOUNT_KV2, SECRET2_KEY, 1), () -> connector.destroySecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
"Destroying existing version failed" "Destroying existing version failed"
); );
meta = assertDoesNotThrow( meta = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading destroyed secret metadata failed" "Reading destroyed secret metadata failed"
); );
assertTrue( assertTrue(
meta.getMetadata().getVersions().get(1).isDestroyed(), meta.getMetadata().getVersions().get(1).isDestroyed(),
"Expected secret 1 to be marked destroyed" "Expected secret 1 to be marked destroyed"
); );
// Delete latest version. // Delete latest version.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.deleteLatestSecretVersion(MOUNT_KV2, SECRET2_KEY), () -> connector.deleteLatestSecretVersion(MOUNT_KV2, SECRET2_KEY),
"Deleting latest version failed" "Deleting latest version failed"
); );
meta = assertDoesNotThrow( meta = assertDoesNotThrow(
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading deleted secret metadata failed" "Reading deleted secret metadata failed"
); );
assertNotNull( assertNotNull(
meta.getMetadata().getVersions().get(2).getDeletionTime(), meta.getMetadata().getVersions().get(2).getDeletionTime(),
"Expected secret 2 to be deleted" "Expected secret 2 to be deleted"
); );
// Delete all versions. // Delete all versions.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.deleteAllSecretVersions(MOUNT_KV2, SECRET2_KEY), () -> connector.deleteAllSecretVersions(MOUNT_KV2, SECRET2_KEY),
"Deleting latest version failed" "Deleting latest version failed"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY), () -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
"Reading metadata of deleted secret should not succeed" "Reading metadata of deleted secret should not succeed"
); );
} }
} }
@@ -566,17 +566,17 @@ class HTTPVaultConnectorIT {
// Authenticate with correct credentials. // Authenticate with correct credentials.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.authAppRole(APPROLE_ROLE, APPROLE_SECRET), () -> connector.authAppRole(APPROLE_ROLE, APPROLE_SECRET),
"Failed to authenticate using AppRole" "Failed to authenticate using AppRole"
); );
assertTrue(connector.isAuthorized(), "Authorization flag not set after AppRole login"); assertTrue(connector.isAuthorized(), "Authorization flag not set after AppRole login");
// Authenticate with valid secret ID against unknown role. // Authenticate with valid secret ID against unknown role.
final String invalidRole = "foo"; final String invalidRole = "foo";
InvalidResponseException e = assertThrows( InvalidResponseException e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.authAppRole(invalidRole, APPROLE_SECRET), () -> connector.authAppRole(invalidRole, APPROLE_SECRET),
"Successfully logged in with unknown role" "Successfully logged in with unknown role"
); );
// Assert that the exception does not reveal role ID or secret. // Assert that the exception does not reveal role ID or secret.
assertFalse(stackTrace(e).contains(invalidRole)); assertFalse(stackTrace(e).contains(invalidRole));
@@ -585,9 +585,9 @@ class HTTPVaultConnectorIT {
// Authenticate without wrong secret ID. // Authenticate without wrong secret ID.
final String invalidSecret = "foo"; final String invalidSecret = "foo";
e = assertThrows( e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.authAppRole(APPROLE_ROLE, "foo"), () -> connector.authAppRole(APPROLE_ROLE, "foo"),
"Successfully logged in without secret ID" "Successfully logged in without secret ID"
); );
// Assert that the exception does not reveal role ID or secret. // Assert that the exception does not reveal role ID or secret.
assertFalse(stackTrace(e).contains(APPROLE_ROLE)); assertFalse(stackTrace(e).contains(APPROLE_ROLE));
@@ -595,17 +595,17 @@ class HTTPVaultConnectorIT {
// Authenticate without secret ID. // Authenticate without secret ID.
e = assertThrows( e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.authAppRole(APPROLE_ROLE), () -> connector.authAppRole(APPROLE_ROLE),
"Successfully logged in without secret ID" "Successfully logged in without secret ID"
); );
// Assert that the exception does not reveal role ID. // Assert that the exception does not reveal role ID.
assertFalse(stackTrace(e).contains(APPROLE_ROLE)); assertFalse(stackTrace(e).contains(APPROLE_ROLE));
// Authenticate with secret ID on role with CIDR whitelist. // Authenticate with secret ID on role with CIDR whitelist.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.authAppRole(APPROLE_ROLE2, APPROLE_SECRET), () -> connector.authAppRole(APPROLE_ROLE2, APPROLE_SECRET),
"Failed to log in without secret ID" "Failed to log in without secret ID"
); );
assertTrue(connector.isAuthorized(), "Authorization flag not set after AppRole login"); assertTrue(connector.isAuthorized(), "Authorization flag not set after AppRole login");
} }
@@ -687,8 +687,8 @@ class HTTPVaultConnectorIT {
// Update role model with custom flags. // Update role model with custom flags.
AppRole role2 = AppRole.builder(roleName) AppRole role2 = AppRole.builder(roleName)
.withTokenPeriod(321) .withTokenPeriod(321)
.build(); .build();
// Create role. // Create role.
boolean res3 = assertDoesNotThrow(() -> connector.createAppRole(role2), "Role creation failed"); boolean res3 = assertDoesNotThrow(() -> connector.createAppRole(role2), "Role creation failed");
@@ -717,8 +717,8 @@ class HTTPVaultConnectorIT {
// Create role by name with policies. // Create role by name with policies.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.createAppRole(roleName3, Collections.singletonList("testpolicy")), () -> connector.createAppRole(roleName3, Collections.singletonList("testpolicy")),
"Creation of role by name failed" "Creation of role by name failed"
); );
res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName3), "Creation of role by name failed"); res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName3), "Creation of role by name failed");
// Note: As of Vault 0.8.3 default policy is not added automatically, so this test should return 1, not 2. // Note: As of Vault 0.8.3 default policy is not added automatically, so this test should return 1, not 2.
@@ -727,9 +727,9 @@ class HTTPVaultConnectorIT {
// Delete role. // Delete role.
assertDoesNotThrow(() -> connector.deleteAppRole(roleName3), "Deletion of role failed"); assertDoesNotThrow(() -> connector.deleteAppRole(roleName3), "Deletion of role failed");
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.lookupAppRole(roleName3), () -> connector.lookupAppRole(roleName3),
"Deleted role could be looked up" "Deleted role could be looked up"
); );
} }
@@ -745,35 +745,35 @@ class HTTPVaultConnectorIT {
// Create default (random) secret for existing role. // Create default (random) secret for existing role.
AppRoleSecretResponse res = assertDoesNotThrow( AppRoleSecretResponse res = assertDoesNotThrow(
() -> connector.createAppRoleSecret(APPROLE_ROLE_NAME), () -> connector.createAppRoleSecret(APPROLE_ROLE_NAME),
"AppRole secret creation failed" "AppRole secret creation failed"
); );
assertNotNull(res.getSecret(), "No secret returned"); assertNotNull(res.getSecret(), "No secret returned");
// Create secret with custom ID. // Create secret with custom ID.
String secretID = "customSecretId"; String secretID = "customSecretId";
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.createAppRoleSecret(APPROLE_ROLE_NAME, secretID), () -> connector.createAppRoleSecret(APPROLE_ROLE_NAME, secretID),
"AppRole secret creation failed" "AppRole secret creation failed"
); );
assertEquals(secretID, res.getSecret().getId(), "Unexpected secret ID returned"); assertEquals(secretID, res.getSecret().getId(), "Unexpected secret ID returned");
// Lookup secret. // Lookup secret.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID), () -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID),
"AppRole secret lookup failed" "AppRole secret lookup failed"
); );
assertNotNull(res.getSecret(), "No secret information returned"); assertNotNull(res.getSecret(), "No secret information returned");
// Destroy secret. // Destroy secret.
assertDoesNotThrow( assertDoesNotThrow(
() -> connector.destroyAppRoleSecret(APPROLE_ROLE_NAME, secretID), () -> connector.destroyAppRoleSecret(APPROLE_ROLE_NAME, secretID),
"AppRole secret destruction failed" "AppRole secret destruction failed"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID), () -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID),
"Destroyed AppRole secret successfully read" "Destroyed AppRole secret successfully read"
); );
} }
} }
@@ -791,17 +791,17 @@ class HTTPVaultConnectorIT {
void authTokenTest() { void authTokenTest() {
final String invalidToken = "52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6"; final String invalidToken = "52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6";
VaultConnectorException e = assertThrows( VaultConnectorException e = assertThrows(
VaultConnectorException.class, VaultConnectorException.class,
() -> connector.authToken(invalidToken), () -> connector.authToken(invalidToken),
"Logged in with invalid token" "Logged in with invalid token"
); );
// Assert that the exception does not reveal the token. // Assert that the exception does not reveal the token.
assertFalse(stackTrace(e).contains(invalidToken)); assertFalse(stackTrace(e).contains(invalidToken));
TokenResponse res = assertDoesNotThrow( TokenResponse res = assertDoesNotThrow(
() -> connector.authToken(TOKEN_ROOT), () -> connector.authToken(TOKEN_ROOT),
"Login failed with valid token" "Login failed with valid token"
); );
assertNotNull(res, "Login failed with valid token"); assertNotNull(res, "Login failed with valid token");
assertTrue(connector.isAuthorized(), "Login failed with valid token"); assertTrue(connector.isAuthorized(), "Login failed with valid token");
@@ -819,10 +819,10 @@ class HTTPVaultConnectorIT {
// Create token. // Create token.
Token token = Token.builder() Token token = Token.builder()
.withId("test-id") .withId("test-id")
.withType(Token.Type.SERVICE) .withType(Token.Type.SERVICE)
.withDisplayName("test name") .withDisplayName("test name")
.build(); .build();
// Create token. // Create token.
AuthResponse res = assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed"); AuthResponse res = assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed");
@@ -841,12 +841,12 @@ class HTTPVaultConnectorIT {
// Create token with attributes. // Create token with attributes.
Token token2 = Token.builder() Token token2 = Token.builder()
.withId("test-id2") .withId("test-id2")
.withDisplayName("test name 2") .withDisplayName("test name 2")
.withPolicies(Collections.singletonList("testpolicy")) .withPolicies(Collections.singletonList("testpolicy"))
.withoutDefaultPolicy() .withoutDefaultPolicy()
.withMeta("foo", "bar") .withMeta("foo", "bar")
.build(); .build();
res = assertDoesNotThrow(() -> connector.createToken(token2), "Token creation failed"); res = assertDoesNotThrow(() -> connector.createToken(token2), "Token creation failed");
assertEquals("test-id2", res.getAuth().getClientToken(), "Invalid token ID returned"); assertEquals("test-id2", res.getAuth().getClientToken(), "Invalid token ID returned");
assertEquals(List.of("testpolicy"), res.getAuth().getPolicies(), "Invalid policies returned"); assertEquals(List.of("testpolicy"), res.getAuth().getPolicies(), "Invalid policies returned");
@@ -856,18 +856,18 @@ class HTTPVaultConnectorIT {
// Overwrite token should fail as of Vault 0.8.0. // Overwrite token should fail as of Vault 0.8.0.
Token token3 = Token.builder() Token token3 = Token.builder()
.withId("test-id2") .withId("test-id2")
.withDisplayName("test name 3") .withDisplayName("test name 3")
.withPolicies(Arrays.asList("pol1", "pol2")) .withPolicies(Arrays.asList("pol1", "pol2"))
.withDefaultPolicy() .withDefaultPolicy()
.withMeta("test", "success") .withMeta("test", "success")
.withMeta("key", "value") .withMeta("key", "value")
.withTtl(1234) .withTtl(1234L)
.build(); .build();
InvalidResponseException e = assertThrows( InvalidResponseException e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.createToken(token3), () -> connector.createToken(token3),
"Overwriting token should fail as of Vault 0.8.0" "Overwriting token should fail as of Vault 0.8.0"
); );
assertEquals(400, e.getStatusCode()); assertEquals(400, e.getStatusCode());
// Assert that the exception does not reveal token ID. // Assert that the exception does not reveal token ID.
@@ -875,16 +875,16 @@ class HTTPVaultConnectorIT {
// Create token with batch type. // Create token with batch type.
Token token4 = Token.builder() Token token4 = Token.builder()
.withDisplayName("test name 3") .withDisplayName("test name 3")
.withPolicy("batchpolicy") .withPolicy("batchpolicy")
.withoutDefaultPolicy() .withoutDefaultPolicy()
.withType(Token.Type.BATCH) .withType(Token.Type.BATCH)
.build(); .build();
res = assertDoesNotThrow(() -> connector.createToken(token4), "Token creation failed"); res = assertDoesNotThrow(() -> connector.createToken(token4), "Token creation failed");
assertTrue( assertTrue(
// Expecting batch token. "hvb." Prefix as of Vault 1.10, "b." before. // Expecting batch token. "hvb." Prefix as of Vault 1.10, "b." before.
res.getAuth().getClientToken().startsWith("b.") || res.getAuth().getClientToken().startsWith("hvb."), res.getAuth().getClientToken().startsWith("b.") || res.getAuth().getClientToken().startsWith("hvb."),
"Unexpected token prefix" "Unexpected token prefix"
); );
assertEquals(1, res.getAuth().getPolicies().size(), "Invalid number of policies returned"); assertEquals(1, res.getAuth().getPolicies().size(), "Invalid number of policies returned");
assertTrue(res.getAuth().getPolicies().contains("batchpolicy"), "Custom policy policy not set"); assertTrue(res.getAuth().getPolicies().contains("batchpolicy"), "Custom policy policy not set");
@@ -905,9 +905,9 @@ class HTTPVaultConnectorIT {
// Create token with attributes. // Create token with attributes.
Token token = Token.builder() Token token = Token.builder()
.withId("my-token") .withId("my-token")
.withType(Token.Type.SERVICE) .withType(Token.Type.SERVICE)
.build(); .build();
assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed"); assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed");
authRoot(); authRoot();
@@ -936,15 +936,15 @@ class HTTPVaultConnectorIT {
final TokenRole role = TokenRole.builder().build(); final TokenRole role = TokenRole.builder().build();
boolean creationRes = assertDoesNotThrow( boolean creationRes = assertDoesNotThrow(
() -> connector.createOrUpdateTokenRole(roleName, role), () -> connector.createOrUpdateTokenRole(roleName, role),
"Token role creation failed" "Token role creation failed"
); );
assertTrue(creationRes, "Token role creation failed"); assertTrue(creationRes, "Token role creation failed");
// Read the role. // Read the role.
TokenRoleResponse res = assertDoesNotThrow( TokenRoleResponse res = assertDoesNotThrow(
() -> connector.readTokenRole(roleName), () -> connector.readTokenRole(roleName),
"Reading token role failed" "Reading token role failed"
); );
assertNotNull(res, "Token role response must not be null"); assertNotNull(res, "Token role response must not be null");
assertNotNull(res.getData(), "Token role must not be null"); assertNotNull(res.getData(), "Token role must not be null");
@@ -955,16 +955,16 @@ class HTTPVaultConnectorIT {
// Update the role, i.e. change some attributes. // Update the role, i.e. change some attributes.
final TokenRole role2 = TokenRole.builder() final TokenRole role2 = TokenRole.builder()
.forName(roleName) .forName(roleName)
.withPathSuffix("suffix") .withPathSuffix("suffix")
.orphan(true) .orphan(true)
.renewable(false) .renewable(false)
.withTokenNumUses(42) .withTokenNumUses(42)
.build(); .build();
creationRes = assertDoesNotThrow( creationRes = assertDoesNotThrow(
() -> connector.createOrUpdateTokenRole(role2), () -> connector.createOrUpdateTokenRole(role2),
"Token role update failed" "Token role update failed"
); );
assertTrue(creationRes, "Token role update failed"); assertTrue(creationRes, "Token role update failed");
@@ -1072,8 +1072,8 @@ class HTTPVaultConnectorIT {
assumeTrue(connector.isAuthorized()); assumeTrue(connector.isAuthorized());
List<AuthBackend> supportedBackends = assertDoesNotThrow( List<AuthBackend> supportedBackends = assertDoesNotThrow(
() -> connector.getAuthBackends(), () -> connector.getAuthBackends(),
"Could not list supported auth backends" "Could not list supported auth backends"
); );
assertEquals(3, supportedBackends.size()); assertEquals(3, supportedBackends.size());
@@ -1089,17 +1089,17 @@ class HTTPVaultConnectorIT {
final String invalidUser = "foo"; final String invalidUser = "foo";
final String invalidPass = "bar"; final String invalidPass = "bar";
VaultConnectorException e = assertThrows( VaultConnectorException e = assertThrows(
VaultConnectorException.class, VaultConnectorException.class,
() -> connector.authUserPass(invalidUser, invalidPass), () -> connector.authUserPass(invalidUser, invalidPass),
"Logged in with invalid credentials" "Logged in with invalid credentials"
); );
// Assert that the exception does not reveal credentials. // Assert that the exception does not reveal credentials.
assertFalse(stackTrace(e).contains(invalidUser)); assertFalse(stackTrace(e).contains(invalidUser));
assertFalse(stackTrace(e).contains(invalidPass)); assertFalse(stackTrace(e).contains(invalidPass));
AuthResponse res = assertDoesNotThrow( AuthResponse res = assertDoesNotThrow(
() -> connector.authUserPass(USER_VALID, PASS_VALID), () -> connector.authUserPass(USER_VALID, PASS_VALID),
"Login failed with valid credentials: Exception thrown" "Login failed with valid credentials: Exception thrown"
); );
assertNotNull(res.getAuth(), "Login failed with valid credentials: Response not available"); assertNotNull(res.getAuth(), "Login failed with valid credentials: Response not available");
assertTrue(connector.isAuthorized(), "Login failed with valid credentials: Connector not authorized"); assertTrue(connector.isAuthorized(), "Login failed with valid credentials: Connector not authorized");
@@ -1113,14 +1113,14 @@ class HTTPVaultConnectorIT {
@DisplayName("TLS connection test") @DisplayName("TLS connection test")
void tlsConnectionTest() { void tlsConnectionTest() {
assertThrows( assertThrows(
VaultConnectorException.class, VaultConnectorException.class,
() -> connector.authToken("52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6"), () -> connector.authToken("52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6"),
"Logged in with invalid token" "Logged in with invalid token"
); );
TokenResponse res = assertDoesNotThrow( TokenResponse res = assertDoesNotThrow(
() -> connector.authToken(TOKEN_ROOT), () -> connector.authToken(TOKEN_ROOT),
"Login failed with valid token" "Login failed with valid token"
); );
assertNotNull(res, "Login failed with valid token"); assertNotNull(res, "Login failed with valid token");
assertTrue(connector.isAuthorized(), "Login failed with valid token"); assertTrue(connector.isAuthorized(), "Login failed with valid token");
@@ -1207,22 +1207,22 @@ class HTTPVaultConnectorIT {
// Generate vault local unencrypted configuration. // Generate vault local unencrypted configuration.
VaultConfiguration config = new VaultConfiguration() VaultConfiguration config = new VaultConfiguration()
.withHost("localhost") .withHost("localhost")
.withPort(getFreePort()) .withPort(getFreePort())
.withDataLocation(dataDir.toPath()) .withDataLocation(dataDir.toPath())
.disableMlock(); .disableMlock();
// Enable TLS with custom certificate and key, if required. // Enable TLS with custom certificate and key, if required.
if (tls) { if (tls) {
config.enableTLS() config.enableTLS()
.withCert(getClass().getResource("/tls/server.pem").getPath()) .withCert(getClass().getResource("/tls/server.pem").getPath())
.withKey(getClass().getResource("/tls/server.key").getPath()); .withKey(getClass().getResource("/tls/server.key").getPath());
} }
// Write configuration file. // Write configuration file.
File configFile = new File(dir, "vault.conf"); File configFile = new File(dir, "vault.conf");
try { try {
Files.write(configFile.toPath(), config.toString().getBytes(UTF_8)); Files.writeString(configFile.toPath(), config.toString(), UTF_8);
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unable to generate config file", e); throw new IllegalStateException("Unable to generate config file", e);
} }
@@ -1282,10 +1282,8 @@ class HTTPVaultConnectorIT {
return socket.getLocalPort(); return socket.getLocalPort();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); throw new IllegalStateException("Unable to find a free TCP port", e);
} }
throw new IllegalStateException("Unable to find a free TCP port");
} }
/** /**

View File

@@ -17,13 +17,13 @@
package de.stklcode.jvault.connector; package de.stklcode.jvault.connector;
import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import de.stklcode.jvault.connector.exception.ConnectionException; import de.stklcode.jvault.connector.exception.ConnectionException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.exception.PermissionDeniedException; import de.stklcode.jvault.connector.exception.PermissionDeniedException;
import de.stklcode.jvault.connector.exception.VaultConnectorException; import de.stklcode.jvault.connector.exception.VaultConnectorException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.Executable;
import java.io.IOException; import java.io.IOException;
@@ -36,9 +36,7 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Collections; import java.util.Collections;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
@@ -48,26 +46,23 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.7.0 * @since 0.7.0
*/ */
@WireMockTest
class HTTPVaultConnectorTest { class HTTPVaultConnectorTest {
@RegisterExtension
static WireMockExtension wireMock = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
.build();
/** /**
* Test exceptions thrown during request. * Test exceptions thrown during request.
*/ */
@Test @Test
void requestExceptionTest() throws IOException, URISyntaxException { void requestExceptionTest(WireMockRuntimeInfo wireMock) throws IOException, URISyntaxException {
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build(); HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
// Test invalid response code. // Test invalid response code.
final int responseCode = 400; final int responseCode = 400;
mockHttpResponse(responseCode, "", "application/json"); mockHttpResponse(responseCode, "", "application/json");
VaultConnectorException e = assertThrows( VaultConnectorException e = assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
connector::getHealth, connector::getHealth,
"Querying health status succeeded on invalid instance" "Querying health status succeeded on invalid instance"
); );
assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message"); assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message");
assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception"); assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception");
@@ -76,9 +71,9 @@ class HTTPVaultConnectorTest {
// Simulate permission denied response. // Simulate permission denied response.
mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json"); mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json");
assertThrows( assertThrows(
PermissionDeniedException.class, PermissionDeniedException.class,
connector::getHealth, connector::getHealth,
"Querying health status succeeded on invalid instance" "Querying health status succeeded on invalid instance"
); );
// Test exception thrown during request. // Test exception thrown during request.
@@ -86,22 +81,22 @@ class HTTPVaultConnectorTest {
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build(); connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build();
} }
e = assertThrows( e = assertThrows(
ConnectionException.class, ConnectionException.class,
connector::getHealth, connector::getHealth,
"Querying health status succeeded on invalid instance" "Querying health status succeeded on invalid instance"
); );
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message"); assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
assertInstanceOf(IOException.class, e.getCause(), "Unexpected cause"); assertInstanceOf(IOException.class, e.getCause(), "Unexpected cause");
// Now simulate a failing request that succeeds on second try. // Now simulate a failing request that succeeds on second try.
connector = HTTPVaultConnector.builder(wireMock.url("/")).withNumberOfRetries(1).withTimeout(250).build(); connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withNumberOfRetries(1).withTimeout(250).build();
wireMock.stubFor( stubFor(
WireMock.any(anyUrl()) WireMock.any(anyUrl())
.willReturn(aResponse().withStatus(500)) .willReturn(aResponse().withStatus(500))
.willReturn(aResponse().withStatus(500)) .willReturn(aResponse().withStatus(500))
.willReturn(aResponse().withStatus(500)) .willReturn(aResponse().withStatus(500))
.willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json")) .willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json"))
); );
assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly"); assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly");
} }
@@ -164,9 +159,9 @@ class HTTPVaultConnectorTest {
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort()).withTimeout(250).build(); connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort()).withTimeout(250).build();
} }
ConnectionException e = assertThrows( ConnectionException e = assertThrows(
ConnectionException.class, ConnectionException.class,
connector::sealStatus, connector::sealStatus,
"Querying seal status succeeded on invalid instance" "Querying seal status succeeded on invalid instance"
); );
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message"); assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
} }
@@ -182,9 +177,9 @@ class HTTPVaultConnectorTest {
connector = HTTPVaultConnector.builder("http://localhost:" + s.getLocalPort() + "/").withTimeout(250).build(); connector = HTTPVaultConnector.builder("http://localhost:" + s.getLocalPort() + "/").withTimeout(250).build();
} }
ConnectionException e = assertThrows( ConnectionException e = assertThrows(
ConnectionException.class, ConnectionException.class,
connector::getHealth, connector::getHealth,
"Querying health status succeeded on invalid instance" "Querying health status succeeded on invalid instance"
); );
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message"); assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
} }
@@ -193,8 +188,8 @@ class HTTPVaultConnectorTest {
* Test behavior on unparsable responses. * Test behavior on unparsable responses.
*/ */
@Test @Test
void parseExceptionTest() throws URISyntaxException { void parseExceptionTest(WireMockRuntimeInfo wireMock) throws URISyntaxException {
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build(); HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
// Mock authorization. // Mock authorization.
setPrivate(connector, "authorized", true); setPrivate(connector, "authorized", true);
// Mock response. // Mock response.
@@ -227,8 +222,8 @@ class HTTPVaultConnectorTest {
* Test requests that expect an empty response with code 204, but receive a 200 body. * Test requests that expect an empty response with code 204, but receive a 200 body.
*/ */
@Test @Test
void nonEmpty204ResponseTest() throws URISyntaxException { void nonEmpty204ResponseTest(WireMockRuntimeInfo wireMock) throws URISyntaxException {
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build(); HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
// Mock authorization. // Mock authorization.
setPrivate(connector, "authorized", true); setPrivate(connector, "authorized", true);
// Mock response. // Mock response.
@@ -236,45 +231,45 @@ class HTTPVaultConnectorTest {
// Now test the methods expecting a 204. // Now test the methods expecting a 204.
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.createAppRole("appID", Collections.singletonList("policy")), () -> connector.createAppRole("appID", Collections.singletonList("policy")),
"createAppRole() with 200 response succeeded" "createAppRole() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.deleteAppRole("roleName"), () -> connector.deleteAppRole("roleName"),
"deleteAppRole() with 200 response succeeded" "deleteAppRole() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.setAppRoleID("roleName", "roleID"), () -> connector.setAppRoleID("roleName", "roleID"),
"setAppRoleID() with 200 response succeeded" "setAppRoleID() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.destroyAppRoleSecret("roleName", "secretID"), () -> connector.destroyAppRoleSecret("roleName", "secretID"),
"destroyAppRoleSecret() with 200 response succeeded" "destroyAppRoleSecret() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.destroyAppRoleSecret("roleName", "secretUD"), () -> connector.destroyAppRoleSecret("roleName", "secretUD"),
"destroyAppRoleSecret() with 200 response succeeded" "destroyAppRoleSecret() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.delete("key"), () -> connector.delete("key"),
"delete() with 200 response succeeded" "delete() with 200 response succeeded"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> connector.revoke("leaseID"), () -> connector.revoke("leaseID"),
"destroyAppRoleSecret() with 200 response succeeded" "destroyAppRoleSecret() with 200 response succeeded"
); );
} }
@@ -310,10 +305,10 @@ class HTTPVaultConnectorTest {
} }
private void mockHttpResponse(int status, String body, String contentType) { private void mockHttpResponse(int status, String body, String contentType) {
wireMock.stubFor( stubFor(
WireMock.any(anyUrl()).willReturn( WireMock.any(anyUrl()).willReturn(
aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType) aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType)
) )
); );
} }
} }

View File

@@ -35,10 +35,11 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> { class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
private static final String TEST_ID = "abc123"; private static final String TEST_ID = "abc123";
private static final Map<String, Object> TEST_META = Map.of( private static final Map<String, Object> TEST_META = Map.of(
"foo", "bar", "foo", "bar",
"number", 1337 "number", 1337
); );
private static final List<String> TEST_CIDR = List.of("203.0.113.0/24", "198.51.100.0/24"); private static final List<String> TEST_CIDR = List.of("203.0.113.0/24", "198.51.100.0/24");
private static final List<String> TEST_TOKEN_CIDR = List.of("192.0.2.0/24", "198.51.100.0/24");
AppRoleSecretTest() { AppRoleSecretTest() {
super(AppRoleSecret.class); super(AppRoleSecret.class);
@@ -61,6 +62,8 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
assertNull(secret.getMetadata()); assertNull(secret.getMetadata());
assertNull(secret.getCidrList()); assertNull(secret.getCidrList());
assertEquals("", secret.getCidrListString()); assertEquals("", secret.getCidrListString());
assertNull(secret.getTokenBoundCidrs());
assertEquals("", secret.getTokenBoundCidrsString());
assertNull(secret.getCreationTime()); assertNull(secret.getCreationTime());
assertNull(secret.getExpirationTime()); assertNull(secret.getExpirationTime());
assertNull(secret.getLastUpdatedTime()); assertNull(secret.getLastUpdatedTime());
@@ -74,6 +77,8 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
assertNull(secret.getMetadata()); assertNull(secret.getMetadata());
assertNull(secret.getCidrList()); assertNull(secret.getCidrList());
assertEquals("", secret.getCidrListString()); assertEquals("", secret.getCidrListString());
assertNull(secret.getTokenBoundCidrs());
assertEquals("", secret.getTokenBoundCidrsString());
assertNull(secret.getCreationTime()); assertNull(secret.getCreationTime());
assertNull(secret.getExpirationTime()); assertNull(secret.getExpirationTime());
assertNull(secret.getLastUpdatedTime()); assertNull(secret.getLastUpdatedTime());
@@ -87,6 +92,8 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
assertEquals(TEST_META, secret.getMetadata()); assertEquals(TEST_META, secret.getMetadata());
assertEquals(TEST_CIDR, secret.getCidrList()); assertEquals(TEST_CIDR, secret.getCidrList());
assertEquals(String.join(",", TEST_CIDR), secret.getCidrListString()); assertEquals(String.join(",", TEST_CIDR), secret.getCidrListString());
assertNull(secret.getTokenBoundCidrs());
assertEquals("", secret.getTokenBoundCidrsString());
assertNull(secret.getCreationTime()); assertNull(secret.getCreationTime());
assertNull(secret.getExpirationTime()); assertNull(secret.getExpirationTime());
assertNull(secret.getLastUpdatedTime()); assertNull(secret.getLastUpdatedTime());
@@ -108,6 +115,15 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
secret.setCidrList(null); secret.setCidrList(null);
assertNull(secret.getCidrList()); assertNull(secret.getCidrList());
assertEquals("", secret.getCidrListString()); assertEquals("", secret.getCidrListString());
assertNull(secret.getTokenBoundCidrs());
assertEquals("", secret.getTokenBoundCidrsString());
secret.setTokenBoundCidrs(TEST_TOKEN_CIDR);
assertEquals(TEST_TOKEN_CIDR, secret.getTokenBoundCidrs());
assertEquals(String.join(",", TEST_TOKEN_CIDR), secret.getTokenBoundCidrsString());
secret.setTokenBoundCidrs(null);
assertNull(secret.getTokenBoundCidrs());
assertEquals("", secret.getTokenBoundCidrsString());
} }
/** /**
@@ -122,8 +138,8 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
String secretJson2 = commaSeparatedToList(secretJson); String secretJson2 = commaSeparatedToList(secretJson);
AppRoleSecret secret2 = assertDoesNotThrow( AppRoleSecret secret2 = assertDoesNotThrow(
() -> objectMapper.readValue(secretJson2, AppRoleSecret.class), () -> objectMapper.readValue(secretJson2, AppRoleSecret.class),
"Deserialization failed" "Deserialization failed"
); );
assertEquals(secret2.getId(), secret.getId()); assertEquals(secret2.getId(), secret.getId());
assertEquals(secret2.getMetadata(), secret.getMetadata()); assertEquals(secret2.getMetadata(), secret.getMetadata());
@@ -144,8 +160,8 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
assumeTrue(secret.getTtl() == 12345); assumeTrue(secret.getTtl() == 12345);
String secretJson3 = assertDoesNotThrow(() -> objectMapper.writeValueAsString(secret), "Serialization failed"); String secretJson3 = assertDoesNotThrow(() -> objectMapper.writeValueAsString(secret), "Serialization failed");
secret2 = assertDoesNotThrow( secret2 = assertDoesNotThrow(
() -> objectMapper.readValue(commaSeparatedToList(secretJson3), AppRoleSecret.class), () -> objectMapper.readValue(commaSeparatedToList(secretJson3), AppRoleSecret.class),
"Deserialization failed" "Deserialization failed"
); );
assertEquals(secret2.getId(), secret.getId()); assertEquals(secret2.getId(), secret.getId());
assertEquals(secret2.getMetadata(), secret.getMetadata()); assertEquals(secret2.getMetadata(), secret.getMetadata());
@@ -159,9 +175,10 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
// Those fields should be deserialized from JSON though. // Those fields should be deserialized from JSON though.
String secretJson4 = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," + String secretJson4 = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," + "\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"cidr_list\":[\"192.0.2.0/24\",\"198.51.100.0/24\"]," +
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," + "\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}"; "\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}";
secret2 = assertDoesNotThrow(() -> objectMapper.readValue(secretJson4, AppRoleSecret.class), "Deserialization failed"); secret2 = assertDoesNotThrow(() -> objectMapper.readValue(secretJson4, AppRoleSecret.class), "Deserialization failed");
assertEquals("TEST_ACCESSOR", secret2.getAccessor()); assertEquals("TEST_ACCESSOR", secret2.getAccessor());
assertEquals("TEST_CREATION", secret2.getCreationTime()); assertEquals("TEST_CREATION", secret2.getCreationTime());
@@ -181,6 +198,7 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
private static String commaSeparatedToList(String json) { private static String commaSeparatedToList(String json) {
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":[$1]") return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":[$1]")
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\""); .replaceAll("\"token_bound_cidrs\":\"([^\"]*)\"", "\"token_bound_cidrs\":[$1]")
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
} }
} }

View File

@@ -42,18 +42,18 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
private static final String POLICY = "policy"; private static final String POLICY = "policy";
private static final String POLICY_2 = "policy2"; private static final String POLICY_2 = "policy2";
private static final Integer SECRET_ID_NUM_USES = 10; private static final Integer SECRET_ID_NUM_USES = 10;
private static final Integer SECRET_ID_TTL = 7200; private static final Long SECRET_ID_TTL = 7200L;
private static final Boolean LOCAL_SECRET_IDS = false; private static final Boolean LOCAL_SECRET_IDS = false;
private static final Integer TOKEN_TTL = 4800; private static final Long TOKEN_TTL = 4800L;
private static final Integer TOKEN_MAX_TTL = 9600; private static final Long TOKEN_MAX_TTL = 9600L;
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 14400; private static final Long TOKEN_EXPLICIT_MAX_TTL = 14400L;
private static final Boolean TOKEN_NO_DEFAULT_POLICY = false; private static final Boolean TOKEN_NO_DEFAULT_POLICY = false;
private static final Integer TOKEN_NUM_USES = 42; private static final Integer TOKEN_NUM_USES = 42;
private static final Integer TOKEN_PERIOD = 1234; private static final Integer TOKEN_PERIOD = 1234;
private static final Token.Type TOKEN_TYPE = Token.Type.DEFAULT_SERVICE; private static final Token.Type TOKEN_TYPE = Token.Type.DEFAULT_SERVICE;
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,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}", private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}",
NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value()); NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value());
AppRoleTest() { AppRoleTest() {
super(AppRole.class); super(AppRole.class);
@@ -62,22 +62,22 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
@Override @Override
protected AppRole createFull() { protected AppRole createFull() {
return AppRole.builder(NAME) return AppRole.builder(NAME)
.withId(ID) .withId(ID)
.withBindSecretID(BIND_SECRET_ID) .withBindSecretID(BIND_SECRET_ID)
.withSecretIdBoundCidrs(BOUND_CIDR_LIST) .withSecretIdBoundCidrs(BOUND_CIDR_LIST)
.withTokenPolicies(POLICIES) .withTokenPolicies(POLICIES)
.withSecretIdNumUses(SECRET_ID_NUM_USES) .withSecretIdNumUses(SECRET_ID_NUM_USES)
.withSecretIdTtl(SECRET_ID_TTL) .withSecretIdTtl(SECRET_ID_TTL)
.withLocalSecretIds(LOCAL_SECRET_IDS) .withLocalSecretIds(LOCAL_SECRET_IDS)
.withTokenTtl(TOKEN_TTL) .withTokenTtl(TOKEN_TTL)
.withTokenMaxTtl(TOKEN_MAX_TTL) .withTokenMaxTtl(TOKEN_MAX_TTL)
.withTokenBoundCidrs(BOUND_CIDR_LIST) .withTokenBoundCidrs(BOUND_CIDR_LIST)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL) .withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY) .withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES) .withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD) .withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE) .withTokenType(TOKEN_TYPE)
.build(); .build();
} }
@BeforeAll @BeforeAll
@@ -159,11 +159,11 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
assertEquals(1, role.getTokenBoundCidrs().size()); assertEquals(1, role.getTokenBoundCidrs().size());
assertEquals(CIDR_2, role.getTokenBoundCidrs().get(0)); assertEquals(CIDR_2, role.getTokenBoundCidrs().get(0));
role = AppRole.builder(NAME) role = AppRole.builder(NAME)
.withSecretIdBoundCidrs(BOUND_CIDR_LIST) .withSecretIdBoundCidrs(BOUND_CIDR_LIST)
.withSecretBoundCidr(CIDR_2) .withSecretBoundCidr(CIDR_2)
.withTokenBoundCidrs(BOUND_CIDR_LIST) .withTokenBoundCidrs(BOUND_CIDR_LIST)
.withTokenBoundCidr(CIDR_2) .withTokenBoundCidr(CIDR_2)
.build(); .build();
assertEquals(2, role.getSecretIdBoundCidrs().size()); assertEquals(2, role.getSecretIdBoundCidrs().size());
assertTrue(role.getSecretIdBoundCidrs().containsAll(List.of(CIDR_1, CIDR_2))); assertTrue(role.getSecretIdBoundCidrs().containsAll(List.of(CIDR_1, CIDR_2)));
assertEquals(2, role.getTokenBoundCidrs().size()); assertEquals(2, role.getTokenBoundCidrs().size());
@@ -174,9 +174,9 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
assertEquals(1, role.getTokenPolicies().size()); assertEquals(1, role.getTokenPolicies().size());
assertEquals(POLICY_2, role.getTokenPolicies().get(0)); assertEquals(POLICY_2, role.getTokenPolicies().get(0));
role = AppRole.builder(NAME) role = AppRole.builder(NAME)
.withTokenPolicies(POLICIES) .withTokenPolicies(POLICIES)
.withTokenPolicy(POLICY_2) .withTokenPolicy(POLICY_2)
.build(); .build();
assertEquals(2, role.getTokenPolicies().size()); assertEquals(2, role.getTokenPolicies().size());
assertTrue(role.getTokenPolicies().containsAll(List.of(POLICY, POLICY_2))); assertTrue(role.getTokenPolicies().containsAll(List.of(POLICY, POLICY_2)));
} }

View File

@@ -59,28 +59,28 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
private static final String TOKEN_BOUND_CIDR_2 = "198.51.100.0/24"; private static final String TOKEN_BOUND_CIDR_2 = "198.51.100.0/24";
private static final String TOKEN_BOUND_CIDR_3 = "203.0.113.0/24"; private static final String TOKEN_BOUND_CIDR_3 = "203.0.113.0/24";
private static final List<String> TOKEN_BOUND_CIDRS = Arrays.asList(TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_1); private static final List<String> TOKEN_BOUND_CIDRS = Arrays.asList(TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_1);
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 1234; private static final Long TOKEN_EXPLICIT_MAX_TTL = 1234L;
private static final Boolean TOKEN_NO_DEFAULT_POLICY = false; private static final Boolean TOKEN_NO_DEFAULT_POLICY = false;
private static final Integer TOKEN_NUM_USES = 5; private static final Integer TOKEN_NUM_USES = 5;
private static final Integer TOKEN_PERIOD = 2345; private static final Integer TOKEN_PERIOD = 2345;
private static final Token.Type TOKEN_TYPE = Token.Type.SERVICE; private static final Token.Type TOKEN_TYPE = Token.Type.SERVICE;
private static final String JSON_FULL = "{" + private static final String JSON_FULL = "{" +
"\"name\":\"" + NAME + "\"," + "\"name\":\"" + NAME + "\"," +
"\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," + "\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," +
"\"allowed_policies_glob\":[\"" + ALLOWED_POLICY_GLOB_1 + "\",\"" + ALLOWED_POLICY_GLOB_2 + "\",\"" + ALLOWED_POLICY_GLOB_3 + "\"]," + "\"allowed_policies_glob\":[\"" + ALLOWED_POLICY_GLOB_1 + "\",\"" + ALLOWED_POLICY_GLOB_2 + "\",\"" + ALLOWED_POLICY_GLOB_3 + "\"]," +
"\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," + "\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," +
"\"disallowed_policies_glob\":[\"" + DISALLOWED_POLICY_GLOB_1 + "\",\"" + DISALLOWED_POLICY_GLOB_2 + "\",\"" + DISALLOWED_POLICY_GLOB_3 + "\"]," + "\"disallowed_policies_glob\":[\"" + DISALLOWED_POLICY_GLOB_1 + "\",\"" + DISALLOWED_POLICY_GLOB_2 + "\",\"" + DISALLOWED_POLICY_GLOB_3 + "\"]," +
"\"orphan\":" + ORPHAN + "," + "\"orphan\":" + ORPHAN + "," +
"\"renewable\":" + RENEWABLE + "," + "\"renewable\":" + RENEWABLE + "," +
"\"path_suffix\":\"" + PATH_SUFFIX + "\"," + "\"path_suffix\":\"" + PATH_SUFFIX + "\"," +
"\"allowed_entity_aliases\":[\"" + ALLOWED_ENTITY_ALIAS_1 + "\",\"" + ALLOWED_ENTITY_ALIAS_3 + "\",\"" + ALLOWED_ENTITY_ALIAS_2 + "\"]," + "\"allowed_entity_aliases\":[\"" + ALLOWED_ENTITY_ALIAS_1 + "\",\"" + ALLOWED_ENTITY_ALIAS_3 + "\",\"" + ALLOWED_ENTITY_ALIAS_2 + "\"]," +
"\"token_bound_cidrs\":[\"" + TOKEN_BOUND_CIDR_3 + "\",\"" + TOKEN_BOUND_CIDR_2 + "\",\"" + TOKEN_BOUND_CIDR_1 + "\"]," + "\"token_bound_cidrs\":[\"" + TOKEN_BOUND_CIDR_3 + "\",\"" + TOKEN_BOUND_CIDR_2 + "\",\"" + TOKEN_BOUND_CIDR_1 + "\"]," +
"\"token_explicit_max_ttl\":" + TOKEN_EXPLICIT_MAX_TTL + "," + "\"token_explicit_max_ttl\":" + TOKEN_EXPLICIT_MAX_TTL + "," +
"\"token_no_default_policy\":" + TOKEN_NO_DEFAULT_POLICY + "," + "\"token_no_default_policy\":" + TOKEN_NO_DEFAULT_POLICY + "," +
"\"token_num_uses\":" + TOKEN_NUM_USES + "," + "\"token_num_uses\":" + TOKEN_NUM_USES + "," +
"\"token_period\":" + TOKEN_PERIOD + "," + "\"token_period\":" + TOKEN_PERIOD + "," +
"\"token_type\":\"" + TOKEN_TYPE.value() + "\"}"; "\"token_type\":\"" + TOKEN_TYPE.value() + "\"}";
TokenRoleTest() { TokenRoleTest() {
super(TokenRole.class); super(TokenRole.class);
@@ -89,28 +89,28 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
@Override @Override
protected TokenRole createFull() { protected TokenRole createFull() {
return TokenRole.builder() return TokenRole.builder()
.forName(NAME) .forName(NAME)
.withAllowedPolicies(ALLOWED_POLICIES) .withAllowedPolicies(ALLOWED_POLICIES)
.withAllowedPolicy(ALLOWED_POLICY_3) .withAllowedPolicy(ALLOWED_POLICY_3)
.withAllowedPolicyGlob(ALLOWED_POLICY_GLOB_1) .withAllowedPolicyGlob(ALLOWED_POLICY_GLOB_1)
.withAllowedPoliciesGlob(ALLOWED_POLICIES_GLOB) .withAllowedPoliciesGlob(ALLOWED_POLICIES_GLOB)
.withDisallowedPolicy(DISALLOWED_POLICY_1) .withDisallowedPolicy(DISALLOWED_POLICY_1)
.withDisallowedPolicies(DISALLOWED_POLICIES) .withDisallowedPolicies(DISALLOWED_POLICIES)
.withDisallowedPoliciesGlob(DISALLOWED_POLICIES_GLOB) .withDisallowedPoliciesGlob(DISALLOWED_POLICIES_GLOB)
.withDisallowedPolicyGlob(DISALLOWED_POLICY_GLOB_3) .withDisallowedPolicyGlob(DISALLOWED_POLICY_GLOB_3)
.orphan(ORPHAN) .orphan(ORPHAN)
.renewable(RENEWABLE) .renewable(RENEWABLE)
.withPathSuffix(PATH_SUFFIX) .withPathSuffix(PATH_SUFFIX)
.withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES) .withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES)
.withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2) .withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2)
.withTokenBoundCidr(TOKEN_BOUND_CIDR_3) .withTokenBoundCidr(TOKEN_BOUND_CIDR_3)
.withTokenBoundCidrs(TOKEN_BOUND_CIDRS) .withTokenBoundCidrs(TOKEN_BOUND_CIDRS)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL) .withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY) .withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES) .withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD) .withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE) .withTokenType(TOKEN_TYPE)
.build(); .build();
} }
/** /**
@@ -141,24 +141,24 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
@Test @Test
void buildNullTest() throws JsonProcessingException { void buildNullTest() throws JsonProcessingException {
TokenRole role = TokenRole.builder() TokenRole role = TokenRole.builder()
.forName(null) .forName(null)
.withAllowedPolicies(null) .withAllowedPolicies(null)
.withAllowedPolicy(null) .withAllowedPolicy(null)
.withDisallowedPolicy(null) .withDisallowedPolicy(null)
.withDisallowedPolicies(null) .withDisallowedPolicies(null)
.orphan(null) .orphan(null)
.renewable(null) .renewable(null)
.withPathSuffix(null) .withPathSuffix(null)
.withAllowedEntityAliases(null) .withAllowedEntityAliases(null)
.withAllowedEntityAlias(null) .withAllowedEntityAlias(null)
.withTokenBoundCidr(null) .withTokenBoundCidr(null)
.withTokenBoundCidrs(null) .withTokenBoundCidrs(null)
.withTokenExplicitMaxTtl(null) .withTokenExplicitMaxTtl(null)
.withTokenNoDefaultPolicy(null) .withTokenNoDefaultPolicy(null)
.withTokenNumUses(null) .withTokenNumUses(null)
.withTokenPeriod(null) .withTokenPeriod(null)
.withTokenType(null) .withTokenType(null)
.build(); .build();
assertNull(role.getAllowedPolicies()); assertNull(role.getAllowedPolicies());
assertNull(role.getDisallowedPolicies()); assertNull(role.getDisallowedPolicies());

View File

@@ -35,8 +35,8 @@ class TokenTest extends AbstractModelTest<Token> {
private static final String DISPLAY_NAME = "display-name"; private static final String DISPLAY_NAME = "display-name";
private static final Boolean NO_PARENT = false; private static final Boolean NO_PARENT = false;
private static final Boolean NO_DEFAULT_POLICY = false; private static final Boolean NO_DEFAULT_POLICY = false;
private static final Integer TTL = 123; private static final Long TTL = 123L;
private static final Integer EXPLICIT_MAX_TTL = 456; private static final Long EXPLICIT_MAX_TTL = 456L;
private static final Integer NUM_USES = 4; private static final Integer NUM_USES = 4;
private static final List<String> POLICIES = new ArrayList<>(); private static final List<String> POLICIES = new ArrayList<>();
private static final String POLICY = "policy"; private static final String POLICY = "policy";
@@ -59,20 +59,20 @@ class TokenTest extends AbstractModelTest<Token> {
@Override @Override
protected Token createFull() { protected Token createFull() {
return Token.builder() return Token.builder()
.withId(ID) .withId(ID)
.withType(Token.Type.SERVICE) .withType(Token.Type.SERVICE)
.withDisplayName(DISPLAY_NAME) .withDisplayName(DISPLAY_NAME)
.withNoParent(NO_PARENT) .withNoParent(NO_PARENT)
.withNoDefaultPolicy(NO_DEFAULT_POLICY) .withNoDefaultPolicy(NO_DEFAULT_POLICY)
.withTtl(TTL) .withTtl(TTL)
.withExplicitMaxTtl(EXPLICIT_MAX_TTL) .withExplicitMaxTtl(EXPLICIT_MAX_TTL)
.withNumUses(NUM_USES) .withNumUses(NUM_USES)
.withPolicies(POLICIES) .withPolicies(POLICIES)
.withMeta(META) .withMeta(META)
.withRenewable(RENEWABLE) .withRenewable(RENEWABLE)
.withPeriod(PERIOD) .withPeriod(PERIOD)
.withEntityAlias(ENTITY_ALIAS) .withEntityAlias(ENTITY_ALIAS)
.build(); .build();
} }
@BeforeAll @BeforeAll
@@ -159,9 +159,9 @@ class TokenTest extends AbstractModelTest<Token> {
assertEquals(1, token.getPolicies().size()); assertEquals(1, token.getPolicies().size());
assertEquals(List.of(POLICY_2), token.getPolicies()); assertEquals(List.of(POLICY_2), token.getPolicies());
token = Token.builder() token = Token.builder()
.withPolicies(POLICY, POLICY_2) .withPolicies(POLICY, POLICY_2)
.withPolicy(POLICY_3) .withPolicy(POLICY_3)
.build(); .build();
assertEquals(3, token.getPolicies().size()); assertEquals(3, token.getPolicies().size());
assertTrue(token.getPolicies().containsAll(List.of(POLICY, POLICY_2, POLICY_3))); assertTrue(token.getPolicies().containsAll(List.of(POLICY, POLICY_2, POLICY_3)));
@@ -171,9 +171,9 @@ class TokenTest extends AbstractModelTest<Token> {
assertEquals(Set.of(META_KEY_2), token.getMeta().keySet()); assertEquals(Set.of(META_KEY_2), token.getMeta().keySet());
assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2)); assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2));
token = Token.builder() token = Token.builder()
.withMeta(META) .withMeta(META)
.withMeta(META_KEY_2, META_VALUE_2) .withMeta(META_KEY_2, META_VALUE_2)
.build(); .build();
assertEquals(2, token.getMeta().size()); assertEquals(2, token.getMeta().size());
assertEquals(META_VALUE, token.getMeta().get(META_KEY)); assertEquals(META_VALUE, token.getMeta().get(META_KEY));
assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2)); assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2));

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import de.stklcode.jvault.connector.model.AppRole; import de.stklcode.jvault.connector.model.AppRole;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -32,34 +31,34 @@ import static org.junit.jupiter.api.Assertions.*;
* @since 0.6.2 * @since 0.6.2
*/ */
class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> { class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
private static final Integer ROLE_TOKEN_TTL = 1200; private static final Long ROLE_TOKEN_TTL = 1200L;
private static final Integer ROLE_TOKEN_MAX_TTL = 1800; private static final Long ROLE_TOKEN_MAX_TTL = 1800L;
private static final Integer ROLE_SECRET_TTL = 600; private static final Long ROLE_SECRET_TTL = 600L;
private static final Integer ROLE_SECRET_NUM_USES = 40; private static final Integer ROLE_SECRET_NUM_USES = 40;
private static final String ROLE_POLICY = "default"; private static final String ROLE_POLICY = "default";
private static final Integer ROLE_PERIOD = 0; private static final Integer ROLE_PERIOD = 0;
private static final Boolean ROLE_BIND_SECRET = true; private static final Boolean ROLE_BIND_SECRET = true;
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"auth\": null,\n" + " \"auth\": null,\n" +
" \"warnings\": null,\n" + " \"warnings\": null,\n" +
" \"wrap_info\": null,\n" + " \"wrap_info\": null,\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"token_ttl\": " + ROLE_TOKEN_TTL + ",\n" + " \"token_ttl\": " + ROLE_TOKEN_TTL + ",\n" +
" \"token_max_ttl\": " + ROLE_TOKEN_MAX_TTL + ",\n" + " \"token_max_ttl\": " + ROLE_TOKEN_MAX_TTL + ",\n" +
" \"secret_id_ttl\": " + ROLE_SECRET_TTL + ",\n" + " \"secret_id_ttl\": " + ROLE_SECRET_TTL + ",\n" +
" \"secret_id_num_uses\": " + ROLE_SECRET_NUM_USES + ",\n" + " \"secret_id_num_uses\": " + ROLE_SECRET_NUM_USES + ",\n" +
" \"token_policies\": [\n" + " \"token_policies\": [\n" +
" \"" + ROLE_POLICY + "\"\n" + " \"" + ROLE_POLICY + "\"\n" +
" ],\n" + " ],\n" +
" \"token_period\": " + ROLE_PERIOD + ",\n" + " \"token_period\": " + ROLE_PERIOD + ",\n" +
" \"bind_secret_id\": " + ROLE_BIND_SECRET + ",\n" + " \"bind_secret_id\": " + ROLE_BIND_SECRET + ",\n" +
" \"bound_cidr_list\": \"\"\n" + " \"bound_cidr_list\": \"\"\n" +
" },\n" + " },\n" +
" \"lease_duration\": 0,\n" + " \"lease_duration\": 0,\n" +
" \"renewable\": false,\n" + " \"renewable\": false,\n" +
" \"lease_id\": \"\"\n" + " \"lease_id\": \"\"\n" +
"}"; "}";
AppRoleResponseTest() { AppRoleResponseTest() {
super(AppRoleResponse.class); super(AppRoleResponse.class);
@@ -67,12 +66,10 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
@Override @Override
protected AppRoleResponse createFull() { protected AppRoleResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, AppRoleResponse.class); () -> objectMapper.readValue(RES_JSON, AppRoleResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -91,8 +88,8 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AppRoleResponse res = assertDoesNotThrow( AppRoleResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, AppRoleResponse.class), () -> objectMapper.readValue(RES_JSON, AppRoleResponse.class),
"AuthResponse deserialization failed" "AuthResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
// Extract role data. // Extract role data.

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import de.stklcode.jvault.connector.model.AuthBackend; import de.stklcode.jvault.connector.model.AuthBackend;
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod; import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
@@ -45,44 +44,44 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
private static final String TK_UUID = "32ea9681-6bd6-6cec-eec3-d11260ba9741"; private static final String TK_UUID = "32ea9681-6bd6-6cec-eec3-d11260ba9741";
private static final String TK_ACCESSOR = "auth_token_ac0dd95a"; private static final String TK_ACCESSOR = "auth_token_ac0dd95a";
private static final String TK_DESCR = "token based credentials"; private static final String TK_DESCR = "token based credentials";
private static final Integer TK_LEASE_TTL = 0; private static final Long TK_LEASE_TTL = 0L;
private static final Boolean TK_FORCE_NO_CACHE = false; private static final Boolean TK_FORCE_NO_CACHE = false;
private static final Integer TK_MAX_LEASE_TTL = 0; private static final Long TK_MAX_LEASE_TTL = 0L;
private static final String TK_TOKEN_TYPE = "default-service"; private static final String TK_TOKEN_TYPE = "default-service";
private static final String TK_RUNNING_PLUGIN_VERSION = "v1.15.3+builtin.vault"; private static final String TK_RUNNING_PLUGIN_VERSION = "v1.15.3+builtin.vault";
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"data\": {" + " \"data\": {" +
" \"" + GH_PATH + "\": {\n" + " \"" + GH_PATH + "\": {\n" +
" \"uuid\": \"" + GH_UUID + "\",\n" + " \"uuid\": \"" + GH_UUID + "\",\n" +
" \"type\": \"" + GH_TYPE + "\",\n" + " \"type\": \"" + GH_TYPE + "\",\n" +
" \"accessor\": \"" + GH_ACCESSOR + "\",\n" + " \"accessor\": \"" + GH_ACCESSOR + "\",\n" +
" \"description\": \"" + GH_DESCR + "\",\n" + " \"description\": \"" + GH_DESCR + "\",\n" +
" \"external_entropy_access\": false,\n" + " \"external_entropy_access\": false,\n" +
" \"local\": false,\n" + " \"local\": false,\n" +
" \"seal_wrap\": false\n" + " \"seal_wrap\": false\n" +
" },\n" + " },\n" +
" \"" + TK_PATH + "\": {\n" + " \"" + TK_PATH + "\": {\n" +
" \"config\": {\n" + " \"config\": {\n" +
" \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" + " \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" +
" \"force_no_cache\": " + TK_FORCE_NO_CACHE + ",\n" + " \"force_no_cache\": " + TK_FORCE_NO_CACHE + ",\n" +
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + ",\n" + " \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + ",\n" +
" \"token_type\": \"" + TK_TOKEN_TYPE + "\"\n" + " \"token_type\": \"" + TK_TOKEN_TYPE + "\"\n" +
" },\n" + " },\n" +
" \"description\": \"" + TK_DESCR + "\",\n" + " \"description\": \"" + TK_DESCR + "\",\n" +
" \"options\": null,\n" + " \"options\": null,\n" +
" \"plugin_version\": \"\",\n" + " \"plugin_version\": \"\",\n" +
" \"running_plugin_version\": \"" + TK_RUNNING_PLUGIN_VERSION + "\",\n" + " \"running_plugin_version\": \"" + TK_RUNNING_PLUGIN_VERSION + "\",\n" +
" \"running_sha256\": \"\",\n" + " \"running_sha256\": \"\",\n" +
" \"type\": \"" + TK_TYPE + "\",\n" + " \"type\": \"" + TK_TYPE + "\",\n" +
" \"uuid\": \"" + TK_UUID + "\",\n" + " \"uuid\": \"" + TK_UUID + "\",\n" +
" \"accessor\": \"" + TK_ACCESSOR + "\",\n" + " \"accessor\": \"" + TK_ACCESSOR + "\",\n" +
" \"external_entropy_access\": false,\n" + " \"external_entropy_access\": false,\n" +
" \"local\": true,\n" + " \"local\": true,\n" +
" \"seal_wrap\": false\n" + " \"seal_wrap\": false\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
"}"; "}";
AuthMethodsResponseTest() { AuthMethodsResponseTest() {
super(AuthMethodsResponse.class); super(AuthMethodsResponse.class);
@@ -90,12 +89,10 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
@Override @Override
protected AuthMethodsResponse createFull() { protected AuthMethodsResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, AuthMethodsResponse.class); () -> objectMapper.readValue(RES_JSON, AuthMethodsResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -114,8 +111,8 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AuthMethodsResponse res = assertDoesNotThrow( AuthMethodsResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, AuthMethodsResponse.class), () -> objectMapper.readValue(RES_JSON, AuthMethodsResponse.class),
"AuthResponse deserialization failed" "AuthResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
// Extract auth data. // Extract auth data.

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import de.stklcode.jvault.connector.model.response.embedded.AuthData; import de.stklcode.jvault.connector.model.response.embedded.AuthData;
import de.stklcode.jvault.connector.model.response.embedded.MfaConstraintAny; import de.stklcode.jvault.connector.model.response.embedded.MfaConstraintAny;
@@ -101,12 +100,10 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
@Override @Override
protected AuthResponse createFull() { protected AuthResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, AuthResponse.class); () -> objectMapper.readValue(RES_JSON, AuthResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
@Test @Test
@@ -122,8 +119,8 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AuthResponse res = assertDoesNotThrow( AuthResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, AuthResponse.class), () -> objectMapper.readValue(RES_JSON, AuthResponse.class),
"AuthResponse deserialization failed" "AuthResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
// Extract auth data. // Extract auth data.

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -32,16 +31,16 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
private static final String VAL_USER = "testUserName"; private static final String VAL_USER = "testUserName";
private static final String VAL_PASS = "5up3r5ecr3tP455"; private static final String VAL_PASS = "5up3r5ecr3tP455";
private static final String JSON = "{\n" + private static final String JSON = "{\n" +
" \"request_id\": \"68315073-6658-e3ff-2da7-67939fb91bbd\",\n" + " \"request_id\": \"68315073-6658-e3ff-2da7-67939fb91bbd\",\n" +
" \"lease_id\": \"\",\n" + " \"lease_id\": \"\",\n" +
" \"lease_duration\": 2764800,\n" + " \"lease_duration\": 2764800,\n" +
" \"renewable\": false,\n" + " \"renewable\": false,\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"username\": \"" + VAL_USER + "\",\n" + " \"username\": \"" + VAL_USER + "\",\n" +
" \"password\": \"" + VAL_PASS + "\"\n" + " \"password\": \"" + VAL_PASS + "\"\n" +
" },\n" + " },\n" +
" \"warnings\": null\n" + " \"warnings\": null\n" +
"}"; "}";
CredentialsResponseTest() { CredentialsResponseTest() {
super(CredentialsResponse.class); super(CredentialsResponse.class);
@@ -49,12 +48,10 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
@Override @Override
protected CredentialsResponse createFull() { protected CredentialsResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(JSON, CredentialsResponse.class); () -> objectMapper.readValue(JSON, CredentialsResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -68,8 +65,8 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
assertNull(res.getPassword(), "Password not present in data map should not return anything"); assertNull(res.getPassword(), "Password not present in data map should not return anything");
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, CredentialsResponse.class), () -> objectMapper.readValue(JSON, CredentialsResponse.class),
"Deserialization of CredentialsResponse failed" "Deserialization of CredentialsResponse failed"
); );
assertEquals(VAL_USER, res.getUsername(), "Incorrect username"); assertEquals(VAL_USER, res.getUsername(), "Incorrect username");
assertEquals(VAL_PASS, res.getPassword(), "Incorrect password"); assertEquals(VAL_PASS, res.getPassword(), "Incorrect password");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -42,12 +41,10 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
@Override @Override
protected ErrorResponse createFull() { protected ErrorResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(JSON, ErrorResponse.class); () -> objectMapper.readValue(JSON, ErrorResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -56,15 +53,15 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
ErrorResponse res = assertDoesNotThrow( ErrorResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, ErrorResponse.class), () -> objectMapper.readValue(JSON, ErrorResponse.class),
"ErrorResponse deserialization failed" "ErrorResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(List.of(ERROR_1, ERROR_2), res.getErrors(), "Unexpected error messages"); assertEquals(List.of(ERROR_1, ERROR_2), res.getErrors(), "Unexpected error messages");
assertEquals( assertEquals(
JSON, JSON,
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "ErrorResponse serialization failed"), assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "ErrorResponse serialization failed"),
"Unexpected JSON string after serialization" "Unexpected JSON string after serialization"
); );
} }
@@ -72,14 +69,14 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
@Test @Test
void testToString() { void testToString() {
ErrorResponse res = assertDoesNotThrow( ErrorResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, ErrorResponse.class), () -> objectMapper.readValue(JSON, ErrorResponse.class),
"ErrorResponse deserialization failed" "ErrorResponse deserialization failed"
); );
assertEquals(ERROR_1, res.toString()); assertEquals(ERROR_1, res.toString());
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON_EMPTY, ErrorResponse.class), () -> objectMapper.readValue(JSON_EMPTY, ErrorResponse.class),
"ErrorResponse deserialization failed with empty list" "ErrorResponse deserialization failed with empty list"
); );
assertEquals("error response", res.toString()); assertEquals("error response", res.toString());

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -45,21 +44,21 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
private static final Boolean ENTERPRISE = false; private static final Boolean ENTERPRISE = false;
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" + " \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" + " \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
" \"version\": \"" + VERSION + "\",\n" + " \"version\": \"" + VERSION + "\",\n" +
" \"server_time_utc\": " + SERVER_TIME_UTC + ",\n" + " \"server_time_utc\": " + SERVER_TIME_UTC + ",\n" +
" \"standby\": " + STANDBY + ",\n" + " \"standby\": " + STANDBY + ",\n" +
" \"sealed\": " + SEALED + ",\n" + " \"sealed\": " + SEALED + ",\n" +
" \"initialized\": " + INITIALIZED + ",\n" + " \"initialized\": " + INITIALIZED + ",\n" +
" \"replication_performance_mode\": \"" + REPL_PERF_MODE + "\",\n" + " \"replication_performance_mode\": \"" + REPL_PERF_MODE + "\",\n" +
" \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" + " \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" +
" \"performance_standby\": " + PERF_STANDBY + ",\n" + " \"performance_standby\": " + PERF_STANDBY + ",\n" +
" \"echo_duration_ms\": " + ECHO_DURATION + ",\n" + " \"echo_duration_ms\": " + ECHO_DURATION + ",\n" +
" \"clock_skew_ms\": " + CLOCK_SKEW + ",\n" + " \"clock_skew_ms\": " + CLOCK_SKEW + ",\n" +
" \"replication_primary_canary_age_ms\": " + REPL_PRIM_CANARY_AGE + ",\n" + " \"replication_primary_canary_age_ms\": " + REPL_PRIM_CANARY_AGE + ",\n" +
" \"enterprise\": " + ENTERPRISE + "\n" + " \"enterprise\": " + ENTERPRISE + "\n" +
"}"; "}";
HealthResponseTest() { HealthResponseTest() {
super(HealthResponse.class); super(HealthResponse.class);
@@ -67,12 +66,10 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
@Override @Override
protected HealthResponse createFull() { protected HealthResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, HealthResponse.class); () -> objectMapper.readValue(RES_JSON, HealthResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -81,8 +78,8 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
HealthResponse res = assertDoesNotThrow( HealthResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, HealthResponse.class), () -> objectMapper.readValue(RES_JSON, HealthResponse.class),
"Health deserialization failed" "Health deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(CLUSTER_ID, res.getClusterID(), "Incorrect cluster ID"); assertEquals(CLUSTER_ID, res.getClusterID(), "Incorrect cluster ID");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -38,12 +37,10 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
@Override @Override
protected HelpResponse createFull() { protected HelpResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(JSON, HelpResponse.class); () -> objectMapper.readValue(JSON, HelpResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -52,15 +49,15 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
HelpResponse res = assertDoesNotThrow( HelpResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, HelpResponse.class), () -> objectMapper.readValue(JSON, HelpResponse.class),
"HelpResponse deserialization failed" "HelpResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(HELP, res.getHelp(), "Unexpected help text"); assertEquals(HELP, res.getHelp(), "Unexpected help text");
assertEquals( assertEquals(
JSON, JSON,
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "HelpResponse serialization failed"), assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "HelpResponse serialization failed"),
"Unexpected JSON string after serialization" "Unexpected JSON string after serialization"
); );
} }
} }

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -47,47 +46,47 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
private static final String CUSTOM_META_VAL = "bar"; private static final String CUSTOM_META_VAL = "bar";
private static final String SECRET_JSON_V2 = "{\n" + private static final String SECRET_JSON_V2 = "{\n" +
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" + " \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" + " \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" + " \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
" \"renewable\": " + SECRET_RENEWABLE + ",\n" + " \"renewable\": " + SECRET_RENEWABLE + ",\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" + " \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" + " \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
" },\n" + " },\n" +
" \"metadata\": {\n" + " \"metadata\": {\n" +
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" + " \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
" \"custom_metadata\": null,\n" + " \"custom_metadata\": null,\n" +
" \"deletion_time\": \"\",\n" + " \"deletion_time\": \"\",\n" +
" \"destroyed\": false,\n" + " \"destroyed\": false,\n" +
" \"version\": 1\n" + " \"version\": 1\n" +
" }\n" + " }\n" +
" },\n" + " },\n" +
" \"warnings\": " + SECRET_WARNINGS + "\n" + " \"warnings\": " + SECRET_WARNINGS + "\n" +
"}"; "}";
private static final String SECRET_JSON_V2_2 = "{\n" + private static final String SECRET_JSON_V2_2 = "{\n" +
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" + " \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" + " \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" + " \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
" \"renewable\": " + SECRET_RENEWABLE + ",\n" + " \"renewable\": " + SECRET_RENEWABLE + ",\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" + " \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" + " \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
" },\n" + " },\n" +
" \"metadata\": {\n" + " \"metadata\": {\n" +
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" + " \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
" \"custom_metadata\": {" + " \"custom_metadata\": {" +
" \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" + " \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" +
" },\n" + " },\n" +
" \"deletion_time\": \"" + SECRET_META_DELETED + "\",\n" + " \"deletion_time\": \"" + SECRET_META_DELETED + "\",\n" +
" \"destroyed\": true,\n" + " \"destroyed\": true,\n" +
" \"version\": 2\n" + " \"version\": 2\n" +
" }\n" + " }\n" +
" },\n" + " },\n" +
" \"warnings\": " + SECRET_WARNINGS + "\n" + " \"warnings\": " + SECRET_WARNINGS + "\n" +
"}"; "}";
MetaSecretResponseTest() { MetaSecretResponseTest() {
super(MetaSecretResponse.class); super(MetaSecretResponse.class);
@@ -95,12 +94,10 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
@Override @Override
protected MetaSecretResponse createFull() { protected MetaSecretResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class); () -> objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -110,8 +107,8 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
void jsonRoundtrip() { void jsonRoundtrip() {
// KV v2 secret. // KV v2 secret.
MetaSecretResponse res = assertDoesNotThrow( MetaSecretResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class), () -> objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertSecretData(res); assertSecretData(res);
assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata"); assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata");
@@ -123,8 +120,8 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
// Deleted KV v2 secret. // Deleted KV v2 secret.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> objectMapper.readValue(SECRET_JSON_V2_2, MetaSecretResponse.class), () -> objectMapper.readValue(SECRET_JSON_V2_2, MetaSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertSecretData(res); assertSecretData(res);
assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata"); assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -43,36 +42,36 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
private static final String DELETE_VERSION_AFTER = "0s"; private static final String DELETE_VERSION_AFTER = "0s";
private static final String META_JSON = "{\n" + private static final String META_JSON = "{\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"cas_required\": " + CAS_REQUIRED + ",\n" + " \"cas_required\": " + CAS_REQUIRED + ",\n" +
" \"created_time\": \"" + V1_TIME + "\",\n" + " \"created_time\": \"" + V1_TIME + "\",\n" +
" \"current_version\": " + CURRENT_VERSION + ",\n" + " \"current_version\": " + CURRENT_VERSION + ",\n" +
" \"custom_metadata\": {" + " \"custom_metadata\": {" +
" \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" + " \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" +
" },\n" + " },\n" +
" \"delete_version_after\": \"" + DELETE_VERSION_AFTER + "\"," + " \"delete_version_after\": \"" + DELETE_VERSION_AFTER + "\"," +
" \"max_versions\": " + MAX_VERSIONS + ",\n" + " \"max_versions\": " + MAX_VERSIONS + ",\n" +
" \"oldest_version\": " + OLDEST_VERSION + ",\n" + " \"oldest_version\": " + OLDEST_VERSION + ",\n" +
" \"updated_time\": \"" + V3_TIME + "\",\n" + " \"updated_time\": \"" + V3_TIME + "\",\n" +
" \"versions\": {\n" + " \"versions\": {\n" +
" \"1\": {\n" + " \"1\": {\n" +
" \"created_time\": \"" + V1_TIME + "\",\n" + " \"created_time\": \"" + V1_TIME + "\",\n" +
" \"deletion_time\": \"" + V2_TIME + "\",\n" + " \"deletion_time\": \"" + V2_TIME + "\",\n" +
" \"destroyed\": true\n" + " \"destroyed\": true\n" +
" },\n" + " },\n" +
" \"2\": {\n" + " \"2\": {\n" +
" \"created_time\": \"" + V2_TIME + "\",\n" + " \"created_time\": \"" + V2_TIME + "\",\n" +
" \"deletion_time\": \"\",\n" + " \"deletion_time\": \"\",\n" +
" \"destroyed\": false\n" + " \"destroyed\": false\n" +
" },\n" + " },\n" +
" \"3\": {\n" + " \"3\": {\n" +
" \"created_time\": \"" + V3_TIME + "\",\n" + " \"created_time\": \"" + V3_TIME + "\",\n" +
" \"deletion_time\": \"\",\n" + " \"deletion_time\": \"\",\n" +
" \"destroyed\": false\n" + " \"destroyed\": false\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
"}"; "}";
MetadataResponseTest() { MetadataResponseTest() {
super(MetadataResponse.class); super(MetadataResponse.class);
@@ -80,12 +79,10 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
@Override @Override
protected MetadataResponse createFull() { protected MetadataResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(META_JSON, MetadataResponse.class); () -> objectMapper.readValue(META_JSON, MetadataResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -94,8 +91,8 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
MetadataResponse res = assertDoesNotThrow( MetadataResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(META_JSON, MetadataResponse.class), () -> objectMapper.readValue(META_JSON, MetadataResponse.class),
"MetadataResponse deserialization failed" "MetadataResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertNotNull(res.getMetadata(), "Parsed metadata is NULL"); assertNotNull(res.getMetadata(), "Parsed metadata is NULL");

View File

@@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -43,16 +42,16 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
private static final String SECRET_DATA_V2 = "world"; private static final String SECRET_DATA_V2 = "world";
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" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" + " \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" + " \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
" \"renewable\": " + SECRET_RENEWABLE + ",\n" + " \"renewable\": " + SECRET_RENEWABLE + ",\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" + " \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" + " \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
" },\n" + " },\n" +
" \"warnings\": " + SECRET_WARNINGS + "\n" + " \"warnings\": " + SECRET_WARNINGS + "\n" +
"}"; "}";
PlainSecretResponseTest() { PlainSecretResponseTest() {
super(PlainSecretResponse.class); super(PlainSecretResponse.class);
@@ -60,12 +59,10 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
@Override @Override
protected PlainSecretResponse createFull() { protected PlainSecretResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class); () -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -74,8 +71,8 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class), () -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
@@ -106,74 +103,74 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
final var complexVal = new ComplexType("val1", 678); final var complexVal = new ComplexType("val1", 678);
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> objectMapper.readValue( () -> objectMapper.readValue(
"{\n" + "{\n" +
" \"request_id\": \"req-id\",\n" + " \"request_id\": \"req-id\",\n" +
" \"lease_id\": \"lea-id\",\n" + " \"lease_id\": \"lea-id\",\n" +
" \"lease_duration\": " + 123456 + ",\n" + " \"lease_duration\": " + 123456 + ",\n" +
" \"renewable\": true,\n" + " \"renewable\": true,\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"" + stringKey + "\": \"" + stringVal + "\",\n" + " \"" + stringKey + "\": \"" + stringVal + "\",\n" +
" \"" + numberKey + "\": \"" + numberVal + "\",\n" + " \"" + numberKey + "\": \"" + numberVal + "\",\n" +
" \"" + listKey + "\": [\"" + String.join("\", \"", listVal) + "\"],\n" + " \"" + listKey + "\": [\"" + String.join("\", \"", listVal) + "\"],\n" +
" \"" + complexKey + "\": {" + " \"" + complexKey + "\": {" +
" \"field1\": \"" + complexVal.field1 + "\",\n" + " \"field1\": \"" + complexVal.field1 + "\",\n" +
" \"field2\": " + complexVal.field2 + "\n" + " \"field2\": " + complexVal.field2 + "\n" +
" },\n" + " },\n" +
" \"" + complexKey + "Json\": \"" + objectMapper.writeValueAsString(complexVal).replace("\"", "\\\"") + "\"\n" + " \"" + complexKey + "Json\": \"" + objectMapper.writeValueAsString(complexVal).replace("\"", "\\\"") + "\"\n" +
" }\n" + " }\n" +
"}", "}",
PlainSecretResponse.class PlainSecretResponse.class
), ),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertEquals(stringVal, res.get(stringKey), "unexpected value for string (implicit)"); assertEquals(stringVal, res.get(stringKey), "unexpected value for string (implicit)");
assertEquals( assertEquals(
stringVal, stringVal,
assertDoesNotThrow(() -> res.get(stringKey, String.class), "getting string failed"), assertDoesNotThrow(() -> res.get(stringKey, String.class), "getting string failed"),
"unexpected value for string (explicit)" "unexpected value for string (explicit)"
); );
assertEquals(String.valueOf(numberVal), res.get(numberKey), "unexpected value for number (implicit)"); assertEquals(String.valueOf(numberVal), res.get(numberKey), "unexpected value for number (implicit)");
assertEquals( assertEquals(
numberVal, numberVal,
assertDoesNotThrow(() -> res.get(numberKey, Double.class), "getting number failed"), assertDoesNotThrow(() -> res.get(numberKey, Double.class), "getting number failed"),
"unexpected value for number (explicit)" "unexpected value for number (explicit)"
); );
assertEquals( assertEquals(
String.valueOf(numberVal), String.valueOf(numberVal),
assertDoesNotThrow(() -> res.get(numberKey, String.class), "getting number as string failed"), assertDoesNotThrow(() -> res.get(numberKey, String.class), "getting number as string failed"),
"unexpected value for number as string (explicit)" "unexpected value for number as string (explicit)"
); );
assertEquals(listVal, res.get(listKey), "unexpected value for list (implicit)"); assertEquals(listVal, res.get(listKey), "unexpected value for list (implicit)");
assertEquals( assertEquals(
listVal, listVal,
assertDoesNotThrow(() -> res.get(listKey, ArrayList.class), "getting list failed"), assertDoesNotThrow(() -> res.get(listKey, ArrayList.class), "getting list failed"),
"unexpected value for list (explicit)" "unexpected value for list (explicit)"
); );
assertEquals(complexVal.toMap(), res.get(complexKey), "unexpected value for complex type (implicit)"); assertEquals(complexVal.toMap(), res.get(complexKey), "unexpected value for complex type (implicit)");
assertEquals( assertEquals(
complexVal.toMap(), complexVal.toMap(),
assertDoesNotThrow(() -> res.get(complexKey, HashMap.class), "getting complex type as map failed"), assertDoesNotThrow(() -> res.get(complexKey, HashMap.class), "getting complex type as map failed"),
"unexpected value for complex type as map (explicit)" "unexpected value for complex type as map (explicit)"
); );
assertEquals( assertEquals(
complexVal, complexVal,
assertDoesNotThrow(() -> res.get(complexKey, ComplexType.class), "getting complex type failed"), assertDoesNotThrow(() -> res.get(complexKey, ComplexType.class), "getting complex type failed"),
"unexpected value for complex type (explicit)" "unexpected value for complex type (explicit)"
); );
assertThrows( assertThrows(
InvalidResponseException.class, InvalidResponseException.class,
() -> res.get(complexKey, Integer.class), () -> res.get(complexKey, Integer.class),
"getting complex type as integer should fail" "getting complex type as integer should fail"
); );
assertEquals( assertEquals(
complexVal, complexVal,
assertDoesNotThrow(() -> res.get(complexKey + "Json", ComplexType.class), "getting complex type from JSON string failed"), assertDoesNotThrow(() -> res.get(complexKey + "Json", ComplexType.class), "getting complex type from JSON string failed"),
"unexpected value for complex type from JSON string" "unexpected value for complex type from JSON string"
); );
} }
@@ -199,8 +196,8 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
private Map<String, Object> toMap() { private Map<String, Object> toMap() {
return Map.of( return Map.of(
"field1", field1, "field1", field1,
"field2", field2 "field2", field2
); );
} }

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -46,36 +45,36 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
private static final String STORAGE_TYPE = "file"; private static final String STORAGE_TYPE = "file";
private static final String RES_SEALED = "{\n" + private static final String RES_SEALED = "{\n" +
" \"type\": \"" + TYPE + "\",\n" + " \"type\": \"" + TYPE + "\",\n" +
" \"sealed\": true,\n" + " \"sealed\": true,\n" +
" \"initialized\": true,\n" + " \"initialized\": true,\n" +
" \"t\": " + THRESHOLD + ",\n" + " \"t\": " + THRESHOLD + ",\n" +
" \"n\": " + SHARES + ",\n" + " \"n\": " + SHARES + ",\n" +
" \"progress\": " + PROGRESS_SEALED + ",\n" + " \"progress\": " + PROGRESS_SEALED + ",\n" +
" \"nonce\": \"\",\n" + " \"nonce\": \"\",\n" +
" \"version\": \"" + VERSION + "\",\n" + " \"version\": \"" + VERSION + "\",\n" +
" \"build_date\": \"" + BUILD_DATE + "\",\n" + " \"build_date\": \"" + BUILD_DATE + "\",\n" +
" \"migration\": \"" + MIGRATION + "\",\n" + " \"migration\": \"" + MIGRATION + "\",\n" +
" \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" + " \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" +
" \"storage_type\": \"" + STORAGE_TYPE + "\"\n" + " \"storage_type\": \"" + STORAGE_TYPE + "\"\n" +
"}"; "}";
private static final String RES_UNSEALED = "{\n" + private static final String RES_UNSEALED = "{\n" +
" \"type\": \"" + TYPE + "\",\n" + " \"type\": \"" + TYPE + "\",\n" +
" \"sealed\": false,\n" + " \"sealed\": false,\n" +
" \"initialized\": true,\n" + " \"initialized\": true,\n" +
" \"t\": " + THRESHOLD + ",\n" + " \"t\": " + THRESHOLD + ",\n" +
" \"n\": " + SHARES + ",\n" + " \"n\": " + SHARES + ",\n" +
" \"progress\": " + PROGRESS_UNSEALED + ",\n" + " \"progress\": " + PROGRESS_UNSEALED + ",\n" +
" \"version\": \"" + VERSION + "\",\n" + " \"version\": \"" + VERSION + "\",\n" +
" \"build_date\": \"" + BUILD_DATE + "\",\n" + " \"build_date\": \"" + BUILD_DATE + "\",\n" +
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" + " \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" + " \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
" \"nonce\": \"" + NONCE + "\",\n" + " \"nonce\": \"" + NONCE + "\",\n" +
" \"migration\": \"" + MIGRATION + "\",\n" + " \"migration\": \"" + MIGRATION + "\",\n" +
" \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" + " \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" +
" \"storage_type\": \"" + STORAGE_TYPE + "\"\n" + " \"storage_type\": \"" + STORAGE_TYPE + "\"\n" +
"}"; "}";
SealResponseTest() { SealResponseTest() {
super(SealResponse.class); super(SealResponse.class);
@@ -83,12 +82,10 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
@Override @Override
protected SealResponse createFull() { protected SealResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_UNSEALED, SealResponse.class); () -> objectMapper.readValue(RES_UNSEALED, SealResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -98,8 +95,8 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
void jsonRoundtripSealed() { void jsonRoundtripSealed() {
// First test sealed Vault's response. // First test sealed Vault's response.
SealResponse res = assertDoesNotThrow( SealResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_SEALED, SealResponse.class), () -> objectMapper.readValue(RES_SEALED, SealResponse.class),
"SealResponse deserialization failed" "SealResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(TYPE, res.getType(), "Incorrect seal type"); assertEquals(TYPE, res.getType(), "Incorrect seal type");
@@ -121,8 +118,8 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
// Not test unsealed Vault's response. // Not test unsealed Vault's response.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_UNSEALED, SealResponse.class), () -> objectMapper.readValue(RES_UNSEALED, SealResponse.class),
"SealResponse deserialization failed" "SealResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(TYPE, res.getType(), "Incorrect seal type"); assertEquals(TYPE, res.getType(), "Incorrect seal type");

View File

@@ -16,13 +16,13 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* JUnit Test for {@link SecretListResponse} model. * JUnit Test for {@link SecretListResponse} model.
@@ -34,17 +34,17 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
private static final String KEY1 = "key1"; private static final String KEY1 = "key1";
private static final String KEY2 = "key-2"; private static final String KEY2 = "key-2";
private static final String JSON = "{\n" + private static final String JSON = "{\n" +
" \"auth\": null,\n" + " \"auth\": null,\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"keys\": [" + " \"keys\": [" +
" \"" + KEY1 + "\",\n" + " \"" + KEY1 + "\",\n" +
" \"" + KEY2 + "\"\n" + " \"" + KEY2 + "\"\n" +
" ]\n" + " ]\n" +
" },\n" + " },\n" +
" \"lease_duration\": 2764800,\n" + " \"lease_duration\": 2764800,\n" +
" \"lease_id\": \"\",\n" + " \"lease_id\": \"\",\n" +
" \"renewable\": false\n" + " \"renewable\": false\n" +
"}"; "}";
SecretListResponseTest() { SecretListResponseTest() {
super(SecretListResponse.class); super(SecretListResponse.class);
@@ -52,12 +52,10 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
@Override @Override
protected SecretListResponse createFull() { protected SecretListResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(JSON, SecretListResponse.class); () -> objectMapper.readValue(JSON, SecretListResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -66,8 +64,8 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
@Test @Test
void getKeysTest() { void getKeysTest() {
SecretListResponse res = assertDoesNotThrow( SecretListResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, SecretListResponse.class), () -> objectMapper.readValue(JSON, SecretListResponse.class),
"SecretListResponse deserialization failed" "SecretListResponse deserialization failed"
); );
assertEquals(List.of(KEY1, KEY2), res.getKeys(), "Unexpected secret keys"); assertEquals(List.of(KEY1, KEY2), res.getKeys(), "Unexpected secret keys");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -34,13 +33,13 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
private static final Integer VERSION = 42; private static final Integer VERSION = 42;
private static final String META_JSON = "{\n" + private static final String META_JSON = "{\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"created_time\": \"" + CREATION_TIME + "\",\n" + " \"created_time\": \"" + CREATION_TIME + "\",\n" +
" \"deletion_time\": \"" + DELETION_TIME + "\",\n" + " \"deletion_time\": \"" + DELETION_TIME + "\",\n" +
" \"destroyed\": false,\n" + " \"destroyed\": false,\n" +
" \"version\": " + VERSION + "\n" + " \"version\": " + VERSION + "\n" +
" }\n" + " }\n" +
"}"; "}";
SecretVersionResponseTest() { SecretVersionResponseTest() {
super(SecretVersionResponse.class); super(SecretVersionResponse.class);
@@ -48,12 +47,10 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
@Override @Override
protected SecretVersionResponse createFull() { protected SecretVersionResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(META_JSON, SecretVersionResponse.class); () -> objectMapper.readValue(META_JSON, SecretVersionResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -62,8 +59,8 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
SecretVersionResponse res = assertDoesNotThrow( SecretVersionResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(META_JSON, SecretVersionResponse.class), () -> objectMapper.readValue(META_JSON, SecretVersionResponse.class),
"SecretVersionResponse deserialization failed" "SecretVersionResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertNotNull(res.getMetadata(), "Parsed metadata is NULL"); assertNotNull(res.getMetadata(), "Parsed metadata is NULL");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import de.stklcode.jvault.connector.model.response.embedded.TokenData; import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -35,8 +34,8 @@ import static org.junit.jupiter.api.Assertions.*;
*/ */
class TokenResponseTest extends AbstractModelTest<TokenResponse> { class TokenResponseTest extends AbstractModelTest<TokenResponse> {
private static final Integer TOKEN_CREATION_TIME = 1457533232; private static final Integer TOKEN_CREATION_TIME = 1457533232;
private static final Integer TOKEN_TTL = 2764800; private static final Long TOKEN_TTL = 2764800L;
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 0; private static final Long TOKEN_EXPLICIT_MAX_TTL = 0L;
private static final String TOKEN_DISPLAY_NAME = "token"; private static final String TOKEN_DISPLAY_NAME = "token";
private static final String TOKEN_META_KEY = "foo"; private static final String TOKEN_META_KEY = "foo";
private static final String TOKEN_META_VALUE = "bar"; private static final String TOKEN_META_VALUE = "bar";
@@ -47,7 +46,7 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
private static final String TOKEN_POLICY_1 = "default"; private static final String TOKEN_POLICY_1 = "default";
private static final String TOKEN_POLICY_2 = "web"; private static final String TOKEN_POLICY_2 = "web";
private static final Boolean RES_RENEWABLE = false; private static final Boolean RES_RENEWABLE = false;
private static final Integer RES_TTL = 2591976; private static final Long RES_TTL = 2591976L;
private static final Integer RES_LEASE_DURATION = 0; private static final Integer RES_LEASE_DURATION = 0;
private static final String TOKEN_ACCESSOR = "VKvzT2fKHFsZFUus9LyoXCvu"; private static final String TOKEN_ACCESSOR = "VKvzT2fKHFsZFUus9LyoXCvu";
private static final String TOKEN_ENTITY_ID = "7d2e3179-f69b-450c-7179-ac8ee8bd8ca9"; private static final String TOKEN_ENTITY_ID = "7d2e3179-f69b-450c-7179-ac8ee8bd8ca9";
@@ -58,37 +57,37 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
private static final String MOUNT_TYPE = "token"; private static final String MOUNT_TYPE = "token";
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"lease_id\": \"\",\n" + " \"lease_id\": \"\",\n" +
" \"renewable\": " + RES_RENEWABLE + ",\n" + " \"renewable\": " + RES_RENEWABLE + ",\n" +
" \"lease_duration\": " + RES_LEASE_DURATION + ",\n" + " \"lease_duration\": " + RES_LEASE_DURATION + ",\n" +
" \"data\": {\n" + " \"data\": {\n" +
" \"accessor\": \"" + TOKEN_ACCESSOR + "\",\n" + " \"accessor\": \"" + TOKEN_ACCESSOR + "\",\n" +
" \"creation_time\": " + TOKEN_CREATION_TIME + ",\n" + " \"creation_time\": " + TOKEN_CREATION_TIME + ",\n" +
" \"creation_ttl\": " + TOKEN_TTL + ",\n" + " \"creation_ttl\": " + TOKEN_TTL + ",\n" +
" \"display_name\": \"" + TOKEN_DISPLAY_NAME + "\",\n" + " \"display_name\": \"" + TOKEN_DISPLAY_NAME + "\",\n" +
" \"entity_id\": \"" + TOKEN_ENTITY_ID + "\",\n" + " \"entity_id\": \"" + TOKEN_ENTITY_ID + "\",\n" +
" \"expire_time\": \"" + TOKEN_EXPIRE_TIME + "\",\n" + " \"expire_time\": \"" + TOKEN_EXPIRE_TIME + "\",\n" +
" \"explicit_max_ttl\": \"" + TOKEN_EXPLICIT_MAX_TTL + "\",\n" + " \"explicit_max_ttl\": \"" + TOKEN_EXPLICIT_MAX_TTL + "\",\n" +
" \"id\": \"" + TOKEN_ID + "\",\n" + " \"id\": \"" + TOKEN_ID + "\",\n" +
" \"issue_time\": \"" + TOKEN_ISSUE_TIME + "\",\n" + " \"issue_time\": \"" + TOKEN_ISSUE_TIME + "\",\n" +
" \"meta\": {\n" + " \"meta\": {\n" +
" \"" + TOKEN_META_KEY + "\": \"" + TOKEN_META_VALUE + "\"\n" + " \"" + TOKEN_META_KEY + "\": \"" + TOKEN_META_VALUE + "\"\n" +
" },\n" + " },\n" +
" \"num_uses\": " + TOKEN_NUM_USES + ",\n" + " \"num_uses\": " + TOKEN_NUM_USES + ",\n" +
" \"orphan\": " + TOKEN_ORPHAN + ",\n" + " \"orphan\": " + TOKEN_ORPHAN + ",\n" +
" \"path\": \"" + TOKEN_PATH + "\",\n" + " \"path\": \"" + TOKEN_PATH + "\",\n" +
" \"policies\": [\n" + " \"policies\": [\n" +
" \"" + TOKEN_POLICY_1 + "\", \n" + " \"" + TOKEN_POLICY_1 + "\", \n" +
" \"" + TOKEN_POLICY_2 + "\"\n" + " \"" + TOKEN_POLICY_2 + "\"\n" +
" ],\n" + " ],\n" +
" \"renewable\": " + TOKEN_RENEWABLE + ",\n" + " \"renewable\": " + TOKEN_RENEWABLE + ",\n" +
" \"ttl\": " + RES_TTL + ",\n" + " \"ttl\": " + RES_TTL + ",\n" +
" \"type\": \"" + TOKEN_TYPE + "\"\n" + " \"type\": \"" + TOKEN_TYPE + "\"\n" +
" },\n" + " },\n" +
" \"warnings\": null,\n" + " \"warnings\": null,\n" +
" \"auth\": null,\n" + " \"auth\": null,\n" +
" \"mount_type\": \"" + MOUNT_TYPE + "\"\n" + " \"mount_type\": \"" + MOUNT_TYPE + "\"\n" +
"}"; "}";
TokenResponseTest() { TokenResponseTest() {
super(TokenResponse.class); super(TokenResponse.class);
@@ -96,12 +95,10 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
@Override @Override
protected TokenResponse createFull() { protected TokenResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, TokenResponse.class); () -> objectMapper.readValue(RES_JSON, TokenResponse.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**
@@ -120,8 +117,8 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
TokenResponse res = assertDoesNotThrow( TokenResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, TokenResponse.class), () -> objectMapper.readValue(RES_JSON, TokenResponse.class),
"TokenResponse deserialization failed" "TokenResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(RES_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration"); assertEquals(RES_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration");

View File

@@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -39,19 +38,17 @@ class TransitResponseTest extends AbstractModelTest<TransitResponse> {
@Override @Override
protected TransitResponse createFull() { protected TransitResponse createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue( () -> objectMapper.readValue(
json( json(
"\"ciphertext\": \"" + CIPHERTEXT + "\", " + "\"ciphertext\": \"" + CIPHERTEXT + "\", " +
"\"plaintext\": \"" + PLAINTEXT + "\", " + "\"plaintext\": \"" + PLAINTEXT + "\", " +
"\"sum\": \"" + SUM + "\"" "\"sum\": \"" + SUM + "\""
), ),
TransitResponse.class TransitResponse.class
); ),
} catch (JsonProcessingException e) { "Creation of full model failed"
fail("Creation of full model failed", e); );
return null;
}
} }
@Test @Test

View File

@@ -1,6 +1,5 @@
package de.stklcode.jvault.connector.model.response.embedded; package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -14,8 +13,8 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
*/ */
class MountConfigTest extends AbstractModelTest<MountConfig> { class MountConfigTest extends AbstractModelTest<MountConfig> {
private static final Integer DEFAULT_LEASE_TTL = 1800; private static final Long DEFAULT_LEASE_TTL = 1800L;
private static final Integer MAX_LEASE_TTL = 3600; private static final Long MAX_LEASE_TTL = 3600L;
private static final Boolean FORCE_NO_CACHE = false; private static final Boolean FORCE_NO_CACHE = false;
private static final String TOKEN_TYPE = "default-service"; private static final String TOKEN_TYPE = "default-service";
private static final String AUDIT_NON_HMAC_REQ_KEYS_1 = "req1"; private static final String AUDIT_NON_HMAC_REQ_KEYS_1 = "req1";
@@ -62,12 +61,10 @@ class MountConfigTest extends AbstractModelTest<MountConfig> {
@Override @Override
protected MountConfig createFull() { protected MountConfig createFull() {
try { return assertDoesNotThrow(
return objectMapper.readValue(RES_JSON, MountConfig.class); () -> objectMapper.readValue(RES_JSON, MountConfig.class),
} catch (JsonProcessingException e) { "Creation of full model instance failed"
fail("Creation of full model instance failed", e); );
return null;
}
} }
/** /**

View File

@@ -93,14 +93,14 @@ public class VaultConfiguration {
@Override @Override
public String toString() { public String toString() {
return "storage \"file\" {\n" + return "storage \"file\" {\n" +
" path = \"" + dataLocation + "\"\n" + " path = \"" + dataLocation + "\"\n" +
"}\n" + "}\n" +
"listener \"tcp\" {\n" + "listener \"tcp\" {\n" +
" address = \"" + host + ":" + port + "\"\n" + " address = \"" + host + ":" + port + "\"\n" +
((disableTLS) ? " tls_disable = 1\n" : "") + ((disableTLS) ? " tls_disable = 1\n" : "") +
((certFile != null) ? " tls_cert_file = \"" + certFile + "\"\n" : "") + ((certFile != null) ? " tls_cert_file = \"" + certFile + "\"\n" : "") +
((keyFile != null) ? " tls_key_file = \"" + keyFile + "\"\n" : "") + ((keyFile != null) ? " tls_key_file = \"" + keyFile + "\"\n" : "") +
"}\n" + "}\n" +
((disableMlock) ? "disable_mlock = true" : ""); ((disableMlock) ? "disable_mlock = true" : "");
} }
} }