55 Commits

Author SHA1 Message Date
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
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
2412a291f6 prepare release of v1.1.1
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-29 10:02:41 +02:00
b5ed7704e3 test: scan for "Vault server started" instead of fixed delay
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-29 09:42:23 +02:00
a1626aa1c7 ci: fix drone CI pipeline
All checks were successful
continuous-integration/drone/push Build is passing
The Ubuntu Focal base image does not ship "unzip" by default, so using
the current Maven/JDK image we cannot extract the Vault binary.
Add an additional setup step to solve this problem.
2022-08-16 16:56:28 +02:00
3fb8454711 ci: update CI pipelines and test dependencies
Some checks failed
continuous-integration/drone/push Build is failing
2022-08-14 20:35:54 +02:00
ecf18881b9 test: extend assertion for warnings creating token with custom ID
All checks were successful
continuous-integration/drone/push Build is passing
With Vault 1.11 a second warning is raised. We accept "at least one"
for now.
2022-06-23 18:29:23 +02:00
69287f7196 deps: update jackson dependency to 2.13.2 2022-06-23 18:28:17 +02:00
4b1b4399e1 test against Vault 1.11.0 2022-06-23 18:16:40 +02:00
9ce819b1d0 prepare release of v1.1.0
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-24 17:54:04 +02:00
64e55eddd8 model: add request ID to data response models
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-24 16:44:50 +02:00
feb6e147fe model: add support for (dis)allowed policy glob patterns in TokenRole
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-24 16:40:33 +02:00
b0d2b038eb model: add missing fields to AuthMethod model
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-24 16:32:49 +02:00
f3cc16f44a test: bundle serialization tests into abstract test case
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-19 17:24:17 +02:00
4f3cb4b330 model: eliminate double-mapping of generic data in response classes
Explicitly declare mapping of the "data" field in response classes.
Therefore, the JSON setter setData() is no longer used. SecretResponse
is split into subclasses for secret with and without metadata.
2022-04-19 17:24:16 +02:00
021421a54c model: implement Serializable with model classes
implement equals() and hashCode()
2022-04-19 17:24:09 +02:00
18cb89ace4 test: update to JRE8+ version of Wiremock with Junit5 extension
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-12 21:01:40 +02:00
85aa5c3c30 deps: update Jackson Databind to 2.13.2.2 + minor plugin updates
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-02 10:25:23 +02:00
912b9ec61b test: minor adjustments for integration tests against Vault 1.10
All checks were successful
continuous-integration/drone/push Build is passing
Accept token prefixes "hvb." and "b." as valid results for creation
without specific preferences.
2022-03-24 20:43:00 +01:00
bd0c5b08fe model: add wrap_info to data response model
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-06 18:11:31 +01:00
5f3a36e2c5 update copyright notice to 2022 2022-03-06 18:10:33 +01:00
deb03cc2b0 minor dependency updates 2022-03-06 17:56:52 +01:00
f6180c4f90 model: add migration, recovery and storage type fields to seal status
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-05 13:01:57 +01:00
dc4b62496a model: use correct "replication_performance_mode" JSON field
All checks were successful
continuous-integration/drone/push Build is passing
The official docs incorrectly state "replication_perf_mode" which was
renamed to "replication_performance_mode" way back in Vault 0.9. We now
use the correct field name that is emitted by the API.
2021-12-27 18:54:49 +01:00
130 changed files with 2672 additions and 934 deletions

View File

@ -3,7 +3,7 @@ name: default
steps: steps:
- name: compile - name: compile
image: maven:3-jdk-11 image: maven:3-eclipse-temurin-17
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-jdk-11 image: maven:3-eclipse-temurin-17
commands: commands:
- mvn -B test - mvn -B test
when: when:
@ -22,16 +22,27 @@ steps:
- develop - develop
- feature/* - feature/*
- fix/* - fix/*
- name: unit-integration-tests - name: setup-vault
image: maven:3-jdk-11 image: alpine:latest
environment: environment:
VAULT_VERSION: 1.9.0 VAULT_VERSION: 1.14.0
commands: commands:
- curl -s -o vault_1.9.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.9.0/vault_1.9.0_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
- curl -s https://releases.hashicorp.com/vault/1.9.0/vault_1.9.0_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
- unzip vault_1.9.0_linux_amd64.zip - unzip vault_$${VAULT_VERSION}_linux_amd64.zip
- rm vault_1.9.0_linux_amd64.zip - rm vault_$${VAULT_VERSION}_linux_amd64.zip
- mv vault /bin/ - mkdir -p .bin
- mv vault .bin/
when:
branch:
- main
- release/*
- name: unit-integration-tests
image: maven:3-eclipse-temurin-17
environment:
VAULT_VERSION: 1.14.0
commands:
- export PATH=.bin:$${PATH}
- mvn -B -P integration-test verify - mvn -B -P integration-test verify
when: when:
branch: branch:

View File

@ -5,19 +5,19 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
jdk: [ 11, 17 ] jdk: [ 11, 17, 20 ]
vault: [ '1.9.0' ] vault: [ '1.2.0', '1.11.12', '1.14.0' ]
include: include:
- jdk: 11 - jdk: 17
vault: '1.9.0' vault: '1.11.12'
analysis: true analysis: true
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Java - name: Set up Java
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
java-version: ${{ matrix.jdk }} java-version: ${{ matrix.jdk }}
distribution: 'temurin' distribution: 'temurin'
@ -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 }}

21
.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,79 @@
## 1.1.5 (2023-08-19)
### Fix
* Fixed JSON type conversion in `SecretResponse#get(String, Class)` (#67)
## 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)
### Dependencies
* Updated Jackson to 2.13.3
### Test
* Tested against Vault 1.11.2
* Tested with Java 18
## 1.1.0 (2022-04-24)
### Fix
* Use `replication_performance_mode` instead of `replication_perf_mode` in health response.
### Improvements
* Add `migration`, `recovery_seal` and `storage_type` fields to `SealReponse` model
* Add support for `wrap_info` in data response models
* Dependency updates
* Model and response classes implement `Serializable` (#57)
* Split `SercretResponse` into `PlainSecretResponse` and `MetaSecretResponse` subclasses (common API unchanged)
* Add missing fields to `AuthMethod` model
* Add support for (dis)allowed policy glob patterns in `TokenRole`
* Add request ID to data response models
### Test
* Tested against Vault 1.10.1
## 1.0.1 (2021-11-21) ## 1.0.1 (2021-11-21)
### Fix ### Fix

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.9.0 * Tested against Vault 1.2 to 1.14
## 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.0.1</version> <version>1.1.5</version>
</dependency> </dependency>
``` ```

190
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.0.1</version> <version>1.1.5</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,34 +40,104 @@
<url>https://github.com/stklcode/jvaultconnector/issues</url> <url>https://github.com/stklcode/jvaultconnector/issues</url>
</issueManagement> </issueManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<argLine></argLine>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<version>3.15.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.1.0</version> <version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version> <version>3.3.1</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.1.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>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version> <version>3.3.0</version>
<configuration> <configuration>
<archive> <archive>
<manifestEntries> <manifestEntries>
@ -83,18 +148,18 @@
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
<version>2.5.2</version> <version>3.3.1</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>2.8.2</version> <version>3.3.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version> <version>3.1.2</version>
<configuration> <configuration>
<argLine> <argLine>
@{argLine} @{argLine}
@ -108,60 +173,20 @@
</argLine> </argLine>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
</build> </build>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.27.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles> <profiles>
<profile> <profile>
<id>sources</id> <id>sources</id>
@ -173,7 +198,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>
@ -197,7 +221,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.3.1</version> <version>3.5.0</version>
<configuration> <configuration>
<source>11</source> <source>11</source>
</configuration> </configuration>
@ -221,7 +245,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>
@ -246,7 +270,6 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions> <executions>
<execution> <execution>
<id>default-prepare-agent</id> <id>default-prepare-agent</id>
@ -273,7 +296,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>
@ -294,7 +316,7 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>6.5.0</version> <version>8.3.1</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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
@ -411,23 +415,22 @@ public class HTTPVaultConnector implements VaultConnector {
public final SecretResponse read(final String key) throws VaultConnectorException { public final SecretResponse read(final String key) throws VaultConnectorException {
requireAuth(); requireAuth();
/* Issue request and parse secret response */ /* Issue request and parse secret response */
return request.get(key, emptyMap(), token, SecretResponse.class); return request.get(key, emptyMap(), token, PlainSecretResponse.class);
} }
@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, SecretResponse.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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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

@ -127,7 +127,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 +144,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 +256,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("&"))
); );
} }
@ -386,7 +388,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 +402,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 +417,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-2021 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.
@ -18,27 +18,21 @@ package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.*;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Vault AppRole role metamodel. * Vault AppRole role metamodel.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRole { public final class AppRole implements Serializable {
/** 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;
@ -129,6 +123,17 @@ public final class AppRole {
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
*/ */
@ -316,6 +321,39 @@ public final class AppRole {
return tokenType; return tokenType;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
AppRole appRole = (AppRole) o;
return Objects.equals(name, appRole.name) &&
Objects.equals(id, appRole.id) &&
Objects.equals(bindSecretId, appRole.bindSecretId) &&
Objects.equals(secretIdBoundCidrs, appRole.secretIdBoundCidrs) &&
Objects.equals(secretIdNumUses, appRole.secretIdNumUses) &&
Objects.equals(secretIdTtl, appRole.secretIdTtl) &&
Objects.equals(enableLocalSecretIds, appRole.enableLocalSecretIds) &&
Objects.equals(tokenTtl, appRole.tokenTtl) &&
Objects.equals(tokenMaxTtl, appRole.tokenMaxTtl) &&
Objects.equals(tokenPolicies, appRole.tokenPolicies) &&
Objects.equals(tokenBoundCidrs, appRole.tokenBoundCidrs) &&
Objects.equals(tokenExplicitMaxTtl, appRole.tokenExplicitMaxTtl) &&
Objects.equals(tokenNoDefaultPolicy, appRole.tokenNoDefaultPolicy) &&
Objects.equals(tokenNumUses, appRole.tokenNumUses) &&
Objects.equals(tokenPeriod, appRole.tokenPeriod) &&
Objects.equals(tokenType, appRole.tokenType);
}
@Override
public int hashCode() {
return Objects.hash(name, id, bindSecretId, secretIdBoundCidrs, secretIdNumUses, secretIdTtl,
enableLocalSecretIds, tokenTtl, tokenMaxTtl, tokenPolicies, tokenBoundCidrs, tokenExplicitMaxTtl,
tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType);
}
/** /**
* A builder for vault AppRole roles.. * A builder for vault AppRole roles..

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -18,17 +18,22 @@ package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.*;
import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Vault AppRole role metamodel. * Vault AppRole role metamodel.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRoleSecret { public final class AppRoleSecret implements Serializable {
private static final long serialVersionUID = -3401074170145792641L;
@JsonProperty("secret_id") @JsonProperty("secret_id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private String id; private String id;
@ -166,4 +171,29 @@ public final class AppRoleSecret {
public Integer getTtl() { public Integer getTtl() {
return ttl; return ttl;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
AppRoleSecret that = (AppRoleSecret) o;
return Objects.equals(id, that.id) &&
Objects.equals(accessor, that.accessor) &&
Objects.equals(metadata, that.metadata) &&
Objects.equals(cidrList, that.cidrList) &&
Objects.equals(creationTime, that.creationTime) &&
Objects.equals(expirationTime, that.expirationTime) &&
Objects.equals(lastUpdatedTime, that.lastUpdatedTime) &&
Objects.equals(numUses, that.numUses) &&
Objects.equals(ttl, that.ttl);
}
@Override
public int hashCode() {
return Objects.hash(id, accessor, metadata, cidrList, creationTime, expirationTime, lastUpdatedTime, numUses,
ttl);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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-2021 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.
@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.*; import java.util.*;
/** /**
@ -27,18 +28,11 @@ import java.util.*;
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class Token { public final class Token implements Serializable {
/** 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)
@ -119,6 +113,16 @@ public final class Token {
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
*/ */
@ -214,6 +218,35 @@ public final class Token {
return entityAlias; return entityAlias;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
Token token = (Token) o;
return Objects.equals(id, token.id) &&
Objects.equals(type, token.type) &&
Objects.equals(displayName, token.displayName) &&
Objects.equals(noParent, token.noParent) &&
Objects.equals(noDefaultPolicy, token.noDefaultPolicy) &&
Objects.equals(ttl, token.ttl) &&
Objects.equals(explicitMaxTtl, token.explicitMaxTtl) &&
Objects.equals(numUses, token.numUses) &&
Objects.equals(policies, token.policies) &&
Objects.equals(meta, token.meta) &&
Objects.equals(renewable, token.renewable) &&
Objects.equals(period, token.period) &&
Objects.equals(entityAlias, token.entityAlias);
}
@Override
public int hashCode() {
return Objects.hash(id, type, displayName, noParent, noDefaultPolicy, ttl, explicitMaxTtl, numUses, policies,
meta, renewable, period, entityAlias);
}
/** /**
* Constants for token types. * Constants for token types.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -20,25 +20,21 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Vault Token Role metamodel. * Vault Token Role metamodel.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.9 * @since 0.9
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenRole { public final class TokenRole implements Serializable {
/** 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)
@ -48,10 +44,18 @@ public final class TokenRole {
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> allowedPolicies; private List<String> allowedPolicies;
@JsonProperty("allowed_policies_glob")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> allowedPoliciesGlob;
@JsonProperty("disallowed_policies") @JsonProperty("disallowed_policies")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> disallowedPolicies; private List<String> disallowedPolicies;
@JsonProperty("disallowed_policies_glob")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> disallowedPoliciesGlob;
@JsonProperty("orphan") @JsonProperty("orphan")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean orphan; private Boolean orphan;
@ -101,7 +105,9 @@ public final class TokenRole {
public TokenRole(final Builder builder) { public TokenRole(final Builder builder) {
this.name = builder.name; this.name = builder.name;
this.allowedPolicies = builder.allowedPolicies; this.allowedPolicies = builder.allowedPolicies;
this.allowedPoliciesGlob = builder.allowedPoliciesGlob;
this.disallowedPolicies = builder.disallowedPolicies; this.disallowedPolicies = builder.disallowedPolicies;
this.disallowedPoliciesGlob = builder.disallowedPoliciesGlob;
this.orphan = builder.orphan; this.orphan = builder.orphan;
this.renewable = builder.renewable; this.renewable = builder.renewable;
this.pathSuffix = builder.pathSuffix; this.pathSuffix = builder.pathSuffix;
@ -114,6 +120,15 @@ public final class TokenRole {
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
*/ */
@ -128,6 +143,14 @@ public final class TokenRole {
return allowedPolicies; return allowedPolicies;
} }
/**
* @return List of allowed policy glob patterns
* @since 1.1
*/
public List<String> getAllowedPoliciesGlob() {
return allowedPoliciesGlob;
}
/** /**
* @return List of disallowed policies * @return List of disallowed policies
*/ */
@ -135,6 +158,14 @@ public final class TokenRole {
return disallowedPolicies; return disallowedPolicies;
} }
/**
* @return List of disallowed policy glob patterns
* @since 1.1
*/
public List<String> getDisallowedPoliciesGlob() {
return disallowedPoliciesGlob;
}
/** /**
* @return Is Token Role orphan? * @return Is Token Role orphan?
*/ */
@ -205,6 +236,38 @@ public final class TokenRole {
return tokenType; return tokenType;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
TokenRole tokenRole = (TokenRole) o;
return Objects.equals(name, tokenRole.name) &&
Objects.equals(allowedPolicies, tokenRole.allowedPolicies) &&
Objects.equals(allowedPoliciesGlob, tokenRole.allowedPoliciesGlob) &&
Objects.equals(disallowedPolicies, tokenRole.disallowedPolicies) &&
Objects.equals(disallowedPoliciesGlob, tokenRole.disallowedPoliciesGlob) &&
Objects.equals(orphan, tokenRole.orphan) &&
Objects.equals(renewable, tokenRole.renewable) &&
Objects.equals(pathSuffix, tokenRole.pathSuffix) &&
Objects.equals(allowedEntityAliases, tokenRole.allowedEntityAliases) &&
Objects.equals(tokenBoundCidrs, tokenRole.tokenBoundCidrs) &&
Objects.equals(tokenExplicitMaxTtl, tokenRole.tokenExplicitMaxTtl) &&
Objects.equals(tokenNoDefaultPolicy, tokenRole.tokenNoDefaultPolicy) &&
Objects.equals(tokenNumUses, tokenRole.tokenNumUses) &&
Objects.equals(tokenPeriod, tokenRole.tokenPeriod) &&
Objects.equals(tokenType, tokenRole.tokenType);
}
@Override
public int hashCode() {
return Objects.hash(name, allowedPolicies, allowedPoliciesGlob, disallowedPolicies, disallowedPoliciesGlob,
orphan, renewable, pathSuffix, allowedEntityAliases, tokenBoundCidrs, tokenExplicitMaxTtl,
tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType);
}
/** /**
* A builder for vault token roles. * A builder for vault token roles.
* *
@ -214,7 +277,9 @@ public final class TokenRole {
public static final class Builder { public static final class Builder {
private String name; private String name;
private List<String> allowedPolicies; private List<String> allowedPolicies;
private List<String> allowedPoliciesGlob;
private List<String> disallowedPolicies; private List<String> disallowedPolicies;
private List<String> disallowedPoliciesGlob;
private Boolean orphan; private Boolean orphan;
private Boolean renewable; private Boolean renewable;
private String pathSuffix; private String pathSuffix;
@ -269,6 +334,40 @@ public final class TokenRole {
return this; return this;
} }
/**
* Add an allowed policy glob pattern.
*
* @param allowedPolicyGlob allowed policy glob pattern to add
* @return self
* @since 1.1
*/
public Builder withAllowedPolicyGlob(final String allowedPolicyGlob) {
if (allowedPolicyGlob != null) {
if (this.allowedPoliciesGlob == null) {
this.allowedPoliciesGlob = new ArrayList<>();
}
this.allowedPoliciesGlob.add(allowedPolicyGlob);
}
return this;
}
/**
* Add allowed policy glob patterns.
*
* @param allowedPoliciesGlob list of allowed policy glob patterns
* @return self
* @since 1.1
*/
public Builder withAllowedPoliciesGlob(final List<String> allowedPoliciesGlob) {
if (allowedPoliciesGlob != null) {
if (this.allowedPoliciesGlob == null) {
this.allowedPoliciesGlob = new ArrayList<>();
}
this.allowedPoliciesGlob.addAll(allowedPoliciesGlob);
}
return this;
}
/** /**
* Add a disallowed policy. * Add a disallowed policy.
* *
@ -301,6 +400,40 @@ public final class TokenRole {
return this; return this;
} }
/**
* Add an allowed policy glob pattern.
*
* @param disallowedPolicyGlob disallowed policy glob pattern to add
* @return self
* @since 1.1
*/
public Builder withDisallowedPolicyGlob(final String disallowedPolicyGlob) {
if (disallowedPolicyGlob != null) {
if (this.disallowedPoliciesGlob == null) {
this.disallowedPoliciesGlob = new ArrayList<>();
}
this.disallowedPoliciesGlob.add(disallowedPolicyGlob);
}
return this;
}
/**
* Add disallowed policy glob patterns.
*
* @param disallowedPoliciesGlob list of disallowed policy glob patterns
* @return self
* @since 1.1
*/
public Builder withDisallowedPoliciesGlob(final List<String> disallowedPoliciesGlob) {
if (disallowedPoliciesGlob != null) {
if (this.disallowedPoliciesGlob == null) {
this.disallowedPoliciesGlob = new ArrayList<>();
}
this.disallowedPoliciesGlob.addAll(disallowedPoliciesGlob);
}
return this;
}
/** /**
* Set TRUE if the token role should be created orphan. * Set TRUE if the token role should be created orphan.
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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-2021 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,13 +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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AppRole; import de.stklcode.jvault.connector.model.AppRole;
import java.io.IOException; import java.util.Objects;
import java.util.HashMap;
import java.util.Map;
/** /**
* Vault response for AppRole lookup. * Vault response for AppRole lookup.
@ -33,24 +30,10 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRoleResponse extends VaultDataResponse { public final class AppRoleResponse extends VaultDataResponse {
private AppRole role; private static final long serialVersionUID = -6536422219633829177L;
@Override @JsonProperty("data")
public void setData(final Map<String, Object> data) throws InvalidResponseException { private AppRole role;
var mapper = new ObjectMapper();
try {
/* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
data.forEach((k, v) -> {
if (!(v instanceof String && ((String) v).isEmpty())) {
filteredData.put(k, v);
}
});
this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* @return The role * @return The role
@ -58,4 +41,20 @@ public final class AppRoleResponse extends VaultDataResponse {
public AppRole getRole() { public AppRole getRole() {
return role; return role;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
AppRoleResponse that = (AppRoleResponse) o;
return Objects.equals(role, that.role);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), role);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,13 +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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AppRoleSecret; import de.stklcode.jvault.connector.model.AppRoleSecret;
import java.io.IOException; import java.util.Objects;
import java.util.HashMap;
import java.util.Map;
/** /**
* Vault response for AppRole lookup. * Vault response for AppRole lookup.
@ -33,24 +30,10 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRoleSecretResponse extends VaultDataResponse { public final class AppRoleSecretResponse extends VaultDataResponse {
private AppRoleSecret secret; private static final long serialVersionUID = -2484103304072370585L;
@Override @JsonProperty("data")
public void setData(final Map<String, Object> data) throws InvalidResponseException { private AppRoleSecret secret;
var mapper = new ObjectMapper();
try {
/* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
data.forEach((k, v) -> {
if (!(v instanceof String && ((String) v).isEmpty())) {
filteredData.put(k, v);
}
});
this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* @return The secret * @return The secret
@ -58,4 +41,20 @@ public final class AppRoleSecretResponse extends VaultDataResponse {
public AppRoleSecret getSecret() { public AppRoleSecret getSecret() {
return secret; return secret;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
AppRoleSecretResponse that = (AppRoleSecretResponse) o;
return Objects.equals(secret, that.secret);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), secret);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,13 +17,12 @@
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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod; import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Authentication method response. * Authentication method response.
@ -33,6 +32,9 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthMethodsResponse extends VaultDataResponse { public final class AuthMethodsResponse extends VaultDataResponse {
private static final long serialVersionUID = -1802724129533405375L;
@JsonProperty("data")
private Map<String, AuthMethod> supportedMethods; private Map<String, AuthMethod> supportedMethods;
/** /**
@ -42,23 +44,26 @@ public final class AuthMethodsResponse extends VaultDataResponse {
this.supportedMethods = new HashMap<>(); this.supportedMethods = new HashMap<>();
} }
@Override
public void setData(final Map<String, Object> data) throws InvalidResponseException {
var mapper = new ObjectMapper();
for (Map.Entry<String, Object> entry : data.entrySet()) {
try {
this.supportedMethods.put(entry.getKey(),
mapper.readValue(mapper.writeValueAsString(entry.getValue()), AuthMethod.class));
} catch (IOException e) {
throw new InvalidResponseException();
}
}
}
/** /**
* @return Supported authentication methods * @return Supported authentication methods
*/ */
public Map<String, AuthMethod> getSupportedMethods() { public Map<String, AuthMethod> getSupportedMethods() {
return supportedMethods; return supportedMethods;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
AuthMethodsResponse that = (AuthMethodsResponse) o;
return Objects.equals(supportedMethods, that.supportedMethods);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), supportedMethods);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -18,12 +18,9 @@ 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 com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.AuthData; import de.stklcode.jvault.connector.model.response.embedded.AuthData;
import java.io.IOException; import java.util.Objects;
import java.util.Map;
/** /**
* Vault response for authentication providing auth info in {@link AuthData} field. * Vault response for authentication providing auth info in {@link AuthData} field.
@ -33,37 +30,10 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthResponse extends VaultDataResponse { public final class AuthResponse extends VaultDataResponse {
private Map<String, Object> data; private static final long serialVersionUID = 1628851361067456715L;
private AuthData auth;
/**
* Set authentication data. The input will be mapped to the {@link AuthData} model.
*
* @param auth Raw authentication data
* @throws InvalidResponseException on mapping errors
*/
@JsonProperty("auth") @JsonProperty("auth")
public void setAuth(final Map<String, Object> auth) throws InvalidResponseException { private AuthData auth;
var mapper = new ObjectMapper();
try {
this.auth = mapper.readValue(mapper.writeValueAsString(auth), AuthData.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
@Override
public void setData(final Map<String, Object> data) {
this.data = data;
}
/**
* @return Raw data
*/
public Map<String, Object> getData() {
return data;
}
/** /**
* @return Authentication data * @return Authentication data
@ -71,4 +41,20 @@ public final class AuthResponse extends VaultDataResponse {
public AuthData getAuth() { public AuthData getAuth() {
return auth; return auth;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
AuthResponse that = (AuthResponse) o;
return Objects.equals(auth, that.auth);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), auth);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,7 +25,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
* @since 0.5.0 * @since 0.5.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class CredentialsResponse extends SecretResponse { public final class CredentialsResponse extends PlainSecretResponse {
private static final long serialVersionUID = -1439692963299045425L;
/** /**
* @return Username * @return Username

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Vault response in case of errors. * Vault response in case of errors.
@ -29,6 +30,8 @@ import java.util.List;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class ErrorResponse implements VaultResponse { public final class ErrorResponse implements VaultResponse {
private static final long serialVersionUID = -6227368087842549149L;
@JsonProperty("errors") @JsonProperty("errors")
private List<String> errors; private List<String> errors;
@ -47,4 +50,20 @@ public final class ErrorResponse implements VaultResponse {
return errors.get(0); return errors.get(0);
} }
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
ErrorResponse that = (ErrorResponse) o;
return Objects.equals(errors, that.errors);
}
@Override
public int hashCode() {
return Objects.hash(errors);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@ 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.util.Objects;
/** /**
* Vault response for health query. * Vault response for health query.
* *
@ -27,6 +29,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class HealthResponse implements VaultResponse { public final class HealthResponse implements VaultResponse {
private static final long serialVersionUID = 6483840078694294401L;
@JsonProperty("cluster_id") @JsonProperty("cluster_id")
private String clusterID; private String clusterID;
@ -48,7 +52,7 @@ public final class HealthResponse implements VaultResponse {
@JsonProperty("initialized") @JsonProperty("initialized")
private Boolean initialized; private Boolean initialized;
@JsonProperty("replication_perf_mode") @JsonProperty("replication_performance_mode")
private String replicationPerfMode; private String replicationPerfMode;
@JsonProperty("replication_dr_mode") @JsonProperty("replication_dr_mode")
@ -129,4 +133,30 @@ public final class HealthResponse implements VaultResponse {
public Boolean isPerformanceStandby() { public Boolean isPerformanceStandby() {
return performanceStandby; return performanceStandby;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
HealthResponse that = (HealthResponse) o;
return Objects.equals(clusterID, that.clusterID) &&
Objects.equals(clusterName, that.clusterName) &&
Objects.equals(version, that.version) &&
Objects.equals(serverTimeUTC, that.serverTimeUTC) &&
Objects.equals(standby, that.standby) &&
Objects.equals(sealed, that.sealed) &&
Objects.equals(initialized, that.initialized) &&
Objects.equals(replicationPerfMode, that.replicationPerfMode) &&
Objects.equals(replicationDrMode, that.replicationDrMode) &&
Objects.equals(performanceStandby, that.performanceStandby);
}
@Override
public int hashCode() {
return Objects.hash(clusterID, clusterName, version, serverTimeUTC, standby, sealed, initialized,
replicationPerfMode, replicationDrMode, performanceStandby);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@ 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.util.Objects;
/** /**
* Vault response for help request. * Vault response for help request.
* *
@ -27,6 +29,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class HelpResponse implements VaultResponse { public final class HelpResponse implements VaultResponse {
private static final long serialVersionUID = -1152070966642848490L;
@JsonProperty("help") @JsonProperty("help")
private String help; private String help;
@ -36,4 +40,20 @@ public final class HelpResponse implements VaultResponse {
public String getHelp() { public String getHelp() {
return help; return help;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
HelpResponse that = (HelpResponse) o;
return Objects.equals(help, that.help);
}
@Override
public int hashCode() {
return Objects.hash(help);
}
} }

View File

@ -0,0 +1,75 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.model.response.embedded.SecretWrapper;
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
/**
* Vault response for secret responses with metadata.
*
* @author Stefan Kalscheuer
* @since 1.1 abstract
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class MetaSecretResponse extends SecretResponse {
private static final long serialVersionUID = -1076542846391240162L;
@JsonProperty("data")
private SecretWrapper secret;
@Override
public final Map<String, Serializable> getData() {
if (secret != null) {
return secret.getData();
} else {
return Collections.emptyMap();
}
}
@Override
public final VersionMetadata getMetadata() {
if (secret != null) {
return secret.getMetadata();
} else {
return null;
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
MetaSecretResponse that = (MetaSecretResponse) o;
return Objects.equals(secret, that.secret);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), secret);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,12 +17,11 @@
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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.SecretMetadata; import de.stklcode.jvault.connector.model.response.embedded.SecretMetadata;
import java.io.IOException; import java.util.Objects;
import java.util.Map;
/** /**
* Vault response for secret metadata (KV v2). * Vault response for secret metadata (KV v2).
@ -32,19 +31,11 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class MetadataResponse extends VaultDataResponse { public class MetadataResponse extends VaultDataResponse {
private static final long serialVersionUID = -3679762333630984679L;
@JsonProperty("data")
private SecretMetadata metadata; private SecretMetadata metadata;
@Override
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
var mapper = new ObjectMapper();
try {
this.metadata = mapper.readValue(mapper.writeValueAsString(data), SecretMetadata.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* Get the actual metadata. * Get the actual metadata.
* *
@ -53,4 +44,20 @@ public class MetadataResponse extends VaultDataResponse {
public SecretMetadata getMetadata() { public SecretMetadata getMetadata() {
return metadata; return metadata;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
MetadataResponse that = (MetadataResponse) o;
return Objects.equals(metadata, that.metadata);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), metadata);
}
} }

View File

@ -0,0 +1,66 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
/**
* Vault response for plain secret responses.
*
* @author Stefan Kalscheuer
* @since 1.1 abstract
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class PlainSecretResponse extends SecretResponse {
private static final long serialVersionUID = 3010138542437913023L;
@JsonProperty("data")
private Map<String, Serializable> data;
@Override
public final Map<String, Serializable> getData() {
return Objects.requireNonNullElseGet(data, Collections::emptyMap);
}
@Override
public final VersionMetadata getMetadata() {
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
PlainSecretResponse that = (PlainSecretResponse) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), data);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 +17,11 @@
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.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Simple Vault data response. * Simple Vault data response.
@ -28,17 +31,31 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class RawDataResponse extends VaultDataResponse { public final class RawDataResponse extends VaultDataResponse {
private Map<String, Object> data; private static final long serialVersionUID = -319727427792124071L;
@Override @JsonProperty("data")
public void setData(final Map<String, Object> data) { private Map<String, Serializable> data;
this.data = data;
}
/** /**
* @return Raw data {@link Map} * @return Raw data {@link Map}
*/ */
public Map<String, Object> getData() { public Map<String, Serializable> getData() {
return data; return data;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
RawDataResponse that = (RawDataResponse) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), data);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@ 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.util.Objects;
/** /**
* Vault response for seal status or unseal request. * Vault response for seal status or unseal request.
* *
@ -27,6 +29,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class SealResponse implements VaultResponse { public final class SealResponse implements VaultResponse {
private static final long serialVersionUID = -3661916639367542617L;
@JsonProperty("type") @JsonProperty("type")
private String type; private String type;
@ -57,6 +61,15 @@ public final class SealResponse implements VaultResponse {
@JsonProperty("cluster_id") @JsonProperty("cluster_id")
private String clusterId; private String clusterId;
@JsonProperty("migration")
private Boolean migration;
@JsonProperty("recovery_seal")
private Boolean recoverySeal;
@JsonProperty("storage_type")
private String storageType;
/** /**
* @return Seal type. * @return Seal type.
* @since 0.8 * @since 0.8
@ -132,4 +145,57 @@ public final class SealResponse implements VaultResponse {
public String getClusterId() { public String getClusterId() {
return clusterId; return clusterId;
} }
/**
* @return Migration status (since Vault 1.4)
* @since 1.1
*/
public Boolean getMigration() {
return migration;
}
/**
* @return Recovery seal status.
* @since 1.1
*/
public Boolean getRecoverySeal() {
return recoverySeal;
}
/**
* @return Storage type (since Vault 1.3).
* @since 1.1
*/
public String getStorageType() {
return storageType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
SealResponse that = (SealResponse) o;
return sealed == that.sealed &&
initialized == that.initialized &&
Objects.equals(type, that.type) &&
Objects.equals(threshold, that.threshold) &&
Objects.equals(numberOfShares, that.numberOfShares) &&
Objects.equals(progress, that.progress) &&
Objects.equals(version, that.version) &&
Objects.equals(nonce, that.nonce) &&
Objects.equals(clusterName, that.clusterName) &&
Objects.equals(clusterId, that.clusterId) &&
Objects.equals(migration, that.migration) &&
Objects.equals(recoverySeal, that.recoverySeal) &&
Objects.equals(storageType, that.storageType);
}
@Override
public int hashCode() {
return Objects.hash(type, sealed, initialized, threshold, numberOfShares, progress, version, nonce,
clusterName, clusterId, migration, recoverySeal, storageType);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -18,10 +18,11 @@ 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 de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.model.response.embedded.SecretListWrapper;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Objects;
/** /**
* Vault response for secret list request. * Vault response for secret list request.
@ -31,27 +32,34 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class SecretListResponse extends VaultDataResponse { public final class SecretListResponse extends VaultDataResponse {
private List<String> keys;
/** private static final long serialVersionUID = 8597121175002967213L;
* Set data. Extracts list of keys from raw response data.
*
* @param data Raw data
* @throws InvalidResponseException on parsing errors
*/
@JsonProperty("data") @JsonProperty("data")
public void setData(final Map<String, Object> data) throws InvalidResponseException { private SecretListWrapper data;
try {
this.keys = (List<String>) data.get("keys");
} catch (ClassCastException e) {
throw new InvalidResponseException("Keys could not be parsed from data.", e);
}
}
/** /**
* @return List of secret keys * @return List of secret keys
*/ */
public List<String> getKeys() { public List<String> getKeys() {
return keys; if (data == null) {
return Collections.emptyList();
}
return Objects.requireNonNullElseGet(data.getKeys(), Collections::emptyList);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
SecretListResponse that = (SecretListResponse) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), data);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,7 @@ 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;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.io.Serializable;
import java.util.Map; import java.util.Map;
/** /**
@ -30,46 +30,20 @@ import java.util.Map;
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
* @since 1.1 abstract
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SecretResponse extends VaultDataResponse { public abstract class SecretResponse extends VaultDataResponse {
private static final String KEY_DATA = "data"; private static final long serialVersionUID = 5198088815871692951L;
private static final String KEY_METADATA = "metadata";
private Map<String, Object> data;
private VersionMetadata metadata;
@Override
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
if (data.size() == 2
&& data.containsKey(KEY_DATA) && data.get(KEY_DATA) instanceof Map
&& data.containsKey(KEY_METADATA) && data.get(KEY_METADATA) instanceof Map) {
var mapper = new ObjectMapper();
try {
// This is apparently a KV v2 value.
this.data = (Map<String, Object>) data.get(KEY_DATA);
this.metadata = mapper.readValue(mapper.writeValueAsString(data.get(KEY_METADATA)), VersionMetadata.class);
} catch (ClassCastException | IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
} else {
// For KV v1 without metadata just store the data map.
this.data = data;
}
}
/** /**
* Get complete data object. * Get complete data object.
* *
* @return data map * @return data map
* @since 0.4.0 * @since 0.4.0
* @since 1.1 Serializable map value.
*/ */
public final Map<String, Object> getData() { public abstract Map<String, Serializable> getData();
if (data == null) {
return Collections.emptyMap();
}
return data;
}
/** /**
* Get secret metadata. This is only available for KV v2 secrets. * Get secret metadata. This is only available for KV v2 secrets.
@ -77,9 +51,7 @@ public class SecretResponse extends VaultDataResponse {
* @return Metadata of the secret. * @return Metadata of the secret.
* @since 0.8 * @since 0.8
*/ */
public final VersionMetadata getMetadata() { public abstract VersionMetadata getMetadata();
return metadata;
}
/** /**
* Get a single value for given key. * Get a single value for given key.
@ -89,9 +61,6 @@ public class SecretResponse extends VaultDataResponse {
* @since 0.4.0 * @since 0.4.0
*/ */
public final Object get(final String key) { public final Object get(final String key) {
if (data == null) {
return null;
}
return getData().get(key); return getData().get(key);
} }
@ -100,18 +69,26 @@ public class SecretResponse extends VaultDataResponse {
* *
* @param key the key * @param key the key
* @param type Class to parse response * @param type Class to parse response
* @param <T> Class to parse response * @param <C> Class to parse response
* @return Parsed object or {@code null} if absent * @return Parsed object or {@code null} if absent
* @throws InvalidResponseException on parsing error * @throws InvalidResponseException on parsing error
* @since 0.4.0 * @since 0.4.0
*/ */
public final <T> T get(final String key, final Class<T> type) throws InvalidResponseException { public final <C> C get(final String key, final Class<C> type) throws InvalidResponseException {
try { try {
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();
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-2021 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,12 +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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
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;
import java.io.IOException; import java.util.Objects;
import java.util.Map;
/** /**
* Vault response for a single secret version metadata, i.e. after update (KV v2). * Vault response for a single secret version metadata, i.e. after update (KV v2).
@ -32,19 +30,11 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SecretVersionResponse extends VaultDataResponse { public class SecretVersionResponse extends VaultDataResponse {
private static final long serialVersionUID = 2748635005258576174L;
@JsonProperty("data")
private VersionMetadata metadata; private VersionMetadata metadata;
@Override
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
var mapper = new ObjectMapper();
try {
this.metadata = mapper.readValue(mapper.writeValueAsString(data), VersionMetadata.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* Get the actual metadata. * Get the actual metadata.
* *
@ -53,4 +43,20 @@ public class SecretVersionResponse extends VaultDataResponse {
public VersionMetadata getMetadata() { public VersionMetadata getMetadata() {
return metadata; return metadata;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
SecretVersionResponse that = (SecretVersionResponse) o;
return Objects.equals(metadata, that.metadata);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), metadata);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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.
@ -18,12 +18,9 @@ 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 com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.TokenData; import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import java.io.IOException; import java.util.Objects;
import java.util.Map;
/** /**
* Vault response from token lookup providing Token information in {@link TokenData} field. * Vault response from token lookup providing Token information in {@link TokenData} field.
@ -33,31 +30,41 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenResponse extends VaultDataResponse { public final class TokenResponse extends VaultDataResponse {
private static final long serialVersionUID = -4053126653764241197L;
@JsonProperty("data")
private TokenData data; private TokenData data;
@JsonProperty("auth") @JsonProperty("auth")
private Boolean auth; private Boolean auth;
/**
* Set data. Parses response data map to {@link TokenData}.
*
* @param data Raw response data
* @throws InvalidResponseException on parsing errors
*/
@Override
public void setData(final Map<String, Object> data) throws InvalidResponseException {
var mapper = new ObjectMapper();
try {
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenData.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* @return Token data * @return Token data
*/ */
public TokenData getData() { public TokenData getData() {
return data; return data;
} }
/**
* @return Auth data
*/
public Boolean getAuth() {
return auth;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
TokenResponse that = (TokenResponse) o;
return Objects.equals(data, that.data) && Objects.equals(auth, that.auth);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), data, auth);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,13 +17,11 @@
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.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.TokenRole; import de.stklcode.jvault.connector.model.TokenRole;
import de.stklcode.jvault.connector.model.response.embedded.TokenData; import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import java.io.IOException; import java.util.Objects;
import java.util.Map;
/** /**
* Vault response from token role lookup providing Token information in {@link TokenData} field. * Vault response from token role lookup providing Token information in {@link TokenData} field.
@ -33,23 +31,10 @@ import java.util.Map;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenRoleResponse extends VaultDataResponse { public final class TokenRoleResponse extends VaultDataResponse {
private TokenRole data; private static final long serialVersionUID = 5265363857731948626L;
/** @JsonProperty("data")
* Set data. Parses response data map to {@link TokenRole}. private TokenRole data;
*
* @param data Raw response data
* @throws InvalidResponseException on parsing errors
*/
@Override
public void setData(final Map<String, Object> data) throws InvalidResponseException {
var mapper = new ObjectMapper();
try {
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenRole.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/** /**
* @return TokenRole data * @return TokenRole data
@ -57,4 +42,20 @@ public final class TokenRoleResponse extends VaultDataResponse {
public TokenRole getData() { public TokenRole getData() {
return data; return data;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
TokenRoleResponse that = (TokenRoleResponse) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), data);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,10 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.model.response.embedded.WrapInfo;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Objects;
/** /**
* Abstract Vault response with default payload fields. * Abstract Vault response with default payload fields.
@ -29,6 +29,11 @@ import java.util.Map;
* @since 0.1 * @since 0.1
*/ */
public abstract class VaultDataResponse implements VaultResponse { public abstract class VaultDataResponse implements VaultResponse {
private static final long serialVersionUID = 7486270767477652184L;
@JsonProperty("request_id")
private String requestId;
@JsonProperty("lease_id") @JsonProperty("lease_id")
private String leaseId; private String leaseId;
@ -41,14 +46,16 @@ public abstract class VaultDataResponse implements VaultResponse {
@JsonProperty("warnings") @JsonProperty("warnings")
private List<String> warnings; private List<String> warnings;
@JsonProperty("wrap_info")
private WrapInfo wrapInfo;
/** /**
* Set data. To be implemented in the specific subclasses, as data can be of arbitrary structure. * @return Request ID
* * @since 1.1
* @param data Raw response data
* @throws InvalidResponseException on parsing errors
*/ */
@JsonProperty("data") public final String getRequestId() {
public abstract void setData(final Map<String, Object> data) throws InvalidResponseException; return requestId;
}
/** /**
* @return Lease ID * @return Lease ID
@ -77,4 +84,33 @@ public abstract class VaultDataResponse implements VaultResponse {
public final List<String> getWarnings() { public final List<String> getWarnings() {
return warnings; return warnings;
} }
/**
* @return Wrapping information
* @since 1.1
*/
public final WrapInfo getWrapInfo() {
return wrapInfo;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
VaultDataResponse that = (VaultDataResponse) o;
return renewable == that.renewable &&
Objects.equals(requestId, that.requestId) &&
Objects.equals(leaseId, that.leaseId) &&
Objects.equals(leaseDuration, that.leaseDuration) &&
Objects.equals(warnings, that.warnings) &&
Objects.equals(wrapInfo, that.wrapInfo);
}
@Override
public int hashCode() {
return Objects.hash(requestId, leaseId, renewable, leaseDuration, warnings, wrapInfo);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,11 +16,14 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import java.io.Serializable;
/** /**
* Marker interface for responses from Vault backend. * Marker interface for responses from Vault backend.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
* @since 1.1 extends {@link Serializable}
*/ */
public interface VaultResponse { public interface VaultResponse extends Serializable {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,17 +19,22 @@ package de.stklcode.jvault.connector.model.response.embedded;
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.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Embedded authorization information inside Vault response. * Embedded authorization information inside Vault response.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthData { public final class AuthData implements Serializable {
private static final long serialVersionUID = -6962244199229885869L;
@JsonProperty("client_token") @JsonProperty("client_token")
private String clientToken; private String clientToken;
@ -133,4 +138,31 @@ public final class AuthData {
public boolean isOrphan() { public boolean isOrphan() {
return orphan; return orphan;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AuthData authData = (AuthData) o;
return renewable == authData.renewable &&
orphan == authData.orphan &&
Objects.equals(clientToken, authData.clientToken) &&
Objects.equals(accessor, authData.accessor) &&
Objects.equals(policies, authData.policies) &&
Objects.equals(tokenPolicies, authData.tokenPolicies) &&
Objects.equals(metadata, authData.metadata) &&
Objects.equals(leaseDuration, authData.leaseDuration) &&
Objects.equals(entityId, authData.entityId) &&
Objects.equals(tokenType, authData.tokenType);
}
@Override
public int hashCode() {
return Objects.hash(clientToken, accessor, policies, tokenPolicies, metadata, leaseDuration, renewable,
entityId, tokenType, orphan);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,28 +21,45 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.JsonSetter;
import de.stklcode.jvault.connector.model.AuthBackend; import de.stklcode.jvault.connector.model.AuthBackend;
import java.io.Serializable;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Embedded authentication method response. * Embedded authentication method response.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class AuthMethod { public final class AuthMethod implements Serializable {
private static final long serialVersionUID = -2718660627880077335L;
private AuthBackend type; private AuthBackend type;
private String rawType; private String rawType;
@JsonProperty("accessor")
private String accessor;
@JsonProperty("description") @JsonProperty("description")
private String description; private String description;
@JsonProperty("config") @JsonProperty("config")
private Map<String, String> config; private Map<String, String> config;
@JsonProperty("external_entropy_access")
private boolean externalEntropyAccess;
@JsonProperty("local") @JsonProperty("local")
private boolean local; private boolean local;
@JsonProperty("seal_wrap")
private boolean sealWrap;
@JsonProperty("uuid")
private String uuid;
/** /**
* @param type Backend type, passed to {@link AuthBackend#forType(String)} * @param type Backend type, passed to {@link AuthBackend#forType(String)}
*/ */
@ -66,6 +83,14 @@ public final class AuthMethod {
return rawType; return rawType;
} }
/**
* @return Accessor
* @since 1.1
*/
public String getAccessor() {
return accessor;
}
/** /**
* @return Description * @return Description
*/ */
@ -80,10 +105,58 @@ public final class AuthMethod {
return config; return config;
} }
/**
* @return Backend has access to external entropy source
* @since 1.1
*/
public boolean isExternalEntropyAccess() {
return externalEntropyAccess;
}
/** /**
* @return Is local backend * @return Is local backend
*/ */
public boolean isLocal() { public boolean isLocal() {
return local; return local;
} }
/**
* @return Seal wrapping enabled
* @since 1.1
*/
public boolean isSealWrap() {
return sealWrap;
}
/**
* @return Backend UUID
* @since 1.1
*/
public String getUuid() {
return uuid;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
AuthMethod that = (AuthMethod) o;
return local == that.local &&
type == that.type &&
externalEntropyAccess == that.externalEntropyAccess &&
sealWrap == that.sealWrap &&
Objects.equals(rawType, that.rawType) &&
Objects.equals(accessor, that.accessor) &&
Objects.equals(description, that.description) &&
Objects.equals(config, that.config) &&
Objects.equals(uuid, that.uuid);
}
@Override
public int hashCode() {
return Objects.hash(type, rawType, accessor, description, config, externalEntropyAccess, local, sealWrap, uuid);
}
} }

View File

@ -0,0 +1,42 @@
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;
/**
* Wrapper object for secret key lists.
*
* @author Stefan Kalscheuer
* @since 1.1
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SecretListWrapper implements Serializable {
private static final long serialVersionUID = -8777605197063766125L;
@JsonProperty("keys")
private List<String> keys;
public List<String> getKeys() {
return keys;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
SecretListWrapper that = (SecretListWrapper) o;
return Objects.equals(keys, that.keys);
}
@Override
public int hashCode() {
return Objects.hash(keys);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,20 +19,26 @@ package de.stklcode.jvault.connector.model.response.embedded;
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.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.time.format.DateTimeParseException;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Embedded metadata for Key-Value v2 secrets. * Embedded metadata for Key-Value v2 secrets.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class SecretMetadata { public final class SecretMetadata implements Serializable {
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX"); private static final long serialVersionUID = 1684891108903409038L;
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 String createdTimeString;
@ -124,4 +130,24 @@ public final class SecretMetadata {
return versions; return versions;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
SecretMetadata that = (SecretMetadata) o;
return Objects.equals(createdTimeString, that.createdTimeString) &&
Objects.equals(currentVersion, that.currentVersion) &&
Objects.equals(maxVersions, that.maxVersions) &&
Objects.equals(oldestVersion, that.oldestVersion) &&
Objects.equals(updatedTime, that.updatedTime) &&
Objects.equals(versions, that.versions);
}
@Override
public int hashCode() {
return Objects.hash(createdTimeString, currentVersion, maxVersions, oldestVersion, updatedTime, versions);
}
} }

View File

@ -0,0 +1,49 @@
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;
/**
* Wrapper object for secret data and metadata.
*
* @author Stefan Kalscheuer
* @since 1.1
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SecretWrapper implements Serializable {
private static final long serialVersionUID = 8600413181758893378L;
@JsonProperty("data")
private Map<String, Serializable> data;
@JsonProperty("metadata")
private VersionMetadata metadata;
public Map<String, Serializable> getData() {
return data;
}
public VersionMetadata getMetadata() {
return metadata;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
SecretWrapper that = (SecretWrapper) o;
return Objects.equals(data, that.data) && Objects.equals(metadata, that.metadata);
}
@Override
public int hashCode() {
return Objects.hash(data, metadata);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,18 +19,23 @@ package de.stklcode.jvault.connector.model.response.embedded;
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.io.Serializable;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Embedded token information inside Vault response. * Embedded token information inside Vault response.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenData { public final class TokenData implements Serializable {
private static final long serialVersionUID = 2915180734313753649L;
@JsonProperty("accessor") @JsonProperty("accessor")
private String accessor; private String accessor;
@ -231,4 +236,37 @@ public final class TokenData {
public Map<String, Object> getMeta() { public Map<String, Object> getMeta() {
return meta; return meta;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
TokenData tokenData = (TokenData) o;
return orphan == tokenData.orphan &&
renewable == tokenData.renewable &&
Objects.equals(accessor, tokenData.accessor) &&
Objects.equals(creationTime, tokenData.creationTime) &&
Objects.equals(creationTtl, tokenData.creationTtl) &&
Objects.equals(name, tokenData.name) &&
Objects.equals(entityId, tokenData.entityId) &&
Objects.equals(expireTime, tokenData.expireTime) &&
Objects.equals(explicitMaxTtl, tokenData.explicitMaxTtl) &&
Objects.equals(id, tokenData.id) &&
Objects.equals(issueTime, tokenData.issueTime) &&
Objects.equals(meta, tokenData.meta) &&
Objects.equals(numUses, tokenData.numUses) &&
Objects.equals(path, tokenData.path) &&
Objects.equals(policies, tokenData.policies) &&
Objects.equals(ttl, tokenData.ttl) &&
Objects.equals(type, tokenData.type);
}
@Override
public int hashCode() {
return Objects.hash(accessor, creationTime, creationTtl, name, entityId, expireTime, explicitMaxTtl, id,
issueTime, meta, numUses, orphan, path, policies, renewable, ttl, type);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,19 +19,25 @@ package de.stklcode.jvault.connector.model.response.embedded;
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.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.time.format.DateTimeParseException;
import java.util.Objects;
/** /**
* Embedded metadata for a single Key-Value v2 version. * Embedded metadata for a single Key-Value v2 version.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
* @since 1.1 implements {@link Serializable}
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public final class VersionMetadata { public final class VersionMetadata implements Serializable {
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX"); private static final long serialVersionUID = -5286693953873839611L;
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 String createdTimeString;
@ -103,4 +109,22 @@ public final class VersionMetadata {
return version; return version;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
VersionMetadata that = (VersionMetadata) o;
return destroyed == that.destroyed &&
Objects.equals(createdTimeString, that.createdTimeString) &&
Objects.equals(deletionTimeString, that.deletionTimeString) &&
Objects.equals(version, that.version);
}
@Override
public int hashCode() {
return Objects.hash(createdTimeString, deletionTimeString, destroyed, version);
}
} }

View File

@ -0,0 +1,91 @@
/*
* 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.JsonProperty;
import java.io.Serializable;
import java.util.Objects;
/**
* Wrapping information object.
*
* @author Stefan Kalscheuer
* @since 1.1
*/
public class WrapInfo implements Serializable {
private static final long serialVersionUID = -7764500642913116581L;
@JsonProperty("token")
private String token;
@JsonProperty("ttl")
private Integer ttl;
@JsonProperty("creation_time")
private String creationTime;
@JsonProperty("creation_path")
private String creationPath;
/**
* @return Token
*/
public String getToken() {
return token;
}
/**
* @return TTL (in seconds)
*/
public Integer getTtl() {
return ttl;
}
/**
* @return Creation time
*/
public String getCreationTime() {
return creationTime;
}
/**
* @return Creation path
*/
public String getCreationPath() {
return creationPath;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
WrapInfo that = (WrapInfo) o;
return Objects.equals(token, that.token) &&
Objects.equals(ttl, that.ttl) &&
Objects.equals(creationTime, that.creationTime) &&
Objects.equals(creationPath, that.creationPath);
}
@Override
public int hashCode() {
return Objects.hash(token, ttl, creationTime, creationPath);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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.*;
@ -37,6 +38,7 @@ import java.util.regex.Pattern;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static org.apache.commons.io.FileUtils.copyDirectory; import static org.apache.commons.io.FileUtils.copyDirectory;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue;
@ -49,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.9.0"; // The vault version this test is supposed to run against. private static String VAULT_VERSION = "1.14.0"; // 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";
@ -57,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;
@ -67,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;
}
} }
/** /**
@ -80,11 +86,6 @@ class HTTPVaultConnectorIT {
// Initialize Vault. // Initialize Vault.
VaultConfiguration config = initializeVault(tempDir, isTls); VaultConfiguration config = initializeVault(tempDir, isTls);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Initialize connector. // Initialize connector.
HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder() HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder()
@ -551,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";
@ -561,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());
@ -584,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();
@ -908,7 +910,8 @@ class HTTPVaultConnectorIT {
assertFalse(res.getAuth().isOrphan(), "Root token should not be orphan"); assertFalse(res.getAuth().isOrphan(), "Root token should not be orphan");
// Starting with Vault 1.0 a warning "custom ID uses weaker SHA1.." is given. // Starting with Vault 1.0 a warning "custom ID uses weaker SHA1.." is given.
assertEquals(1, res.getWarnings().size(), "Token creation did not return expected warning"); // Starting with Vault 1.11 a second warning "Endpoint ignored unrecognized parameters" is given.
assertFalse(res.getWarnings().isEmpty(), "Token creation did not return expected warning");
// Create token with attributes. // Create token with attributes.
Token token2 = Token.builder() Token token2 = Token.builder()
@ -952,7 +955,11 @@ class HTTPVaultConnectorIT {
.withType(Token.Type.BATCH) .withType(Token.Type.BATCH)
.build(); .build();
res = assertDoesNotThrow(() -> connector.createToken(token4), "Token creation failed"); res = assertDoesNotThrow(() -> connector.createToken(token4), "Token creation failed");
assertTrue(res.getAuth().getClientToken().startsWith("b"), "Unexpected token prefix"); assertTrue(
// Expecting batch token. "hvb." Prefix as of Vault 1.10, "b." before.
res.getAuth().getClientToken().startsWith("b.") || res.getAuth().getClientToken().startsWith("hvb."),
"Unexpected token prefix"
);
assertEquals(1, res.getAuth().getPolicies().size(), "Invalid number of policies returned"); assertEquals(1, res.getAuth().getPolicies().size(), "Invalid number of policies returned");
assertTrue(res.getAuth().getPolicies().contains("batchpolicy"), "Custom policy policy not set"); assertTrue(res.getAuth().getPolicies().contains("batchpolicy"), "Custom policy policy not set");
assertFalse(res.getAuth().isRenewable(), "Token should not be renewable"); assertFalse(res.getAuth().isRenewable(), "Token should not be renewable");
@ -1073,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)));
}
} }
/** /**
@ -1200,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()
@ -1217,30 +1233,37 @@ class HTTPVaultConnectorIT {
} }
// Write configuration file. // Write configuration file.
BufferedWriter bw = null; File configFile = new File(dir, "vault.conf");
File configFile; try (BufferedWriter bw = new BufferedWriter(new FileWriter(configFile))) {
try {
configFile = new File(dir, "vault.conf");
bw = new BufferedWriter(new FileWriter(configFile));
bw.write(config.toString()); bw.write(config.toString());
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unable to generate config file", e); throw new IllegalStateException("Unable to generate config file", e);
} finally {
try {
if (bw != null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
// Start vault process. // Start vault process.
try { try {
vaultProcess = Runtime.getRuntime().exec("vault server -config " + configFile.toString()); vaultProcess = Runtime.getRuntime().exec("vault server -config " + configFile);
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unable to start vault. Make sure vault binary is in your executable path", e); throw new IllegalStateException("Unable to start vault. Make sure vault binary is in your executable path", e);
} }
await().atMost(5, TimeUnit.SECONDS).until(() -> {
try (InputStream stdout = vaultProcess.getInputStream();
InputStreamReader reader = new InputStreamReader(stdout);
BufferedReader br = new BufferedReader(reader)) {
String line = br.readLine();
while (line != null) {
if (line.contains("Vault server started")) {
return true;
} else {
line = br.readLine();
}
}
return false;
}
});
return config; return config;
} }
@ -1265,28 +1288,14 @@ class HTTPVaultConnectorIT {
* @return port number * @return port number
*/ */
private static Integer getFreePort() { private static Integer getFreePort() {
ServerSocket socket = null; try (ServerSocket socket = new ServerSocket(0)) {
try {
socket = new ServerSocket(0);
socket.setReuseAddress(true); socket.setReuseAddress(true);
int port = socket.getLocalPort();
try { return socket.getLocalPort();
socket.close();
} catch (IOException e) {
// Ignore IOException on close()
}
return port;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
throw new IllegalStateException("Unable to find a free TCP port"); throw new IllegalStateException("Unable to find a free TCP port");
} }
@ -1301,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-2021 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,16 +16,14 @@
package de.stklcode.jvault.connector; package de.stklcode.jvault.connector;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import de.stklcode.jvault.connector.exception.ConnectionException; import de.stklcode.jvault.connector.exception.ConnectionException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.exception.PermissionDeniedException; import de.stklcode.jvault.connector.exception.PermissionDeniedException;
import de.stklcode.jvault.connector.exception.VaultConnectorException; import de.stklcode.jvault.connector.exception.VaultConnectorException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.Executable;
import java.io.IOException; import java.io.IOException;
@ -40,6 +38,7 @@ import java.util.Collections;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
@ -50,21 +49,10 @@ import static org.junit.jupiter.api.Assertions.*;
* @since 0.7.0 * @since 0.7.0
*/ */
class HTTPVaultConnectorTest { class HTTPVaultConnectorTest {
private static WireMockServer wireMock; @RegisterExtension
static WireMockExtension wireMock = WireMockExtension.newInstance()
@BeforeAll .options(wireMockConfig().dynamicPort())
static void prepare() { .build();
// Initialize HTTP mock.
wireMock = new WireMockServer(WireMockConfiguration.options().dynamicPort());
wireMock.start();
WireMock.configureFor("localhost", wireMock.port());
}
@AfterAll
static void tearDown() {
wireMock.stop();
wireMock = null;
}
/** /**
* Test exceptions thrown during request. * Test exceptions thrown during request.
@ -108,7 +96,7 @@ class HTTPVaultConnectorTest {
// Now simulate a failing request that succeeds on second try. // Now simulate a failing request that succeeds on second try.
connector = HTTPVaultConnector.builder(wireMock.url("/")).withNumberOfRetries(1).withTimeout(250).build(); connector = HTTPVaultConnector.builder(wireMock.url("/")).withNumberOfRetries(1).withTimeout(250).build();
WireMock.stubFor( wireMock.stubFor(
WireMock.any(anyUrl()) WireMock.any(anyUrl())
.willReturn(aResponse().withStatus(500)) .willReturn(aResponse().withStatus(500))
.willReturn(aResponse().withStatus(500)) .willReturn(aResponse().withStatus(500))
@ -334,7 +322,7 @@ class HTTPVaultConnectorTest {
} }
private void mockHttpResponse(int status, String body, String contentType) { private void mockHttpResponse(int status, String body, String contentType) {
WireMock.stubFor( wireMock.stubFor(
WireMock.any(anyUrl()).willReturn( WireMock.any(anyUrl()).willReturn(
aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType) aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType)
) )

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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

@ -0,0 +1,73 @@
package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.databind.ObjectMapper;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test;
import java.io.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
/**
* Abstract testcase for model classes.
*
* @author Stefan Kalscheuer
* @since 1.1
*/
public abstract class AbstractModelTest<T> {
protected final Class<?> modelClass;
protected final ObjectMapper objectMapper;
/**
* Test case constructor.
*
* @param modelClass Target class to test.
*/
protected AbstractModelTest(Class<T> modelClass) {
this.modelClass = modelClass;
this.objectMapper = new ObjectMapper();
}
/**
* Create a "full" model instance.
*
* @return Model instance.
*/
protected abstract T createFull();
/**
* Test if {@link Object#equals(Object)} and {@link Object#hashCode()} are implemented, s.t. all fields are covered.
*/
@Test
void testEqualsHashcode() {
EqualsVerifier.simple().forClass(modelClass).verify();
}
/**
* Test Java serialization of a full model instance.
* Serialization and deserialization must not fail and the resulting object should equal the original object.
*/
@Test
void serializationTest() {
T original = createFull();
byte[] bytes;
try (var bos = new ByteArrayOutputStream();
var oos = new ObjectOutputStream(bos)) {
oos.writeObject(original);
bytes = bos.toByteArray();
} catch (IOException e) {
fail("Serialization failed", e);
return;
}
try (var bis = new ByteArrayInputStream(bytes);
var ois = new ObjectInputStream(bis)) {
Object copy = ois.readObject();
assertEquals(modelClass, copy.getClass(), "Invalid class after deserialization");
assertEquals(original, copy, "Deserialized object should be equal to the original");
} catch (IOException | ClassNotFoundException e) {
fail("Deserialization failed", e);
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,12 +16,9 @@
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;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -35,14 +32,21 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.5.0 * @since 0.5.0
*/ */
class AppRoleSecretTest { class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
private static final String TEST_ID = "abc123"; private static final String TEST_ID = "abc123";
private static final Map<String, Object> TEST_META = new HashMap<>(); private static final Map<String, Object> TEST_META = Map.of(
private static final List<String> TEST_CIDR = Arrays.asList("203.0.113.0/24", "198.51.100.0/24"); "foo", "bar",
"number", 1337
);
private static final List<String> TEST_CIDR = List.of("203.0.113.0/24", "198.51.100.0/24");
static { AppRoleSecretTest() {
TEST_META.put("foo", "bar"); super(AppRoleSecret.class);
TEST_META.put("number", 1337); }
@Override
protected AppRoleSecret createFull() {
return new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
} }
/** /**
@ -111,16 +115,14 @@ class AppRoleSecretTest {
*/ */
@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());
@ -140,9 +142,9 @@ class AppRoleSecretTest {
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());
@ -160,14 +162,13 @@ class AppRoleSecretTest {
"\"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());
assertEquals("TEST_LASTUPDATE", secret2.getLastUpdatedTime()); assertEquals("TEST_LASTUPDATE", secret2.getLastUpdatedTime());
assertEquals(678, secret2.getNumUses()); assertEquals(678, secret2.getNumUses());
assertEquals(12345, secret2.getTtl()); assertEquals(12345, secret2.getTtl());
} }
private static void setPrivateField(Object object, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { private static void setPrivateField(Object object, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
@ -182,5 +183,4 @@ class AppRoleSecretTest {
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":\\[$1\\]") return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":\\[$1\\]")
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\""); .replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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;
@ -32,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
class AppRoleTest { class AppRoleTest extends AbstractModelTest<AppRole> {
private static final String NAME = "TestRole"; private static final String NAME = "TestRole";
private static final String ID = "test-id"; private static final String ID = "test-id";
private static final Boolean BIND_SECRET_ID = true; private static final Boolean BIND_SECRET_ID = true;
@ -56,6 +55,31 @@ class AppRoleTest {
private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"enable_local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}", private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"enable_local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}",
NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, ENABLE_LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value()); NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, ENABLE_LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value());
AppRoleTest() {
super(AppRole.class);
}
@Override
protected AppRole createFull() {
return AppRole.builder(NAME)
.withId(ID)
.withBindSecretID(BIND_SECRET_ID)
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
.withTokenPolicies(POLICIES)
.withSecretIdNumUses(SECRET_ID_NUM_USES)
.withSecretIdTtl(SECRET_ID_TTL)
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
.withTokenTtl(TOKEN_TTL)
.withTokenMaxTtl(TOKEN_MAX_TTL)
.withTokenBoundCidrs(BOUND_CIDR_LIST)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
}
@BeforeAll @BeforeAll
static void init() { static void init() {
BOUND_CIDR_LIST.add(CIDR_1); BOUND_CIDR_LIST.add(CIDR_1);
@ -85,7 +109,7 @@ class AppRoleTest {
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));
} }
/** /**
@ -93,23 +117,7 @@ class AppRoleTest {
*/ */
@Test @Test
void buildFullTest() throws JsonProcessingException { void buildFullTest() throws JsonProcessingException {
AppRole role = AppRole.builder(NAME) AppRole role = createFull();
.withId(ID)
.withBindSecretID(BIND_SECRET_ID)
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
.withTokenPolicies(POLICIES)
.withSecretIdNumUses(SECRET_ID_NUM_USES)
.withSecretIdTtl(SECRET_ID_TTL)
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
.withTokenTtl(TOKEN_TTL)
.withTokenMaxTtl(TOKEN_MAX_TTL)
.withTokenBoundCidrs(BOUND_CIDR_LIST)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
assertEquals(NAME, role.getName()); assertEquals(NAME, role.getName());
assertEquals(ID, role.getId()); assertEquals(ID, role.getId());
assertEquals(BIND_SECRET_ID, role.getBindSecretId()); assertEquals(BIND_SECRET_ID, role.getBindSecretId());
@ -128,7 +136,7 @@ class AppRoleTest {
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-2021 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-2021 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;
@ -26,21 +25,29 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
* Unit Test for {@link Token.Builder} * Unit Test for {@link TokenRole} and {@link TokenRole.Builder}.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.9 * @since 0.9
*/ */
class TokenRoleBuilderTest { class TokenRoleTest extends AbstractModelTest<TokenRole> {
private static final String NAME = "test-role"; private static final String NAME = "test-role";
private static final String ALLOWED_POLICY_1 = "apol-1"; private static final String ALLOWED_POLICY_1 = "apol-1";
private static final String ALLOWED_POLICY_2 = "apol-2"; private static final String ALLOWED_POLICY_2 = "apol-2";
private static final String ALLOWED_POLICY_3 = "apol-3"; private static final String ALLOWED_POLICY_3 = "apol-3";
private static final List<String> ALLOWED_POLICIES = Arrays.asList(ALLOWED_POLICY_1, ALLOWED_POLICY_2); private static final List<String> ALLOWED_POLICIES = Arrays.asList(ALLOWED_POLICY_1, ALLOWED_POLICY_2);
private static final String ALLOWED_POLICY_GLOB_1 = "apol-g1*";
private static final String ALLOWED_POLICY_GLOB_2 = "apol-g2*";
private static final String ALLOWED_POLICY_GLOB_3 = "apol-g3*";
private static final List<String> ALLOWED_POLICIES_GLOB = Arrays.asList(ALLOWED_POLICY_GLOB_2, ALLOWED_POLICY_GLOB_3);
private static final String DISALLOWED_POLICY_1 = "dpol-1"; private static final String DISALLOWED_POLICY_1 = "dpol-1";
private static final String DISALLOWED_POLICY_2 = "dpol-2"; private static final String DISALLOWED_POLICY_2 = "dpol-2";
private static final String DISALLOWED_POLICY_3 = "dpol-3"; private static final String DISALLOWED_POLICY_3 = "dpol-3";
private static final List<String> DISALLOWED_POLICIES = Arrays.asList(DISALLOWED_POLICY_2, DISALLOWED_POLICY_3); private static final List<String> DISALLOWED_POLICIES = Arrays.asList(DISALLOWED_POLICY_2, DISALLOWED_POLICY_3);
private static final String DISALLOWED_POLICY_GLOB_1 = "dpol-g1*";
private static final String DISALLOWED_POLICY_GLOB_2 = "dpol-g2*";
private static final String DISALLOWED_POLICY_GLOB_3 = "dpol-g3*";
private static final List<String> DISALLOWED_POLICIES_GLOB = Arrays.asList(DISALLOWED_POLICY_GLOB_1, DISALLOWED_POLICY_GLOB_2);
private static final Boolean ORPHAN = false; private static final Boolean ORPHAN = false;
private static final Boolean RENEWABLE = true; private static final Boolean RENEWABLE = true;
private static final String PATH_SUFFIX = "ps"; private static final String PATH_SUFFIX = "ps";
@ -61,7 +68,9 @@ class TokenRoleBuilderTest {
private static final String JSON_FULL = "{" + private static final String JSON_FULL = "{" +
"\"name\":\"" + NAME + "\"," + "\"name\":\"" + NAME + "\"," +
"\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," + "\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," +
"\"allowed_policies_glob\":[\"" + ALLOWED_POLICY_GLOB_1 + "\",\"" + ALLOWED_POLICY_GLOB_2 + "\",\"" + ALLOWED_POLICY_GLOB_3 + "\"]," +
"\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," + "\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," +
"\"disallowed_policies_glob\":[\"" + DISALLOWED_POLICY_GLOB_1 + "\",\"" + DISALLOWED_POLICY_GLOB_2 + "\",\"" + DISALLOWED_POLICY_GLOB_3 + "\"]," +
"\"orphan\":" + ORPHAN + "," + "\"orphan\":" + ORPHAN + "," +
"\"renewable\":" + RENEWABLE + "," + "\"renewable\":" + RENEWABLE + "," +
"\"path_suffix\":\"" + PATH_SUFFIX + "\"," + "\"path_suffix\":\"" + PATH_SUFFIX + "\"," +
@ -73,6 +82,37 @@ class TokenRoleBuilderTest {
"\"token_period\":" + TOKEN_PERIOD + "," + "\"token_period\":" + TOKEN_PERIOD + "," +
"\"token_type\":\"" + TOKEN_TYPE.value() + "\"}"; "\"token_type\":\"" + TOKEN_TYPE.value() + "\"}";
TokenRoleTest() {
super(TokenRole.class);
}
@Override
protected TokenRole createFull() {
return TokenRole.builder()
.forName(NAME)
.withAllowedPolicies(ALLOWED_POLICIES)
.withAllowedPolicy(ALLOWED_POLICY_3)
.withAllowedPolicyGlob(ALLOWED_POLICY_GLOB_1)
.withAllowedPoliciesGlob(ALLOWED_POLICIES_GLOB)
.withDisallowedPolicy(DISALLOWED_POLICY_1)
.withDisallowedPolicies(DISALLOWED_POLICIES)
.withDisallowedPoliciesGlob(DISALLOWED_POLICIES_GLOB)
.withDisallowedPolicyGlob(DISALLOWED_POLICY_GLOB_3)
.orphan(ORPHAN)
.renewable(RENEWABLE)
.withPathSuffix(PATH_SUFFIX)
.withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES)
.withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2)
.withTokenBoundCidr(TOKEN_BOUND_CIDR_3)
.withTokenBoundCidrs(TOKEN_BOUND_CIDRS)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
}
/** /**
* Build token without any parameters. * Build token without any parameters.
*/ */
@ -92,7 +132,7 @@ class TokenRoleBuilderTest {
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));
} }
/** /**
@ -132,8 +172,11 @@ class TokenRoleBuilderTest {
assertNull(role.getTokenPeriod()); assertNull(role.getTokenPeriod());
assertNull(role.getTokenType()); assertNull(role.getTokenType());
// Empty builder should be equal to no-arg construction.
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));
} }
/** /**
@ -141,30 +184,16 @@ class TokenRoleBuilderTest {
*/ */
@Test @Test
void buildFullTest() throws JsonProcessingException { void buildFullTest() throws JsonProcessingException {
TokenRole role = TokenRole.builder() TokenRole role = createFull();
.forName(NAME)
.withAllowedPolicies(ALLOWED_POLICIES)
.withAllowedPolicy(ALLOWED_POLICY_3)
.withDisallowedPolicy(DISALLOWED_POLICY_1)
.withDisallowedPolicies(DISALLOWED_POLICIES)
.orphan(ORPHAN)
.renewable(RENEWABLE)
.withPathSuffix(PATH_SUFFIX)
.withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES)
.withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2)
.withTokenBoundCidr(TOKEN_BOUND_CIDR_3)
.withTokenBoundCidrs(TOKEN_BOUND_CIDRS)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
assertEquals(NAME, role.getName()); assertEquals(NAME, role.getName());
assertEquals(ALLOWED_POLICIES.size() + 1, role.getAllowedPolicies().size()); assertEquals(ALLOWED_POLICIES.size() + 1, role.getAllowedPolicies().size());
assertTrue(role.getAllowedPolicies().containsAll(List.of(ALLOWED_POLICY_1, ALLOWED_POLICY_2, ALLOWED_POLICY_3))); assertTrue(role.getAllowedPolicies().containsAll(List.of(ALLOWED_POLICY_1, ALLOWED_POLICY_2, ALLOWED_POLICY_3)));
assertEquals(ALLOWED_POLICIES_GLOB.size() + 1, role.getAllowedPoliciesGlob().size());
assertTrue(role.getAllowedPoliciesGlob().containsAll(List.of(ALLOWED_POLICY_GLOB_1, ALLOWED_POLICY_GLOB_2, ALLOWED_POLICY_GLOB_3)));
assertEquals(DISALLOWED_POLICIES.size() + 1, role.getDisallowedPolicies().size()); assertEquals(DISALLOWED_POLICIES.size() + 1, role.getDisallowedPolicies().size());
assertTrue(role.getDisallowedPolicies().containsAll(List.of(DISALLOWED_POLICY_1, DISALLOWED_POLICY_2, DISALLOWED_POLICY_3))); assertTrue(role.getDisallowedPolicies().containsAll(List.of(DISALLOWED_POLICY_1, DISALLOWED_POLICY_2, DISALLOWED_POLICY_3)));
assertEquals(DISALLOWED_POLICIES_GLOB.size() + 1, role.getDisallowedPoliciesGlob().size());
assertTrue(role.getDisallowedPoliciesGlob().containsAll(List.of(DISALLOWED_POLICY_GLOB_1, DISALLOWED_POLICY_GLOB_2, DISALLOWED_POLICY_GLOB_3)));
assertEquals(ORPHAN, role.getOrphan()); assertEquals(ORPHAN, role.getOrphan());
assertEquals(RENEWABLE, role.getRenewable()); assertEquals(RENEWABLE, role.getRenewable());
assertEquals(PATH_SUFFIX, role.getPathSuffix()); assertEquals(PATH_SUFFIX, role.getPathSuffix());
@ -178,6 +207,6 @@ class TokenRoleBuilderTest {
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-2021 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;
@ -31,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
class TokenTest { class TokenTest extends AbstractModelTest<Token> {
private static final String ID = "test-id"; private static final String ID = "test-id";
private static final String DISPLAY_NAME = "display-name"; private static final String DISPLAY_NAME = "display-name";
private static final Boolean NO_PARENT = false; private static final Boolean NO_PARENT = false;
@ -53,6 +52,29 @@ class TokenTest {
private static final String ENTITY_ALIAS = "alias-value"; private static final String ENTITY_ALIAS = "alias-value";
private static final String JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"explicit_max_ttl\":456,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true,\"period\":3600,\"entity_alias\":\"alias-value\"}"; private static final String JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"explicit_max_ttl\":456,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true,\"period\":3600,\"entity_alias\":\"alias-value\"}";
TokenTest() {
super(Token.class);
}
@Override
protected Token createFull() {
return Token.builder()
.withId(ID)
.withType(Token.Type.SERVICE)
.withDisplayName(DISPLAY_NAME)
.withNoParent(NO_PARENT)
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
.withTtl(TTL)
.withExplicitMaxTtl(EXPLICIT_MAX_TTL)
.withNumUses(NUM_USES)
.withPolicies(POLICIES)
.withMeta(META)
.withRenewable(RENEWABLE)
.withPeriod(PERIOD)
.withEntityAlias(ENTITY_ALIAS)
.build();
}
@BeforeAll @BeforeAll
static void init() { static void init() {
POLICIES.add(POLICY); POLICIES.add(POLICY);
@ -80,7 +102,10 @@ class TokenTest {
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.
assertEquals(token, new Token());
} }
/** /**
@ -88,21 +113,7 @@ class TokenTest {
*/ */
@Test @Test
void buildFullTest() throws JsonProcessingException { void buildFullTest() throws JsonProcessingException {
Token token = Token.builder() Token token = createFull();
.withId(ID)
.withType(Token.Type.SERVICE)
.withDisplayName(DISPLAY_NAME)
.withNoParent(NO_PARENT)
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
.withTtl(TTL)
.withExplicitMaxTtl(EXPLICIT_MAX_TTL)
.withNumUses(NUM_USES)
.withPolicies(POLICIES)
.withMeta(META)
.withRenewable(RENEWABLE)
.withPeriod(PERIOD)
.withEntityAlias(ENTITY_ALIAS)
.build();
assertEquals(ID, token.getId()); assertEquals(ID, token.getId());
assertEquals(Token.Type.SERVICE.value(), token.getType()); assertEquals(Token.Type.SERVICE.value(), token.getType());
assertEquals(DISPLAY_NAME, token.getDisplayName()); assertEquals(DISPLAY_NAME, token.getDisplayName());
@ -117,7 +128,7 @@ class TokenTest {
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-2021 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,14 +16,12 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; 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;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -33,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.6.2 * @since 0.6.2
*/ */
class AppRoleResponseTest { class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
private static final Integer ROLE_TOKEN_TTL = 1200; private static final Integer ROLE_TOKEN_TTL = 1200;
private static final Integer ROLE_TOKEN_MAX_TTL = 1800; private static final Integer ROLE_TOKEN_MAX_TTL = 1800;
private static final Integer ROLE_SECRET_TTL = 600; private static final Integer ROLE_SECRET_TTL = 600;
@ -63,10 +61,18 @@ class AppRoleResponseTest {
" \"lease_id\": \"\"\n" + " \"lease_id\": \"\"\n" +
"}"; "}";
private static final Map<String, Object> INVALID_DATA = new HashMap<>(); AppRoleResponseTest() {
super(AppRoleResponse.class);
}
static { @Override
INVALID_DATA.put("token_policies", "fancy-policy"); protected AppRoleResponse createFull() {
try {
return objectMapper.readValue(RES_JSON, AppRoleResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
} }
/** /**
@ -77,13 +83,6 @@ class AppRoleResponseTest {
// Create empty Object. // Create empty Object.
AppRoleResponse res = new AppRoleResponse(); AppRoleResponse res = new AppRoleResponse();
assertNull(res.getRole(), "Initial data should be empty"); assertNull(res.getRole(), "Initial data should be empty");
// Parsing invalid auth data map should fail.
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_DATA),
"Parsing invalid data succeeded"
);
} }
/** /**
@ -92,7 +91,7 @@ class AppRoleResponseTest {
@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-2021 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,14 +16,13 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; 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;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -35,12 +34,16 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.6.2 * @since 0.6.2
*/ */
class AuthMethodsResponseTest { class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
private static final String GH_PATH = "github/"; private static final String GH_PATH = "github/";
private static final String GH_TYPE = "github"; private static final String GH_TYPE = "github";
private static final String GH_UUID = "4b42d1a4-0a0d-3c88-ae90-997e0c8b41be";
private static final String GH_ACCESSOR = "auth_github_badd7fd0";
private static final String GH_DESCR = "GitHub auth"; private static final String GH_DESCR = "GitHub auth";
private static final String TK_PATH = "token/"; private static final String TK_PATH = "token/";
private static final String TK_TYPE = "token"; private static final String TK_TYPE = "token";
private static final String TK_UUID = "32ea9681-6bd6-6cec-eec3-d11260ba9741";
private static final String TK_ACCESSOR = "auth_token_ac0dd95a";
private static final String TK_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 Integer TK_MAX_LEASE_TTL = 0; private static final Integer TK_MAX_LEASE_TTL = 0;
@ -48,8 +51,13 @@ class AuthMethodsResponseTest {
private static final String RES_JSON = "{\n" + private static final String RES_JSON = "{\n" +
" \"data\": {" + " \"data\": {" +
" \"" + GH_PATH + "\": {\n" + " \"" + GH_PATH + "\": {\n" +
" \"uuid\": \"" + GH_UUID + "\",\n" +
" \"type\": \"" + GH_TYPE + "\",\n" + " \"type\": \"" + GH_TYPE + "\",\n" +
" \"description\": \"" + GH_DESCR + "\"\n" + " \"accessor\": \"" + GH_ACCESSOR + "\",\n" +
" \"description\": \"" + GH_DESCR + "\",\n" +
" \"external_entropy_access\": false,\n" +
" \"local\": false,\n" +
" \"seal_wrap\": false\n" +
" },\n" + " },\n" +
" \"" + TK_PATH + "\": {\n" + " \"" + TK_PATH + "\": {\n" +
" \"config\": {\n" + " \"config\": {\n" +
@ -57,15 +65,28 @@ class AuthMethodsResponseTest {
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + "\n" + " \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + "\n" +
" },\n" + " },\n" +
" \"description\": \"" + TK_DESCR + "\",\n" + " \"description\": \"" + TK_DESCR + "\",\n" +
" \"type\": \"" + TK_TYPE + "\"\n" + " \"type\": \"" + TK_TYPE + "\",\n" +
" \"uuid\": \"" + TK_UUID + "\",\n" +
" \"accessor\": \"" + TK_ACCESSOR + "\",\n" +
" \"external_entropy_access\": false,\n" +
" \"local\": true,\n" +
" \"seal_wrap\": false\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
"}"; "}";
private static final Map<String, Object> INVALID_DATA = new HashMap<>(); AuthMethodsResponseTest() {
super(AuthMethodsResponse.class);
}
static { @Override
INVALID_DATA.put("dummy/", new Dummy()); protected AuthMethodsResponse createFull() {
try {
return objectMapper.readValue(RES_JSON, AuthMethodsResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
} }
/** /**
@ -76,13 +97,6 @@ class AuthMethodsResponseTest {
// Create empty Object. // Create empty Object.
AuthMethodsResponse res = new AuthMethodsResponse(); AuthMethodsResponse res = new AuthMethodsResponse();
assertEquals(Collections.emptyMap(), res.getSupportedMethods(), "Initial method map should be empty"); assertEquals(Collections.emptyMap(), res.getSupportedMethods(), "Initial method map should be empty");
// Parsing invalid data map should fail.
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_DATA),
"Parsing invalid data succeeded"
);
} }
/** /**
@ -91,7 +105,7 @@ class AuthMethodsResponseTest {
@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");
@ -107,19 +121,31 @@ class AuthMethodsResponseTest {
assertEquals(AuthBackend.GITHUB, method.getType(), "Incorrect parsed type for GitHub"); assertEquals(AuthBackend.GITHUB, method.getType(), "Incorrect parsed type for GitHub");
assertEquals(GH_DESCR, method.getDescription(), "Incorrect description for GitHub"); assertEquals(GH_DESCR, method.getDescription(), "Incorrect description for GitHub");
assertNull(method.getConfig(), "Unexpected config for GitHub"); assertNull(method.getConfig(), "Unexpected config for GitHub");
assertEquals(GH_UUID, method.getUuid(), "Unexpected UUID for GitHub");
assertEquals(GH_ACCESSOR, method.getAccessor(), "Unexpected accessor for GitHub");
assertFalse(method.isLocal(), "Unexpected local flag for GitHub");
assertFalse(method.isExternalEntropyAccess(), "Unexpected external entropy flag for GitHub");
assertFalse(method.isSealWrap(), "Unexpected seal wrap flag for GitHub");
// Verify first method. // Verify second method.
method = supported.get(TK_PATH); method = supported.get(TK_PATH);
assertEquals(TK_TYPE, method.getRawType(), "Incorrect raw type for Token"); assertEquals(TK_TYPE, method.getRawType(), "Incorrect raw type for Token");
assertEquals(AuthBackend.TOKEN, method.getType(), "Incorrect parsed type for Token"); assertEquals(AuthBackend.TOKEN, method.getType(), "Incorrect parsed type for Token");
assertEquals(TK_DESCR, method.getDescription(), "Incorrect description for Token"); assertEquals(TK_DESCR, method.getDescription(), "Incorrect description for Token");
assertEquals(TK_UUID, method.getUuid(), "Unexpected UUID for Token");
assertEquals(TK_ACCESSOR, method.getAccessor(), "Unexpected accessor for Token");
assertTrue(method.isLocal(), "Unexpected local flag for Token");
assertFalse(method.isExternalEntropyAccess(), "Unexpected external entropy flag for Token");
assertFalse(method.isSealWrap(), "Unexpected seal wrap flag for GitHub");
assertNotNull(method.getConfig(), "Missing config for Token"); assertNotNull(method.getConfig(), "Missing config for Token");
assertEquals(2, method.getConfig().size(), "Unexpected config size for Token"); assertEquals(
assertEquals(TK_LEASE_TTL.toString(), method.getConfig().get("default_lease_ttl"), "Incorrect lease TTL config"); Map.of(
assertEquals(TK_MAX_LEASE_TTL.toString(), method.getConfig().get("max_lease_ttl"), "Incorrect max lease TTL config"); "default_lease_ttl", TK_LEASE_TTL.toString(),
} "max_lease_ttl", TK_MAX_LEASE_TTL.toString()
),
private static class Dummy { method.getConfig(),
"Unexpected config for Token"
);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,12 +16,11 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; 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 org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -33,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.6.2 * @since 0.6.2
*/ */
class AuthResponseTest { class AuthResponseTest extends AbstractModelTest<AuthResponse> {
private static final String AUTH_ACCESSOR = "2c84f488-2133-4ced-87b0-570f93a76830"; private static final String AUTH_ACCESSOR = "2c84f488-2133-4ced-87b0-570f93a76830";
private static final String AUTH_CLIENT_TOKEN = "ABCD"; private static final String AUTH_CLIENT_TOKEN = "ABCD";
private static final String AUTH_POLICY_1 = "web"; private static final String AUTH_POLICY_1 = "web";
@ -69,31 +68,18 @@ class AuthResponseTest {
" }\n" + " }\n" +
"}"; "}";
private static final Map<String, Object> INVALID_AUTH_DATA = new HashMap<>(); AuthResponseTest() {
super(AuthResponse.class);
static {
INVALID_AUTH_DATA.put("policies", "fancy-policy");
} }
/** @Override
* Test getter, setter and get-methods for response data. protected AuthResponse createFull() {
*/ try {
@Test return objectMapper.readValue(RES_JSON, AuthResponse.class);
void getDataRoundtrip() { } catch (JsonProcessingException e) {
// Create empty Object. fail("Creation of full model instance failed", e);
AuthResponse res = new AuthResponse(); return null;
assertNull(res.getData(), "Initial data should be empty"); }
// Parsing invalid auth data map should fail.
assertThrows(
InvalidResponseException.class,
() -> res.setAuth(INVALID_AUTH_DATA),
"Parsing invalid auth data succeeded"
);
// Data method should be agnostic.
res.setData(INVALID_AUTH_DATA);
assertEquals(INVALID_AUTH_DATA, res.getData(), "Data not passed through");
} }
/** /**
@ -102,7 +88,7 @@ class AuthResponseTest {
@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");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,14 +16,12 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/** /**
* JUnit Test for {@link CredentialsResponse} model. * JUnit Test for {@link CredentialsResponse} model.
@ -31,14 +29,33 @@ import static org.junit.jupiter.api.Assertions.assertNull;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
*/ */
class CredentialsResponseTest { class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String VAL_USER = "testUserName"; private static final String VAL_USER = "testUserName";
private static final String VAL_PASS = "5up3r5ecr3tP455"; private static final String VAL_PASS = "5up3r5ecr3tP455";
private static final String JSON = "{\n" +
" \"request_id\": \"68315073-6658-e3ff-2da7-67939fb91bbd\",\n" +
" \"lease_id\": \"\",\n" +
" \"lease_duration\": 2764800,\n" +
" \"renewable\": false,\n" +
" \"data\": {\n" +
" \"username\": \"" + VAL_USER + "\",\n" +
" \"password\": \"" + VAL_PASS + "\"\n" +
" },\n" +
" \"warnings\": null\n" +
"}";
static { CredentialsResponseTest() {
DATA.put("username", VAL_USER); super(CredentialsResponse.class);
DATA.put("password", VAL_PASS); }
@Override
protected CredentialsResponse createFull() {
try {
return objectMapper.readValue(JSON, CredentialsResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
} }
/** /**
@ -47,15 +64,16 @@ class CredentialsResponseTest {
* @throws InvalidResponseException Should not occur * @throws InvalidResponseException Should not occur
*/ */
@Test @Test
@SuppressWarnings("unchecked")
void getCredentialsTest() throws InvalidResponseException { void getCredentialsTest() throws InvalidResponseException {
// Create empty Object. // Create empty Object.
CredentialsResponse res = new CredentialsResponse(); CredentialsResponse res = new CredentialsResponse();
assertNull(res.getUsername(), "Username not present in data map should not return anything"); assertNull(res.getUsername(), "Username not present in data map should not return anything");
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");
// Fill data map. res = assertDoesNotThrow(
res.setData(DATA); () -> objectMapper.readValue(JSON, CredentialsResponse.class),
"Deserialization of CredentialsResponse failed"
);
assertEquals(VAL_USER, res.getUsername(), "Incorrect username"); assertEquals(VAL_USER, res.getUsername(), "Incorrect username");
assertEquals(VAL_PASS, res.getPassword(), "Incorrect password"); assertEquals(VAL_PASS, res.getPassword(), "Incorrect password");
} }

View File

@ -0,0 +1,88 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.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.*;
/**
* JUnit Test for {@link ErrorResponse} model.
*
* @author Stefan Kalscheuer
*/
class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
private static final String ERROR_1 = "Error #1";
private static final String ERROR_2 = "Error #2";
private static final String JSON = "{\"errors\":[\"" + ERROR_1 + "\",\"" + ERROR_2 + "\"]}";
private static final String JSON_EMPTY = "{\"errors\":[]}";
ErrorResponseTest() {
super(ErrorResponse.class);
}
@Override
protected ErrorResponse createFull() {
try {
return objectMapper.readValue(JSON, ErrorResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
}
/**
* Test creation from JSON value as returned by Vault.
*/
@Test
void jsonRoundtrip() {
ErrorResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, ErrorResponse.class),
"ErrorResponse deserialization failed"
);
assertNotNull(res, "Parsed response is NULL");
assertEquals(List.of(ERROR_1, ERROR_2), res.getErrors(), "Unexpected error messages");
assertEquals(
JSON,
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "ErrorResponse serialization failed"),
"Unexpected JSON string after serialization"
);
}
@Test
void testToString() {
ErrorResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, ErrorResponse.class),
"ErrorResponse deserialization failed"
);
assertEquals(ERROR_1, res.toString());
res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON_EMPTY, ErrorResponse.class),
"ErrorResponse deserialization failed with empty list"
);
assertEquals("error response", res.toString());
assertEquals("error response", new ErrorResponse().toString());
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -27,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.7.0 * @since 0.7.0
*/ */
class HealthResponseTest { class HealthResponseTest extends AbstractModelTest<HealthResponse> {
private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228"; private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228";
private static final String CLUSTER_NAME = "vault-cluster-5515c810"; private static final String CLUSTER_NAME = "vault-cluster-5515c810";
private static final String VERSION = "0.9.2"; private static final String VERSION = "0.9.2";
@ -47,18 +48,32 @@ class HealthResponseTest {
" \"standby\": " + STANDBY + ",\n" + " \"standby\": " + STANDBY + ",\n" +
" \"sealed\": " + SEALED + ",\n" + " \"sealed\": " + SEALED + ",\n" +
" \"initialized\": " + INITIALIZED + ",\n" + " \"initialized\": " + INITIALIZED + ",\n" +
" \"replication_perf_mode\": \"" + REPL_PERF_MODE + "\",\n" + " \"replication_performance_mode\": \"" + REPL_PERF_MODE + "\",\n" +
" \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" + " \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" +
" \"performance_standby\": " + PERF_STANDBY + "\n" + " \"performance_standby\": " + PERF_STANDBY + "\n" +
"}"; "}";
HealthResponseTest() {
super(HealthResponse.class);
}
@Override
protected HealthResponse createFull() {
try {
return objectMapper.readValue(RES_JSON, HealthResponse.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 creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/ */
@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

@ -0,0 +1,66 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* JUnit Test for {@link HelpResponse} model.
*
* @author Stefan Kalscheuer
*/
class HelpResponseTest extends AbstractModelTest<HelpResponse> {
private static final String HELP = "Help Text.";
private static final String JSON = "{\"help\":\"" + HELP + "\"}";
HelpResponseTest() {
super(HelpResponse.class);
}
@Override
protected HelpResponse createFull() {
try {
return objectMapper.readValue(JSON, HelpResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
}
/**
* Test creation from JSON value as returned by Vault.
*/
@Test
void jsonRoundtrip() {
HelpResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(JSON, HelpResponse.class),
"HelpResponse deserialization failed"
);
assertNotNull(res, "Parsed response is NULL");
assertEquals(HELP, res.getHelp(), "Unexpected help text");
assertEquals(
JSON,
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "HelpResponse serialization failed"),
"Unexpected JSON string after serialization"
);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,33 +16,21 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
* JUnit Test for {@link SecretResponse} model. * JUnit Test for {@link MetaSecretResponse} model.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.6.2 * @since 0.6.2
*/ */
class SecretResponseTest { class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String KEY_UNKNOWN = "unknown";
private static final String KEY_STRING = "test1";
private static final String VAL_STRING = "testvalue";
private static final String KEY_INTEGER = "test2";
private static final Integer VAL_INTEGER = 42;
private static final String KEY_LIST = "list";
private static final String VAL_LIST = "[\"first\",\"second\"]";
private static final String SECRET_REQUEST_ID = "68315073-6658-e3ff-2da7-67939fb91bbd"; private static final String SECRET_REQUEST_ID = "68315073-6658-e3ff-2da7-67939fb91bbd";
private static final String SECRET_LEASE_ID = ""; private static final String SECRET_LEASE_ID = "";
private static final Integer SECRET_LEASE_DURATION = 2764800; private static final Integer SECRET_LEASE_DURATION = 2764800;
@ -54,17 +42,6 @@ class SecretResponseTest {
private static final String SECRET_META_CREATED = "2018-03-22T02:24:06.945319214Z"; private static final String SECRET_META_CREATED = "2018-03-22T02:24:06.945319214Z";
private static final String SECRET_META_DELETED = "2018-03-23T03:25:07.056420325Z"; private static final String SECRET_META_DELETED = "2018-03-23T03:25:07.056420325Z";
private static final List<String> SECRET_WARNINGS = null; private static final List<String> SECRET_WARNINGS = null;
private static final String SECRET_JSON = "{\n" +
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
" \"renewable\": " + SECRET_RENEWABLE + ",\n" +
" \"data\": {\n" +
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
" },\n" +
" \"warnings\": " + SECRET_WARNINGS + "\n" +
"}";
private static final String SECRET_JSON_V2 = "{\n" + private static final String SECRET_JSON_V2 = "{\n" +
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" + " \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" + " \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
@ -104,49 +81,18 @@ class SecretResponseTest {
" \"warnings\": " + SECRET_WARNINGS + "\n" + " \"warnings\": " + SECRET_WARNINGS + "\n" +
"}"; "}";
MetaSecretResponseTest() {
static { super(MetaSecretResponse.class);
DATA.put(KEY_STRING, VAL_STRING);
DATA.put(KEY_INTEGER, VAL_INTEGER);
DATA.put(KEY_LIST, VAL_LIST);
} }
/** @Override
* Test getter, setter and get-methods for response data. protected MetaSecretResponse createFull() {
* try {
* @throws InvalidResponseException Should not occur return objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class);
*/ } catch (JsonProcessingException e) {
@Test fail("Creation of full model instance failed", e);
@SuppressWarnings("unchecked") return null;
void getDataRoundtrip() throws InvalidResponseException { }
// Create empty Object.
SecretResponse res = new SecretResponse();
assertNotNull(res.getData(), "Initial data should be Map");
assertTrue(res.getData().isEmpty(), "Initial data should be empty");
assertNull(res.get(KEY_STRING), "Getter should return NULL on empty data map");
// Fill data map.
res.setData(DATA);
assertEquals(DATA, res.getData(), "Data setter/getter not transparent");
assertEquals(DATA.size(), res.getData().keySet().size(), "Data size modified");
assertTrue(res.getData().keySet().containsAll(Set.of(KEY_STRING, KEY_INTEGER, KEY_LIST)), "Data keys not passed correctly");
assertEquals(VAL_STRING, res.get(KEY_STRING), "Data values not passed correctly");
assertEquals(VAL_INTEGER, res.get(KEY_INTEGER), "Data values not passed correctly");
assertNull(res.get(KEY_UNKNOWN), "Non-Null returned on unknown key");
// Try explicit JSON conversion.
final List<?> list = res.get(KEY_LIST, List.class);
assertNotNull(list, "JSON parsing of list failed");
assertEquals(2, list.size(), "JSON parsing of list returned incorrect size");
assertTrue(list.containsAll(List.of("first", "second")), "JSON parsing of list returned incorrect elements");
assertNull(res.get(KEY_UNKNOWN, Object.class), "Non-Null returned on unknown key");
// Requesting invalid class should result in Exception.
assertThrows(
InvalidResponseException.class,
() -> res.get(KEY_LIST, Double.class),
"JSON parsing to incorrect type succeeded"
);
} }
/** /**
@ -154,15 +100,9 @@ class SecretResponseTest {
*/ */
@Test @Test
void jsonRoundtrip() { void jsonRoundtrip() {
SecretResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class),
"SecretResponse deserialization failed"
);
assertSecretData(res);
// KV v2 secret. // KV v2 secret.
res = assertDoesNotThrow( MetaSecretResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON_V2, SecretResponse.class), () -> objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertSecretData(res); assertSecretData(res);
@ -171,12 +111,12 @@ class SecretResponseTest {
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed"); assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
assertEquals("", res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string"); assertEquals("", res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date"); assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
assertEquals(false, 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, SecretResponse.class), () -> objectMapper.readValue(SECRET_JSON_V2_2, MetaSecretResponse.class),
"SecretResponse deserialization failed" "SecretResponse deserialization failed"
); );
assertSecretData(res); assertSecretData(res);
@ -185,12 +125,13 @@ class SecretResponseTest {
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed"); assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
assertEquals(SECRET_META_DELETED, res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string"); assertEquals(SECRET_META_DELETED, res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
assertNotNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date"); assertNotNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
assertEquals(true, res.getMetadata().isDestroyed(), "Secret destroyed when not expected"); assertTrue(res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
assertEquals(2, res.getMetadata().getVersion(), "Incorrect secret version"); assertEquals(2, res.getMetadata().getVersion(), "Incorrect secret version");
} }
private void assertSecretData(SecretResponse res) { private void assertSecretData(SecretResponse res) {
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(SECRET_REQUEST_ID, res.getRequestId(), "Incorrect request ID");
assertEquals(SECRET_LEASE_ID, res.getLeaseId(), "Incorrect lease ID"); assertEquals(SECRET_LEASE_ID, res.getLeaseId(), "Incorrect lease ID");
assertEquals(SECRET_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration"); assertEquals(SECRET_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration");
assertEquals(SECRET_RENEWABLE, res.isRenewable(), "Incorrect renewable status"); assertEquals(SECRET_RENEWABLE, res.isRenewable(), "Incorrect renewable status");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -27,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
*/ */
class MetadataResponseTest { class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
private static final String V1_TIME = "2018-03-22T02:24:06.945319214Z"; private static final String V1_TIME = "2018-03-22T02:24:06.945319214Z";
private static final String V3_TIME = "2018-03-22T02:36:43.986212308Z"; private static final String V3_TIME = "2018-03-22T02:36:43.986212308Z";
private static final String V2_TIME = "2018-03-22T02:36:33.954880664Z"; private static final String V2_TIME = "2018-03-22T02:36:33.954880664Z";
@ -62,13 +63,27 @@ class MetadataResponseTest {
" }\n" + " }\n" +
"}"; "}";
MetadataResponseTest() {
super(MetadataResponse.class);
}
@Override
protected MetadataResponse createFull() {
try {
return objectMapper.readValue(META_JSON, MetadataResponse.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 creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/ */
@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

@ -0,0 +1,223 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* JUnit Test for {@link PlainSecretResponse} model.
*
* @author Stefan Kalscheuer
* @since 0.6.2
*/
class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
private static final String SECRET_REQUEST_ID = "68315073-6658-e3ff-2da7-67939fb91bbd";
private static final String SECRET_LEASE_ID = "";
private static final Integer SECRET_LEASE_DURATION = 2764800;
private static final boolean SECRET_RENEWABLE = false;
private static final String SECRET_DATA_K1 = "excited";
private static final String SECRET_DATA_V1 = "yes";
private static final String SECRET_DATA_K2 = "value";
private static final String SECRET_DATA_V2 = "world";
private static final List<String> SECRET_WARNINGS = null;
private static final String SECRET_JSON = "{\n" +
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
" \"renewable\": " + SECRET_RENEWABLE + ",\n" +
" \"data\": {\n" +
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
" },\n" +
" \"warnings\": " + SECRET_WARNINGS + "\n" +
"}";
PlainSecretResponseTest() {
super(PlainSecretResponse.class);
}
@Override
protected PlainSecretResponse createFull() {
try {
return objectMapper.readValue(SECRET_JSON, PlainSecretResponse.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() {
SecretResponse res = assertDoesNotThrow(
() -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class),
"SecretResponse deserialization failed"
);
assertNotNull(res, "Parsed response is NULL");
assertEquals(SECRET_REQUEST_ID, res.getRequestId(), "Incorrect request ID");
assertEquals(SECRET_LEASE_ID, res.getLeaseId(), "Incorrect lease ID");
assertEquals(SECRET_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration");
assertEquals(SECRET_RENEWABLE, res.isRenewable(), "Incorrect renewable status");
assertEquals(SECRET_WARNINGS, res.getWarnings(), "Incorrect warnings");
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");
}
/**
* 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-2021 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,8 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -27,16 +28,19 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
*/ */
class SealResponseTest { class SealResponseTest extends AbstractModelTest<SealResponse> {
private static final String TYPE = "shamir"; private static final String TYPE = "shamir";
private static final Integer THRESHOLD = 3; private static final Integer THRESHOLD = 3;
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 = "0.11.2"; private static final String VERSION = "1.8.2";
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";
private static final Boolean MIGRATION = false;
private static final Boolean RECOVERY_SEAL = false;
private static final String STORAGE_TYPE = "file";
private static final String RES_SEALED = "{\n" + private static final String RES_SEALED = "{\n" +
" \"type\": \"" + TYPE + "\",\n" + " \"type\": \"" + TYPE + "\",\n" +
@ -46,7 +50,10 @@ class SealResponseTest {
" \"n\": " + SHARES + ",\n" + " \"n\": " + SHARES + ",\n" +
" \"progress\": " + PROGRESS_SEALED + ",\n" + " \"progress\": " + PROGRESS_SEALED + ",\n" +
" \"nonce\": \"\",\n" + " \"nonce\": \"\",\n" +
" \"version\": \"" + VERSION + "\"\n" + " \"version\": \"" + VERSION + "\",\n" +
" \"migration\": \"" + MIGRATION + "\",\n" +
" \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" +
" \"storage_type\": \"" + STORAGE_TYPE + "\"\n" +
"}"; "}";
private static final String RES_UNSEALED = "{\n" + private static final String RES_UNSEALED = "{\n" +
@ -59,9 +66,26 @@ class SealResponseTest {
" \"version\": \"" + VERSION + "\",\n" + " \"version\": \"" + VERSION + "\",\n" +
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" + " \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" + " \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
" \"nonce\": \"" + NONCE + "\"\n" + " \"nonce\": \"" + NONCE + "\",\n" +
" \"migration\": \"" + MIGRATION + "\",\n" +
" \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" +
" \"storage_type\": \"" + STORAGE_TYPE + "\"\n" +
"}"; "}";
SealResponseTest() {
super(SealResponse.class);
}
@Override
protected SealResponse createFull() {
try {
return objectMapper.readValue(RES_UNSEALED, SealResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
}
/** /**
* Test creation from JSON value as returned by Vault when sealed (JSON example close to Vault documentation). * Test creation from JSON value as returned by Vault when sealed (JSON example close to Vault documentation).
*/ */
@ -69,8 +93,8 @@ class SealResponseTest {
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),
"TokenResponse deserialization failed" "SealResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(TYPE, res.getType(), "Incorrect seal type"); assertEquals(TYPE, res.getType(), "Incorrect seal type");
@ -81,6 +105,9 @@ class SealResponseTest {
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(MIGRATION, res.getMigration(), "Incorrect migration");
assertEquals(RECOVERY_SEAL, res.getRecoverySeal(), "Incorrect recovery seal");
assertEquals(STORAGE_TYPE, res.getStorageType(), "Incorrect storage type");
// And the fields, that should not be filled. // And the fields, that should not be filled.
assertNull(res.getClusterName(), "Cluster name should not be populated"); assertNull(res.getClusterName(), "Cluster name should not be populated");
assertNull(res.getClusterId(), "Cluster ID should not be populated"); assertNull(res.getClusterId(), "Cluster ID should not be populated");
@ -88,8 +115,8 @@ class SealResponseTest {
// 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),
"TokenResponse deserialization failed" "SealResponse deserialization failed"
); );
assertNotNull(res, "Parsed response is NULL"); assertNotNull(res, "Parsed response is NULL");
assertEquals(TYPE, res.getType(), "Incorrect seal type"); assertEquals(TYPE, res.getType(), "Incorrect seal type");
@ -102,5 +129,8 @@ class SealResponseTest {
assertEquals(VERSION, res.getVersion(), "Incorrect version"); assertEquals(VERSION, res.getVersion(), "Incorrect version");
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(RECOVERY_SEAL, res.getRecoverySeal(), "Incorrect recovery seal");
assertEquals(STORAGE_TYPE, res.getStorageType(), "Incorrect storage type");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,10 +16,11 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.*; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -29,40 +30,46 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
*/ */
class SecretListResponseTest { class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String KEY1 = "key1"; private static final String KEY1 = "key1";
private static final String KEY2 = "key-2"; private static final String KEY2 = "key-2";
private static final List<String> KEYS = Arrays.asList(KEY1, KEY2); private static final String JSON = "{\n" +
" \"auth\": null,\n" +
" \"data\": {\n" +
" \"keys\": [" +
" \"" + KEY1 + "\",\n" +
" \"" + KEY2 + "\"\n" +
" ]\n" +
" },\n" +
" \"lease_duration\": 2764800,\n" +
" \"lease_id\": \"\",\n" +
" \"renewable\": false\n" +
"}";
static { SecretListResponseTest() {
DATA.put("keys", KEYS); super(SecretListResponse.class);
}
@Override
protected SecretListResponse createFull() {
try {
return objectMapper.readValue(JSON, SecretListResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
} }
/** /**
* Test getter, setter and get-methods for response data. * Test JSON deserialization and key getter.
*
* @throws InvalidResponseException Should not occur
*/ */
@Test @Test
void getKeysTest() throws InvalidResponseException { void getKeysTest() {
// Create empty Object. SecretListResponse res = assertDoesNotThrow(
SecretListResponse res = new SecretListResponse(); () -> objectMapper.readValue(JSON, SecretListResponse.class),
assertNull(res.getKeys(), "Keys should be null without initialization"); "SecretListResponse deserialization failed"
// Provoke internal ClassCastException.
Map<String, Object> invalidData = new HashMap<>();
invalidData.put("keys", "some string");
assertThrows(
InvalidResponseException.class,
() -> res.setData(invalidData),
"Setting incorrect class succeeded"
); );
// Fill correct data. assertEquals(List.of(KEY1, KEY2), res.getKeys(), "Unexpected secret keys");
res.setData(DATA);
assertNotNull(res.getKeys(), "Keys should be filled here");
assertEquals(2, res.getKeys().size(), "Unexpected number of keys");
assertTrue(res.getKeys().containsAll(Set.of(KEY1, KEY2)), "Unexpected keys");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,8 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.model.AbstractModelTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -27,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.8 * @since 0.8
*/ */
class SecretVersionResponseTest { class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse> {
private static final String CREATION_TIME = "2018-03-22T02:24:06.945319214Z"; private static final String CREATION_TIME = "2018-03-22T02:24:06.945319214Z";
private static final String DELETION_TIME = "2018-03-22T02:36:43.986212308Z"; private static final String DELETION_TIME = "2018-03-22T02:36:43.986212308Z";
private static final Integer VERSION = 42; private static final Integer VERSION = 42;
@ -41,20 +42,34 @@ class SecretVersionResponseTest {
" }\n" + " }\n" +
"}"; "}";
SecretVersionResponseTest() {
super(SecretVersionResponse.class);
}
@Override
protected SecretVersionResponse createFull() {
try {
return objectMapper.readValue(META_JSON, SecretVersionResponse.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 creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/ */
@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");
assertNotNull(res.getMetadata(), "Parsed metadata is NULL"); assertNotNull(res.getMetadata(), "Parsed metadata is NULL");
assertEquals(CREATION_TIME, res.getMetadata().getCreatedTimeString(), "Incorrect created time"); assertEquals(CREATION_TIME, res.getMetadata().getCreatedTimeString(), "Incorrect created time");
assertEquals(DELETION_TIME, res.getMetadata().getDeletionTimeString(), "Incorrect deletion time"); assertEquals(DELETION_TIME, res.getMetadata().getDeletionTimeString(), "Incorrect deletion time");
assertEquals(false, res.getMetadata().isDestroyed(), "Incorrect destroyed state"); assertFalse(res.getMetadata().isDestroyed(), "Incorrect destroyed state");
assertEquals(VERSION, res.getMetadata().getVersion(), "Incorrect version"); assertEquals(VERSION, res.getMetadata().getVersion(), "Incorrect version");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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,13 +16,12 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException;
import de.stklcode.jvault.connector.exception.InvalidResponseException; 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;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,7 +33,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.6.2 * @since 0.6.2
*/ */
class TokenResponseTest { class TokenResponseTest extends AbstractModelTest<TokenResponse> {
private static final Integer TOKEN_CREATION_TIME = 1457533232; private static final Integer TOKEN_CREATION_TIME = 1457533232;
private static final Integer TOKEN_TTL = 2764800; private static final Integer TOKEN_TTL = 2764800;
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 0; private static final Integer TOKEN_EXPLICIT_MAX_TTL = 0;
@ -89,10 +88,18 @@ class TokenResponseTest {
" \"auth\": null\n" + " \"auth\": null\n" +
"}"; "}";
private static final Map<String, Object> INVALID_TOKEN_DATA = new HashMap<>(); TokenResponseTest() {
super(TokenResponse.class);
}
static { @Override
INVALID_TOKEN_DATA.put("num_uses", "fourtytwo"); protected TokenResponse createFull() {
try {
return objectMapper.readValue(RES_JSON, TokenResponse.class);
} catch (JsonProcessingException e) {
fail("Creation of full model instance failed", e);
return null;
}
} }
/** /**
@ -103,13 +110,6 @@ class TokenResponseTest {
// Create empty Object. // Create empty Object.
TokenResponse res = new TokenResponse(); TokenResponse res = new TokenResponse();
assertNull(res.getData(), "Initial data should be empty"); assertNull(res.getData(), "Initial data should be empty");
// Parsing invalid data map should fail.
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_TOKEN_DATA),
"Parsing invalid token data succeeded"
);
} }
/** /**
@ -118,7 +118,7 @@ class TokenResponseTest {
@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

@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2021 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-2021 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"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQKHd7fFuNKfj/RnIQoxQEOTorNNl1NfcVtynLwYvtvZGDvhAO34YmOFKJSQVSiT4Js08ik48DWWnZHCZzAyMlK0HqNGYQRzCkuHkzYpH0uLrTcddXLuKyc7j6IiRTl3qYb1pzdlTzDtlwsi4J7s+7orETS146yY/GnGPWM/Tmet7p5qOECRq7m04gBX0pnwZl12iRqWG4aHHY5D4aFp9KjKUBKCIhz2Tb9wcSKV/Aa/ct1d0K0k8pyu1r1OkaJqCQXQeIaJR/WBMECR4omezvg7IGCoBIkMjwFR1urSaB0xNdgk+ByZE0C5zeDfmVRylYlypPAlIBrGL/Q/d6+NWiiOzXdoQoqAa/Pyg7e2gClsKDBFDvSL1QVBdsnBIskDeig2t46Ew5qM00wY58BWlUxqjlCgsNm3nPHtWpc6+XiR4ZkEZ9VeEIQhwC/R+NxS+QCDKeuSfyZM3OqQBwOx22mTL0i86YzlUph0alBmDF1b1FkDbg46MSWTANrkov1LPDnOvvNet7pb0L6exN5Q+HKitmxn36E0KAiqj1hEaHMZF6Pe+IIScLPClgPNeMkZWLeD5kvLv9kfObTYneHVHqj8O9jGtk03T4vOoaUNJY9U0irBGzlV+GkneJUgBL1QBspfK4GvFvUrd0Ds/teayJba8HDxlpCEWr6h062BXsNPg5gUn4H/uvginsFng02M8IyrDA1QOb4XS1zdfrvq"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQKyaZ3WVPXS+CbQr/JTfSM4yHT5DN21JfJlKh7ALVkue05z4cy703LvXnlfx5ZRqszSbFAe98ZzwELK89SEq26v2GYe2/7tFYeIAp0YvWNe5uahL0N6KUhFArPtC9gMV+9f7ZdjRDS6AKIHmzWRiXVtTsb+j4MnE+RM9NmwmvpDDTRAFgzjxEQ9IT/nGXieacg49U8NhjmZMh9Dt/7db3e5bGRJFDc3IDuF5xgHr5q+NJBbGrU3X1siH0oiCUbHUKsssmbVI0rwf6lkhvFQIIckYRgwL8/70WjrfELZeN+CgBliwQ=="}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQII71tl2nQI+IFOoGw3z5x+xUwHdaZUXNW2GLNCJaq7tc2Lv3cLz9loi+q9yDVm/tVDhqK8k0D8lA2adOOGXOiaituANawDLAZu8VrwzpX73+mwtoEk"}

View File

@ -0,0 +1 @@
{"Value":"AAAAAQKKxZ6U5JakeVWOBYonzhPVLF2WNyxMYFqpYnb000GLiTWD0kLJQG5rBFyPadehhAmlQQvy7zDpCf5RCcsZbeCTSIA9yUiGp+G2uBsXAgLYKRocHTw="}

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