56 Commits

Author SHA1 Message Date
7bcd57691c prepare release of v1.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-11 17:44:00 +01:00
531111cb2b test against Vault 1.15.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-11 17:41:31 +01:00
151b58dc82 model: add "build_date" to SealResponse (#73)
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-03 15:11:10 +01:00
65fb01617d model: extend AuthMethod model and embedded config (#72)
Introduce MountConfig and UserLockoutConfig models and add some missing
fields to AuthMethod.
2023-12-03 15:09:45 +01:00
097cb5415a re-generate serial version of AuthData class
All checks were successful
continuous-integration/drone/push Build is passing
Fixes: 2dff8930b7
2023-12-03 15:09:12 +01:00
2dff8930b7 model: add MFA requirement data to auth response (#71)
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-03 14:44:15 +01:00
d82554974c test against Vault 1.15.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-03 10:39:09 +01:00
8352d04c52 deps: update test dependencies
* commons-io 2.15.1
* dependency-check-maven 9.0.2
* equalsverifier 3.15.4
* mockito-core 5.8.0
2023-12-03 10:33:44 +01:00
56d5345fcb ci: run coverage analysis with JDK 21
All checks were successful
continuous-integration/drone/push Build is passing
The JDK 21 build with Vault 1.11 seems to be the only job with full
coverage on conditional code.
2023-11-26 11:36:23 +01:00
52876ef3a4 close HTTPClient when running with JDK21 or newer (#70)
The Java HTTP client implements AutoCloseable since JDK 21. Closing the
client ensures that asynchronous operations and streams are properly
terminated.

As we support Java 11, we add any old school "finally" wrapper and
conditionally close the client when running on a modern platform.
2023-11-26 11:33:28 +01:00
62f2249a4d remove redundant java.base requirement from module-info.java (#69)
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-26 11:08:06 +01:00
10965b01d6 Merge branch 'main' into develop
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-26 11:04:17 +01:00
0f302af3e7 deps: update dependency-check-maven plugin to 9.0.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-26 10:57:53 +01:00
02ae647002 deps: update jackson to 2.16.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-16 18:35:15 +01:00
1d9e1458be deps: update test dependencies and Maven plugins 2023-11-16 18:25:37 +01:00
683052a804 add basic .editorconfig
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-23 18:24:22 +02:00
cc290f4def deps: update test dependencies and Maven plugins
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-23 18:18:24 +02:00
2722a125e5 deps: update jackson to 2.15.3 2023-10-23 18:17:41 +02:00
5e5143168e ci: build and test with JDK 21
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-15 17:10:38 +02:00
08e8c9f090 test against Vault 1.15.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-09-27 20:18:34 +02:00
c06cb9b0fb deps: update test dependencies
All checks were successful
continuous-integration/drone/push Build is passing
* Wiremock 3
* Mockito 5.5
2023-09-08 20:41:37 +02:00
505d420fd6 Merge branch 'main' into develop
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-19 11:47:05 +02:00
be23129441 prepare release of v1.1.5
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-19 11:10:57 +02:00
199dfd30ca update test dependencies and plugins
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-19 11:06:43 +02:00
b72298f2a8 bump Vault versions in integration tests to 1.14.0 and 1.11.12
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-23 17:43:22 +02:00
226b6ad6c4 split lines above 120 characters
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-17 15:17:06 +02:00
d81fc4e5af reorder members and elements to comply with language recommendations 2023-06-17 15:23:49 +02:00
1195b447a2 fix regression from redundant String mapping in SecretResponse getter
All checks were successful
continuous-integration/drone/push Build is passing
Mapping a JSON string into String using a JSON parser will fail, so we
should use the string directly instead of applying double conversion.

Fixes: f3e1f01e38
2023-06-16 18:18:55 +02:00
f3e1f01e38 fix type conversion in SecretResponse getter method (#67)
Some checks failed
continuous-integration/drone/push Build is failing
Converting the payload using toString() is not an appropriate way to
feed a JSON parser. We now use JSON roundtrip for type mapping and
introduce shortcuts of the type already matches the target type.
2023-06-16 17:43:30 +02:00
622b13f508 prepare release of v1.1.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-15 18:08:24 +02:00
0f0b008f2f bump Vault versions in integration tests to 1.13.3 and 1.11.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-15 18:03:59 +02:00
34322b389c fix timezone pattern in datetime parsing 2023-06-15 17:58:41 +02:00
7e5d193d1b parse timestamps as ZonedDateTime internally
All checks were successful
continuous-integration/drone/push Build is passing
Timestamps have been stored with their String representation from the
API with convenience methods to convert them into ZonedDateTime.
We now use the Jackson JavaTimeModule to parse them directly and swap
the real and convenience getters.
2023-06-15 17:50:47 +02:00
7a813cdda3 use common ObjectMapper instance in model unit tests
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-13 21:12:36 +02:00
d9dbdad75b use explicit utf-8 encoding for parsing responses
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-13 18:51:07 +02:00
c97308fb4f deps: update jackson to 2.15.2
Plus some minor dev-dependency updates
2023-06-13 18:51:05 +02:00
fea27910bb minor dev-dependency updates
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-18 18:35:59 +02:00
4d79ef6634 ci: use SONAR_TOKEN env variable instead of sonar.login property
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-29 10:22:53 +02:00
402567a0db deps: update jackson to 2.15.0 2023-04-29 10:21:34 +02:00
00422ea00c ci: build and test with JDK 20
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-06 17:32:50 +02:00
01e1c6e8c7 minor dev-dependency updates 2023-04-06 17:32:01 +02:00
e322a74818 test against Vault 1.13.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-03 20:25:14 +01:00
f9fe57230f prepare release of v1.1.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 13:56:17 +01:00
e0c33b51e4 update .gitignore
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-29 11:51:52 +01:00
5e6dcc64cd test against Vault 1.12.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-29 11:25:00 +01:00
70b7338f3e update copyright notice to 2023 2023-01-29 11:20:59 +01:00
489e450dc8 deps: update jackson to 2.14.2 and mockito to 5.0.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-29 11:16:58 +01:00
909eab762c mark deprecated AppID components for removal
All checks were successful
continuous-integration/drone/push Build is passing
The AppID backend is no longer available in the latest Vault releases,
so we plan removal with a following major release.
2022-11-21 12:01:26 +01:00
abba4dff93 ci: enable SonarQube analysis for pull requests
All checks were successful
continuous-integration/drone/push Build is passing
2022-11-21 11:48:11 +01:00
712fab04e1 combine payload map creation into subroutines
We create payload maps with conditional argument sets in several
places. Combine the generation into subroutines, to keep the actual
endpoint calls short and clear.
2022-11-21 11:40:53 +01:00
39ac32a2f6 minor rework of internal path constants 2022-11-21 11:33:47 +01:00
31e20385d4 prepare release of v1.1.2
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-26 10:18:39 +02:00
30996e9fc9 ci: build and test with JDK 19
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-26 10:14:11 +02:00
81decd1a4c deps: update jackson dependency to 2.13.4.2 2022-10-26 10:11:19 +02:00
adedc277fa test against older Vault versions to provide a supported range
Some checks reported errors
continuous-integration/drone/push Build was killed
We've only tested the connector against the latest Vault version
available at release time. However, we do support a wider range.
Test against the oldest supported release, the latest with AppID
and the actual latest.
2022-10-13 11:01:14 +02:00
0c56813121 test against Vault 1.12.0, conditionally disable AppID tests
The AppID auth backend is removed in Vault 1.12 and prevents the process
from starting. We now enable the legacy tests conditionally depending on
the actual Vault version.
2022-10-13 10:46:45 +02:00
134 changed files with 1665 additions and 529 deletions

View File

@ -3,7 +3,7 @@ name: default
steps: steps:
- name: compile - name: compile
image: maven:3-openjdk-17 image: maven:3-eclipse-temurin-21
commands: commands:
- mvn -B clean compile - mvn -B clean compile
when: when:
@ -14,7 +14,7 @@ steps:
- fix/* - fix/*
- release/* - release/*
- name: unit-tests - name: unit-tests
image: maven:3-openjdk-17 image: maven:3-eclipse-temurin-21
commands: commands:
- mvn -B test - mvn -B test
when: when:
@ -25,7 +25,7 @@ steps:
- name: setup-vault - name: setup-vault
image: alpine:latest image: alpine:latest
environment: environment:
VAULT_VERSION: 1.11.2 VAULT_VERSION: 1.15.4
commands: commands:
- wget -q -O vault_$${VAULT_VERSION}_linux_amd64.zip https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_linux_amd64.zip - wget -q -O vault_$${VAULT_VERSION}_linux_amd64.zip https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_linux_amd64.zip
- wget -q -O - https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c - wget -q -O - https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c
@ -38,9 +38,9 @@ steps:
- main - main
- release/* - release/*
- name: unit-integration-tests - name: unit-integration-tests
image: maven:3-openjdk-17 image: maven:3-eclipse-temurin-21
environment: environment:
VAULT_VERSION: 1.11.2 VAULT_VERSION: 1.15.4
commands: commands:
- export PATH=.bin:$${PATH} - export PATH=.bin:$${PATH}
- mvn -B -P integration-test verify - mvn -B -P integration-test verify

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
tab_width = 4
trim_trailing_whitespace = true
[{*.yaml,*.yml}]
indent_size = 2

View File

@ -5,11 +5,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
jdk: [ 11, 17, 18 ] jdk: [ 11, 17, 21 ]
vault: [ '1.11.2' ] vault: [ '1.2.0', '1.11.12', '1.15.4' ]
include: include:
- jdk: 17 - jdk: 21
vault: '1.11.2' vault: '1.11.12'
analysis: true analysis: true
steps: steps:
- name: Checkout - name: Checkout
@ -40,12 +40,11 @@ jobs:
if: github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/') if: github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/')
run: mvn -B -P coverage verify run: mvn -B -P coverage verify
- name: Analysis - name: Analysis
if: matrix.analysis && github.event_name == 'push' if: matrix.analysis
run: > run: >
mvn -B sonar:sonar mvn -B sonar:sonar
-Dsonar.host.url=https://sonarcloud.io -Dsonar.host.url=https://sonarcloud.io
-Dsonar.organization=stklcode-github -Dsonar.organization=stklcode-github
-Dsonar.login=$SONAR_TOKEN
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

19
.gitignore vendored
View File

@ -1,5 +1,16 @@
/target/ target/
/*.iml pom.xml.tag
/.idea/ pom.xml.releaseBackup
/*.project pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.idea
*.iml
.bin
*~ *~

View File

@ -1,3 +1,69 @@
## 1.2.0 (2023-12-11)
### Deprecations
* `get...TimeString()` methods on various model classes are now deprecated
### Improvements
* Parse timestamps as `ZonedDateTime` instead of `String` representation
* Remove redundant `java.base` requirement from _module-info.java_ (#69)
* Close Java HTTP Client when running on Java 21 or later (#70)
* Add MFA requirements tu `AuthResponse` (#71)
* Extend `AuthMethod` data model (#72)
### Dependencies
* Updated Jackson to 2.16.0
## 1.1.5 (2023-08-19)
### Fix
* Fixed JSON type conversion in `SecretResponse#get(String, Class)` (#67)
### Test
* Tested against Vault 1.2 to 1.15
## 1.1.4 (2023-06-15)
### Fix
* Use `[+-]XX:XX` notation for timezone in date/time parsing
### Improvements
* Use explicit UTF-8 encoding for parsing responses
### Dependencies
* Updated Jackson to 2.15.2
### Test
* Tested against Vault 1.2.0 to 1.13.3
## 1.1.3 (2023-01-31)
### Deprecations
* AppID components (deprecated since 0.4) are marked for removal with the next major release
### Dependencies
* Updated Jackson to 2.14.2
### Improvements
* Minor internal refactoring
### Test
* Tested against Vault 1.2.0 to 1.12.2
## 1.1.2 (2022-10-26)
### Dependencies
* Updated Jackson to 2.13.4.2
### Test
* Tested against Vault 1.2.0 to 1.12.0
* Disable AppID tests for Vault 1.12 and above (auth method removed)
* Tested with Java 19
## 1.1.1 (2022-08-29) ## 1.1.1 (2022-08-29)
### Dependencies ### Dependencies

View File

@ -32,7 +32,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
* SQL secret handling * SQL secret handling
* KV v1 and v2 support * KV v1 and v2 support
* Connector Factory with builder pattern * Connector Factory with builder pattern
* Tested against Vault 1.11.2 * Tested against Vault 1.2 to 1.15
## Maven Artifact ## Maven Artifact
@ -40,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.1.1</version> <version>1.2.0</version>
</dependency> </dependency>
``` ```

214
pom.xml
View File

@ -4,7 +4,7 @@
<groupId>de.stklcode.jvault</groupId> <groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId> <artifactId>jvault-connector</artifactId>
<version>1.1.1</version> <version>1.2.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -21,16 +21,11 @@
</license> </license>
</licenses> </licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<argLine></argLine>
</properties>
<developers> <developers>
<developer> <developer>
<name>Stefan Kalscheuer</name> <name>Stefan Kalscheuer</name>
<email>stefan@stklcode.de</email> <email>stefan@stklcode.de</email>
<timezone>+1</timezone> <timezone>Europe/Berlin</timezone>
</developer> </developer>
</developers> </developers>
@ -45,90 +40,33 @@
<url>https://github.com/stklcode/jvaultconnector/issues</url> <url>https://github.com/stklcode/jvaultconnector/issues</url>
</issueManagement> </issueManagement>
<build> <properties>
<plugins> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin> <argLine></argLine>
<groupId>org.apache.maven.plugins</groupId> </properties>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>de.stklcode.jvault.connector</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.0.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>
@{argLine}
--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
</argLine>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<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.13.3</version> <version>2.16.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.16.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.9.0</version> <version>5.10.1</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>4.7.0</version> <version>5.8.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -138,21 +76,21 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.tomakehurst</groupId> <groupId>org.wiremock</groupId>
<artifactId>wiremock-jre8</artifactId> <artifactId>wiremock</artifactId>
<version>2.33.2</version> <version>3.3.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.11.0</version> <version>2.15.1</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.10.1</version> <version>3.15.4</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -163,16 +101,97 @@
</dependency> </dependency>
</dependencies> </dependencies>
<dependencyManagement> <build>
<dependencies> <pluginManagement>
<dependency> <plugins>
<groupId>org.sonarsource.scanner.maven</groupId> <plugin>
<artifactId>sonar-maven-plugin</artifactId> <groupId>org.apache.maven.plugins</groupId>
<version>3.9.1.2184</version> <artifactId>maven-compiler-plugin</artifactId>
</dependency> <version>3.11.0</version>
</dependencies> <configuration>
</dependencyManagement> <source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<argLine>
@{argLine}
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>de.stklcode.jvault.connector</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<argLine>
@{argLine}
--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>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.10.0.2594</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles> <profiles>
<profile> <profile>
@ -185,7 +204,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions> <executions>
<execution> <execution>
<id>attach-sources</id> <id>attach-sources</id>
@ -209,7 +227,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.4.1</version> <version>3.6.2</version>
<configuration> <configuration>
<source>11</source> <source>11</source>
</configuration> </configuration>
@ -233,7 +251,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.0.1</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -258,7 +276,6 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions> <executions>
<execution> <execution>
<id>default-prepare-agent</id> <id>default-prepare-agent</id>
@ -285,7 +302,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -306,7 +322,11 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>7.1.2</version> <version>9.0.4</version>
<configuration>
<nvdApiKey>${env.NVD_API_KEY}</nvdApiKey>
<nvdDatafeedUrl>${env.NVD_DATAFEED_URL}</nvdDatafeedUrl>
</configuration>
<executions> <executions>
<execution> <execution>
<goals> <goals>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -41,24 +41,30 @@ 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_SEAL_STATUS = "sys/seal-status"; private static final String PATH_SYS = "sys";
private static final String PATH_SEAL = "sys/seal"; private static final String PATH_SYS_AUTH = PATH_SYS + "/auth";
private static final String PATH_UNSEAL = "sys/unseal"; private static final String PATH_RENEW = PATH_SYS + "/leases/renew";
private static final String PATH_RENEW = "sys/leases/renew"; private static final String PATH_REVOKE = PATH_SYS + "/leases/revoke/";
private static final String PATH_AUTH = "sys/auth"; private static final String PATH_HEALTH = PATH_SYS + "/health";
private static final String PATH_TOKEN = "auth/token"; 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_LOOKUP = "/lookup";
private static final String PATH_CREATE = "/create"; private static final String PATH_CREATE = "/create";
private static final String PATH_ROLES = "/roles"; private static final String PATH_ROLES = "/roles";
private static final String PATH_CREATE_ORPHAN = "/create-orphan"; private static final String PATH_CREATE_ORPHAN = "/create-orphan";
private static final String PATH_AUTH_USERPASS = "auth/userpass/login/"; private static final String PATH_AUTH_USERPASS = PATH_AUTH + "/userpass/login/";
private static final String PATH_AUTH_APPID = "auth/app-id/"; private static final String PATH_AUTH_APPID = PATH_AUTH + "/app-id";
private static final String PATH_AUTH_APPROLE = "auth/approle/"; private static final String PATH_AUTH_APPROLE = PATH_AUTH + "/approle";
private static final String PATH_AUTH_APPROLE_ROLE = "auth/approle/role/%s%s"; private static final String PATH_AUTH_APPROLE_ROLE = PATH_AUTH_APPROLE + "/role/%s%s";
private static final String PATH_REVOKE = "sys/leases/revoke/";
private static final String PATH_HEALTH = "sys/health";
private static final String PATH_DATA = "/data/"; private static final String PATH_DATA = "/data/";
private static final String PATH_METADATA = "/metadata/"; 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_DELETE = "/delete/";
private static final String PATH_UNDELETE = "/undelete/"; private static final String PATH_UNDELETE = "/undelete/";
private static final String PATH_DESTROY = "/destroy/"; private static final String PATH_DESTROY = "/destroy/";
@ -69,6 +75,24 @@ public class HTTPVaultConnector implements VaultConnector {
private String token; // Current token. private String token; // Current token.
private long tokenTTL = 0; // Expiration time for current token. private long tokenTTL = 0; // Expiration time for current token.
/**
* Create connector using a {@link HTTPVaultConnectorBuilder}.
*
* @param builder The builder.
*/
HTTPVaultConnector(final HTTPVaultConnectorBuilder builder) {
this.request = new RequestHelper(
((builder.isWithTLS()) ? "https" : "http") + "://" +
builder.getHost() +
((builder.getPort() != null) ? ":" + builder.getPort() : "") +
builder.getPrefix(),
builder.getNumberOfRetries(),
builder.getTimeout(),
builder.getTlsVersion(),
builder.getTrustedCA()
);
}
/** /**
* Get a new builder for a connector. * Get a new builder for a connector.
* *
@ -102,24 +126,6 @@ public class HTTPVaultConnector implements VaultConnector {
return new HTTPVaultConnectorBuilder().withBaseURL(baseURL); return new HTTPVaultConnectorBuilder().withBaseURL(baseURL);
} }
/**
* Create connector using a {@link HTTPVaultConnectorBuilder}.
*
* @param builder The builder.
*/
HTTPVaultConnector(final HTTPVaultConnectorBuilder builder) {
this.request = new RequestHelper(
((builder.isWithTLS()) ? "https" : "http") + "://" +
builder.getHost() +
((builder.getPort() != null) ? ":" + builder.getPort() : "") +
builder.getPrefix(),
builder.getNumberOfRetries(),
builder.getTimeout(),
builder.getTlsVersion(),
builder.getTrustedCA()
);
}
@Override @Override
public final void resetAuth() { public final void resetAuth() {
token = null; token = null;
@ -139,11 +145,10 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException { public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException {
Map<String, String> param = new HashMap<>(2, 1); Map<String, String> param = mapOfStrings(
param.put("key", key); "key", key,
if (reset != null) { "reset", reset
param.put("reset", reset.toString()); );
}
return request.put(PATH_UNSEAL, param, token, SealResponse.class); return request.put(PATH_UNSEAL, param, token, SealResponse.class);
} }
@ -172,7 +177,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_AUTH, emptyMap(), token, AuthMethodsResponse.class); AuthMethodsResponse amr = request.get(PATH_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());
} }
@ -182,7 +187,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_TOKEN + PATH_LOOKUP, emptyMap(), token, TokenResponse.class); TokenResponse res = request.post(PATH_AUTH_TOKEN + PATH_LOOKUP, emptyMap(), token, TokenResponse.class);
authorized = true; authorized = true;
return res; return res;
@ -196,10 +201,10 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException { public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
return queryAuth( return queryAuth(
PATH_AUTH_APPID + "login", PATH_AUTH_APPID + PATH_LOGIN,
Map.of( Map.of(
"app_id", appID, "app_id", appID,
"user_id", userID "user_id", userID
@ -209,12 +214,11 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException { public final AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
final Map<String, String> payload = new HashMap<>(2, 1); final Map<String, String> payload = mapOfStrings(
payload.put("role_id", roleID); "role_id", roleID,
if (secretID != null) { "secret_id", secretID
payload.put("secret_id", secretID); );
} return queryAuth(PATH_AUTH_APPROLE + PATH_LOGIN, payload);
return queryAuth(PATH_AUTH_APPROLE + "login", payload);
} }
/** /**
@ -238,14 +242,14 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
public final boolean registerAppId(final String appID, final String policy, final String displayName) public final boolean registerAppId(final String appID, final String policy, final String displayName)
throws VaultConnectorException { throws VaultConnectorException {
requireAuth(); requireAuth();
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.postWithoutResponse( request.postWithoutResponse(
PATH_AUTH_APPID + "map/app-id/" + appID, PATH_AUTH_APPID + "/map/app-id/" + appID,
Map.of( Map.of(
"value", policy, "value", policy,
"display_name", displayName "display_name", displayName
@ -257,13 +261,13 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException { public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
requireAuth(); requireAuth();
/* Issue request and expect code 204 with empty response */ /* Issue request and expect code 204 with empty response */
request.postWithoutResponse( request.postWithoutResponse(
PATH_AUTH_APPID + "map/user-id/" + userID, PATH_AUTH_APPID + "/map/user-id/" + userID,
singletonMap("value", appID), singletonMap("value", appID),
token token
); );
@ -384,7 +388,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
SecretListResponse secrets = request.get( SecretListResponse secrets = request.get(
PATH_AUTH_APPROLE + "role?list=true", PATH_AUTH_APPROLE + "/role?list=true",
emptyMap(), emptyMap(),
token, token,
SecretListResponse.class SecretListResponse.class
@ -415,19 +419,18 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public final SecretResponse readSecretVersion(final String mount, final String key, final Integer version) throws VaultConnectorException { public final SecretResponse readSecretVersion(final String mount, final String key, final Integer version)
throws VaultConnectorException {
requireAuth(); requireAuth();
/* Request HTTP response and parse secret metadata */ /* Request HTTP response and parse secret metadata */
Map<String, String> args = new HashMap<>(1, 1); Map<String, String> args = mapOfStrings("version", version);
if (version != null) {
args.put("version", version.toString());
}
return request.get(mount + PATH_DATA + key, args, token, MetaSecretResponse.class); return request.get(mount + PATH_DATA + key, args, token, MetaSecretResponse.class);
} }
@Override @Override
public final MetadataResponse readSecretMetadata(final String mount, final String key) throws VaultConnectorException { public final MetadataResponse readSecretMetadata(final String mount, final String key)
throws VaultConnectorException {
requireAuth(); requireAuth();
/* Request HTTP response and parse secret metadata */ /* Request HTTP response and parse secret metadata */
@ -435,20 +438,25 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public void updateSecretMetadata(final String mount, final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException { public void updateSecretMetadata(final String mount,
final String key,
final Integer maxVersions,
final boolean casRequired) throws VaultConnectorException {
requireAuth(); requireAuth();
Map<String, Object> payload = new HashMap<>(2, 1); Map<String, Object> payload = mapOf(
if (maxVersions != null) { "max_versions", maxVersions,
payload.put("max_versions", maxVersions); "cas_required", casRequired
} );
payload.put("cas_required", casRequired);
write(mount + PATH_METADATA + key, payload); write(mount + PATH_METADATA + key, payload);
} }
@Override @Override
public final SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data, final Integer cas) throws VaultConnectorException { public final SecretVersionResponse writeSecretData(final String mount,
final String key,
final Map<String, Object> data,
final Integer cas) throws VaultConnectorException {
requireAuth(); requireAuth();
if (key == null || key.isEmpty()) { if (key == null || key.isEmpty()) {
@ -456,12 +464,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
// Add CAS value to options map if present. // Add CAS value to options map if present.
Map<String, Object> options; Map<String, Object> options = mapOf("cas", cas);
if (cas != null) {
options = singletonMap("cas", cas);
} else {
options = emptyMap();
}
/* Issue request and parse metadata response */ /* Issue request and parse metadata response */
return request.post( return request.post(
@ -485,7 +488,8 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public final void write(final String key, final Map<String, Object> data, final Map<String, Object> options) throws VaultConnectorException { public final void write(final String key, final Map<String, Object> data, final Map<String, Object> options)
throws VaultConnectorException {
requireAuth(); requireAuth();
if (key == null || key.isEmpty()) { if (key == null || key.isEmpty()) {
@ -526,17 +530,20 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public final void deleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException { public final void deleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException {
handleSecretVersions(mount, PATH_DELETE, key, versions); handleSecretVersions(mount, PATH_DELETE, key, versions);
} }
@Override @Override
public final void undeleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException { public final void undeleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException {
handleSecretVersions(mount, PATH_UNDELETE, key, versions); handleSecretVersions(mount, PATH_UNDELETE, key, versions);
} }
@Override @Override
public final void destroySecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException { public final void destroySecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException {
handleSecretVersions(mount, PATH_DESTROY, key, versions); handleSecretVersions(mount, PATH_DESTROY, key, versions);
} }
@ -550,7 +557,10 @@ public class HTTPVaultConnector implements VaultConnector {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
private void handleSecretVersions(final String mount, final String pathPart, final String key, final int... versions) throws VaultConnectorException { private void handleSecretVersions(final String mount,
final String pathPart,
final String key,
final int... versions) throws VaultConnectorException {
requireAuth(); requireAuth();
/* Request HTTP response and expect empty result */ /* Request HTTP response and expect empty result */
@ -572,11 +582,10 @@ public class HTTPVaultConnector implements VaultConnector {
public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException { public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException {
requireAuth(); requireAuth();
Map<String, String> payload = new HashMap<>(2, 1); Map<String, String> payload = mapOfStrings(
payload.put("lease_id", leaseID); "lease_id", leaseID,
if (increment != null) { "increment", increment
payload.put("increment", increment.toString()); );
}
/* Issue request and parse secret response */ /* Issue request and parse secret response */
return request.put(PATH_RENEW, payload, token, SecretResponse.class); return request.put(PATH_RENEW, payload, token, SecretResponse.class);
@ -584,12 +593,12 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
public final AuthResponse createToken(final Token token) throws VaultConnectorException { public final AuthResponse createToken(final Token token) throws VaultConnectorException {
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE); return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_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_TOKEN + PATH_CREATE_ORPHAN); return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_CREATE_ORPHAN);
} }
@Override @Override
@ -597,7 +606,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_TOKEN + PATH_CREATE + "/" + role); return createTokenInternal(token, PATH_AUTH_TOKEN + PATH_CREATE + "/" + role);
} }
@Override @Override
@ -632,7 +641,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_TOKEN + PATH_LOOKUP, PATH_AUTH_TOKEN + PATH_LOOKUP,
singletonMap("token", token), singletonMap("token", token),
token, token,
TokenResponse.class TokenResponse.class
@ -650,7 +659,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_TOKEN + PATH_ROLES + "/" + name, role, token); request.postWithoutResponse(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, role, token);
return true; return true;
} }
@ -660,14 +669,14 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth(); requireAuth();
// Request HTTP response and parse response. // Request HTTP response and parse response.
return request.get(PATH_TOKEN + PATH_ROLES + "/" + name, emptyMap(), token, TokenRoleResponse.class); return request.get(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, emptyMap(), token, TokenRoleResponse.class);
} }
@Override @Override
public List<String> listTokenRoles() throws VaultConnectorException { public List<String> listTokenRoles() throws VaultConnectorException {
requireAuth(); requireAuth();
return list(PATH_TOKEN + PATH_ROLES); return list(PATH_AUTH_TOKEN + PATH_ROLES);
} }
@Override @Override
@ -679,7 +688,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_TOKEN + PATH_ROLES + "/" + name, token); request.deleteWithoutResponse(PATH_AUTH_TOKEN + PATH_ROLES + "/" + name, token);
return true; return true;
} }
@ -695,4 +704,42 @@ public class HTTPVaultConnector implements VaultConnector {
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
} }
} }
/**
* Generate a map of non-null {@link String} keys and values
*
* @param keyValues Key-value tuples as vararg.
* @return The map of non-null keys and values.
*/
private static Map<String, String> mapOfStrings(Object... keyValues) {
Map<String, String> map = new HashMap<>(keyValues.length / 2, 1);
for (int i = 0; i < keyValues.length - 1; i = i + 2) {
Object key = keyValues[i];
Object val = keyValues[i + 1];
if (key instanceof String && val != null) {
map.put((String) key, val.toString());
}
}
return map;
}
/**
* Generate a map of non-null {@link String} keys and {@link Object} values
*
* @param keyValues Key-value tuples as vararg.
* @return The map of non-null keys and values.
*/
private static Map<String, Object> mapOf(Object... keyValues) {
Map<String, Object> map = new HashMap<>(keyValues.length / 2, 1);
for (int i = 0; i < keyValues.length; i = i + 2) {
Object key = keyValues[i];
Object val = keyValues[i + 1];
if (key instanceof String && val != null) {
map.put((String) key, val);
}
}
return map;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -119,9 +119,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param userID The User ID * @param userID The User ID
* @return The {@link AuthResponse} * @return The {@link AuthResponse}
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. App-ID was removed in Vault 1.12.
* Consider using {@link #authAppRole} instead.
*/ */
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException; AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
/** /**
@ -155,9 +156,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param displayName Arbitrary name to display * @param displayName Arbitrary name to display
* @return {@code true} on success * @return {@code true} on success
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. App-ID was removed in Vault 1.12.
* Consider using {@link #createAppRole} instead.
*/ */
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
boolean registerAppId(final String appID, final String policy, final String displayName) boolean registerAppId(final String appID, final String policy, final String displayName)
throws VaultConnectorException; throws VaultConnectorException;
@ -349,10 +351,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param userID The User-ID * @param userID The User-ID
* @return {@code true} on success * @return {@code true} on success
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. App-ID was removed in Vault 1.12.
* Consider using {@link #createAppRoleSecret} instead. * Consider using {@link #createAppRoleSecret} instead.
*/ */
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException; boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
/** /**
@ -364,9 +366,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param userID The User-ID * @param userID The User-ID
* @return {@code true} on success * @return {@code true} on success
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. App-ID was removed in Vault 1.12.
*/ */
@Deprecated(since = "0.4", forRemoval = false) @Deprecated(since = "0.4", forRemoval = true)
default boolean registerAppUserId(final String appID, default boolean registerAppUserId(final String appID,
final String policy, final String policy,
final String displayName, final String displayName,
@ -420,7 +422,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
default SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data) throws VaultConnectorException { default SecretVersionResponse writeSecretData(final String mount,
final String key,
final Map<String, Object> data) throws VaultConnectorException {
return writeSecretData(mount, key, data, null); return writeSecretData(mount, key, data, null);
} }
@ -438,7 +442,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data, final Integer cas) throws VaultConnectorException; SecretVersionResponse writeSecretData(final String mount,
final String key,
final Map<String, Object> data,
final Integer cas) throws VaultConnectorException;
/** /**
* Retrieve secret data from Vault. * Retrieve secret data from Vault.
@ -453,7 +460,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
SecretResponse readSecretVersion(final String mount, final String key, final Integer version) throws VaultConnectorException; SecretResponse readSecretVersion(final String mount, final String key, final Integer version)
throws VaultConnectorException;
/** /**
* Retrieve secret metadata from Vault. * Retrieve secret metadata from Vault.
@ -482,7 +490,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
void updateSecretMetadata(final String mount, final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException; void updateSecretMetadata(final String mount,
final String key,
final Integer maxVersions,
final boolean casRequired) throws VaultConnectorException;
/** /**
* List available nodes from Vault. * List available nodes from Vault.
@ -527,7 +538,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 {@code options} parameter added * @since 0.8 {@code options} parameter added
*/ */
void write(final String key, final Map<String, Object> data, final Map<String, Object> options) throws VaultConnectorException; void write(final String key, final Map<String, Object> data, final Map<String, Object> options)
throws VaultConnectorException;
/** /**
* Delete key from Vault. * Delete key from Vault.
@ -574,7 +586,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
void deleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException; void deleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException;
/** /**
* Undelete (restore) secret versions from Vault. * Undelete (restore) secret versions from Vault.
@ -586,7 +599,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
void undeleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException; void undeleteSecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException;
/** /**
* Destroy secret versions from Vault. * Destroy secret versions from Vault.
@ -598,7 +612,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.8 * @since 0.8
*/ */
void destroySecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException; void destroySecretVersions(final String mount, final String key, final int... versions)
throws VaultConnectorException;
/** /**
* Revoke given lease immediately. * Revoke given lease immediately.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,7 +1,10 @@
package de.stklcode.jvault.connector.internal; package de.stklcode.jvault.connector.internal;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import de.stklcode.jvault.connector.exception.*; import de.stklcode.jvault.connector.exception.*;
import de.stklcode.jvault.connector.model.response.ErrorResponse; import de.stklcode.jvault.connector.model.response.ErrorResponse;
@ -62,7 +65,10 @@ public final class RequestHelper implements Serializable {
this.timeout = timeout; this.timeout = timeout;
this.tlsVersion = tlsVersion; this.tlsVersion = tlsVersion;
this.trustedCaCert = trustedCaCert; this.trustedCaCert = trustedCaCert;
this.jsonMapper = new ObjectMapper(); this.jsonMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
} }
/** /**
@ -127,7 +133,8 @@ public final class RequestHelper implements Serializable {
* @throws VaultConnectorException on connection error * @throws VaultConnectorException on connection error
* @since 0.8 * @since 0.8
*/ */
public void postWithoutResponse(final String path, final Object payload, final String token) throws VaultConnectorException { public void postWithoutResponse(final String path, final Object payload, final String token)
throws VaultConnectorException {
if (!post(path, payload, token).isEmpty()) { if (!post(path, payload, token).isEmpty()) {
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE); throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
} }
@ -143,7 +150,8 @@ public final class RequestHelper implements Serializable {
* @throws VaultConnectorException on connection error * @throws VaultConnectorException on connection error
* @since 0.8 Added {@code token} parameter. * @since 0.8 Added {@code token} parameter.
*/ */
public String put(final String path, final Map<String, String> payload, final String token) throws VaultConnectorException { public String put(final String path, final Map<String, String> payload, final String token)
throws VaultConnectorException {
// Initialize PUT. // Initialize PUT.
var req = HttpRequest.newBuilder(URI.create(baseURL + path)); var req = HttpRequest.newBuilder(URI.create(baseURL + path));
@ -254,8 +262,8 @@ public final class RequestHelper implements Serializable {
if (!payload.isEmpty()) { if (!payload.isEmpty()) {
uriBuilder.append("?").append( uriBuilder.append("?").append(
payload.entrySet().stream().map( payload.entrySet().stream().map(par ->
par -> URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8) URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8)
).collect(Collectors.joining("&")) ).collect(Collectors.joining("&"))
); );
} }
@ -355,6 +363,15 @@ public final class RequestHelper implements Serializable {
} }
} catch (CompletionException e) { } catch (CompletionException e) {
throw new ConnectionException(Error.CONNECTION, e.getCause()); throw new ConnectionException(Error.CONNECTION, e.getCause());
} finally {
if (client instanceof AutoCloseable) {
// Close the client, which is supported since JDK21.
try {
((AutoCloseable) client).close();
} catch (Exception ignored) {
// Ignore
}
}
} }
} }
@ -386,7 +403,8 @@ public final class RequestHelper implements Serializable {
} }
return sslContext; return sslContext;
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) { } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException |
KeyManagementException e) {
throw new TlsException(Error.INIT_SSL_CONTEXT, e); throw new TlsException(Error.INIT_SSL_CONTEXT, e);
} }
} }
@ -399,7 +417,7 @@ public final class RequestHelper implements Serializable {
* @throws InvalidResponseException on reading errors * @throws InvalidResponseException on reading errors
*/ */
private String handleResult(final HttpResponse<InputStream> response) throws InvalidResponseException { private String handleResult(final HttpResponse<InputStream> response) throws InvalidResponseException {
try (var reader = new BufferedReader(new InputStreamReader(response.body()))) { try (var reader = new BufferedReader(new InputStreamReader(response.body(), UTF_8))) {
return reader.lines().collect(Collectors.joining("\n")); return reader.lines().collect(Collectors.joining("\n"));
} catch (IOException ignored) { } catch (IOException ignored) {
throw new InvalidResponseException(Error.READ_RESPONSE, 200); throw new InvalidResponseException(Error.READ_RESPONSE, 200);
@ -414,7 +432,7 @@ public final class RequestHelper implements Serializable {
*/ */
private void handleError(final HttpResponse<InputStream> response) throws VaultConnectorException { private void handleError(final HttpResponse<InputStream> response) throws VaultConnectorException {
if (response.body() != null) { if (response.body() != null) {
try (var reader = new BufferedReader(new InputStreamReader(response.body()))) { try (var reader = new BufferedReader(new InputStreamReader(response.body(), UTF_8))) {
var responseString = reader.lines().collect(Collectors.joining("\n")); var responseString = reader.lines().collect(Collectors.joining("\n"));
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class); ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
/* Check for "permission denied" response */ /* Check for "permission denied" response */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,17 +34,6 @@ import java.util.Objects;
public final class AppRole implements Serializable { public final class AppRole implements Serializable {
private static final long serialVersionUID = -6248529625864573990L; private static final long serialVersionUID = -6248529625864573990L;
/**
* Get {@link Builder} instance.
*
* @param name Role name.
* @return AppRole Builder.
* @since 0.8
*/
public static Builder builder(final String name) {
return new Builder(name);
}
@JsonProperty("role_name") @JsonProperty("role_name")
private String name; private String name;
@ -134,6 +123,17 @@ public final class AppRole implements Serializable {
this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null; this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null;
} }
/**
* Get {@link Builder} instance.
*
* @param name Role name.
* @return AppRole Builder.
* @since 0.8
*/
public static Builder builder(final String name) {
return new Builder(name);
}
/** /**
* @return the role name * @return the role name
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ package de.stklcode.jvault.connector.model;
*/ */
public enum AuthBackend { public enum AuthBackend {
TOKEN("token"), TOKEN("token"),
@Deprecated(since = "1.1.3", forRemoval = true)
APPID("app-id"), APPID("app-id"),
APPROLE("approle"), APPROLE("approle"),
USERPASS("userpass"), USERPASS("userpass"),

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,16 +34,6 @@ import java.util.*;
public final class Token implements Serializable { public final class Token implements Serializable {
private static final long serialVersionUID = 5208508683665365287L; private static final long serialVersionUID = 5208508683665365287L;
/**
* Get {@link Builder} instance.
*
* @return Token Builder.
* @since 0.8
*/
public static Builder builder() {
return new Builder();
}
@JsonProperty("id") @JsonProperty("id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private String id; private String id;
@ -123,6 +113,16 @@ public final class Token implements Serializable {
this.entityAlias = builder.entityAlias; this.entityAlias = builder.entityAlias;
} }
/**
* Get {@link Builder} instance.
*
* @return Token Builder.
* @since 0.8
*/
public static Builder builder() {
return new Builder();
}
/** /**
* @return Token ID * @return Token ID
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,15 +36,6 @@ import java.util.Objects;
public final class TokenRole implements Serializable { public final class TokenRole implements Serializable {
private static final long serialVersionUID = -3505215215838576321L; private static final long serialVersionUID = -3505215215838576321L;
/**
* Get {@link Builder} instance.
*
* @return Token Role Builder.
*/
public static Builder builder() {
return new Builder();
}
@JsonProperty("name") @JsonProperty("name")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private String name; private String name;
@ -129,6 +120,15 @@ public final class TokenRole implements Serializable {
this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null; this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null;
} }
/**
* Get {@link Builder} instance.
*
* @return Token Role Builder.
*/
public static Builder builder() {
return new Builder();
}
/** /**
* @return Token Role name * @return Token Role name
*/ */
@ -264,7 +264,7 @@ public final class TokenRole implements Serializable {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(name, allowedPolicies, allowedPoliciesGlob, disallowedPolicies, disallowedPoliciesGlob, return Objects.hash(name, allowedPolicies, allowedPoliciesGlob, disallowedPolicies, disallowedPoliciesGlob,
orphan, renewable, pathSuffix, allowedEntityAliases, tokenBoundCidrs, tokenExplicitMaxTtl, orphan, renewable, pathSuffix, allowedEntityAliases, tokenBoundCidrs, tokenExplicitMaxTtl,
tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType); tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -41,7 +41,7 @@ public class MetaSecretResponse extends SecretResponse {
@Override @Override
public final Map<String, Serializable> getData() { public final Map<String, Serializable> getData() {
if (secret != null) { if (secret != null) {
return secret.getData(); return secret.getData();
} else { } else {
return Collections.emptyMap(); return Collections.emptyMap();
@ -50,7 +50,7 @@ public class MetaSecretResponse extends SecretResponse {
@Override @Override
public final VersionMetadata getMetadata() { public final VersionMetadata getMetadata() {
if (secret != null) { if (secret != null) {
return secret.getMetadata(); return secret.getMetadata();
} else { } else {
return null; return null;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.ZonedDateTime;
import java.util.Objects; import java.util.Objects;
/** /**
@ -29,7 +30,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class SealResponse implements VaultResponse { public final class SealResponse implements VaultResponse {
private static final long serialVersionUID = -3661916639367542617L; private static final long serialVersionUID = -6000309255473305787L;
@JsonProperty("type") @JsonProperty("type")
private String type; private String type;
@ -52,6 +53,9 @@ public final class SealResponse implements VaultResponse {
@JsonProperty("version") @JsonProperty("version")
private String version; private String version;
@JsonProperty("build_date")
private ZonedDateTime buildDate;
@JsonProperty("nonce") @JsonProperty("nonce")
private String nonce; private String nonce;
@ -122,6 +126,14 @@ public final class SealResponse implements VaultResponse {
return version; return version;
} }
/**
* @return Vault build date.
* @since 1.2
*/
public ZonedDateTime getBuildDate() {
return buildDate;
}
/** /**
* @return A random nonce. * @return A random nonce.
* @since 0.8 * @since 0.8
@ -185,6 +197,7 @@ public final class SealResponse implements VaultResponse {
Objects.equals(numberOfShares, that.numberOfShares) && Objects.equals(numberOfShares, that.numberOfShares) &&
Objects.equals(progress, that.progress) && Objects.equals(progress, that.progress) &&
Objects.equals(version, that.version) && Objects.equals(version, that.version) &&
Objects.equals(buildDate, that.buildDate) &&
Objects.equals(nonce, that.nonce) && Objects.equals(nonce, that.nonce) &&
Objects.equals(clusterName, that.clusterName) && Objects.equals(clusterName, that.clusterName) &&
Objects.equals(clusterId, that.clusterId) && Objects.equals(clusterId, that.clusterId) &&
@ -195,7 +208,7 @@ public final class SealResponse implements VaultResponse {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(type, sealed, initialized, threshold, numberOfShares, progress, version, nonce, return Objects.hash(type, sealed, initialized, threshold, numberOfShares, progress, version, buildDate, nonce,
clusterName, clusterId, migration, recoverySeal, storageType); clusterName, clusterId, migration, recoverySeal, storageType);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,10 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata; import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
@ -79,8 +82,20 @@ public abstract class SecretResponse extends VaultDataResponse {
Object rawValue = get(key); Object rawValue = get(key);
if (rawValue == null) { if (rawValue == null) {
return null; return null;
} else if (type.isInstance(rawValue)) {
return type.cast(rawValue);
} else {
var om = new ObjectMapper()
.registerModule(new JavaTimeModule())
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
if (rawValue instanceof String) {
return om.readValue((String) rawValue, type);
} else {
return om.readValue(om.writeValueAsString(rawValue), type);
}
} }
return new ObjectMapper().readValue(rawValue.toString(), type);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage()); throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,7 +33,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthData implements Serializable { public final class AuthData implements Serializable {
private static final long serialVersionUID = -6962244199229885869L; private static final long serialVersionUID = 3067695351664603536L;
@JsonProperty("client_token") @JsonProperty("client_token")
private String clientToken; private String clientToken;
@ -65,6 +65,9 @@ public final class AuthData implements Serializable {
@JsonProperty("orphan") @JsonProperty("orphan")
private boolean orphan; private boolean orphan;
@JsonProperty("mfa_requirement")
private MfaRequirement mfaRequirement;
/** /**
* @return Client token * @return Client token
*/ */
@ -139,6 +142,14 @@ public final class AuthData implements Serializable {
return orphan; return orphan;
} }
/**
* @return multi-factor requirement
* @since 1.2
*/
public MfaRequirement getMfaRequirement() {
return mfaRequirement;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
@ -157,12 +168,13 @@ public final class AuthData implements Serializable {
Objects.equals(metadata, authData.metadata) && Objects.equals(metadata, authData.metadata) &&
Objects.equals(leaseDuration, authData.leaseDuration) && Objects.equals(leaseDuration, authData.leaseDuration) &&
Objects.equals(entityId, authData.entityId) && Objects.equals(entityId, authData.entityId) &&
Objects.equals(tokenType, authData.tokenType); Objects.equals(tokenType, authData.tokenType) &&
Objects.equals(mfaRequirement, authData.mfaRequirement);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(clientToken, accessor, policies, tokenPolicies, metadata, leaseDuration, renewable, return Objects.hash(clientToken, accessor, policies, tokenPolicies, metadata, leaseDuration, renewable,
entityId, tokenType, orphan); entityId, tokenType, orphan, mfaRequirement);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,7 +34,7 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthMethod implements Serializable { public final class AuthMethod implements Serializable {
private static final long serialVersionUID = -2718660627880077335L; private static final long serialVersionUID = -439987082190917691L;
private AuthBackend type; private AuthBackend type;
private String rawType; private String rawType;
@ -42,11 +42,14 @@ public final class AuthMethod implements Serializable {
@JsonProperty("accessor") @JsonProperty("accessor")
private String accessor; private String accessor;
@JsonProperty("deprecation_status")
private String deprecationStatus;
@JsonProperty("description") @JsonProperty("description")
private String description; private String description;
@JsonProperty("config") @JsonProperty("config")
private Map<String, String> config; private MountConfig config;
@JsonProperty("external_entropy_access") @JsonProperty("external_entropy_access")
private boolean externalEntropyAccess; private boolean externalEntropyAccess;
@ -54,6 +57,18 @@ public final class AuthMethod implements Serializable {
@JsonProperty("local") @JsonProperty("local")
private boolean local; private boolean local;
@JsonProperty("options")
private Map<String, String> options;
@JsonProperty("plugin_version")
private String pluginVersion;
@JsonProperty("running_plugin_version")
private String runningPluginVersion;
@JsonProperty("running_sha256")
private String runningSha256;
@JsonProperty("seal_wrap") @JsonProperty("seal_wrap")
private boolean sealWrap; private boolean sealWrap;
@ -91,6 +106,14 @@ public final class AuthMethod implements Serializable {
return accessor; return accessor;
} }
/**
* @return Deprecation status
* @since 1.2
*/
public String getDeprecationStatus() {
return deprecationStatus;
}
/** /**
* @return Description * @return Description
*/ */
@ -100,8 +123,10 @@ public final class AuthMethod implements Serializable {
/** /**
* @return Configuration data * @return Configuration data
* @since 0.2
* @since 1.2 Returns {@link MountConfig} instead of {@link Map}
*/ */
public Map<String, String> getConfig() { public MountConfig getConfig() {
return config; return config;
} }
@ -120,6 +145,38 @@ public final class AuthMethod implements Serializable {
return local; return local;
} }
/**
* @return Options
* @since 1.2
*/
public Map<String, String> getOptions() {
return options;
}
/**
* @return Plugin version
* @since 1.2
*/
public String getPluginVersion() {
return pluginVersion;
}
/**
* @return Running plugin version
* @since 1.2
*/
public String getRunningPluginVersion() {
return runningPluginVersion;
}
/**
* @return Running SHA256
* @since 1.2
*/
public String getRunningSha256() {
return runningSha256;
}
/** /**
* @return Seal wrapping enabled * @return Seal wrapping enabled
* @since 1.1 * @since 1.1
@ -150,13 +207,19 @@ public final class AuthMethod implements Serializable {
sealWrap == that.sealWrap && sealWrap == that.sealWrap &&
Objects.equals(rawType, that.rawType) && Objects.equals(rawType, that.rawType) &&
Objects.equals(accessor, that.accessor) && Objects.equals(accessor, that.accessor) &&
Objects.equals(deprecationStatus, that.deprecationStatus) &&
Objects.equals(description, that.description) && Objects.equals(description, that.description) &&
Objects.equals(config, that.config) && Objects.equals(config, that.config) &&
Objects.equals(options, that.options) &&
Objects.equals(pluginVersion, that.pluginVersion) &&
Objects.equals(runningPluginVersion, that.runningPluginVersion) &&
Objects.equals(runningSha256, that.runningSha256) &&
Objects.equals(uuid, that.uuid); Objects.equals(uuid, that.uuid);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(type, rawType, accessor, description, config, externalEntropyAccess, local, sealWrap, uuid); return Objects.hash(type, rawType, accessor, deprecationStatus, description, config, externalEntropyAccess,
local, options, pluginVersion, runningPluginVersion, runningSha256, sealWrap, uuid);
} }
} }

View File

@ -0,0 +1,62 @@
/*
* Copyright 2016-2023 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
* Embedded multi-factor-authentication (MFA) constraint "any".
*
* @author Stefan Kalscheuer
* @since 1.2
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class MfaConstraintAny implements Serializable {
private static final long serialVersionUID = 1226126781813149627L;
@JsonProperty("any")
private List<MfaMethodId> any;
/**
* @return List of "any" MFA methods
*/
public List<MfaMethodId> getAny() {
return any;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MfaConstraintAny mfaRequirement = (MfaConstraintAny) o;
return Objects.equals(any, mfaRequirement.any);
}
@Override
public int hashCode() {
return Objects.hash(any);
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 2016-2023 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Objects;
/**
* Embedded multi-factor-authentication (MFA) requirement.
*
* @author Stefan Kalscheuer
* @since 1.2
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class MfaMethodId implements Serializable {
private static final long serialVersionUID = 691298070242998814L;
@JsonProperty("type")
private String type;
@JsonProperty("id")
private String id;
@JsonProperty("uses_passcode")
private Boolean usesPasscode;
@JsonProperty("name")
private String name;
/**
* @return MFA method type
*/
public String getType() {
return type;
}
/**
* @return MFA method id
*/
public String getId() {
return id;
}
/**
* @return MFA uses passcode id
*/
public Boolean getUsesPasscode() {
return usesPasscode;
}
/**
* @return MFA method name
*/
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MfaMethodId mfaMethodId = (MfaMethodId) o;
return Objects.equals(type, mfaMethodId.type) &&
Objects.equals(id, mfaMethodId.id) &&
Objects.equals(usesPasscode, mfaMethodId.usesPasscode) &&
Objects.equals(name, mfaMethodId.name);
}
@Override
public int hashCode() {
return Objects.hash(type, id, usesPasscode, name);
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2016-2023 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
/**
* Embedded multi-factor-authentication (MFA) requirement.
*
* @author Stefan Kalscheuer
* @since 1.2
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class MfaRequirement implements Serializable {
private static final long serialVersionUID = -2516941512455319638L;
@JsonProperty("mfa_request_id")
private String mfaRequestId;
@JsonProperty("mfa_constraints")
private Map<String, MfaConstraintAny> mfaConstraints;
/**
* @return MFA request ID
*/
public String getMfaRequestId() {
return mfaRequestId;
}
/**
* @return MFA constraints
*/
public Map<String, MfaConstraintAny> getMfaConstraints() {
return mfaConstraints;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MfaRequirement mfaRequirement = (MfaRequirement) o;
return Objects.equals(mfaRequestId, mfaRequirement.mfaRequestId) &&
Objects.equals(mfaConstraints, mfaRequirement.mfaConstraints);
}
@Override
public int hashCode() {
return Objects.hash(mfaRequestId, mfaConstraints);
}
}

View File

@ -0,0 +1,168 @@
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
* Embedded mount config output.
*
* @author Stefan Kalscheuer
* @since 1.2
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class MountConfig implements Serializable {
private static final long serialVersionUID = -8653909672663717792L;
@JsonProperty("default_lease_ttl")
private Integer defaultLeaseTtl;
@JsonProperty("max_lease_ttl")
private Integer maxLeaseTtl;
@JsonProperty("force_no_cache")
private Boolean forceNoCache;
@JsonProperty("token_type")
private String tokenType;
@JsonProperty("audit_non_hmac_request_keys")
private List<String> auditNonHmacRequestKeys;
@JsonProperty("audit_non_hmac_response_keys")
private List<String> auditNonHmacResponseKeys;
@JsonProperty("listing_visibility")
private String listingVisibility;
@JsonProperty("passthrough_request_headers")
private List<String> passthroughRequestHeaders;
@JsonProperty("allowed_response_headers")
private List<String> allowedResponseHeaders;
@JsonProperty("allowed_managed_keys")
private List<String> allowedManagedKeys;
@JsonProperty("delegated_auth_accessors")
private List<String> delegatedAuthAccessors;
@JsonProperty("user_lockout_config")
private UserLockoutConfig userLockoutConfig;
/**
* @return Default lease TTL
*/
public Integer getDefaultLeaseTtl() {
return defaultLeaseTtl;
}
/**
* @return Maximum lease TTL
*/
public Integer getMaxLeaseTtl() {
return maxLeaseTtl;
}
/**
* @return Force no cache?
*/
public Boolean getForceNoCache() {
return forceNoCache;
}
/**
* @return Token type
*/
public String getTokenType() {
return tokenType;
}
/**
* @return Audit non HMAC request keys
*/
public List<String> getAuditNonHmacRequestKeys() {
return auditNonHmacRequestKeys;
}
/**
* @return Audit non HMAC response keys
*/
public List<String> getAuditNonHmacResponseKeys() {
return auditNonHmacResponseKeys;
}
/**
* @return Listing visibility
*/
public String getListingVisibility() {
return listingVisibility;
}
/**
* @return Passthrough request headers
*/
public List<String> getPassthroughRequestHeaders() {
return passthroughRequestHeaders;
}
/**
* @return Allowed response headers
*/
public List<String> getAllowedResponseHeaders() {
return allowedResponseHeaders;
}
/**
* @return Allowed managed keys
*/
public List<String> getAllowedManagedKeys() {
return allowedManagedKeys;
}
/**
* @return Delegated auth accessors
*/
public List<String> getDelegatedAuthAccessors() {
return delegatedAuthAccessors;
}
/**
* @return User lockout config
*/
public UserLockoutConfig getUserLockoutConfig() {
return userLockoutConfig;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
MountConfig that = (MountConfig) o;
return Objects.equals(defaultLeaseTtl, that.defaultLeaseTtl) &&
Objects.equals(maxLeaseTtl, that.maxLeaseTtl) &&
Objects.equals(forceNoCache, that.forceNoCache) &&
Objects.equals(tokenType, that.tokenType) &&
Objects.equals(auditNonHmacRequestKeys, that.auditNonHmacRequestKeys) &&
Objects.equals(auditNonHmacResponseKeys, that.auditNonHmacResponseKeys) &&
Objects.equals(listingVisibility, that.listingVisibility) &&
Objects.equals(passthroughRequestHeaders, that.passthroughRequestHeaders) &&
Objects.equals(allowedResponseHeaders, that.allowedResponseHeaders) &&
Objects.equals(allowedManagedKeys, that.allowedManagedKeys) &&
Objects.equals(delegatedAuthAccessors, that.delegatedAuthAccessors) &&
Objects.equals(userLockoutConfig, that.userLockoutConfig);
}
@Override
public int hashCode() {
return Objects.hash(defaultLeaseTtl, maxLeaseTtl, forceNoCache, tokenType, auditNonHmacRequestKeys,
auditNonHmacResponseKeys, listingVisibility, passthroughRequestHeaders, allowedResponseHeaders,
allowedManagedKeys, delegatedAuthAccessors, userLockoutConfig);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable; import java.io.Serializable;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -35,12 +34,13 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class SecretMetadata implements Serializable { public final class SecretMetadata implements Serializable {
private static final long serialVersionUID = 1684891108903409038L; private static final long serialVersionUID = -4967896264361344676L;
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX"); private static final DateTimeFormatter TIME_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("created_time") @JsonProperty("created_time")
private String createdTimeString; private ZonedDateTime createdTime;
@JsonProperty("current_version") @JsonProperty("current_version")
private Integer currentVersion; private Integer currentVersion;
@ -52,31 +52,29 @@ public final class SecretMetadata implements Serializable {
private Integer oldestVersion; private Integer oldestVersion;
@JsonProperty("updated_time") @JsonProperty("updated_time")
private String updatedTime; private ZonedDateTime updatedTime;
@JsonProperty("versions") @JsonProperty("versions")
private Map<Integer, VersionMetadata> versions; private Map<Integer, VersionMetadata> versions;
/** /**
* @return Time of secret creation as raw string representation. * @return Time of secret creation as raw string representation.
* @deprecated Method left for backwards compatibility only. Use {@link #getCreatedTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getCreatedTimeString() { public String getCreatedTimeString() {
return createdTimeString; if (createdTime != null) {
return TIME_FORMAT.format(createdTime);
}
return null;
} }
/** /**
* @return Time of secret creation. * @return Time of secret creation.
*/ */
public ZonedDateTime getCreatedTime() { public ZonedDateTime getCreatedTime() {
if (createdTimeString != null && !createdTimeString.isEmpty()) { return createdTime;
try {
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
} catch (DateTimeParseException e) {
// Ignore.
}
}
return null;
} }
/** /**
@ -102,26 +100,24 @@ public final class SecretMetadata implements Serializable {
/** /**
* @return Time of secret update as raw string representation. * @return Time of secret update as raw string representation.
* @deprecated Method left for backwards compatibility only. Use {@link #getUpdatedTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getUpdatedTimeString() { public String getUpdatedTimeString() {
return updatedTime; if (updatedTime != null) {
} return TIME_FORMAT.format(updatedTime);
/**
* @return Time of secret update..
*/
public ZonedDateTime getUpdatedTime() {
if (updatedTime != null && !updatedTime.isEmpty()) {
try {
return ZonedDateTime.parse(updatedTime, TIME_FORMAT);
} catch (DateTimeParseException e) {
// Ignore.
}
} }
return null; return null;
} }
/**
* @return Time of secret update.
*/
public ZonedDateTime getUpdatedTime() {
return updatedTime;
}
/** /**
* @return Version of the entry. * @return Version of the entry.
*/ */
@ -137,7 +133,7 @@ public final class SecretMetadata implements Serializable {
return false; return false;
} }
SecretMetadata that = (SecretMetadata) o; SecretMetadata that = (SecretMetadata) o;
return Objects.equals(createdTimeString, that.createdTimeString) && return Objects.equals(createdTime, that.createdTime) &&
Objects.equals(currentVersion, that.currentVersion) && Objects.equals(currentVersion, that.currentVersion) &&
Objects.equals(maxVersions, that.maxVersions) && Objects.equals(maxVersions, that.maxVersions) &&
Objects.equals(oldestVersion, that.oldestVersion) && Objects.equals(oldestVersion, that.oldestVersion) &&
@ -147,6 +143,6 @@ public final class SecretMetadata implements Serializable {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(createdTimeString, currentVersion, maxVersions, oldestVersion, updatedTime, versions); return Objects.hash(createdTime, currentVersion, maxVersions, oldestVersion, updatedTime, versions);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable; import java.io.Serializable;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -34,7 +35,10 @@ 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 = 2915180734313753649L; private static final long serialVersionUID = -5749716740973138916L;
private static final DateTimeFormatter TIME_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("accessor") @JsonProperty("accessor")
private String accessor; private String accessor;
@ -52,7 +56,7 @@ public final class TokenData implements Serializable {
private String entityId; private String entityId;
@JsonProperty("expire_time") @JsonProperty("expire_time")
private String expireTime; private ZonedDateTime expireTime;
@JsonProperty("explicit_max_ttl") @JsonProperty("explicit_max_ttl")
private Integer explicitMaxTtl; private Integer explicitMaxTtl;
@ -61,7 +65,7 @@ public final class TokenData implements Serializable {
private String id; private String id;
@JsonProperty("issue_time") @JsonProperty("issue_time")
private String issueTime; private ZonedDateTime issueTime;
@JsonProperty("meta") @JsonProperty("meta")
private Map<String, Object> meta; private Map<String, Object> meta;
@ -126,9 +130,15 @@ public final class TokenData implements Serializable {
/** /**
* @return Expire time as raw string value * @return Expire time as raw string value
* @since 0.9 * @since 0.9
* @deprecated Method left for backwards compatibility only. Use {@link #getExpireTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getExpireTimeString() { public String getExpireTimeString() {
return expireTime; if (expireTime != null) {
return TIME_FORMAT.format(expireTime);
}
return null;
} }
/** /**
@ -136,11 +146,7 @@ public final class TokenData implements Serializable {
* @since 0.9 * @since 0.9
*/ */
public ZonedDateTime getExpireTime() { public ZonedDateTime getExpireTime() {
if (expireTime == null) { return expireTime;
return null;
} else {
return ZonedDateTime.parse(expireTime);
}
} }
/** /**
@ -161,9 +167,15 @@ public final class TokenData implements Serializable {
/** /**
* @return Issue time as raw string value * @return Issue time as raw string value
* @since 0.9 * @since 0.9
* @deprecated Method left for backwards compatibility only. Use {@link #getIssueTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getIssueTimeString() { public String getIssueTimeString() {
return issueTime; if (issueTime != null) {
return TIME_FORMAT.format(issueTime);
}
return null;
} }
/** /**
@ -171,11 +183,7 @@ public final class TokenData implements Serializable {
* @since 0.9 * @since 0.9
*/ */
public ZonedDateTime getIssueTime() { public ZonedDateTime getIssueTime() {
if (issueTime == null) { return issueTime;
return null;
} else {
return ZonedDateTime.parse(issueTime);
}
} }
/** /**

View File

@ -0,0 +1,77 @@
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Objects;
/**
* Embedded user lockout config output.
*
* @author Stefan Kalscheuer
* @since 1.2
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserLockoutConfig implements Serializable {
private static final long serialVersionUID = -8051060041593140550L;
@JsonProperty("lockout_threshold")
private Integer lockoutThreshold;
@JsonProperty("lockout_duration")
private Integer lockoutDuration;
@JsonProperty("lockout_counter_reset_duration")
private Integer lockoutCounterResetDuration;
@JsonProperty("lockout_disable")
private Boolean lockoutDisable;
/**
* @return Lockout threshold
*/
public Integer getLockoutThreshold() {
return lockoutThreshold;
}
/**
* @return Lockout duration
*/
public Integer getLockoutDuration() {
return lockoutDuration;
}
/**
* @return Lockout counter reset duration
*/
public Integer getLockoutCounterResetDuration() {
return lockoutCounterResetDuration;
}
/**
* @return Lockout disabled?
*/
public Boolean getLockoutDisable() {
return lockoutDisable;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
UserLockoutConfig that = (UserLockoutConfig) o;
return Objects.equals(lockoutThreshold, that.lockoutThreshold) &&
Objects.equals(lockoutDuration, that.lockoutDuration) &&
Objects.equals(lockoutCounterResetDuration, that.lockoutCounterResetDuration) &&
Objects.equals(lockoutDisable, that.lockoutDisable);
}
@Override
public int hashCode() {
return Objects.hash(lockoutThreshold, lockoutDuration, lockoutCounterResetDuration, lockoutDisable);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable; import java.io.Serializable;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Objects; import java.util.Objects;
/** /**
@ -34,15 +33,16 @@ import java.util.Objects;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class VersionMetadata implements Serializable { public final class VersionMetadata implements Serializable {
private static final long serialVersionUID = -5286693953873839611L; private static final long serialVersionUID = -6815731513868586713L;
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX"); private static final DateTimeFormatter TIME_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("created_time") @JsonProperty("created_time")
private String createdTimeString; private ZonedDateTime createdTime;
@JsonProperty("deletion_time") @JsonProperty("deletion_time")
private String deletionTimeString; private ZonedDateTime deletionTime;
@JsonProperty("destroyed") @JsonProperty("destroyed")
private boolean destroyed; private boolean destroyed;
@ -52,46 +52,42 @@ public final class VersionMetadata implements Serializable {
/** /**
* @return Time of secret creation as raw string representation. * @return Time of secret creation as raw string representation.
* @deprecated Method left for backwards compatibility only. Use {@link #getCreatedTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getCreatedTimeString() { public String getCreatedTimeString() {
return createdTimeString; if (createdTime != null) {
return TIME_FORMAT.format(createdTime);
}
return null;
} }
/** /**
* @return Time of secret creation. * @return Time of secret creation.
*/ */
public ZonedDateTime getCreatedTime() { public ZonedDateTime getCreatedTime() {
if (createdTimeString != null && !createdTimeString.isEmpty()) { return createdTime;
try {
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
} catch (DateTimeParseException e) {
// Ignore.
}
}
return null;
} }
/** /**
* @return Time for secret deletion as raw string representation. * @return Time for secret deletion as raw string representation.
* @deprecated Method left for backwards compatibility only. Use {@link #getDeletionTime()} instead.
*/ */
@Deprecated(since = "1.2", forRemoval = true)
public String getDeletionTimeString() { public String getDeletionTimeString() {
return deletionTimeString; if (deletionTime != null) {
return TIME_FORMAT.format(deletionTime);
}
return null;
} }
/** /**
* @return Time for secret deletion. * @return Time for secret deletion.
*/ */
public ZonedDateTime getDeletionTime() { public ZonedDateTime getDeletionTime() {
if (deletionTimeString != null && !deletionTimeString.isEmpty()) { return deletionTime;
try {
return ZonedDateTime.parse(deletionTimeString, TIME_FORMAT);
} catch (DateTimeParseException e) {
// Ignore.
}
}
return null;
} }
/** /**
@ -117,13 +113,13 @@ public final class VersionMetadata implements Serializable {
} }
VersionMetadata that = (VersionMetadata) o; VersionMetadata that = (VersionMetadata) o;
return destroyed == that.destroyed && return destroyed == that.destroyed &&
Objects.equals(createdTimeString, that.createdTimeString) && Objects.equals(createdTime, that.createdTime) &&
Objects.equals(deletionTimeString, that.deletionTimeString) && Objects.equals(deletionTime, that.deletionTime) &&
Objects.equals(version, that.version); Objects.equals(version, that.version);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(createdTimeString, deletionTimeString, destroyed, version); return Objects.hash(createdTime, deletionTime, destroyed, version);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable; import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.Objects; import java.util.Objects;
/** /**
@ -28,7 +29,7 @@ import java.util.Objects;
* @since 1.1 * @since 1.1
*/ */
public class WrapInfo implements Serializable { public class WrapInfo implements Serializable {
private static final long serialVersionUID = -7764500642913116581L; private static final long serialVersionUID = 4864973237090355607L;
@JsonProperty("token") @JsonProperty("token")
private String token; private String token;
@ -37,7 +38,7 @@ public class WrapInfo implements Serializable {
private Integer ttl; private Integer ttl;
@JsonProperty("creation_time") @JsonProperty("creation_time")
private String creationTime; private ZonedDateTime creationTime;
@JsonProperty("creation_path") @JsonProperty("creation_path")
private String creationPath; private String creationPath;
@ -59,7 +60,7 @@ public class WrapInfo implements Serializable {
/** /**
* @return Creation time * @return Creation time
*/ */
public String getCreationTime() { public ZonedDateTime getCreationTime() {
return creationTime; return creationTime;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -30,7 +30,7 @@ module de.stklcode.jvault.connector {
opens de.stklcode.jvault.connector.model.response to com.fasterxml.jackson.databind; opens de.stklcode.jvault.connector.model.response to com.fasterxml.jackson.databind;
opens de.stklcode.jvault.connector.model.response.embedded to com.fasterxml.jackson.databind; opens de.stklcode.jvault.connector.model.response.embedded to com.fasterxml.jackson.databind;
requires java.base;
requires java.net.http; requires java.net.http;
requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.datatype.jsr310;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import de.stklcode.jvault.connector.model.response.*;
import de.stklcode.jvault.connector.test.Credentials; import de.stklcode.jvault.connector.test.Credentials;
import de.stklcode.jvault.connector.test.VaultConfiguration; import de.stklcode.jvault.connector.test.VaultConfiguration;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDir;
import java.io.*; import java.io.*;
@ -50,7 +51,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.11.2"; // The vault version this test is supposed to run against. private static String VAULT_VERSION = "1.15.4"; // 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";
@ -58,6 +59,7 @@ class HTTPVaultConnectorIT {
private static final String USER_VALID = "validUser"; private static final String USER_VALID = "validUser";
private static final String PASS_VALID = "validPass"; private static final String PASS_VALID = "validPass";
private static boolean legacy;
private Process vaultProcess; private Process vaultProcess;
private VaultConnector connector; private VaultConnector connector;
@ -68,6 +70,9 @@ class HTTPVaultConnectorIT {
VAULT_VERSION = System.getenv("VAULT_VERSION"); VAULT_VERSION = System.getenv("VAULT_VERSION");
System.out.println("Vault version set to " + VAULT_VERSION); System.out.println("Vault version set to " + VAULT_VERSION);
} }
if (compareVersions(VAULT_VERSION, "1.12.0") < 0) {
legacy = true;
}
} }
/** /**
@ -547,6 +552,9 @@ class HTTPVaultConnectorIT {
@Nested @Nested
@DisplayName("App-ID Tests") @DisplayName("App-ID Tests")
@EnabledIf(value = "de.stklcode.jvault.connector.HTTPVaultConnectorIT#isLegacy",
disabledReason = "AppID tests no longer available for Vault 1.12 and above")
@SuppressWarnings("deprecation")
class AppIdTests { class AppIdTests {
private static final String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA"; private static final String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA";
private static final String USER_ID = "5ADF8218-D7FB-4089-9E38-287465DBF37E"; private static final String USER_ID = "5ADF8218-D7FB-4089-9E38-287465DBF37E";
@ -557,7 +565,6 @@ class HTTPVaultConnectorIT {
@Test @Test
@Order(10) @Order(10)
@DisplayName("Authenticate with App-ID") @DisplayName("Authenticate with App-ID")
@SuppressWarnings("deprecation")
void authAppIdTest() { void authAppIdTest() {
// Try unauthorized access first. // Try unauthorized access first.
assumeFalse(connector.isAuthorized()); assumeFalse(connector.isAuthorized());
@ -580,7 +587,6 @@ class HTTPVaultConnectorIT {
@Test @Test
@Order(20) @Order(20)
@DisplayName("Register App-ID") @DisplayName("Register App-ID")
@SuppressWarnings("deprecation")
void registerAppIdTest() { void registerAppIdTest() {
// Authorize. // Authorize.
authRoot(); authRoot();
@ -1074,8 +1080,13 @@ class HTTPVaultConnectorIT {
() -> connector.getAuthBackends(), () -> connector.getAuthBackends(),
"Could not list supported auth backends" "Could not list supported auth backends"
); );
assertEquals(4, supportedBackends.size()); if (legacy) {
assertTrue(supportedBackends.containsAll(List.of(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID, AuthBackend.APPROLE))); assertEquals(4, supportedBackends.size());
assertTrue(supportedBackends.containsAll(List.of(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID, AuthBackend.APPROLE)));
} else {
assertEquals(3, supportedBackends.size());
assertTrue(supportedBackends.containsAll(List.of(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPROLE)));
}
} }
/** /**
@ -1201,7 +1212,11 @@ class HTTPVaultConnectorIT {
*/ */
private VaultConfiguration initializeVault(File dir, boolean tls) throws IllegalStateException, IOException { private VaultConfiguration initializeVault(File dir, boolean tls) throws IllegalStateException, IOException {
File dataDir = new File(dir, "data"); File dataDir = new File(dir, "data");
copyDirectory(new File(getClass().getResource("/data_dir").getPath()), dataDir); if (legacy) {
copyDirectory(new File(getClass().getResource("/data_dir_legacy").getPath()), dataDir);
} else {
copyDirectory(new File(getClass().getResource("/data_dir").getPath()), dataDir);
}
// Generate vault local unencrypted configuration. // Generate vault local unencrypted configuration.
VaultConfiguration config = new VaultConfiguration() VaultConfiguration config = new VaultConfiguration()
@ -1295,4 +1310,35 @@ class HTTPVaultConnectorIT {
th.printStackTrace(new PrintWriter(sw, true)); th.printStackTrace(new PrintWriter(sw, true));
return sw.getBuffer().toString(); return sw.getBuffer().toString();
} }
/**
* Compare two version strings.
*
* @param version1 Version 1
* @param version2 Version 2
* @return negative value if version 1 is smaller than version2, positive value of version 1 is greater, 0 if equal
*/
private static int compareVersions(String version1, String version2) {
int comparisonResult = 0;
String[] version1Splits = version1.split("\\.");
String[] version2Splits = version2.split("\\.");
int maxLengthOfVersionSplits = Math.max(version1Splits.length, version2Splits.length);
for (int i = 0; i < maxLengthOfVersionSplits; i++) {
Integer v1 = i < version1Splits.length ? Integer.parseInt(version1Splits[i]) : 0;
Integer v2 = i < version2Splits.length ? Integer.parseInt(version2Splits[i]) : 0;
int compare = v1.compareTo(v2);
if (compare != 0) {
comparisonResult = compare;
break;
}
}
return comparisonResult;
}
private static boolean isLegacy() {
return legacy;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,9 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import nl.jqno.equalsverifier.EqualsVerifier; import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -16,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.fail;
*/ */
public abstract class AbstractModelTest<T> { public abstract class AbstractModelTest<T> {
protected final Class<?> modelClass; protected final Class<?> modelClass;
protected final ObjectMapper objectMapper;
/** /**
* Test case constructor. * Test case constructor.
@ -24,6 +29,10 @@ public abstract class AbstractModelTest<T> {
*/ */
protected AbstractModelTest(Class<T> modelClass) { protected AbstractModelTest(Class<T> modelClass) {
this.modelClass = modelClass; this.modelClass = modelClass;
this.objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -116,16 +115,14 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
*/ */
@Test @Test
void jsonTest() throws NoSuchFieldException, IllegalAccessException { void jsonTest() throws NoSuchFieldException, IllegalAccessException {
ObjectMapper mapper = new ObjectMapper();
// A simple roundtrip first. All set fields should be present afterwards.. // A simple roundtrip first. All set fields should be present afterwards..
AppRoleSecret secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR); AppRoleSecret secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
String secretJson = assertDoesNotThrow(() -> mapper.writeValueAsString(secret), "Serialization failed"); String secretJson = assertDoesNotThrow(() -> objectMapper.writeValueAsString(secret), "Serialization failed");
// CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list. // CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list.
String secretJson2 = commaSeparatedToList(secretJson); String secretJson2 = commaSeparatedToList(secretJson);
AppRoleSecret secret2 = assertDoesNotThrow( AppRoleSecret secret2 = assertDoesNotThrow(
() -> mapper.readValue(secretJson2, AppRoleSecret.class), () -> objectMapper.readValue(secretJson2, AppRoleSecret.class),
"Deserialization failed" "Deserialization failed"
); );
assertEquals(secret2.getId(), secret.getId()); assertEquals(secret2.getId(), secret.getId());
@ -145,9 +142,9 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
assumeTrue(secret.getNumUses() == 678); assumeTrue(secret.getNumUses() == 678);
setPrivateField(secret, "ttl", 12345); setPrivateField(secret, "ttl", 12345);
assumeTrue(secret.getTtl() == 12345); assumeTrue(secret.getTtl() == 12345);
String secretJson3 = assertDoesNotThrow(() -> mapper.writeValueAsString(secret), "Serialization failed"); String secretJson3 = assertDoesNotThrow(() -> objectMapper.writeValueAsString(secret), "Serialization failed");
secret2 = assertDoesNotThrow( secret2 = assertDoesNotThrow(
() -> mapper.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());
@ -165,7 +162,7 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
"\"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\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," + "\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}"; "\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}";
secret2 = assertDoesNotThrow(() -> mapper.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());
assertEquals("TEST_EXPIRATION", secret2.getExpirationTime()); assertEquals("TEST_EXPIRATION", secret2.getExpirationTime());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -110,7 +109,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
assertNull(role.getTokenType()); assertNull(role.getTokenType());
// Optional fields should be ignored, so JSON string should only contain role_name. // Optional fields should be ignored, so JSON string should only contain role_name.
assertEquals(JSON_MIN, new ObjectMapper().writeValueAsString(role)); assertEquals(JSON_MIN, objectMapper.writeValueAsString(role));
} }
/** /**
@ -137,7 +136,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
assertEquals(TOKEN_TYPE.value(), role.getTokenType()); assertEquals(TOKEN_TYPE.value(), role.getTokenType());
// Verify that all parameters are included in JSON string. // Verify that all parameters are included in JSON string.
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role)); assertEquals(JSON_FULL, objectMapper.writeValueAsString(role));
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,6 +33,7 @@ class AuthBackendTest {
* Test forType() method. * Test forType() method.
*/ */
@Test @Test
@SuppressWarnings("deprecation")
void forTypeTest() { void forTypeTest() {
assertEquals(AuthBackend.TOKEN, AuthBackend.forType("token")); assertEquals(AuthBackend.TOKEN, AuthBackend.forType("token"));
assertEquals(AuthBackend.APPID, AuthBackend.forType("app-id")); assertEquals(AuthBackend.APPID, AuthBackend.forType("app-id"));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Arrays; import java.util.Arrays;
@ -133,7 +132,7 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
assertNull(role.getTokenType()); assertNull(role.getTokenType());
// Optional fields should be ignored, so JSON string should be empty. // Optional fields should be ignored, so JSON string should be empty.
assertEquals("{}", new ObjectMapper().writeValueAsString(role)); assertEquals("{}", objectMapper.writeValueAsString(role));
} }
/** /**
@ -177,7 +176,7 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
assertEquals(role, new TokenRole()); assertEquals(role, new TokenRole());
// Optional fields should be ignored, so JSON string should be empty. // Optional fields should be ignored, so JSON string should be empty.
assertEquals("{}", new ObjectMapper().writeValueAsString(role)); assertEquals("{}", objectMapper.writeValueAsString(role));
} }
/** /**
@ -208,6 +207,6 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
assertEquals(TOKEN_TYPE.value(), role.getTokenType()); assertEquals(TOKEN_TYPE.value(), role.getTokenType());
// Verify that all parameters are included in JSON string. // Verify that all parameters are included in JSON string.
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role)); assertEquals(JSON_FULL, objectMapper.writeValueAsString(role));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -103,7 +102,7 @@ class TokenTest extends AbstractModelTest<Token> {
assertNull(token.getEntityAlias()); assertNull(token.getEntityAlias());
// Optional fields should be ignored, so JSON string should be empty. // Optional fields should be ignored, so JSON string should be empty.
assertEquals("{}", new ObjectMapper().writeValueAsString(token)); assertEquals("{}", objectMapper.writeValueAsString(token));
// Empty builder should be equal to no-arg construction. // Empty builder should be equal to no-arg construction.
assertEquals(token, new Token()); assertEquals(token, new Token());
@ -129,7 +128,7 @@ class TokenTest extends AbstractModelTest<Token> {
assertEquals(PERIOD, token.getPeriod()); assertEquals(PERIOD, token.getPeriod());
// Verify that all parameters are included in JSON string. // Verify that all parameters are included in JSON string.
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(token)); assertEquals(JSON_FULL, objectMapper.writeValueAsString(token));
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -69,7 +68,7 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
@Override @Override
protected AppRoleResponse createFull() { protected AppRoleResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class); return objectMapper.readValue(RES_JSON, AppRoleResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -92,7 +91,7 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AppRoleResponse res = assertDoesNotThrow( AppRoleResponse res = assertDoesNotThrow(
() -> new 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");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -47,7 +46,10 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
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 Integer TK_LEASE_TTL = 0;
private static final Boolean TK_FORCE_NO_CACHE = false;
private static final Integer TK_MAX_LEASE_TTL = 0; private static final Integer TK_MAX_LEASE_TTL = 0;
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 RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"data\": {" + " \"data\": {" +
@ -63,9 +65,15 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
" \"" + TK_PATH + "\": {\n" + " \"" + TK_PATH + "\": {\n" +
" \"config\": {\n" + " \"config\": {\n" +
" \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" + " \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" +
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + "\n" + " \"force_no_cache\": " + TK_FORCE_NO_CACHE + ",\n" +
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + ",\n" +
" \"token_type\": \"" + TK_TOKEN_TYPE + "\"\n" +
" },\n" + " },\n" +
" \"description\": \"" + TK_DESCR + "\",\n" + " \"description\": \"" + TK_DESCR + "\",\n" +
" \"options\": null,\n" +
" \"plugin_version\": \"\",\n" +
" \"running_plugin_version\": \"" + TK_RUNNING_PLUGIN_VERSION + "\",\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" +
@ -83,7 +91,7 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
@Override @Override
protected AuthMethodsResponse createFull() { protected AuthMethodsResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class); return objectMapper.readValue(RES_JSON, AuthMethodsResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -106,7 +114,7 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AuthMethodsResponse res = assertDoesNotThrow( AuthMethodsResponse res = assertDoesNotThrow(
() -> new 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");
@ -138,15 +146,16 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
assertTrue(method.isLocal(), "Unexpected local flag for Token"); assertTrue(method.isLocal(), "Unexpected local flag for Token");
assertFalse(method.isExternalEntropyAccess(), "Unexpected external entropy flag for Token"); assertFalse(method.isExternalEntropyAccess(), "Unexpected external entropy flag for Token");
assertFalse(method.isSealWrap(), "Unexpected seal wrap flag for GitHub"); assertFalse(method.isSealWrap(), "Unexpected seal wrap flag for GitHub");
assertEquals("", method.getPluginVersion(), "Unexpected plugin version");
assertEquals(TK_RUNNING_PLUGIN_VERSION, method.getRunningPluginVersion(), "Unexpected running plugin version");
assertEquals("", method.getRunningSha256(), "Unexpected running SHA256");
assertNotNull(method.getConfig(), "Missing config for Token"); assertNotNull(method.getConfig(), "Missing config for Token");
assertEquals( assertEquals(TK_LEASE_TTL, method.getConfig().getDefaultLeaseTtl(), "Unexpected default TTL");
Map.of( assertEquals(TK_MAX_LEASE_TTL, method.getConfig().getMaxLeaseTtl(), "Unexpected max TTL");
"default_lease_ttl", TK_LEASE_TTL.toString(), assertEquals(TK_FORCE_NO_CACHE, method.getConfig().getForceNoCache(), "Unexpected force no cache flag");
"max_lease_ttl", TK_MAX_LEASE_TTL.toString() assertEquals(TK_TOKEN_TYPE, method.getConfig().getTokenType(), "Unexpected token type");
),
method.getConfig(), assertNull(method.getOptions(), "Unexpected options");
"Unexpected config for Token"
);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,9 +17,12 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.MfaMethodId;
import de.stklcode.jvault.connector.model.response.embedded.MfaRequirement;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Map; import java.util.Map;
@ -45,29 +48,50 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
private static final String AUTH_ENTITY_ID = ""; private static final String AUTH_ENTITY_ID = "";
private static final String AUTH_TOKEN_TYPE = "service"; private static final String AUTH_TOKEN_TYPE = "service";
private static final Boolean AUTH_ORPHAN = false; private static final Boolean AUTH_ORPHAN = false;
private static final String MFA_REQUEST_ID = "d0c9eec7-6921-8cc0-be62-202b289ef163";
private static final String MFA_KEY = "enforcementConfigUserpass";
private static final String MFA_METHOD_TYPE = "totp";
private static final String MFA_METHOD_ID = "820997b3-110e-c251-7e8b-ff4aa428a6e1";
private static final Boolean MFA_METHOD_USES_PASSCODE = true;
private static final String MFA_METHOD_NAME = "sample_mfa_method_name";
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"auth\": {\n" + " \"auth\": {\n" +
" \"accessor\": \"" + AUTH_ACCESSOR + "\",\n" + " \"accessor\": \"" + AUTH_ACCESSOR + "\",\n" +
" \"client_token\": \"" + AUTH_CLIENT_TOKEN + "\",\n" + " \"client_token\": \"" + AUTH_CLIENT_TOKEN + "\",\n" +
" \"policies\": [\n" + " \"policies\": [\n" +
" \"" + AUTH_POLICY_1 + "\", \n" + " \"" + AUTH_POLICY_1 + "\", \n" +
" \"" + AUTH_POLICY_2 + "\"\n" + " \"" + AUTH_POLICY_2 + "\"\n" +
" ],\n" + " ],\n" +
" \"token_policies\": [\n" + " \"token_policies\": [\n" +
" \"" + AUTH_POLICY_2 + "\",\n" + " \"" + AUTH_POLICY_2 + "\",\n" +
" \"" + AUTH_POLICY_1 + "\" \n" + " \"" + AUTH_POLICY_1 + "\" \n" +
" ],\n" + " ],\n" +
" \"metadata\": {\n" + " \"metadata\": {\n" +
" \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" + " \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" +
" },\n" + " },\n" +
" \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" + " \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" +
" \"renewable\": " + AUTH_RENEWABLE + ",\n" + " \"renewable\": " + AUTH_RENEWABLE + ",\n" +
" \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" + " \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" +
" \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" + " \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" +
" \"orphan\": " + AUTH_ORPHAN + "\n" + " \"orphan\": " + AUTH_ORPHAN + ",\n" +
" }\n" + " \"mfa_requirement\": {\n" +
"}"; " \"mfa_request_id\": \"" + MFA_REQUEST_ID + "\",\n" +
" \"mfa_constraints\": {\n" +
" \"" + MFA_KEY + "\": {\n" +
" \"any\": [\n" +
" {\n" +
" \"type\": \"" + MFA_METHOD_TYPE + "\",\n" +
" \"id\": \"" + MFA_METHOD_ID + "\",\n" +
" \"uses_passcode\": " + MFA_METHOD_USES_PASSCODE + ",\n" +
" \"name\": \"" + MFA_METHOD_NAME + "\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
AuthResponseTest() { AuthResponseTest() {
super(AuthResponse.class); super(AuthResponse.class);
@ -76,20 +100,27 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
@Override @Override
protected AuthResponse createFull() { protected AuthResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_JSON, AuthResponse.class); return objectMapper.readValue(RES_JSON, AuthResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
} }
} }
@Test
void testEqualsHashcodeMfa() {
EqualsVerifier.simple().forClass(MfaRequirement.class).verify();
EqualsVerifier.simple().forClass(MfaConstraintAny.class).verify();
EqualsVerifier.simple().forClass(MfaMethodId.class).verify();
}
/** /**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation). * Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/ */
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
AuthResponse res = assertDoesNotThrow( AuthResponse res = assertDoesNotThrow(
() -> new 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");
@ -108,5 +139,14 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
assertEquals(2, data.getTokenPolicies().size(), "Incorrect number of token policies"); assertEquals(2, data.getTokenPolicies().size(), "Incorrect number of token policies");
assertTrue(data.getTokenPolicies().containsAll(Set.of(AUTH_POLICY_2, AUTH_POLICY_1)), "Incorrect token policies"); assertTrue(data.getTokenPolicies().containsAll(Set.of(AUTH_POLICY_2, AUTH_POLICY_1)), "Incorrect token policies");
assertEquals(Map.of(AUTH_META_KEY, AUTH_META_VALUE), data.getMetadata(), "Incorrect auth metadata"); assertEquals(Map.of(AUTH_META_KEY, AUTH_META_VALUE), data.getMetadata(), "Incorrect auth metadata");
assertEquals(MFA_REQUEST_ID, data.getMfaRequirement().getMfaRequestId(), "Incorrect MFA request ID");
assertEquals(Set.of(MFA_KEY), data.getMfaRequirement().getMfaConstraints().keySet(), "Incorrect MFA constraint keys");
var mfaConstraint = data.getMfaRequirement().getMfaConstraints().get(MFA_KEY);
assertEquals(1, mfaConstraint.getAny().size(), "Incorrect number of any constraints");
assertEquals(MFA_METHOD_TYPE, mfaConstraint.getAny().get(0).getType(), "Incorrect MFA method type");
assertEquals(MFA_METHOD_ID, mfaConstraint.getAny().get(0).getId(), "Incorrect MFA method type");
assertEquals(MFA_METHOD_USES_PASSCODE, mfaConstraint.getAny().get(0).getUsesPasscode(), "Incorrect MFA method uses passcode");
assertEquals(MFA_METHOD_NAME, mfaConstraint.getAny().get(0).getName(), "Incorrect MFA method uses passcode");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AbstractModelTest; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -52,7 +51,7 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
@Override @Override
protected CredentialsResponse createFull() { protected CredentialsResponse createFull() {
try { try {
return new ObjectMapper().readValue(JSON, CredentialsResponse.class); return objectMapper.readValue(JSON, CredentialsResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -72,7 +71,7 @@ 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(
() -> new 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");

View File

@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -44,7 +43,7 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
@Override @Override
protected ErrorResponse createFull() { protected ErrorResponse createFull() {
try { try {
return new ObjectMapper().readValue(JSON, ErrorResponse.class); return objectMapper.readValue(JSON, ErrorResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -56,16 +55,15 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
*/ */
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
ObjectMapper om = new ObjectMapper();
ErrorResponse res = assertDoesNotThrow( ErrorResponse res = assertDoesNotThrow(
() -> om.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(() -> om.writeValueAsString(res), "ErrorResponse serialization failed"), assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "ErrorResponse serialization failed"),
"Unexpected JSON string after serialization" "Unexpected JSON string after serialization"
); );
} }
@ -74,13 +72,13 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
@Test @Test
void testToString() { void testToString() {
ErrorResponse res = assertDoesNotThrow( ErrorResponse res = assertDoesNotThrow(
() -> new 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(
() -> new 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

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -61,7 +60,7 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
@Override @Override
protected HealthResponse createFull() { protected HealthResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_JSON, HealthResponse.class); return objectMapper.readValue(RES_JSON, HealthResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -74,7 +73,7 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
HealthResponse res = assertDoesNotThrow( HealthResponse res = assertDoesNotThrow(
() -> new 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");

View File

@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -40,7 +39,7 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
@Override @Override
protected HelpResponse createFull() { protected HelpResponse createFull() {
try { try {
return new ObjectMapper().readValue(JSON, HelpResponse.class); return objectMapper.readValue(JSON, HelpResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -52,16 +51,15 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
*/ */
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
ObjectMapper om = new ObjectMapper();
HelpResponse res = assertDoesNotThrow( HelpResponse res = assertDoesNotThrow(
() -> om.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(() -> om.writeValueAsString(res), "HelpResponse serialization failed"), assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "HelpResponse serialization failed"),
"Unexpected JSON string after serialization" "Unexpected JSON string after serialization"
); );
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -89,7 +88,7 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
@Override @Override
protected MetaSecretResponse createFull() { protected MetaSecretResponse createFull() {
try { try {
return new ObjectMapper().readValue(SECRET_JSON_V2, MetaSecretResponse.class); return objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -103,21 +102,21 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
void jsonRoundtrip() { void jsonRoundtrip() {
// KV v2 secret. // KV v2 secret.
MetaSecretResponse res = assertDoesNotThrow( MetaSecretResponse res = assertDoesNotThrow(
() -> new 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");
assertEquals(SECRET_META_CREATED, res.getMetadata().getCreatedTimeString(), "Incorrect creation date string"); assertEquals(SECRET_META_CREATED, res.getMetadata().getCreatedTimeString(), "Incorrect creation date string");
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed"); assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
assertEquals("", res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string"); assertNull(res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date"); assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
assertFalse(res.getMetadata().isDestroyed(), "Secret destroyed when not expected"); assertFalse(res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
assertEquals(1, res.getMetadata().getVersion(), "Incorrect secret version"); assertEquals(1, res.getMetadata().getVersion(), "Incorrect secret version");
// Deleted KV v2 secret. // Deleted KV v2 secret.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> new 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);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -71,7 +70,7 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
@Override @Override
protected MetadataResponse createFull() { protected MetadataResponse createFull() {
try { try {
return new ObjectMapper().readValue(META_JSON, MetadataResponse.class); return objectMapper.readValue(META_JSON, MetadataResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -84,7 +83,7 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
MetadataResponse res = assertDoesNotThrow( MetadataResponse res = assertDoesNotThrow(
() -> new 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");

View File

@ -16,12 +16,13 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; 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;
import java.util.List; import java.util.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -60,7 +61,7 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
@Override @Override
protected PlainSecretResponse createFull() { protected PlainSecretResponse createFull() {
try { try {
return new ObjectMapper().readValue(SECRET_JSON, PlainSecretResponse.class); return objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -73,7 +74,7 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
SecretResponse res = assertDoesNotThrow( SecretResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON, PlainSecretResponse.class), () -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
@ -86,4 +87,137 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
assertEquals(SECRET_DATA_V1, res.get(SECRET_DATA_K1), "Response does not contain correct data"); assertEquals(SECRET_DATA_V1, res.get(SECRET_DATA_K1), "Response does not contain correct data");
assertEquals(SECRET_DATA_V2, res.get(SECRET_DATA_K2), "Response does not contain correct data"); assertEquals(SECRET_DATA_V2, res.get(SECRET_DATA_K2), "Response does not contain correct data");
} }
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
void testGetter() {
final var stringKey = "string";
final var stringVal = "test";
final var numberKey = "number";
final var numberVal = 123.45;
final var listKey = "list";
final var listVal = List.of("foo", "bar");
final var complexKey = "complex";
final var complexVal = new ComplexType("val1", 678);
SecretResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(
"{\n" +
" \"request_id\": \"req-id\",\n" +
" \"lease_id\": \"lea-id\",\n" +
" \"lease_duration\": " + 123456 + ",\n" +
" \"renewable\": true,\n" +
" \"data\": {\n" +
" \"" + stringKey + "\": \"" + stringVal + "\",\n" +
" \"" + numberKey + "\": \"" + numberVal + "\",\n" +
" \"" + listKey + "\": [\"" + String.join("\", \"", listVal) + "\"],\n" +
" \"" + complexKey + "\": {" +
" \"field1\": \"" + complexVal.field1 + "\",\n" +
" \"field2\": " + complexVal.field2 + "\n" +
" },\n" +
" \"" + complexKey + "Json\": \"" + objectMapper.writeValueAsString(complexVal).replace("\"", "\\\"") + "\"\n" +
" }\n" +
"}",
PlainSecretResponse.class
),
"SecretResponse deserialization failed"
);
assertEquals(stringVal, res.get(stringKey), "unexpected value for string (implicit)");
assertEquals(
stringVal,
assertDoesNotThrow(() -> res.get(stringKey, String.class), "getting string failed"),
"unexpected value for string (explicit)"
);
assertEquals(String.valueOf(numberVal), res.get(numberKey), "unexpected value for number (implicit)");
assertEquals(
numberVal,
assertDoesNotThrow(() -> res.get(numberKey, Double.class), "getting number failed"),
"unexpected value for number (explicit)"
);
assertEquals(
String.valueOf(numberVal),
assertDoesNotThrow(() -> res.get(numberKey, String.class), "getting number as string failed"),
"unexpected value for number as string (explicit)"
);
assertEquals(listVal, res.get(listKey), "unexpected value for list (implicit)");
assertEquals(
listVal,
assertDoesNotThrow(() -> res.get(listKey, ArrayList.class), "getting list failed"),
"unexpected value for list (explicit)"
);
assertEquals(complexVal.toMap(), res.get(complexKey), "unexpected value for complex type (implicit)");
assertEquals(
complexVal.toMap(),
assertDoesNotThrow(() -> res.get(complexKey, HashMap.class), "getting complex type as map failed"),
"unexpected value for complex type as map (explicit)"
);
assertEquals(
complexVal,
assertDoesNotThrow(() -> res.get(complexKey, ComplexType.class), "getting complex type failed"),
"unexpected value for complex type (explicit)"
);
assertThrows(
InvalidResponseException.class,
() -> res.get(complexKey, Integer.class),
"getting complex type as integer should fail"
);
assertEquals(
complexVal,
assertDoesNotThrow(() -> res.get(complexKey + "Json", ComplexType.class), "getting complex type from JSON string failed"),
"unexpected value for complex type from JSON string"
);
}
/**
* Test class for complex field mapping.
*/
private static class ComplexType {
@JsonProperty("field1")
private String field1;
@JsonProperty("field2")
private Integer field2;
private ComplexType() {
// Required for JSON deserialization.
}
private ComplexType(String field1, Integer field2) {
this.field1 = field1;
this.field2 = field2;
}
private Map<String, Object> toMap() {
return Map.of(
"field1", field1,
"field2", field2
);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
ComplexType that = (ComplexType) o;
return Objects.equals(field1, that.field1) && Objects.equals(field2, that.field2);
}
@Override
public int hashCode() {
return Objects.hash(field1, field2);
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,10 +17,11 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.time.ZonedDateTime;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
@ -35,7 +36,8 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
private static final Integer SHARES = 5; private static final Integer SHARES = 5;
private static final Integer PROGRESS_SEALED = 2; private static final Integer PROGRESS_SEALED = 2;
private static final Integer PROGRESS_UNSEALED = 0; private static final Integer PROGRESS_UNSEALED = 0;
private static final String VERSION = "1.8.2"; private static final String VERSION = "1.15.4";
private static final String BUILD_DATE = "2023-11-22T20:59:54Z";
private static final String CLUSTER_NAME = "vault-cluster-d6ec3c7f"; private static final String CLUSTER_NAME = "vault-cluster-d6ec3c7f";
private static final String CLUSTER_ID = "3e8b3fec-3749-e056-ba41-b62a63b997e8"; private static final String CLUSTER_ID = "3e8b3fec-3749-e056-ba41-b62a63b997e8";
private static final String NONCE = "ef05d55d-4d2c-c594-a5e8-55bc88604c24"; private static final String NONCE = "ef05d55d-4d2c-c594-a5e8-55bc88604c24";
@ -52,6 +54,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
" \"progress\": " + PROGRESS_SEALED + ",\n" + " \"progress\": " + PROGRESS_SEALED + ",\n" +
" \"nonce\": \"\",\n" + " \"nonce\": \"\",\n" +
" \"version\": \"" + VERSION + "\",\n" + " \"version\": \"" + VERSION + "\",\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" +
@ -65,6 +68,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
" \"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" +
" \"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" +
@ -80,7 +84,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
@Override @Override
protected SealResponse createFull() { protected SealResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class); return objectMapper.readValue(RES_UNSEALED, SealResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -94,7 +98,7 @@ 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(
() -> new 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");
@ -106,6 +110,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
assertEquals(PROGRESS_SEALED, res.getProgress(), "Incorrect progress"); assertEquals(PROGRESS_SEALED, res.getProgress(), "Incorrect progress");
assertEquals("", res.getNonce(), "Nonce not empty"); assertEquals("", res.getNonce(), "Nonce not empty");
assertEquals(VERSION, res.getVersion(), "Incorrect version"); assertEquals(VERSION, res.getVersion(), "Incorrect version");
assertEquals(ZonedDateTime.parse(BUILD_DATE), res.getBuildDate(), "Incorrect build date");
assertEquals(MIGRATION, res.getMigration(), "Incorrect migration"); assertEquals(MIGRATION, res.getMigration(), "Incorrect migration");
assertEquals(RECOVERY_SEAL, res.getRecoverySeal(), "Incorrect recovery seal"); assertEquals(RECOVERY_SEAL, res.getRecoverySeal(), "Incorrect recovery seal");
assertEquals(STORAGE_TYPE, res.getStorageType(), "Incorrect storage type"); assertEquals(STORAGE_TYPE, res.getStorageType(), "Incorrect storage type");
@ -116,7 +121,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
// Not test unsealed Vault's response. // Not test unsealed Vault's response.
res = assertDoesNotThrow( res = assertDoesNotThrow(
() -> new 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");
@ -128,6 +133,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
assertEquals(PROGRESS_UNSEALED, res.getProgress(), "Incorrect progress"); assertEquals(PROGRESS_UNSEALED, res.getProgress(), "Incorrect progress");
assertEquals(NONCE, res.getNonce(), "Incorrect nonce"); assertEquals(NONCE, res.getNonce(), "Incorrect nonce");
assertEquals(VERSION, res.getVersion(), "Incorrect version"); assertEquals(VERSION, res.getVersion(), "Incorrect version");
assertEquals(ZonedDateTime.parse(BUILD_DATE), res.getBuildDate(), "Incorrect build date");
assertEquals(CLUSTER_NAME, res.getClusterName(), "Incorrect cluster name"); assertEquals(CLUSTER_NAME, res.getClusterName(), "Incorrect cluster name");
assertEquals(CLUSTER_ID, res.getClusterId(), "Incorrect cluster ID"); assertEquals(CLUSTER_ID, res.getClusterId(), "Incorrect cluster ID");
assertEquals(MIGRATION, res.getMigration(), "Incorrect migration"); assertEquals(MIGRATION, res.getMigration(), "Incorrect migration");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -54,7 +53,7 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
@Override @Override
protected SecretListResponse createFull() { protected SecretListResponse createFull() {
try { try {
return new ObjectMapper().readValue(JSON, SecretListResponse.class); return objectMapper.readValue(JSON, SecretListResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -67,7 +66,7 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
@Test @Test
void getKeysTest() { void getKeysTest() {
SecretListResponse res = assertDoesNotThrow( SecretListResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(JSON, SecretListResponse.class), () -> objectMapper.readValue(JSON, SecretListResponse.class),
"SecretListResponse deserialization failed" "SecretListResponse deserialization failed"
); );

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -50,7 +49,7 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
@Override @Override
protected SecretVersionResponse createFull() { protected SecretVersionResponse createFull() {
try { try {
return new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class); return objectMapper.readValue(META_JSON, SecretVersionResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -63,7 +62,7 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
SecretVersionResponse res = assertDoesNotThrow( SecretVersionResponse res = assertDoesNotThrow(
() -> new 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");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
@ -96,7 +95,7 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
@Override @Override
protected TokenResponse createFull() { protected TokenResponse createFull() {
try { try {
return new ObjectMapper().readValue(RES_JSON, TokenResponse.class); return objectMapper.readValue(RES_JSON, TokenResponse.class);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e); fail("Creation of full model instance failed", e);
return null; return null;
@ -119,7 +118,7 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
TokenResponse res = assertDoesNotThrow( TokenResponse res = assertDoesNotThrow(
() -> new 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");

View File

@ -0,0 +1,103 @@
package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* Unit test for {@link MountConfig}.
*
* @author Stefan Kalscheuer
*/
class MountConfigTest extends AbstractModelTest<MountConfig> {
private static final Integer DEFAULT_LEASE_TTL = 1800;
private static final Integer MAX_LEASE_TTL = 3600;
private static final Boolean FORCE_NO_CACHE = false;
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_2 = "req2";
private static final String AUDIT_NON_HMAC_RES_KEYS_1 = "res1";
private static final String AUDIT_NON_HMAC_RES_KEYS_2 = "res2";
private static final String LISTING_VISIBILITY = "unauth";
private static final String PT_REQ_HEADER_1 = "prh1";
private static final String PT_REQ_HEADER_2 = "prh2";
private static final String ALLOWED_RES_HEADER_1 = "arh1";
private static final String ALLOWED_RES_HEADER_2 = "arh2";
private static final String ALLOWED_MANAGED_KEY_1 = "amk1";
private static final String ALLOWED_MANAGED_KEY_2 = "amk2";
private static final String DEL_AUTH_ACCESSOR_1 = "daa1";
private static final String DEL_AUTH_ACCESSOR_2 = "daa2";
private static final Integer LOCKOUT_THRESH = 7200;
private static final Integer LOCKOUT_DURATION = 86400;
private static final Integer LOCKOUT_CNT_RESET_DURATION = 43200;
private static final Boolean LOCKOUT_DISABLE = false;
private static final String RES_JSON = "{\n" +
" \"default_lease_ttl\": " + DEFAULT_LEASE_TTL + ",\n" +
" \"force_no_cache\": " + FORCE_NO_CACHE + ",\n" +
" \"max_lease_ttl\": " + MAX_LEASE_TTL + ",\n" +
" \"token_type\": \"" + TOKEN_TYPE + "\",\n" +
" \"audit_non_hmac_request_keys\": [\"" + AUDIT_NON_HMAC_REQ_KEYS_1 + "\", \"" + AUDIT_NON_HMAC_REQ_KEYS_2 + "\"],\n" +
" \"audit_non_hmac_response_keys\": [\"" + AUDIT_NON_HMAC_RES_KEYS_1 + "\", \"" + AUDIT_NON_HMAC_RES_KEYS_2 + "\"],\n" +
" \"listing_visibility\": \"" + LISTING_VISIBILITY + "\",\n" +
" \"passthrough_request_headers\": [\"" + PT_REQ_HEADER_1 + "\", \"" + PT_REQ_HEADER_2 + "\"],\n" +
" \"allowed_response_headers\": [\"" + ALLOWED_RES_HEADER_1 + "\", \"" + ALLOWED_RES_HEADER_2 + "\"],\n" +
" \"allowed_managed_keys\": [\"" + ALLOWED_MANAGED_KEY_1 + "\", \"" + ALLOWED_MANAGED_KEY_2 + "\"],\n" +
" \"delegated_auth_accessors\": [\"" + DEL_AUTH_ACCESSOR_1 + "\", \"" + DEL_AUTH_ACCESSOR_2 + "\"],\n" +
" \"user_lockout_config\": {\n" +
" \"lockout_threshold\": " + LOCKOUT_THRESH + ",\n" +
" \"lockout_duration\": " + LOCKOUT_DURATION + ",\n" +
" \"lockout_counter_reset_duration\": " + LOCKOUT_CNT_RESET_DURATION + ",\n" +
" \"lockout_disable\": " + LOCKOUT_DISABLE + "\n" +
" }\n" +
"}";
MountConfigTest() {
super(MountConfig.class);
}
@Override
protected MountConfig createFull() {
try {
return objectMapper.readValue(RES_JSON, MountConfig.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
}
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
void jsonRoundtrip() {
MountConfig mountConfig = assertDoesNotThrow(
() -> objectMapper.readValue(RES_JSON, MountConfig.class),
"MountConfig deserialization failed"
);
assertNotNull(mountConfig, "Parsed response is NULL");
// Verify data.
assertEquals(DEFAULT_LEASE_TTL, mountConfig.getDefaultLeaseTtl(), "Unexpected default lease TTL");
assertEquals(MAX_LEASE_TTL, mountConfig.getMaxLeaseTtl(), "Unexpected max lease TTL");
assertEquals(FORCE_NO_CACHE, mountConfig.getForceNoCache(), "Unexpected force no cache");
assertEquals(TOKEN_TYPE, mountConfig.getTokenType(), "Unexpected token type");
assertEquals(List.of(AUDIT_NON_HMAC_REQ_KEYS_1, AUDIT_NON_HMAC_REQ_KEYS_2), mountConfig.getAuditNonHmacRequestKeys(), "Unexpected audit no HMAC request keys");
assertEquals(List.of(AUDIT_NON_HMAC_RES_KEYS_1, AUDIT_NON_HMAC_RES_KEYS_2), mountConfig.getAuditNonHmacResponseKeys(), "Unexpected audit no HMAC response keys");
assertEquals(LISTING_VISIBILITY, mountConfig.getListingVisibility(), "Unexpected listing visibility");
assertEquals(List.of(PT_REQ_HEADER_1, PT_REQ_HEADER_2), mountConfig.getPassthroughRequestHeaders(), "Unexpected passthrough request headers");
assertEquals(List.of(ALLOWED_RES_HEADER_1, ALLOWED_RES_HEADER_2), mountConfig.getAllowedResponseHeaders(), "Unexpected allowed response headers");
assertEquals(List.of(ALLOWED_MANAGED_KEY_1, ALLOWED_MANAGED_KEY_2), mountConfig.getAllowedManagedKeys(), "Unexpected allowed managed keys");
assertEquals(List.of(DEL_AUTH_ACCESSOR_1, DEL_AUTH_ACCESSOR_2), mountConfig.getDelegatedAuthAccessors(), "Unexpected delegate auth accessors");
assertNotNull(mountConfig.getUserLockoutConfig(), "Missing user lockout config");
var ulc = mountConfig.getUserLockoutConfig();
assertEquals(LOCKOUT_THRESH, ulc.getLockoutThreshold(), "Unexpected lockout threshold");
assertEquals(LOCKOUT_DURATION, ulc.getLockoutDuration(), "Unexpected lockout duration");
assertEquals(LOCKOUT_CNT_RESET_DURATION, ulc.getLockoutCounterResetDuration(), "Unexpected lockout counter reset duration");
assertEquals(LOCKOUT_DISABLE, ulc.getLockoutDisable(), "Unexpected lockout disable");
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2022 Stefan Kalscheuer * Copyright 2016-2023 Stefan Kalscheuer
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1 +1 @@
{"Value":"AAAAAQKHd7fFuNKfj/RnIQoxQEOTorNNl1NfcVtynLwYvtvZGDvhAO34YmOFKJSQVSiT4Js08ik48DWWnZHCZzAyMlK0HqNGYQRzCkuHkzYpH0uLrTcddXLuKyc7j6IiRTl3qYb1pzdlTzDtlwsi4J7s+7orETS146yY/GnGPWM/Tmet7p5qOECRq7m04gBX0pnwZl12iRqWG4aHHY5D4aFp9KjKUBKCIhz2Tb9wcSKV/Aa/ct1d0K0k8pyu1r1OkaJqCQXQeIaJR/WBMECR4omezvg7IGCoBIkMjwFR1urSaB0xNdgk+ByZE0C5zeDfmVRylYlypPAlIBrGL/Q/d6+NWiiOzXdoQoqAa/Pyg7e2gClsKDBFDvSL1QVBdsnBIskDeig2t46Ew5qM00wY58BWlUxqjlCgsNm3nPHtWpc6+XiR4ZkEZ9VeEIQhwC/R+NxS+QCDKeuSfyZM3OqQBwOx22mTL0i86YzlUph0alBmDF1b1FkDbg46MSWTANrkov1LPDnOvvNet7pb0L6exN5Q+HKitmxn36E0KAiqj1hEaHMZF6Pe+IIScLPClgPNeMkZWLeD5kvLv9kfObTYneHVHqj8O9jGtk03T4vOoaUNJY9U0irBGzlV+GkneJUgBL1QBspfK4GvFvUrd0Ds/teayJba8HDxlpCEWr6h062BXsNPg5gUn4H/uvginsFng02M8IyrDA1QOb4XS1zdfrvq"} {"Value":"AAAAAQK788ueZMqWkxK0+QrdrSU6/fJE0BHpMFCmXuZch21YdFNQSxZwgbTTH6uAyzxlEpHvAa4v9ScNyYXqRCLFK4X0DtDmpheIr/Ow6BPU8yxNglfI+qW5SKZKeYAYMHal0jX1MYsaIdYp8LJm52VMa+CdjTRx1J7ZhrNqiNHXbVJr6uOM+FDbGU4W8LyDy1ZhBKo17fwMnOycl5vBHu7b964iVHAIDkZHBq/4N1R/w7Sne7K/JvNPfuBNd1evRSErRNJRPp4DEkpK2v8lgIAXFjemE+aOysWYjGh/XVi8EzP09K1QFwfsvgIeIX0XVP4wMNn2xHedDyWQV55FJbD1LcrM2Q54HAHM0YGItI+MwPPzmP06Udoq3PZNRMWRI3l1rdjnIT+3FtbJr43EF8mf6SuYCzf9QWkGkixWAPAsMO+ZYCkHfsp8Ebq5IQmgK2IXzR7Dw8+tizs+8jaXB5JJ1vru0dZJa3b1oV9eizW5U53yIWNhC2v/d0rVxivvMbZ2deAP9OaqXm+oFukIjaFHDNbAskqvpHh8/7e91fqDFla2ZNEEPtVSsBBmyKHO0gDiDHKC3T2hrvvSRHsMHplIpD1mnppE2E4BlngIDgrfAe3G2jKUHg9eYLq9dMXBeysfzc8UtBI="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQINZKQEssY4IzHI/0k27nBtxSvnC6LkivYrqky6CblcjyAmQIg/4/cKQIBCXzmrWEv/SqMQbLw+4Lp63Xu1niF+U0NbyqDmFaPqnD2yfPs7meXvZr21+P9E/0APZMHQaSR7DIEY46zedHRjQ/pkhR2Axcjuy5gdfzBzC2XvUcNqdyR0pQwcDwGhAIdO0gxJfZCeBuvv8ceYS+aPs4gDHtIlA3szi+5qAQ8HvPBTDKQn1lHVYnzTdNbMS7v3mtzCyG8AeMkaUw=="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQJiN0bHxM8aNJpY7aHGZ/p3qOhJbd7JIXwFMEI4LtKmO6pP5Oa4P5z+2LK+2qzZhhX/iDeM4u+nR+lxt/GsBPKf"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQIZ5rvzLtBcBQvWqwwDoRADwUo6W0ECKgmcvXejbLKiYcbO0hP8fceCqB12J41wxcMViQ8vvWoIgyOX2HwcZS09GGCqQbjvyVfz/w+kyox9dJzr845f26tJjHVYlHX2YFsnxytwe5qCKdCsD5QP9kyz8J0="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQJIKXgvJ2Prr92Fn7qZK/WZxb+Q+vJsXyjMo44en/+zqbbnLfs5m7uH7hEUOfDM/MjzTrhfkOWxf6qcrC4MR3ocrFJwtbJ6j+QrNLg61gVIiLBUVBkvh8ErqCFnSjNIqhaIMQhuZXWANsgGF9K2+HBGJerWGe26C1rdWRZV4J0M23HnxLBf8aYDlOfkHe24I30rHUqXIk9/BKEuekcnhETw9Tx4Fk7KxxxEdGmHPbg+4G14c27wVj8IrpWHBpyLmt55Qdb/y24i5RzFYv1FQ2kQZIO6TQiYkwAUxJ5cIdCiAsEDNt+rBJ9zX1MvkEfkVj/WvzC9pxB7ad+j5vYIJgCUD1o09t0w2ChjBojGoOAWDSvNAeY8kr5PDKwYk+gBY5M2JHDI6ELvOVu8gsW+sqk9St9V3VisShTfU3+qln7TOWw/LQ+fUzGvYrAWG6UyPVpIEYeNmN0iGCIM8rzjQYvVC3KcQMG96MwK3ZlSQzgPpvTGxNxFm2omTn3ue7QHn7Ni6+c/K6xVy0bbJ+jS4yyfl2wFBm1tF1l3BITLqw3TiP3LEw=="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQIUt2iYYy9zOwkx1mtNMHt69RjdHbUmcN8zydVQTMGjhv1kjEW+d4AaBv1qE22rPTs0xL3pJ1AjIvkBXXVBAuc/FE63t5dE81Fa+MvSY4tBeMtl6i09ykkAYyQUeeV2HlbjRpMUwPyq2QIslYw3d4lc73yT0S82s5I3MfjodKmDpheWMOgg5hGes/wstBHN5HEZkKV8gOPRZ/BsTM7tMXH1piM/JT8sNfsDh6TAGD1OEsS+N2QlKvS4yImNzcKrH0EgdkXB4sRZ9e/SmMaEVaagB1n0M5LukC+pyExgC7eK4EU8o2Xye3iij3YMWBaGollDzJBJFP5aSO4E5u+NnRc5/ZbLRCbqgfQj8IY86WF9hya31aJxbc8Pg28Yfez8hbGRJZZws/ojIUgEz+VtH3OyaW2Wohnycop7i4fK8xlJ2gYOGvlw43czOH6Y6joTce+QBZWI7KR6ugB0dI8pnK2eFy14OZeww1NEew7r1u7PgD10Obg8okIJSD8cGkxUHu/oOLxvKKOAJBLSPfKnJfKEiKrqYED7EPkmgP/t7okvo4c95qeuWy1BLtKfxw5lkv0="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQKv0Yr+QFSWxYe8o51TBwGz/yAhNYFmkNHPISEK6EbIVGkpEJMHFYvHWxTXUzF7f2/a"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQKs2/ICwQPLv6siBGDbBnB52fBVo52BkSKGvm74p4oHrdMEvejJ4cJljOADYyDT2QYa"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQIq05o3NmsucipTxPrcRbT1sXpAJ8w2PpiShnof74Kuzf/4kkHj3AZL5AObGFLAkYUvUrv3RRmYBIhw6Jk4FCbgdQyJAjPNVUTwBun/kQVyzP5sQ9hUFgHJwINomtVDiDgPkOc92zk8ydr1hfnMmTAtS71G3xloHDn6CF/1Y9WI1PkHdSkZ8d+yBNxr+qjGyewrV3QVmQvAfpY56uQ6AOztItD9NgiPrtNP+clbCczsieY6Y9Ce2FZawmuKFi9svMcBtnEcMILV/SGt4iCiMgFwkCJ9gQsGEdWPifu6ITPB92LgT4Ccw4gVRO31QVcPl6S+FG6iCeN6lk2yRXYjyhBuU+GklouEZIsA6SoxlIXPZuvauyS1MWwMxtSOQUFVYr3kvtXzCpcpEHDyBOEUdxPaYUZXHNdhGtMr/JuJCN50t0ng5mEAqfhjoJfJ/tBTqAjySj4zmEHuY0RnqYLPmsp203Q="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQI695zhv1Tv/6m1Fx/L62lITd+ZWCi+xCDHkev2YtCSIDPrZgNzYnrCHG3cUjBePZt6NYUSgzvZTXbxZPN4rK2rPj/BN9xj9v1vH1woOMY6lNPmBR7r"}

Some files were not shown because too many files have changed in this diff Show More