Compare commits
144 Commits
Author | SHA1 | Date | |
---|---|---|---|
80abbda46f | |||
a8e85b88d1 | |||
91baed4fe5 | |||
2ea261d36a | |||
43da0f5109 | |||
cc5ca13aeb | |||
71842eb758 | |||
e9aeda9a55 | |||
d51af06e29 | |||
7b2b137d53 | |||
ee2543e3ad | |||
dad35023eb | |||
0127cf30be | |||
90f8bb7f20 | |||
ff6d2140cf | |||
076cd8b607 | |||
2e0d092cae | |||
d329af2c67 | |||
f50f5c5de7 | |||
c8a6015f3f | |||
835372eb3b | |||
11ece9974f | |||
0d0fbb5461 | |||
6c9a1fc10e | |||
7e05f4937d | |||
fd9045d7cd | |||
e938f81954 | |||
e5dd207c8c | |||
92d5750c1d | |||
2011a83fd9 | |||
d3da00372c | |||
d90dfc8ba7 | |||
8bf0f9c45f | |||
4fcfa6938e | |||
26cfceb581 | |||
ccf820d524 | |||
5a9d6d9183 | |||
a1dd2b20fb | |||
b0c6ea2d19 | |||
9b6aa91e52 | |||
01812bf492 | |||
e6ef19f1a1 | |||
d4066c1829 | |||
498e46d94d | |||
658f005433 | |||
c8a8f4cbbf | |||
0964c8c41a | |||
ae00b29b4d | |||
10395007bc | |||
91bd6cd572 | |||
8a7ef2d455 | |||
4588703f5c | |||
8a4ebeaad8 | |||
e2c3dd1c35 | |||
b2f7c61654 | |||
8ae024fc36 | |||
c6a9cc2b1a | |||
610464327d | |||
077d670609 | |||
d099995409 | |||
b751b58f11 | |||
59af162c7d | |||
d6b9a805b3 | |||
e585777340 | |||
44f0953998 | |||
318186d9e0 | |||
15ee202167 | |||
defbce0782 | |||
1a18e6b73b | |||
5f1f94f59c | |||
e0711e6108 | |||
a3393ae0cb | |||
8ec160a436 | |||
69da6b9f14 | |||
936928a4fb | |||
a75621d67e | |||
8cb27ed4d1 | |||
7d5996244b | |||
20983e5089 | |||
56fb92178c | |||
4258489dba | |||
e49216f611 | |||
dd5adf897a | |||
d04067db7e | |||
703cc0d87b | |||
c35760d0ab | |||
2f5b25d847 | |||
7681e9e2af | |||
4c4a38cb0b | |||
fe309746fe | |||
df251f1f2c | |||
a008fa2b69 | |||
156156cdef | |||
7bcd57691c | |||
531111cb2b | |||
151b58dc82 | |||
65fb01617d | |||
097cb5415a | |||
2dff8930b7 | |||
d82554974c | |||
8352d04c52 | |||
56d5345fcb | |||
52876ef3a4 | |||
62f2249a4d | |||
10965b01d6 | |||
0f302af3e7 | |||
02ae647002 | |||
1d9e1458be | |||
683052a804 | |||
cc290f4def | |||
2722a125e5 | |||
5e5143168e | |||
08e8c9f090 | |||
c06cb9b0fb | |||
505d420fd6 | |||
be23129441 | |||
199dfd30ca | |||
b72298f2a8 | |||
226b6ad6c4 | |||
d81fc4e5af | |||
1195b447a2 | |||
f3e1f01e38 | |||
622b13f508 | |||
0f0b008f2f | |||
34322b389c | |||
7e5d193d1b | |||
7a813cdda3 | |||
d9dbdad75b | |||
c97308fb4f | |||
fea27910bb | |||
4d79ef6634 | |||
402567a0db | |||
00422ea00c | |||
01e1c6e8c7 | |||
e322a74818 | |||
f9fe57230f | |||
e0c33b51e4 | |||
5e6dcc64cd | |||
70b7338f3e | |||
489e450dc8 | |||
909eab762c | |||
abba4dff93 | |||
712fab04e1 | |||
39ac32a2f6 |
50
.drone.yml
50
.drone.yml
@ -1,50 +0,0 @@
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: compile
|
||||
image: maven:3-eclipse-temurin-17
|
||||
commands:
|
||||
- mvn -B clean compile
|
||||
when:
|
||||
branch:
|
||||
- main
|
||||
- develop
|
||||
- feature/*
|
||||
- fix/*
|
||||
- release/*
|
||||
- name: unit-tests
|
||||
image: maven:3-eclipse-temurin-17
|
||||
commands:
|
||||
- mvn -B test
|
||||
when:
|
||||
branch:
|
||||
- develop
|
||||
- feature/*
|
||||
- fix/*
|
||||
- name: setup-vault
|
||||
image: alpine:latest
|
||||
environment:
|
||||
VAULT_VERSION: 1.12.0
|
||||
commands:
|
||||
- wget -q -O vault_$${VAULT_VERSION}_linux_amd64.zip https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_linux_amd64.zip
|
||||
- wget -q -O - https://releases.hashicorp.com/vault/$${VAULT_VERSION}/vault_$${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||
- unzip vault_$${VAULT_VERSION}_linux_amd64.zip
|
||||
- rm vault_$${VAULT_VERSION}_linux_amd64.zip
|
||||
- mkdir -p .bin
|
||||
- mv vault .bin/
|
||||
when:
|
||||
branch:
|
||||
- main
|
||||
- release/*
|
||||
- name: unit-integration-tests
|
||||
image: maven:3-eclipse-temurin-17
|
||||
environment:
|
||||
VAULT_VERSION: 1.12.0
|
||||
commands:
|
||||
- export PATH=.bin:$${PATH}
|
||||
- mvn -B -P integration-test verify
|
||||
when:
|
||||
branch:
|
||||
- main
|
||||
- release/*
|
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
max_line_length = 120
|
||||
tab_width = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
indent_size = 2
|
56
.github/workflows/ci-it.yml
vendored
Normal file
56
.github/workflows/ci-it.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
build-with-it:
|
||||
if: github.ref_name == 'main' || github.base_ref == 'main' || startsWith(github.ref_name, 'release/')
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
jdk: [ 11, 17, 21 ]
|
||||
vault: [ '1.2.0', '1.19.0' ]
|
||||
include:
|
||||
- jdk: 21
|
||||
vault: '1.19.0'
|
||||
analysis: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
distribution: 'temurin'
|
||||
- name: Compile
|
||||
run: ./mvnw -B clean compile
|
||||
- name: Set up Vault
|
||||
run: |
|
||||
wget -q "https://releases.hashicorp.com/vault/${{ matrix.vault }}/vault_${{ matrix.vault }}_linux_amd64.zip"
|
||||
wget -q -O - "https://releases.hashicorp.com/vault/${{ matrix.vault }}/vault_${{ matrix.vault }}_SHA256SUMS" | grep linux_amd64 | sha256sum -c
|
||||
tmp="$(mktemp -d)"
|
||||
unzip "vault_${{ matrix.vault }}_linux_amd64.zip" -d "$tmp"
|
||||
rm "vault_${{ matrix.vault }}_linux_amd64.zip"
|
||||
sudo mv "$tmp/vault" /usr/bin/vault
|
||||
rm -rf "$tmp"
|
||||
- name: Test (Unit & Integration)
|
||||
env:
|
||||
VAULT_VERSION: ${{ matrix.vault }}
|
||||
run: ./mvnw -B -P coverage -P integration-test verify
|
||||
- name: Analysis
|
||||
if: matrix.analysis && env.SONAR_TOKEN != ''
|
||||
run: >
|
||||
./mvnw -B sonar:sonar
|
||||
-Dsonar.host.url=https://sonarcloud.io
|
||||
-Dsonar.organization=stklcode-github
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
45
.github/workflows/ci.yml
vendored
45
.github/workflows/ci.yml
vendored
@ -1,51 +1,44 @@
|
||||
name: CI
|
||||
on: [ push, pull_request ]
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
- '!main'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
- '!main'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
jdk: [ 11, 17, 19 ]
|
||||
vault: [ '1.2.0', '1.11.4', '1.12.0' ]
|
||||
jdk: [ 11, 17, 21 ]
|
||||
include:
|
||||
- jdk: 17
|
||||
vault: '1.11.4'
|
||||
- jdk: 21
|
||||
analysis: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
distribution: 'temurin'
|
||||
- name: Compile
|
||||
run: mvn -B clean compile
|
||||
- name: Set up Vault
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')
|
||||
run: |
|
||||
wget -q "https://releases.hashicorp.com/vault/${{ matrix.vault }}/vault_${{ matrix.vault }}_linux_amd64.zip"
|
||||
wget -q -O - "https://releases.hashicorp.com/vault/${{ matrix.vault }}/vault_${{ matrix.vault }}_SHA256SUMS" | grep linux_amd64 | sha256sum -c
|
||||
unzip "vault_${{ matrix.vault }}_linux_amd64.zip"
|
||||
rm "vault_${{ matrix.vault }}_linux_amd64.zip"
|
||||
sudo mv vault /usr/bin/vault
|
||||
- name: Test (Unit & Integration)
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')
|
||||
env:
|
||||
VAULT_VERSION: ${{ matrix.vault }}
|
||||
run: mvn -B -P coverage -P integration-test verify
|
||||
run: ./mvnw -B clean compile
|
||||
- name: Test (Unit)
|
||||
if: github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/')
|
||||
run: mvn -B -P coverage verify
|
||||
run: ./mvnw -B -P coverage verify
|
||||
- name: Analysis
|
||||
if: matrix.analysis && github.event_name == 'push'
|
||||
if: matrix.analysis && env.SONAR_TOKEN != ''
|
||||
run: >
|
||||
mvn -B sonar:sonar
|
||||
./mvnw -B sonar:sonar
|
||||
-Dsonar.host.url=https://sonarcloud.io
|
||||
-Dsonar.organization=stklcode-github
|
||||
-Dsonar.login=$SONAR_TOKEN
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -1,5 +1,17 @@
|
||||
/target/
|
||||
/*.iml
|
||||
/.idea/
|
||||
/*.project
|
||||
*~
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
.bin
|
||||
|
||||
*~
|
||||
|
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar
|
135
CHANGELOG.md
135
CHANGELOG.md
@ -1,3 +1,130 @@
|
||||
## 1.5.0 (2025-04-13)
|
||||
|
||||
### Deprecations
|
||||
* `read...Credentials()` methods for specific database mounts (#92)
|
||||
|
||||
### Features
|
||||
* Support Vault transit API (#89)
|
||||
* Support PEM certificate string from `VAULT_CACERT` environment variable (#93)
|
||||
|
||||
### Improvements
|
||||
* Replace deprecated `java.net.URL` usage with `java.net.URI` (#94)
|
||||
|
||||
### Fix
|
||||
* Fix initialization from environment without explicit port
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.18.3 (#90)
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2 to 1.19
|
||||
|
||||
|
||||
## 1.4.0 (2024-12-07)
|
||||
|
||||
### Removal
|
||||
* Remove deprecated `get...TimeString()` on model classes (#77)
|
||||
* Drop support for deprecated `App-ID` auth backend (#61) (#78)
|
||||
|
||||
### Fix
|
||||
* Add jackson-annotations requirement to module-info (#84)
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.18.2 (#85)
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2 to 1.18
|
||||
|
||||
|
||||
## 1.3.1 (2024-10-03)
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.18.0 (#80)
|
||||
|
||||
### Fix
|
||||
* Remove `Automatic-Module-Name` from JAR manifest (#79)
|
||||
|
||||
|
||||
## 1.3.0 (2024-06-29)
|
||||
|
||||
### Improvements
|
||||
* Simplify JSON parsing in error handler
|
||||
* Add new fields from Vault 1.16 and 1.17 to `HealthResponse`
|
||||
* `echo_duration_ms`
|
||||
* `clock_skew_ms`
|
||||
* `replication_primary_canary_age_ms`
|
||||
* `enterprise`
|
||||
* Add missing `num_uses` field to `AuthData`
|
||||
* Add `mount_type` attribute to common response model
|
||||
* Add `auth` attribute to common response model
|
||||
* Add `custom_metadata`, `cas_required` and `delete_version_after` fields for KVv2 metadata
|
||||
* Generate and attach CycloneDX SBOM
|
||||
|
||||
### Fix
|
||||
* Rename `enable_local_secret_id` to `local_secret_ids` in `AppRole` model
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.17.1
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2 to 1.17
|
||||
|
||||
|
||||
## 1.2.0 (2023-12-11)
|
||||
|
||||
### Deprecations
|
||||
* `get...TimeString()` methods on various model classes are now deprecated
|
||||
|
||||
### Improvements
|
||||
* Parse timestamps as `ZonedDateTime` instead of `String` representation
|
||||
* Remove redundant `java.base` requirement from _module-info.java_ (#69)
|
||||
* Close Java HTTP Client when running on Java 21 or later (#70)
|
||||
* Add MFA requirements tu `AuthResponse` (#71)
|
||||
* Extend `AuthMethod` data model (#72)
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.16.0
|
||||
|
||||
|
||||
## 1.1.5 (2023-08-19)
|
||||
|
||||
### Fix
|
||||
* Fixed JSON type conversion in `SecretResponse#get(String, Class)` (#67)
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2 to 1.15
|
||||
|
||||
|
||||
## 1.1.4 (2023-06-15)
|
||||
|
||||
### Fix
|
||||
* Use `[+-]XX:XX` notation for timezone in date/time parsing
|
||||
|
||||
### Improvements
|
||||
* Use explicit UTF-8 encoding for parsing responses
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.15.2
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2.0 to 1.13.3
|
||||
|
||||
|
||||
## 1.1.3 (2023-01-31)
|
||||
|
||||
### Deprecations
|
||||
* AppID components (deprecated since 0.4) are marked for removal with the next major release
|
||||
|
||||
### Dependencies
|
||||
* Updated Jackson to 2.14.2
|
||||
|
||||
### Improvements
|
||||
* Minor internal refactoring
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.2.0 to 1.12.2
|
||||
|
||||
|
||||
## 1.1.2 (2022-10-26)
|
||||
|
||||
### Dependencies
|
||||
@ -135,7 +262,7 @@ Old builders will be removed in 1.0
|
||||
* Added `entity_id`, `token_policies`, `token_type` and `orphan` flags to auth response
|
||||
* Added `entity_id`, `expire_time`, `explicit_max_ttl`, `issue_time`, `renewable` and `type` flags to token data
|
||||
* Added `explicit_max_ttl`, `period` and `entity_alias` flags to _Token_ model (#41)
|
||||
* Added `enable_local_secret_ids`, `token_bound_cidrs`, `token_explicit_max_ttl`, `token_no_default_policy`,
|
||||
* Added `enable_local_secret_ids`, `token_bound_cidrs`, `token_explicit_max_ttl`, `token_no_default_policy`,
|
||||
`token_num_uses`, `token_period` and `token_type` flags to _AppRole_ model
|
||||
* Minor dependency updates
|
||||
|
||||
@ -155,14 +282,14 @@ Old builders will be removed in 1.0
|
||||
## 0.8.2 (2019-10-20)
|
||||
|
||||
### Fixes
|
||||
* Fixed token lookup (#31)
|
||||
* Fixed token lookup (#31)
|
||||
|
||||
### Improvements
|
||||
* Updated dependencies
|
||||
|
||||
## 0.8.1 (2019-08-16)
|
||||
### Fixes
|
||||
* Removed compile dependency to JUnit library (#30)
|
||||
* Removed compile dependency to JUnit library (#30)
|
||||
|
||||
### Improvements
|
||||
* Updated dependencies
|
||||
@ -254,7 +381,7 @@ Old builders will be removed in 1.0
|
||||
### Fixes
|
||||
* `SecretResponse` does not throw NPE on `get(key)` and `getData()`
|
||||
|
||||
### Test
|
||||
### Test
|
||||
* Tested against Vault 0.7.2
|
||||
|
||||
|
||||
|
22
README.md
22
README.md
@ -1,11 +1,11 @@
|
||||
# Java Vault Connector
|
||||
# Java Vault Connector
|
||||
|
||||
[](https://github.com/stklcode/jvaultconnector/actions/workflows/ci.yml)
|
||||
[](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Ajvault-connector)
|
||||
[](https://github.com/stklcode/jvaultconnector/blob/main/LICENSE.txt)
|
||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22jvault-connector%22)
|
||||
[](https://github.com/stklcode/jvaultconnector/actions/workflows/ci.yml)
|
||||
[](https://sonarcloud.io/summary/new_code?id=de.stklcode.jvault%3Ajvault-connector)
|
||||
[](https://github.com/stklcode/jvaultconnector/blob/main/LICENSE.txt)
|
||||
[](https://central.sonatype.com/artifact/de.stklcode.jvault/jvault-connector)
|
||||
|
||||

|
||||

|
||||
|
||||
Java Vault Connector is a connector library for [Vault](https://www.vaultproject.io) by [Hashicorp](https://www.hashicorp.com) written in Java. The connector allows simple usage of Vault's secret store in own applications.
|
||||
|
||||
@ -18,7 +18,6 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
* Token
|
||||
* Username/Password
|
||||
* AppRole (register and authenticate)
|
||||
* AppID (register and authenticate) [_deprecated_]
|
||||
* Tokens
|
||||
* Creation and lookup of tokens and token roles
|
||||
* TokenBuilder for speaking creation of complex configurations
|
||||
@ -29,10 +28,11 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
* Delete secrets
|
||||
* Renew/revoke leases
|
||||
* Raw secret content or JSON decoding
|
||||
* SQL secret handling
|
||||
* KV v1 and v2 support
|
||||
* Database secret handling
|
||||
* Transit API support
|
||||
* Connector Factory with builder pattern
|
||||
* Tested against Vault 1.2.0 to 1.12.0
|
||||
* Tested against Vault 1.2 to 1.19
|
||||
|
||||
|
||||
## Maven Artifact
|
||||
@ -40,7 +40,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
<dependency>
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>jvault-connector</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@ -61,7 +61,7 @@ VaultConnector vault = HTTPVaultConnector.builder("https://example.com:8200/v1/"
|
||||
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
||||
.build();
|
||||
|
||||
// Initialization from environment variables
|
||||
// Initialization from environment variables
|
||||
VaultConnector vault = HTTPVaultConnector.builder()
|
||||
.fromEnv()
|
||||
.build();
|
||||
|
332
mvnw
vendored
Executable file
332
mvnw
vendored
Executable file
@ -0,0 +1,332 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ]; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ]; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ]; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ]; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false
|
||||
darwin=false
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true ;;
|
||||
Darwin*)
|
||||
darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"
|
||||
export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -r /etc/gentoo-release ]; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] \
|
||||
&& CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw; then
|
||||
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME="$(
|
||||
cd "$JAVA_HOME" || (
|
||||
echo "cannot cd into $JAVA_HOME." >&2
|
||||
exit 1
|
||||
)
|
||||
pwd
|
||||
)"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
|
||||
if $darwin; then
|
||||
javaHome="$(dirname "$javaExecutable")"
|
||||
javaExecutable="$(cd "$javaHome" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f "$javaExecutable")"
|
||||
fi
|
||||
javaHome="$(dirname "$javaExecutable")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ]; then
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(
|
||||
\unset -f command 2>/dev/null
|
||||
\command -v java
|
||||
)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ]; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set." >&2
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
if [ -z "$1" ]; then
|
||||
echo "Path not specified to find_maven_basedir" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ]; do
|
||||
if [ -d "$wdir"/.mvn ]; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(
|
||||
cd "$wdir/.." || exit 1
|
||||
pwd
|
||||
)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(
|
||||
cd "$basedir" || exit 1
|
||||
pwd
|
||||
)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the repository with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' <"$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in wrapperUrl)
|
||||
wrapperUrl="$safeValue"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget >/dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl >/dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in wrapperSha256Sum)
|
||||
wrapperSha256Sum=$value
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] \
|
||||
&& CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] \
|
||||
&& MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
206
mvnw.cmd
vendored
Normal file
206
mvnw.cmd
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo. >&2
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo. >&2
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo. >&2
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo. >&2
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %WRAPPER_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
SET WRAPPER_SHA_256_SUM=""
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||
)
|
||||
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||
powershell -Command "&{"^
|
||||
"Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^
|
||||
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||
" Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||
" Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||
" Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||
" exit 1;"^
|
||||
"}"^
|
||||
"}"
|
||||
if ERRORLEVEL 1 goto error
|
||||
)
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
262
pom.xml
262
pom.xml
@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>jvault-connector</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.5.1-SNAPSHOT</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -21,16 +21,11 @@
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<argLine></argLine>
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Stefan Kalscheuer</name>
|
||||
<email>stefan@stklcode.de</email>
|
||||
<timezone>+1</timezone>
|
||||
<timezone>Europe/Berlin</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
@ -38,6 +33,7 @@
|
||||
<connection>scm:git:git://github.com/stklcode/jvaultconnector.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:stklcode/jvaultconnector.git</developerConnection>
|
||||
<url>https://github.com/stklcode/jvaultconnector</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
@ -45,64 +41,123 @@
|
||||
<url>https://github.com/stklcode/jvaultconnector/issues</url>
|
||||
</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.18.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.18.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.12.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>5.17.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>org.wiremock</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.19.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nl.jqno.equalsverifier</groupId>
|
||||
<artifactId>equalsverifier</artifactId>
|
||||
<version>3.19.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>4.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
<release>11</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.4.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Automatic-Module-Name>de.stklcode.jvault.connector</Automatic-Module-Name>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<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.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.3.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine}
|
||||
@ -113,74 +168,55 @@
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response.embedded=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.datatype.jsr310
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.cyclonedx</groupId>
|
||||
<artifactId>cyclonedx-maven-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.8</version>
|
||||
<version>0.8.13</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<version>3.9.1.2184</version>
|
||||
<version>5.1.0.4751</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce-versions</id>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireMavenVersion>
|
||||
<version>[3.6.3,)</version>
|
||||
</requireMavenVersion>
|
||||
<requireJavaVersion>
|
||||
<version>[11,)</version>
|
||||
</requireJavaVersion>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.13.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>4.8.1</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.34.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nl.jqno.equalsverifier</groupId>
|
||||
<artifactId>equalsverifier</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>sources</id>
|
||||
@ -215,7 +251,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.11.2</version>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
</configuration>
|
||||
@ -232,6 +268,29 @@
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>sbom</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.cyclonedx</groupId>
|
||||
<artifactId>cyclonedx-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>makeBom</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skipNotDeployed>false</skipNotDeployed>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>sign</id>
|
||||
<build>
|
||||
@ -239,7 +298,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.2.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
@ -310,7 +369,11 @@
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>7.2.1</version>
|
||||
<version>12.1.1</version>
|
||||
<configuration>
|
||||
<nvdApiKey>${env.NVD_API_KEY}</nvdApiKey>
|
||||
<nvdDatafeedUrl>${env.NVD_DATAFEED_URL}</nvdDatafeedUrl>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@ -324,17 +387,20 @@
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>sonatype</id>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<id>central</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -41,34 +41,62 @@ import static java.util.Collections.singletonMap;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class HTTPVaultConnector implements VaultConnector {
|
||||
private static final String PATH_SEAL_STATUS = "sys/seal-status";
|
||||
private static final String PATH_SEAL = "sys/seal";
|
||||
private static final String PATH_UNSEAL = "sys/unseal";
|
||||
private static final String PATH_RENEW = "sys/leases/renew";
|
||||
private static final String PATH_AUTH = "sys/auth";
|
||||
private static final String PATH_TOKEN = "auth/token";
|
||||
private static final String PATH_SYS = "sys";
|
||||
private static final String PATH_SYS_AUTH = PATH_SYS + "/auth";
|
||||
private static final String PATH_RENEW = PATH_SYS + "/leases/renew";
|
||||
private static final String PATH_REVOKE = PATH_SYS + "/leases/revoke/";
|
||||
private static final String PATH_HEALTH = PATH_SYS + "/health";
|
||||
private static final String PATH_SEAL = PATH_SYS + "/seal";
|
||||
private static final String PATH_SEAL_STATUS = PATH_SYS + "/seal-status";
|
||||
private static final String PATH_UNSEAL = PATH_SYS + "/unseal";
|
||||
|
||||
|
||||
private static final String PATH_AUTH = "auth";
|
||||
private static final String PATH_AUTH_TOKEN = PATH_AUTH + "/token";
|
||||
private static final String PATH_LOOKUP = "/lookup";
|
||||
private static final String PATH_CREATE = "/create";
|
||||
private static final String PATH_ROLES = "/roles";
|
||||
private static final String PATH_CREATE_ORPHAN = "/create-orphan";
|
||||
private static final String PATH_AUTH_USERPASS = "auth/userpass/login/";
|
||||
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
||||
private static final String PATH_AUTH_APPROLE = "auth/approle/";
|
||||
private static final String PATH_AUTH_APPROLE_ROLE = "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_AUTH_USERPASS = PATH_AUTH + "/userpass/login/";
|
||||
private static final String PATH_AUTH_APPROLE = PATH_AUTH + "/approle";
|
||||
private static final String PATH_AUTH_APPROLE_ROLE = PATH_AUTH_APPROLE + "/role/%s%s";
|
||||
|
||||
private static final String PATH_DATA = "/data/";
|
||||
private static final String PATH_METADATA = "/metadata/";
|
||||
private static final String PATH_LOGIN = "/login";
|
||||
private static final String PATH_DELETE = "/delete/";
|
||||
private static final String PATH_UNDELETE = "/undelete/";
|
||||
private static final String PATH_DESTROY = "/destroy/";
|
||||
|
||||
private static final String PATH_TRANSIT = "transit";
|
||||
private static final String PATH_TRANSIT_ENCRYPT = PATH_TRANSIT + "/encrypt/";
|
||||
private static final String PATH_TRANSIT_DECRYPT = PATH_TRANSIT + "/decrypt/";
|
||||
private static final String PATH_TRANSIT_HASH = PATH_TRANSIT + "/hash/";
|
||||
|
||||
private final RequestHelper request;
|
||||
|
||||
private boolean authorized = false; // Authorization status.
|
||||
private String token; // 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.
|
||||
*
|
||||
@ -102,24 +130,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
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
|
||||
public final void resetAuth() {
|
||||
token = null;
|
||||
@ -139,11 +149,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException {
|
||||
Map<String, String> param = new HashMap<>(2, 1);
|
||||
param.put("key", key);
|
||||
if (reset != null) {
|
||||
param.put("reset", reset.toString());
|
||||
}
|
||||
Map<String, String> param = mapOfStrings(
|
||||
"key", key,
|
||||
"reset", reset
|
||||
);
|
||||
|
||||
return request.put(PATH_UNSEAL, param, token, SealResponse.class);
|
||||
}
|
||||
@ -152,15 +161,15 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
public HealthResponse getHealth() throws VaultConnectorException {
|
||||
|
||||
return request.get(
|
||||
PATH_HEALTH,
|
||||
// Force status code to be 200, so we don't need to modify the request sequence.
|
||||
Map.of(
|
||||
"standbycode", "200", // Default: 429.
|
||||
"sealedcode", "200", // Default: 503.
|
||||
"uninitcode", "200" // Default: 501.
|
||||
),
|
||||
token,
|
||||
HealthResponse.class
|
||||
PATH_HEALTH,
|
||||
// Force status code to be 200, so we don't need to modify the request sequence.
|
||||
Map.of(
|
||||
"standbycode", "200", // Default: 429.
|
||||
"sealedcode", "200", // Default: 503.
|
||||
"uninitcode", "200" // Default: 501.
|
||||
),
|
||||
token,
|
||||
HealthResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@ -172,7 +181,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
@Override
|
||||
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
/* 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());
|
||||
}
|
||||
@ -182,7 +191,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
/* set token */
|
||||
this.token = token;
|
||||
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;
|
||||
|
||||
return res;
|
||||
@ -190,31 +199,18 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
public final AuthResponse authUserPass(final String username, final String password)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
final Map<String, String> payload = singletonMap("password", password);
|
||||
return queryAuth(PATH_AUTH_USERPASS + username, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||
return queryAuth(
|
||||
PATH_AUTH_APPID + "login",
|
||||
Map.of(
|
||||
"app_id", appID,
|
||||
"user_id", userID
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>(2, 1);
|
||||
payload.put("role_id", roleID);
|
||||
if (secretID != null) {
|
||||
payload.put("secret_id", secretID);
|
||||
}
|
||||
return queryAuth(PATH_AUTH_APPROLE + "login", payload);
|
||||
final Map<String, String> payload = mapOfStrings(
|
||||
"role_id", roleID,
|
||||
"secret_id", secretID
|
||||
);
|
||||
return queryAuth(PATH_AUTH_APPROLE + PATH_LOGIN, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,7 +222,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @throws VaultConnectorException on errors
|
||||
*/
|
||||
private AuthResponse queryAuth(final String path, final Map<String, String> payload)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
/* Issue request and parse response */
|
||||
AuthResponse auth = request.post(path, payload, token, AuthResponse.class);
|
||||
/* verify response */
|
||||
@ -237,40 +233,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
PATH_AUTH_APPID + "map/app-id/" + appID,
|
||||
Map.of(
|
||||
"value", policy,
|
||||
"display_name", displayName
|
||||
),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
PATH_AUTH_APPID + "map/user-id/" + userID,
|
||||
singletonMap("value", appID),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean createAppRole(final AppRole role) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
@ -287,10 +249,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
requireAuth();
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""),
|
||||
emptyMap(),
|
||||
token,
|
||||
AppRoleResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""),
|
||||
emptyMap(),
|
||||
token,
|
||||
AppRoleResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@ -309,10 +271,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
requireAuth();
|
||||
/* Issue request, parse response and extract Role ID */
|
||||
return request.get(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
emptyMap(),
|
||||
token,
|
||||
RawDataResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
emptyMap(),
|
||||
token,
|
||||
RawDataResponse.class
|
||||
).getData().get("role_id").toString();
|
||||
}
|
||||
|
||||
@ -322,9 +284,9 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
singletonMap("role_id", roleID),
|
||||
token
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
singletonMap("role_id", roleID),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
@ -332,49 +294,49 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (secret.getId() != null && !secret.getId().isEmpty()) {
|
||||
return request.post(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/custom-secret-id"),
|
||||
secret,
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/custom-secret-id"),
|
||||
secret,
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
} else {
|
||||
return request.post(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id"),
|
||||
secret, token,
|
||||
AppRoleSecretResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id"),
|
||||
secret, token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and parse secret response */
|
||||
return request.post(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/lookup"),
|
||||
new AppRoleSecret(secretID),
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/lookup"),
|
||||
new AppRoleSecret(secretID),
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean destroyAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/destroy"),
|
||||
new AppRoleSecret(secretID),
|
||||
token);
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id/destroy"),
|
||||
new AppRoleSecret(secretID),
|
||||
token);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -384,10 +346,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
PATH_AUTH_APPROLE + "role?list=true",
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
PATH_AUTH_APPROLE + "/role?list=true",
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
@ -398,10 +360,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id?list=true"),
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id?list=true"),
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
@ -415,19 +377,18 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@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();
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
Map<String, String> args = new HashMap<>(1, 1);
|
||||
if (version != null) {
|
||||
args.put("version", version.toString());
|
||||
}
|
||||
Map<String, String> args = mapOfStrings("version", version);
|
||||
|
||||
return request.get(mount + PATH_DATA + key, args, token, MetaSecretResponse.class);
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
@ -435,20 +396,25 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
Map<String, Object> payload = new HashMap<>(2, 1);
|
||||
if (maxVersions != null) {
|
||||
payload.put("max_versions", maxVersions);
|
||||
}
|
||||
payload.put("cas_required", casRequired);
|
||||
Map<String, Object> payload = mapOf(
|
||||
"max_versions", maxVersions,
|
||||
"cas_required", casRequired
|
||||
);
|
||||
|
||||
write(mount + PATH_METADATA + key, payload);
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
if (key == null || key.isEmpty()) {
|
||||
@ -456,22 +422,17 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
// Add CAS value to options map if present.
|
||||
Map<String, Object> options;
|
||||
if (cas != null) {
|
||||
options = singletonMap("cas", cas);
|
||||
} else {
|
||||
options = emptyMap();
|
||||
}
|
||||
Map<String, Object> options = mapOf("cas", cas);
|
||||
|
||||
/* Issue request and parse metadata response */
|
||||
return request.post(
|
||||
mount + PATH_DATA + key,
|
||||
Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
),
|
||||
token,
|
||||
SecretVersionResponse.class
|
||||
mount + PATH_DATA + key,
|
||||
Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
),
|
||||
token,
|
||||
SecretVersionResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@ -485,21 +446,22 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
if (key == null || key.isEmpty()) {
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
}
|
||||
|
||||
// By default data is directly passed as payload.
|
||||
// By default, data is directly passed as payload.
|
||||
Object payload = data;
|
||||
|
||||
// If options are given, split payload in two parts.
|
||||
if (options != null) {
|
||||
payload = Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
"data", data,
|
||||
"options", options
|
||||
);
|
||||
}
|
||||
|
||||
@ -526,17 +488,20 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@ -550,7 +515,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
@ -572,11 +540,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, String> payload = new HashMap<>(2, 1);
|
||||
payload.put("lease_id", leaseID);
|
||||
if (increment != null) {
|
||||
payload.put("increment", increment.toString());
|
||||
}
|
||||
Map<String, String> payload = mapOfStrings(
|
||||
"lease_id", leaseID,
|
||||
"increment", increment
|
||||
);
|
||||
|
||||
/* Issue request and parse secret response */
|
||||
return request.put(PATH_RENEW, payload, token, SecretResponse.class);
|
||||
@ -584,12 +551,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
@ -597,7 +564,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
if (role == null || role.isEmpty()) {
|
||||
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
|
||||
@ -632,10 +599,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
PATH_TOKEN + PATH_LOOKUP,
|
||||
singletonMap("token", token),
|
||||
token,
|
||||
TokenResponse.class
|
||||
PATH_AUTH_TOKEN + PATH_LOOKUP,
|
||||
singletonMap("token", token),
|
||||
token,
|
||||
TokenResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@ -650,7 +617,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@ -660,14 +627,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
requireAuth();
|
||||
|
||||
// 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
|
||||
public List<String> listTokenRoles() throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
return list(PATH_TOKEN + PATH_ROLES);
|
||||
return list(PATH_AUTH_TOKEN + PATH_ROLES);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -679,11 +646,52 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitEncrypt(final String keyName, final String plaintext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"plaintext", plaintext
|
||||
);
|
||||
|
||||
return request.post(PATH_TRANSIT_ENCRYPT + keyName, payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitDecrypt(final String keyName, final String ciphertext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"ciphertext", ciphertext
|
||||
);
|
||||
|
||||
return request.post(PATH_TRANSIT_DECRYPT + keyName, payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitHash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException {
|
||||
if (format != null && !"hex".equals(format) && !"base64".equals(format)) {
|
||||
throw new IllegalArgumentException("Unsupported format " + format);
|
||||
}
|
||||
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"input", input,
|
||||
"format", format
|
||||
);
|
||||
|
||||
return request.post(PATH_TRANSIT_HASH + algorithm, payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for required authorization.
|
||||
*
|
||||
@ -695,4 +703,42 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,18 +20,17 @@ import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Vault Connector Builder implementation for HTTP Vault connectors.
|
||||
@ -96,10 +95,14 @@ public final class HTTPVaultConnectorBuilder {
|
||||
* @since 1.0
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder withBaseURL(final URI baseURL) {
|
||||
return withTLS(!("http".equalsIgnoreCase(Objects.requireNonNullElse(baseURL.getScheme(), ""))))
|
||||
.withHost(baseURL.getHost())
|
||||
.withPort(baseURL.getPort())
|
||||
.withPrefix(baseURL.getPath());
|
||||
String path = baseURL.getPath();
|
||||
if (path == null || path.isBlank()) {
|
||||
path = DEFAULT_PREFIX;
|
||||
}
|
||||
return withTLS(!("http".equalsIgnoreCase(baseURL.getScheme())))
|
||||
.withHost(baseURL.getHost())
|
||||
.withPort(baseURL.getPort())
|
||||
.withPrefix(path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -293,7 +296,7 @@ public final class HTTPVaultConnectorBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
|
||||
* Build connector based on the {@code VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
|
||||
*
|
||||
* @return self
|
||||
* @throws VaultConnectorException if Vault address from environment variables is malformed
|
||||
@ -301,13 +304,10 @@ public final class HTTPVaultConnectorBuilder {
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder fromEnv() throws VaultConnectorException {
|
||||
/* Parse URL from environment variable */
|
||||
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
|
||||
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).isBlank()) {
|
||||
try {
|
||||
var url = new URL(System.getenv(ENV_VAULT_ADDR));
|
||||
this.host = url.getHost();
|
||||
this.port = url.getPort();
|
||||
this.tls = url.getProtocol().equals("https");
|
||||
} catch (MalformedURLException e) {
|
||||
withBaseURL(System.getenv(ENV_VAULT_ADDR));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new ConnectionException("URL provided in environment variable malformed", e);
|
||||
}
|
||||
}
|
||||
@ -315,7 +315,7 @@ public final class HTTPVaultConnectorBuilder {
|
||||
/* Read number of retries */
|
||||
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
|
||||
try {
|
||||
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
|
||||
withNumberOfRetries(Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES)));
|
||||
} catch (NumberFormatException ignored) {
|
||||
/* Ignore malformed values. */
|
||||
}
|
||||
@ -325,8 +325,12 @@ public final class HTTPVaultConnectorBuilder {
|
||||
token = System.getenv(ENV_VAULT_TOKEN);
|
||||
|
||||
/* Parse certificate, if set */
|
||||
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
|
||||
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
|
||||
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).isBlank()) {
|
||||
X509Certificate cert = certificateFromString(System.getenv(ENV_VAULT_CACERT));
|
||||
if (cert == null) {
|
||||
cert = certificateFromFile(Paths.get(System.getenv(ENV_VAULT_CACERT)));
|
||||
}
|
||||
return withTrustedCA(cert);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -398,6 +402,28 @@ public final class HTTPVaultConnectorBuilder {
|
||||
return con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given certificate file to X.509 certificate.
|
||||
*
|
||||
* @param cert Certificate string (optionally PEM)
|
||||
* @return X.509 Certificate object if parseable, else {@code null}
|
||||
* @throws TlsException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
private X509Certificate certificateFromString(final String cert) throws TlsException {
|
||||
// Check if PEM header is present in given string
|
||||
if (cert.contains("-BEGIN ") && cert.contains("-END")) {
|
||||
try (var is = new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8))) {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||
} catch (IOException | CertificateException e) {
|
||||
throw new TlsException("Unable to read certificate.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Not am PEM string, skip
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given certificate file to X.509 certificate.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,10 +21,7 @@ import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Vault Connector interface.
|
||||
@ -112,18 +109,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppID method.
|
||||
*
|
||||
* @param appID The App ID
|
||||
* @param userID The User ID
|
||||
* @return The {@link AuthResponse}
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||
*/
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppRole method without secret ID.
|
||||
*
|
||||
@ -147,20 +132,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID with policy.
|
||||
*
|
||||
* @param appID The unique App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||
*/
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
*
|
||||
@ -220,7 +191,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies, final String roleID)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
return createAppRole(AppRole.builder(roleName).withTokenPolicies(policies).withId(roleID).build());
|
||||
}
|
||||
|
||||
@ -286,7 +257,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
@ -300,7 +271,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException;
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
@ -312,7 +283,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException;
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
@ -342,38 +313,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
List<String> listAppRoleSecrets(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register User-ID with App-ID.
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param userID The User-ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
* Consider using {@link #createAppRoleSecret} instead.
|
||||
*/
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID and User-ID at once.
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @param userID The User-ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
*/
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
default boolean registerAppUserId(final String appID,
|
||||
final String policy,
|
||||
final String displayName,
|
||||
final String userID) throws VaultConnectorException {
|
||||
return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization status.
|
||||
*
|
||||
@ -420,7 +359,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -438,7 +379,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data, final Integer cas) throws VaultConnectorException;
|
||||
SecretVersionResponse writeSecretData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data,
|
||||
final Integer cas) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret data from Vault.
|
||||
@ -453,7 +397,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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.
|
||||
@ -482,7 +427,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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.
|
||||
@ -527,7 +475,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8 {@code options} parameter added
|
||||
*/
|
||||
void write(final String key, final Map<String, Object> data, final Map<String, Object> options) throws VaultConnectorException;
|
||||
void write(final String key, final Map<String, Object> data, final Map<String, Object> options)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete key from Vault.
|
||||
@ -574,7 +523,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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.
|
||||
@ -586,7 +536,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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.
|
||||
@ -598,7 +549,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @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.
|
||||
@ -719,6 +671,82 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
boolean deleteTokenRole(final String name) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Text to encrypt (Base64 encoded)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitEncrypt(final String keyName, final String plaintext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Binary data to encrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitEncrypt(final String keyName, final byte[] plaintext)
|
||||
throws VaultConnectorException {
|
||||
return transitEncrypt(keyName, Base64.getEncoder().encodeToString(plaintext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt ciphertext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param ciphertext Text to decrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitDecrypt(final String keyName, final String ciphertext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data in hex format via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitHash(final String algorithm, final String input) throws VaultConnectorException {
|
||||
return transitHash(algorithm, input, "hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash (Base64 encoded)
|
||||
* @param format Specifies the output encoding (hex/base64)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitHash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitHash(final String algorithm, final byte[] input, final String format)
|
||||
throws VaultConnectorException {
|
||||
return transitHash(algorithm, Base64.getEncoder().encodeToString(input), format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MySQL backend at default mount point.
|
||||
*
|
||||
@ -726,7 +754,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
* @deprecated use {@link #readDbCredentials(String, String)} your MySQL mountpoint
|
||||
*/
|
||||
@Deprecated(since = "1.5.0", forRemoval = true)
|
||||
default CredentialsResponse readMySqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mysql");
|
||||
}
|
||||
@ -738,7 +768,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
* @deprecated use {@link #readDbCredentials(String, String)} your PostgreSQL mountpoint
|
||||
*/
|
||||
@Deprecated(since = "1.5.0", forRemoval = true)
|
||||
default CredentialsResponse readPostgreSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "postgresql");
|
||||
}
|
||||
@ -750,34 +782,38 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
* @deprecated use {@link #readDbCredentials(String, String)} your MSSQL mountpoint
|
||||
*/
|
||||
@Deprecated(since = "1.5.0", forRemoval = true)
|
||||
default CredentialsResponse readMsSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mssql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MSSQL backend at default mount point.
|
||||
* Read credentials for MongoDB backend at default mount point.
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
* @deprecated use {@link #readDbCredentials(String, String)} your MongoDB mountpoint
|
||||
*/
|
||||
@Deprecated(since = "1.5.0", forRemoval = true)
|
||||
default CredentialsResponse readMongoDbCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mongodb");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for SQL backends.
|
||||
* Read credentials for database backends.
|
||||
*
|
||||
* @param role the role name
|
||||
* @param mount mount point of the SQL backend
|
||||
* @param mount mount point of the database backend
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readDbCredentials(final String role, final String mount)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
return (CredentialsResponse) read(mount + "/creds/" + role);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,4 +23,5 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class AuthorizationRequiredException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = 2629577936657393880L;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class ConnectionException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = 3005430116002990418L;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class InvalidRequestException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = -6712239648281809159L;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,6 +24,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public final class InvalidResponseException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = 2003151038614163479L;
|
||||
|
||||
private final Integer statusCode;
|
||||
private final String response;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class PermissionDeniedException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = -7149134015090750776L;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TlsException extends VaultConnectorException {
|
||||
private static final long serialVersionUID = -5139276834988258086L;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultConnectorException extends Exception {
|
||||
private static final long serialVersionUID = -2612477894310906036L;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,10 @@
|
||||
package de.stklcode.jvault.connector.internal;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import de.stklcode.jvault.connector.exception.*;
|
||||
import de.stklcode.jvault.connector.model.response.ErrorResponse;
|
||||
|
||||
@ -41,7 +44,7 @@ public final class RequestHelper implements Serializable {
|
||||
private final int retries; // Number of retries on 5xx errors.
|
||||
private final String tlsVersion; // TLS version (#22).
|
||||
private final X509Certificate trustedCaCert; // Trusted CA certificate.
|
||||
private final ObjectMapper jsonMapper;
|
||||
private final JsonMapper jsonMapper;
|
||||
|
||||
/**
|
||||
* Constructor of the request helper.
|
||||
@ -62,7 +65,11 @@ public final class RequestHelper implements Serializable {
|
||||
this.timeout = timeout;
|
||||
this.tlsVersion = tlsVersion;
|
||||
this.trustedCaCert = trustedCaCert;
|
||||
this.jsonMapper = new ObjectMapper();
|
||||
this.jsonMapper = JsonMapper.builder()
|
||||
.addModule(new JavaTimeModule())
|
||||
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +116,7 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8
|
||||
*/
|
||||
public <T> T post(final String path, final Object payload, final String token, final Class<T> target)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
try {
|
||||
String response = post(path, payload, token);
|
||||
return jsonMapper.readValue(response, target);
|
||||
@ -127,7 +134,8 @@ public final class RequestHelper implements Serializable {
|
||||
* @throws VaultConnectorException on connection error
|
||||
* @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()) {
|
||||
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
|
||||
}
|
||||
@ -143,7 +151,8 @@ public final class RequestHelper implements Serializable {
|
||||
* @throws VaultConnectorException on connection error
|
||||
* @since 0.8 Added {@code token} parameter.
|
||||
*/
|
||||
public String put(final String path, final Map<String, String> payload, final String token) throws VaultConnectorException {
|
||||
public String put(final String path, final Map<String, String> payload, final String token)
|
||||
throws VaultConnectorException {
|
||||
// Initialize PUT.
|
||||
var req = HttpRequest.newBuilder(URI.create(baseURL + path));
|
||||
|
||||
@ -177,7 +186,7 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8
|
||||
*/
|
||||
public <T> T put(final String path, final Map<String, String> payload, final String token, final Class<T> target)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
try {
|
||||
String response = put(path, payload, token);
|
||||
return jsonMapper.readValue(response, target);
|
||||
@ -196,7 +205,7 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8
|
||||
*/
|
||||
public void putWithoutResponse(final String path, final Map<String, String> payload, final String token)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
if (!put(path, payload, token).isEmpty()) {
|
||||
throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE);
|
||||
}
|
||||
@ -248,15 +257,15 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8 Added {@code token} parameter.
|
||||
*/
|
||||
public String get(final String path, final Map<String, String> payload, final String token)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
// Add parameters to URI.
|
||||
var uriBuilder = new StringBuilder(baseURL + path);
|
||||
|
||||
if (!payload.isEmpty()) {
|
||||
uriBuilder.append("?").append(
|
||||
payload.entrySet().stream().map(
|
||||
par -> URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8)
|
||||
).collect(Collectors.joining("&"))
|
||||
payload.entrySet().stream().map(par ->
|
||||
URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8)
|
||||
).collect(Collectors.joining("&"))
|
||||
);
|
||||
}
|
||||
|
||||
@ -289,7 +298,7 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8
|
||||
*/
|
||||
public <T> T get(final String path, final Map<String, String> payload, final String token, final Class<T> target)
|
||||
throws VaultConnectorException {
|
||||
throws VaultConnectorException {
|
||||
try {
|
||||
String response = get(path, payload, token);
|
||||
return jsonMapper.readValue(response, target);
|
||||
@ -325,8 +334,8 @@ public final class RequestHelper implements Serializable {
|
||||
// Execute request.
|
||||
try {
|
||||
HttpResponse<InputStream> response = client.sendAsync(
|
||||
requestBuilder.build(),
|
||||
HttpResponse.BodyHandlers.ofInputStream()
|
||||
requestBuilder.build(),
|
||||
HttpResponse.BodyHandlers.ofInputStream()
|
||||
).join();
|
||||
|
||||
/* Check if response is valid */
|
||||
@ -355,6 +364,15 @@ public final class RequestHelper implements Serializable {
|
||||
}
|
||||
} catch (CompletionException e) {
|
||||
throw new ConnectionException(Error.CONNECTION, e.getCause());
|
||||
} finally {
|
||||
if (client instanceof AutoCloseable) {
|
||||
// Close the client, which is supported since JDK21.
|
||||
try {
|
||||
((AutoCloseable) client).close();
|
||||
} catch (Exception ignored) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,7 +404,8 @@ public final class RequestHelper implements Serializable {
|
||||
}
|
||||
|
||||
return sslContext;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
|
||||
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException |
|
||||
KeyManagementException e) {
|
||||
throw new TlsException(Error.INIT_SSL_CONTEXT, e);
|
||||
}
|
||||
}
|
||||
@ -399,7 +418,7 @@ public final class RequestHelper implements Serializable {
|
||||
* @throws InvalidResponseException on reading errors
|
||||
*/
|
||||
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"));
|
||||
} catch (IOException ignored) {
|
||||
throw new InvalidResponseException(Error.READ_RESPONSE, 200);
|
||||
@ -413,18 +432,19 @@ public final class RequestHelper implements Serializable {
|
||||
* @throws VaultConnectorException Expected exception with details to throw
|
||||
*/
|
||||
private void handleError(final HttpResponse<InputStream> response) throws VaultConnectorException {
|
||||
if (response.body() != null) {
|
||||
try (var reader = new BufferedReader(new InputStreamReader(response.body()))) {
|
||||
var responseString = reader.lines().collect(Collectors.joining("\n"));
|
||||
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
|
||||
/* Check for "permission denied" response */
|
||||
if (!er.getErrors().isEmpty() && er.getErrors().get(0).equals("permission denied")) {
|
||||
throw new PermissionDeniedException();
|
||||
try (var body = response.body()) {
|
||||
if (body != null) {
|
||||
try (var reader = new BufferedReader(new InputStreamReader(body, UTF_8))) {
|
||||
ErrorResponse er = jsonMapper.readValue(reader, ErrorResponse.class);
|
||||
/* Check for "permission denied" response */
|
||||
if (!er.getErrors().isEmpty() && er.getErrors().get(0).equals("permission denied")) {
|
||||
throw new PermissionDeniedException();
|
||||
}
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE, response.statusCode(), er.toString());
|
||||
}
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE, response.statusCode(), er.toString());
|
||||
} catch (IOException ignored) {
|
||||
// Exception ignored.
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
// Exception ignored.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -32,18 +32,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
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);
|
||||
}
|
||||
private static final long serialVersionUID = 693228837510483448L;
|
||||
|
||||
@JsonProperty("role_name")
|
||||
private String name;
|
||||
@ -66,9 +55,9 @@ public final class AppRole implements Serializable {
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer secretIdTtl;
|
||||
|
||||
@JsonProperty("enable_local_secret_ids")
|
||||
@JsonProperty("local_secret_ids")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean enableLocalSecretIds;
|
||||
private Boolean localSecretIds;
|
||||
|
||||
@JsonProperty("token_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@ -122,7 +111,7 @@ public final class AppRole implements Serializable {
|
||||
this.secretIdBoundCidrs = builder.secretIdBoundCidrs;
|
||||
this.secretIdNumUses = builder.secretIdNumUses;
|
||||
this.secretIdTtl = builder.secretIdTtl;
|
||||
this.enableLocalSecretIds = builder.enableLocalSecretIds;
|
||||
this.localSecretIds = builder.localSecretIds;
|
||||
this.tokenTtl = builder.tokenTtl;
|
||||
this.tokenMaxTtl = builder.tokenMaxTtl;
|
||||
this.tokenPolicies = builder.tokenPolicies;
|
||||
@ -134,6 +123,17 @@ public final class AppRole implements Serializable {
|
||||
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
|
||||
*/
|
||||
@ -262,9 +262,10 @@ public final class AppRole implements Serializable {
|
||||
/**
|
||||
* @return Enable local secret IDs?
|
||||
* @since 0.9
|
||||
* @since 1.3 renamed to {@code getLocalSecretIds()}
|
||||
*/
|
||||
public Boolean getEnableLocalSecretIds() {
|
||||
return enableLocalSecretIds;
|
||||
public Boolean getLocalSecretIds() {
|
||||
return localSecretIds;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,28 +331,28 @@ public final class AppRole implements Serializable {
|
||||
}
|
||||
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);
|
||||
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(localSecretIds, appRole.localSecretIds) &&
|
||||
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);
|
||||
localSecretIds, tokenTtl, tokenMaxTtl, tokenPolicies, tokenBoundCidrs, tokenExplicitMaxTtl,
|
||||
tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType);
|
||||
}
|
||||
|
||||
|
||||
@ -370,7 +371,7 @@ public final class AppRole implements Serializable {
|
||||
private List<String> tokenPolicies;
|
||||
private Integer secretIdNumUses;
|
||||
private Integer secretIdTtl;
|
||||
private Boolean enableLocalSecretIds;
|
||||
private Boolean localSecretIds;
|
||||
private Integer tokenTtl;
|
||||
private Integer tokenMaxTtl;
|
||||
private List<String> tokenBoundCidrs;
|
||||
@ -527,12 +528,13 @@ public final class AppRole implements Serializable {
|
||||
/**
|
||||
* Enable or disable local secret IDs.
|
||||
*
|
||||
* @param enableLocalSecretIds Enable local secret IDs?
|
||||
* @param localSecretIds Enable local secret IDs?
|
||||
* @return self
|
||||
* @since 0.9
|
||||
* @since 1.3 renamed to {@code withLocalSecretIds()}
|
||||
*/
|
||||
public Builder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) {
|
||||
this.enableLocalSecretIds = enableLocalSecretIds;
|
||||
public Builder withLocalSecretIds(final Boolean localSecretIds) {
|
||||
this.localSecretIds = localSecretIds;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -181,19 +181,19 @@ public final class AppRoleSecret implements Serializable {
|
||||
}
|
||||
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);
|
||||
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);
|
||||
ttl);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,7 +24,6 @@ package de.stklcode.jvault.connector.model;
|
||||
*/
|
||||
public enum AuthBackend {
|
||||
TOKEN("token"),
|
||||
APPID("app-id"),
|
||||
APPROLE("approle"),
|
||||
USERPASS("userpass"),
|
||||
GITHUB("github"), // Not supported yet.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,16 +34,6 @@ import java.util.*;
|
||||
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")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
@ -123,6 +113,16 @@ public final class Token implements Serializable {
|
||||
this.entityAlias = builder.entityAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link Builder} instance.
|
||||
*
|
||||
* @return Token Builder.
|
||||
* @since 0.8
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token ID
|
||||
*/
|
||||
@ -227,24 +227,24 @@ public final class Token implements Serializable {
|
||||
}
|
||||
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);
|
||||
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);
|
||||
meta, renewable, period, entityAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -36,15 +36,6 @@ import java.util.Objects;
|
||||
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")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String name;
|
||||
@ -129,6 +120,15 @@ public final class TokenRole implements Serializable {
|
||||
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
|
||||
*/
|
||||
@ -245,27 +245,27 @@ public final class TokenRole implements Serializable {
|
||||
}
|
||||
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);
|
||||
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);
|
||||
orphan, renewable, pathSuffix, allowedEntityAliases, tokenBoundCidrs, tokenExplicitMaxTtl,
|
||||
tokenNoDefaultPolicy, tokenNumUses, tokenPeriod, tokenType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,11 +17,8 @@
|
||||
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.AuthData;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Vault response for authentication providing auth info in {@link AuthData} field.
|
||||
*
|
||||
@ -31,30 +28,4 @@ import java.util.Objects;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthResponse extends VaultDataResponse {
|
||||
private static final long serialVersionUID = 1628851361067456715L;
|
||||
|
||||
@JsonProperty("auth")
|
||||
private AuthData auth;
|
||||
|
||||
/**
|
||||
* @return Authentication data
|
||||
*/
|
||||
public AuthData 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;
|
||||
}
|
||||
AuthResponse that = (AuthResponse) o;
|
||||
return Objects.equals(auth, that.auth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), auth);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -29,7 +29,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class HealthResponse implements VaultResponse {
|
||||
private static final long serialVersionUID = 6483840078694294401L;
|
||||
private static final long serialVersionUID = 8675155916902904516L;
|
||||
|
||||
@JsonProperty("cluster_id")
|
||||
private String clusterID;
|
||||
@ -61,6 +61,18 @@ public final class HealthResponse implements VaultResponse {
|
||||
@JsonProperty("performance_standby")
|
||||
private Boolean performanceStandby;
|
||||
|
||||
@JsonProperty("echo_duration_ms")
|
||||
private Long echoDurationMs;
|
||||
|
||||
@JsonProperty("clock_skew_ms")
|
||||
private Long clockSkewMs;
|
||||
|
||||
@JsonProperty("replication_primary_canary_age_ms")
|
||||
private Long replicationPrimaryCanaryAgeMs;
|
||||
|
||||
@JsonProperty("enterprise")
|
||||
private Boolean enterprise;
|
||||
|
||||
/**
|
||||
* @return The Cluster ID.
|
||||
*/
|
||||
@ -134,6 +146,38 @@ public final class HealthResponse implements VaultResponse {
|
||||
return performanceStandby;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Heartbeat echo duration in milliseconds (since Vault 1.16)
|
||||
* @since 1.3
|
||||
*/
|
||||
public Long getEchoDurationMs() {
|
||||
return echoDurationMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Clock skew in milliseconds (since Vault 1.16)
|
||||
* @since 1.3
|
||||
*/
|
||||
public Long getClockSkewMs() {
|
||||
return clockSkewMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Replication primary canary age in milliseconds (since Vault 1.17)
|
||||
* @since 1.3
|
||||
*/
|
||||
public Long getReplicationPrimaryCanaryAgeMs() {
|
||||
return replicationPrimaryCanaryAgeMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Enterprise instance? (since Vault 1.17)
|
||||
* @since 1.3
|
||||
*/
|
||||
public Boolean isEnterprise() {
|
||||
return enterprise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -143,20 +187,25 @@ public final class HealthResponse implements VaultResponse {
|
||||
}
|
||||
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);
|
||||
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) &&
|
||||
Objects.equals(echoDurationMs, that.echoDurationMs) &&
|
||||
Objects.equals(clockSkewMs, that.clockSkewMs) &&
|
||||
Objects.equals(replicationPrimaryCanaryAgeMs, that.replicationPrimaryCanaryAgeMs) &&
|
||||
Objects.equals(enterprise, that.enterprise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(clusterID, clusterName, version, serverTimeUTC, standby, sealed, initialized,
|
||||
replicationPerfMode, replicationDrMode, performanceStandby);
|
||||
replicationPerfMode, replicationDrMode, performanceStandby, echoDurationMs, clockSkewMs,
|
||||
replicationPrimaryCanaryAgeMs, enterprise);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -41,7 +41,7 @@ public class MetaSecretResponse extends SecretResponse {
|
||||
|
||||
@Override
|
||||
public final Map<String, Serializable> getData() {
|
||||
if (secret != null) {
|
||||
if (secret != null) {
|
||||
return secret.getData();
|
||||
} else {
|
||||
return Collections.emptyMap();
|
||||
@ -50,7 +50,7 @@ public class MetaSecretResponse extends SecretResponse {
|
||||
|
||||
@Override
|
||||
public final VersionMetadata getMetadata() {
|
||||
if (secret != null) {
|
||||
if (secret != null) {
|
||||
return secret.getMetadata();
|
||||
} else {
|
||||
return null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -29,7 +30,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class SealResponse implements VaultResponse {
|
||||
private static final long serialVersionUID = -3661916639367542617L;
|
||||
private static final long serialVersionUID = -6000309255473305787L;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
@ -52,6 +53,9 @@ public final class SealResponse implements VaultResponse {
|
||||
@JsonProperty("version")
|
||||
private String version;
|
||||
|
||||
@JsonProperty("build_date")
|
||||
private ZonedDateTime buildDate;
|
||||
|
||||
@JsonProperty("nonce")
|
||||
private String nonce;
|
||||
|
||||
@ -122,6 +126,14 @@ public final class SealResponse implements VaultResponse {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vault build date.
|
||||
* @since 1.2
|
||||
*/
|
||||
public ZonedDateTime getBuildDate() {
|
||||
return buildDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A random nonce.
|
||||
* @since 0.8
|
||||
@ -179,23 +191,24 @@ public final class SealResponse implements VaultResponse {
|
||||
}
|
||||
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);
|
||||
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(buildDate, that.buildDate) &&
|
||||
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);
|
||||
return Objects.hash(type, sealed, initialized, threshold, numberOfShares, progress, version, buildDate, nonce,
|
||||
clusterName, clusterId, migration, recoverySeal, storageType);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,10 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
|
||||
|
||||
@ -79,8 +82,21 @@ public abstract class SecretResponse extends VaultDataResponse {
|
||||
Object rawValue = get(key);
|
||||
if (rawValue == null) {
|
||||
return null;
|
||||
} else if (type.isInstance(rawValue)) {
|
||||
return type.cast(rawValue);
|
||||
} else {
|
||||
var om = JsonMapper.builder()
|
||||
.addModule(new JavaTimeModule())
|
||||
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
|
||||
.build();
|
||||
|
||||
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) {
|
||||
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -30,14 +30,11 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class TokenResponse extends VaultDataResponse {
|
||||
private static final long serialVersionUID = -4053126653764241197L;
|
||||
private static final long serialVersionUID = -4341114947980033457L;
|
||||
|
||||
@JsonProperty("data")
|
||||
private TokenData data;
|
||||
|
||||
@JsonProperty("auth")
|
||||
private Boolean auth;
|
||||
|
||||
/**
|
||||
* @return Token data
|
||||
*/
|
||||
@ -45,12 +42,6 @@ public final class TokenResponse extends VaultDataResponse {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Auth data
|
||||
*/
|
||||
public Boolean getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@ -60,11 +51,11 @@ public final class TokenResponse extends VaultDataResponse {
|
||||
return false;
|
||||
}
|
||||
TokenResponse that = (TokenResponse) o;
|
||||
return Objects.equals(data, that.data) && Objects.equals(auth, that.auth);
|
||||
return Objects.equals(data, that.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), data, auth);
|
||||
return Objects.hash(super.hashCode(), data);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Response entity for transit operations.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class TransitResponse extends VaultDataResponse {
|
||||
|
||||
private static final long serialVersionUID = 6873804240772242771L;
|
||||
|
||||
private String ciphertext;
|
||||
private String plaintext;
|
||||
private String sum;
|
||||
|
||||
@JsonSetter("data")
|
||||
private void setData(Map<String, String> data) {
|
||||
ciphertext = data.get("ciphertext");
|
||||
plaintext = data.get("plaintext");
|
||||
sum = data.get("sum");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ciphertext.
|
||||
* Populated after encryption.
|
||||
*
|
||||
* @return Ciphertext
|
||||
*/
|
||||
public String getCiphertext() {
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plaintext.
|
||||
* Base64 encoded, populated after decryption.
|
||||
*
|
||||
* @return Plaintext
|
||||
*/
|
||||
public String getPlaintext() {
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hash sum.
|
||||
* Hex or Base64 string. Populated after hashing.
|
||||
*
|
||||
* @return Hash sum
|
||||
*/
|
||||
public String getSum() {
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o == null || getClass() != o.getClass() || !super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
TransitResponse that = (TransitResponse) o;
|
||||
return Objects.equals(ciphertext, that.ciphertext) &&
|
||||
Objects.equals(plaintext, that.plaintext) &&
|
||||
Objects.equals(sum, that.sum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), ciphertext, plaintext, sum);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,6 +17,7 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.WrapInfo;
|
||||
|
||||
import java.util.List;
|
||||
@ -29,7 +30,7 @@ import java.util.Objects;
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultDataResponse implements VaultResponse {
|
||||
private static final long serialVersionUID = 7486270767477652184L;
|
||||
private static final long serialVersionUID = 4787715235558510045L;
|
||||
|
||||
@JsonProperty("request_id")
|
||||
private String requestId;
|
||||
@ -49,6 +50,12 @@ public abstract class VaultDataResponse implements VaultResponse {
|
||||
@JsonProperty("wrap_info")
|
||||
private WrapInfo wrapInfo;
|
||||
|
||||
@JsonProperty("auth")
|
||||
private AuthData auth;
|
||||
|
||||
@JsonProperty("mount_type")
|
||||
private String mountType;
|
||||
|
||||
/**
|
||||
* @return Request ID
|
||||
* @since 1.1
|
||||
@ -93,6 +100,22 @@ public abstract class VaultDataResponse implements VaultResponse {
|
||||
return wrapInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Authentication information for this response
|
||||
* @since 1.3
|
||||
*/
|
||||
public final AuthData getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Information about the type of mount this secret is from (since Vault 1.17)
|
||||
* @since 1.3
|
||||
*/
|
||||
public final String getMountType() {
|
||||
return mountType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -102,15 +125,17 @@ public abstract class VaultDataResponse implements VaultResponse {
|
||||
}
|
||||
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);
|
||||
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) &&
|
||||
Objects.equals(auth, that.auth) &&
|
||||
Objects.equals(mountType, that.mountType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(requestId, leaseId, renewable, leaseDuration, warnings, wrapInfo);
|
||||
return Objects.hash(requestId, leaseId, renewable, leaseDuration, warnings, wrapInfo, auth, mountType);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -33,7 +33,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthData implements Serializable {
|
||||
private static final long serialVersionUID = -6962244199229885869L;
|
||||
private static final long serialVersionUID = 5969334512309655317L;
|
||||
|
||||
@JsonProperty("client_token")
|
||||
private String clientToken;
|
||||
@ -65,6 +65,12 @@ public final class AuthData implements Serializable {
|
||||
@JsonProperty("orphan")
|
||||
private boolean orphan;
|
||||
|
||||
@JsonProperty("num_uses")
|
||||
private Integer numUses;
|
||||
|
||||
@JsonProperty("mfa_requirement")
|
||||
private MfaRequirement mfaRequirement;
|
||||
|
||||
/**
|
||||
* @return Client token
|
||||
*/
|
||||
@ -131,6 +137,14 @@ public final class AuthData implements Serializable {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return allowed number of uses for the issued token
|
||||
* @since 1.3
|
||||
*/
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token is orphan
|
||||
* @since 0.9
|
||||
@ -139,6 +153,14 @@ public final class AuthData implements Serializable {
|
||||
return orphan;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return multi-factor requirement
|
||||
* @since 1.2
|
||||
*/
|
||||
public MfaRequirement getMfaRequirement() {
|
||||
return mfaRequirement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -149,20 +171,22 @@ public final class AuthData implements Serializable {
|
||||
}
|
||||
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);
|
||||
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) &&
|
||||
Objects.equals(numUses, authData.numUses) &&
|
||||
Objects.equals(mfaRequirement, authData.mfaRequirement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(clientToken, accessor, policies, tokenPolicies, metadata, leaseDuration, renewable,
|
||||
entityId, tokenType, orphan);
|
||||
entityId, tokenType, orphan, numUses, mfaRequirement);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,7 +34,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethod implements Serializable {
|
||||
private static final long serialVersionUID = -2718660627880077335L;
|
||||
private static final long serialVersionUID = -439987082190917691L;
|
||||
|
||||
private AuthBackend type;
|
||||
private String rawType;
|
||||
@ -42,11 +42,14 @@ public final class AuthMethod implements Serializable {
|
||||
@JsonProperty("accessor")
|
||||
private String accessor;
|
||||
|
||||
@JsonProperty("deprecation_status")
|
||||
private String deprecationStatus;
|
||||
|
||||
@JsonProperty("description")
|
||||
private String description;
|
||||
|
||||
@JsonProperty("config")
|
||||
private Map<String, String> config;
|
||||
private MountConfig config;
|
||||
|
||||
@JsonProperty("external_entropy_access")
|
||||
private boolean externalEntropyAccess;
|
||||
@ -54,6 +57,18 @@ public final class AuthMethod implements Serializable {
|
||||
@JsonProperty("local")
|
||||
private boolean local;
|
||||
|
||||
@JsonProperty("options")
|
||||
private Map<String, String> options;
|
||||
|
||||
@JsonProperty("plugin_version")
|
||||
private String pluginVersion;
|
||||
|
||||
@JsonProperty("running_plugin_version")
|
||||
private String runningPluginVersion;
|
||||
|
||||
@JsonProperty("running_sha256")
|
||||
private String runningSha256;
|
||||
|
||||
@JsonProperty("seal_wrap")
|
||||
private boolean sealWrap;
|
||||
|
||||
@ -91,6 +106,14 @@ public final class AuthMethod implements Serializable {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Deprecation status
|
||||
* @since 1.2
|
||||
*/
|
||||
public String getDeprecationStatus() {
|
||||
return deprecationStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Description
|
||||
*/
|
||||
@ -100,8 +123,10 @@ public final class AuthMethod implements Serializable {
|
||||
|
||||
/**
|
||||
* @return Configuration data
|
||||
* @since 0.2
|
||||
* @since 1.2 Returns {@link MountConfig} instead of {@link Map}
|
||||
*/
|
||||
public Map<String, String> getConfig() {
|
||||
public MountConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@ -120,6 +145,38 @@ public final class AuthMethod implements Serializable {
|
||||
return local;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Options
|
||||
* @since 1.2
|
||||
*/
|
||||
public Map<String, String> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Plugin version
|
||||
* @since 1.2
|
||||
*/
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Running plugin version
|
||||
* @since 1.2
|
||||
*/
|
||||
public String getRunningPluginVersion() {
|
||||
return runningPluginVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Running SHA256
|
||||
* @since 1.2
|
||||
*/
|
||||
public String getRunningSha256() {
|
||||
return runningSha256;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Seal wrapping enabled
|
||||
* @since 1.1
|
||||
@ -145,18 +202,24 @@ public final class AuthMethod implements Serializable {
|
||||
}
|
||||
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);
|
||||
type == that.type &&
|
||||
externalEntropyAccess == that.externalEntropyAccess &&
|
||||
sealWrap == that.sealWrap &&
|
||||
Objects.equals(rawType, that.rawType) &&
|
||||
Objects.equals(accessor, that.accessor) &&
|
||||
Objects.equals(deprecationStatus, that.deprecationStatus) &&
|
||||
Objects.equals(description, that.description) &&
|
||||
Objects.equals(config, that.config) &&
|
||||
Objects.equals(options, that.options) &&
|
||||
Objects.equals(pluginVersion, that.pluginVersion) &&
|
||||
Objects.equals(runningPluginVersion, that.runningPluginVersion) &&
|
||||
Objects.equals(runningSha256, that.runningSha256) &&
|
||||
Objects.equals(uuid, that.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, rawType, accessor, description, config, externalEntropyAccess, local, sealWrap, uuid);
|
||||
return Objects.hash(type, rawType, accessor, deprecationStatus, description, config, externalEntropyAccess,
|
||||
local, options, pluginVersion, runningPluginVersion, runningSha256, sealWrap, uuid);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Embedded multi-factor-authentication (MFA) constraint "any".
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.2
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class MfaConstraintAny implements Serializable {
|
||||
private static final long serialVersionUID = 1226126781813149627L;
|
||||
|
||||
@JsonProperty("any")
|
||||
private List<MfaMethodId> any;
|
||||
|
||||
/**
|
||||
* @return List of "any" MFA methods
|
||||
*/
|
||||
public List<MfaMethodId> getAny() {
|
||||
return any;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MfaConstraintAny mfaRequirement = (MfaConstraintAny) o;
|
||||
return Objects.equals(any, mfaRequirement.any);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(any);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Embedded multi-factor-authentication (MFA) requirement.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.2
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class MfaMethodId implements Serializable {
|
||||
private static final long serialVersionUID = 691298070242998814L;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("uses_passcode")
|
||||
private Boolean usesPasscode;
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @return MFA method type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MFA method id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MFA uses passcode id
|
||||
*/
|
||||
public Boolean getUsesPasscode() {
|
||||
return usesPasscode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MFA method name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MfaMethodId mfaMethodId = (MfaMethodId) o;
|
||||
return Objects.equals(type, mfaMethodId.type) &&
|
||||
Objects.equals(id, mfaMethodId.id) &&
|
||||
Objects.equals(usesPasscode, mfaMethodId.usesPasscode) &&
|
||||
Objects.equals(name, mfaMethodId.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, id, usesPasscode, name);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Embedded multi-factor-authentication (MFA) requirement.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.2
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class MfaRequirement implements Serializable {
|
||||
private static final long serialVersionUID = -2516941512455319638L;
|
||||
|
||||
@JsonProperty("mfa_request_id")
|
||||
private String mfaRequestId;
|
||||
|
||||
@JsonProperty("mfa_constraints")
|
||||
private Map<String, MfaConstraintAny> mfaConstraints;
|
||||
|
||||
/**
|
||||
* @return MFA request ID
|
||||
*/
|
||||
public String getMfaRequestId() {
|
||||
return mfaRequestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MFA constraints
|
||||
*/
|
||||
public Map<String, MfaConstraintAny> getMfaConstraints() {
|
||||
return mfaConstraints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MfaRequirement mfaRequirement = (MfaRequirement) o;
|
||||
return Objects.equals(mfaRequestId, mfaRequirement.mfaRequestId) &&
|
||||
Objects.equals(mfaConstraints, mfaRequirement.mfaConstraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mfaRequestId, mfaConstraints);
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Embedded mount config output.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.2
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MountConfig implements Serializable {
|
||||
private static final long serialVersionUID = -8653909672663717792L;
|
||||
|
||||
@JsonProperty("default_lease_ttl")
|
||||
private Integer defaultLeaseTtl;
|
||||
|
||||
@JsonProperty("max_lease_ttl")
|
||||
private Integer maxLeaseTtl;
|
||||
|
||||
@JsonProperty("force_no_cache")
|
||||
private Boolean forceNoCache;
|
||||
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType;
|
||||
|
||||
@JsonProperty("audit_non_hmac_request_keys")
|
||||
private List<String> auditNonHmacRequestKeys;
|
||||
|
||||
@JsonProperty("audit_non_hmac_response_keys")
|
||||
private List<String> auditNonHmacResponseKeys;
|
||||
|
||||
@JsonProperty("listing_visibility")
|
||||
private String listingVisibility;
|
||||
|
||||
@JsonProperty("passthrough_request_headers")
|
||||
private List<String> passthroughRequestHeaders;
|
||||
|
||||
@JsonProperty("allowed_response_headers")
|
||||
private List<String> allowedResponseHeaders;
|
||||
|
||||
@JsonProperty("allowed_managed_keys")
|
||||
private List<String> allowedManagedKeys;
|
||||
|
||||
@JsonProperty("delegated_auth_accessors")
|
||||
private List<String> delegatedAuthAccessors;
|
||||
|
||||
@JsonProperty("user_lockout_config")
|
||||
private UserLockoutConfig userLockoutConfig;
|
||||
|
||||
/**
|
||||
* @return Default lease TTL
|
||||
*/
|
||||
public Integer getDefaultLeaseTtl() {
|
||||
return defaultLeaseTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum lease TTL
|
||||
*/
|
||||
public Integer getMaxLeaseTtl() {
|
||||
return maxLeaseTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Force no cache?
|
||||
*/
|
||||
public Boolean getForceNoCache() {
|
||||
return forceNoCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token type
|
||||
*/
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Audit non HMAC request keys
|
||||
*/
|
||||
public List<String> getAuditNonHmacRequestKeys() {
|
||||
return auditNonHmacRequestKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Audit non HMAC response keys
|
||||
*/
|
||||
public List<String> getAuditNonHmacResponseKeys() {
|
||||
return auditNonHmacResponseKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Listing visibility
|
||||
*/
|
||||
public String getListingVisibility() {
|
||||
return listingVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Passthrough request headers
|
||||
*/
|
||||
public List<String> getPassthroughRequestHeaders() {
|
||||
return passthroughRequestHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Allowed response headers
|
||||
*/
|
||||
public List<String> getAllowedResponseHeaders() {
|
||||
return allowedResponseHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Allowed managed keys
|
||||
*/
|
||||
public List<String> getAllowedManagedKeys() {
|
||||
return allowedManagedKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Delegated auth accessors
|
||||
*/
|
||||
public List<String> getDelegatedAuthAccessors() {
|
||||
return delegatedAuthAccessors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User lockout config
|
||||
*/
|
||||
public UserLockoutConfig getUserLockoutConfig() {
|
||||
return userLockoutConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MountConfig that = (MountConfig) o;
|
||||
return Objects.equals(defaultLeaseTtl, that.defaultLeaseTtl) &&
|
||||
Objects.equals(maxLeaseTtl, that.maxLeaseTtl) &&
|
||||
Objects.equals(forceNoCache, that.forceNoCache) &&
|
||||
Objects.equals(tokenType, that.tokenType) &&
|
||||
Objects.equals(auditNonHmacRequestKeys, that.auditNonHmacRequestKeys) &&
|
||||
Objects.equals(auditNonHmacResponseKeys, that.auditNonHmacResponseKeys) &&
|
||||
Objects.equals(listingVisibility, that.listingVisibility) &&
|
||||
Objects.equals(passthroughRequestHeaders, that.passthroughRequestHeaders) &&
|
||||
Objects.equals(allowedResponseHeaders, that.allowedResponseHeaders) &&
|
||||
Objects.equals(allowedManagedKeys, that.allowedManagedKeys) &&
|
||||
Objects.equals(delegatedAuthAccessors, that.delegatedAuthAccessors) &&
|
||||
Objects.equals(userLockoutConfig, that.userLockoutConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(defaultLeaseTtl, maxLeaseTtl, forceNoCache, tokenType, auditNonHmacRequestKeys,
|
||||
auditNonHmacResponseKeys, listingVisibility, passthroughRequestHeaders, allowedResponseHeaders,
|
||||
allowedManagedKeys, delegatedAuthAccessors, userLockoutConfig);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,8 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -35,12 +34,10 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class SecretMetadata implements Serializable {
|
||||
private static final long serialVersionUID = 1684891108903409038L;
|
||||
|
||||
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX");
|
||||
private static final long serialVersionUID = -905059942871916214L;
|
||||
|
||||
@JsonProperty("created_time")
|
||||
private String createdTimeString;
|
||||
private ZonedDateTime createdTime;
|
||||
|
||||
@JsonProperty("current_version")
|
||||
private Integer currentVersion;
|
||||
@ -52,31 +49,25 @@ public final class SecretMetadata implements Serializable {
|
||||
private Integer oldestVersion;
|
||||
|
||||
@JsonProperty("updated_time")
|
||||
private String updatedTime;
|
||||
private ZonedDateTime updatedTime;
|
||||
|
||||
@JsonProperty("versions")
|
||||
private Map<Integer, VersionMetadata> versions;
|
||||
|
||||
/**
|
||||
* @return Time of secret creation as raw string representation.
|
||||
*/
|
||||
public String getCreatedTimeString() {
|
||||
return createdTimeString;
|
||||
}
|
||||
@JsonProperty("cas_required")
|
||||
private Boolean casRequired;
|
||||
|
||||
@JsonProperty("custom_metadata")
|
||||
private HashMap<String, String> customMetadata;
|
||||
|
||||
@JsonProperty("delete_version_after")
|
||||
private String deleteVersionAfter;
|
||||
|
||||
/**
|
||||
* @return Time of secret creation.
|
||||
*/
|
||||
public ZonedDateTime getCreatedTime() {
|
||||
if (createdTimeString != null && !createdTimeString.isEmpty()) {
|
||||
try {
|
||||
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
|
||||
} catch (DateTimeParseException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,25 +92,10 @@ public final class SecretMetadata implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time of secret update as raw string representation.
|
||||
*/
|
||||
public String getUpdatedTimeString() {
|
||||
return updatedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time of secret update..
|
||||
* @return Time of secret update.
|
||||
*/
|
||||
public ZonedDateTime getUpdatedTime() {
|
||||
if (updatedTime != null && !updatedTime.isEmpty()) {
|
||||
try {
|
||||
return ZonedDateTime.parse(updatedTime, TIME_FORMAT);
|
||||
} catch (DateTimeParseException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return updatedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,6 +105,30 @@ public final class SecretMetadata implements Serializable {
|
||||
return versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CAS required?
|
||||
* @since 1.3
|
||||
*/
|
||||
public Boolean isCasRequired() {
|
||||
return casRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Custom metadata.
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, String> getCustomMetadata() {
|
||||
return customMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return time duration to delete version
|
||||
* @since 1.3
|
||||
*/
|
||||
public String getDeleteVersionAfter() {
|
||||
return deleteVersionAfter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -137,16 +137,20 @@ public final class SecretMetadata implements Serializable {
|
||||
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);
|
||||
return Objects.equals(createdTime, that.createdTime) &&
|
||||
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) &&
|
||||
Objects.equals(casRequired, that.casRequired) &&
|
||||
Objects.equals(customMetadata, that.customMetadata) &&
|
||||
Objects.equals(deleteVersionAfter, that.deleteVersionAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(createdTimeString, currentVersion, maxVersions, oldestVersion, updatedTime, versions);
|
||||
return Objects.hash(createdTime, currentVersion, maxVersions, oldestVersion, updatedTime, versions, casRequired,
|
||||
customMetadata, deleteVersionAfter);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,7 +34,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class TokenData implements Serializable {
|
||||
private static final long serialVersionUID = 2915180734313753649L;
|
||||
private static final long serialVersionUID = -5749716740973138916L;
|
||||
|
||||
@JsonProperty("accessor")
|
||||
private String accessor;
|
||||
@ -52,7 +52,7 @@ public final class TokenData implements Serializable {
|
||||
private String entityId;
|
||||
|
||||
@JsonProperty("expire_time")
|
||||
private String expireTime;
|
||||
private ZonedDateTime expireTime;
|
||||
|
||||
@JsonProperty("explicit_max_ttl")
|
||||
private Integer explicitMaxTtl;
|
||||
@ -61,7 +61,7 @@ public final class TokenData implements Serializable {
|
||||
private String id;
|
||||
|
||||
@JsonProperty("issue_time")
|
||||
private String issueTime;
|
||||
private ZonedDateTime issueTime;
|
||||
|
||||
@JsonProperty("meta")
|
||||
private Map<String, Object> meta;
|
||||
@ -123,24 +123,12 @@ public final class TokenData implements Serializable {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expire time as raw string value
|
||||
* @since 0.9
|
||||
*/
|
||||
public String getExpireTimeString() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expire time (parsed)
|
||||
* @since 0.9
|
||||
*/
|
||||
public ZonedDateTime getExpireTime() {
|
||||
if (expireTime == null) {
|
||||
return null;
|
||||
} else {
|
||||
return ZonedDateTime.parse(expireTime);
|
||||
}
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,24 +146,12 @@ public final class TokenData implements Serializable {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Issue time as raw string value
|
||||
* @since 0.9
|
||||
*/
|
||||
public String getIssueTimeString() {
|
||||
return issueTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expire time (parsed)
|
||||
* @since 0.9
|
||||
*/
|
||||
public ZonedDateTime getIssueTime() {
|
||||
if (issueTime == null) {
|
||||
return null;
|
||||
} else {
|
||||
return ZonedDateTime.parse(issueTime);
|
||||
}
|
||||
return issueTime;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,27 +222,27 @@ public final class TokenData implements Serializable {
|
||||
}
|
||||
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);
|
||||
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);
|
||||
issueTime, meta, numUses, orphan, path, policies, renewable, ttl, type);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Embedded user lockout config output.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.2
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class UserLockoutConfig implements Serializable {
|
||||
private static final long serialVersionUID = -8051060041593140550L;
|
||||
|
||||
@JsonProperty("lockout_threshold")
|
||||
private Integer lockoutThreshold;
|
||||
|
||||
@JsonProperty("lockout_duration")
|
||||
private Integer lockoutDuration;
|
||||
|
||||
@JsonProperty("lockout_counter_reset_duration")
|
||||
private Integer lockoutCounterResetDuration;
|
||||
|
||||
@JsonProperty("lockout_disable")
|
||||
private Boolean lockoutDisable;
|
||||
|
||||
/**
|
||||
* @return Lockout threshold
|
||||
*/
|
||||
public Integer getLockoutThreshold() {
|
||||
return lockoutThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lockout duration
|
||||
*/
|
||||
public Integer getLockoutDuration() {
|
||||
return lockoutDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lockout counter reset duration
|
||||
*/
|
||||
public Integer getLockoutCounterResetDuration() {
|
||||
return lockoutCounterResetDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lockout disabled?
|
||||
*/
|
||||
public Boolean getLockoutDisable() {
|
||||
return lockoutDisable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
UserLockoutConfig that = (UserLockoutConfig) o;
|
||||
return Objects.equals(lockoutThreshold, that.lockoutThreshold) &&
|
||||
Objects.equals(lockoutDuration, that.lockoutDuration) &&
|
||||
Objects.equals(lockoutCounterResetDuration, that.lockoutCounterResetDuration) &&
|
||||
Objects.equals(lockoutDisable, that.lockoutDisable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(lockoutThreshold, lockoutDuration, lockoutCounterResetDuration, lockoutDisable);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,8 +21,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -34,15 +34,13 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class VersionMetadata implements Serializable {
|
||||
private static final long serialVersionUID = -5286693953873839611L;
|
||||
|
||||
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSX");
|
||||
private static final long serialVersionUID = 8495687554714216478L;
|
||||
|
||||
@JsonProperty("created_time")
|
||||
private String createdTimeString;
|
||||
private ZonedDateTime createdTime;
|
||||
|
||||
@JsonProperty("deletion_time")
|
||||
private String deletionTimeString;
|
||||
private ZonedDateTime deletionTime;
|
||||
|
||||
@JsonProperty("destroyed")
|
||||
private boolean destroyed;
|
||||
@ -50,48 +48,21 @@ public final class VersionMetadata implements Serializable {
|
||||
@JsonProperty("version")
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* @return Time of secret creation as raw string representation.
|
||||
*/
|
||||
public String getCreatedTimeString() {
|
||||
return createdTimeString;
|
||||
}
|
||||
@JsonProperty("custom_metadata")
|
||||
private HashMap<String, String> customMetadata;
|
||||
|
||||
/**
|
||||
* @return Time of secret creation.
|
||||
*/
|
||||
public ZonedDateTime getCreatedTime() {
|
||||
if (createdTimeString != null && !createdTimeString.isEmpty()) {
|
||||
try {
|
||||
return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
|
||||
} catch (DateTimeParseException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time for secret deletion as raw string representation.
|
||||
*/
|
||||
public String getDeletionTimeString() {
|
||||
return deletionTimeString;
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time for secret deletion.
|
||||
*/
|
||||
public ZonedDateTime getDeletionTime() {
|
||||
if (deletionTimeString != null && !deletionTimeString.isEmpty()) {
|
||||
try {
|
||||
return ZonedDateTime.parse(deletionTimeString, TIME_FORMAT);
|
||||
} catch (DateTimeParseException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return deletionTime;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +79,14 @@ public final class VersionMetadata implements Serializable {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Custom metadata.
|
||||
* @since 1.3
|
||||
*/
|
||||
public Map<String, String> getCustomMetadata() {
|
||||
return customMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -117,13 +96,14 @@ public final class VersionMetadata implements Serializable {
|
||||
}
|
||||
VersionMetadata that = (VersionMetadata) o;
|
||||
return destroyed == that.destroyed &&
|
||||
Objects.equals(createdTimeString, that.createdTimeString) &&
|
||||
Objects.equals(deletionTimeString, that.deletionTimeString) &&
|
||||
Objects.equals(version, that.version);
|
||||
Objects.equals(createdTime, that.createdTime) &&
|
||||
Objects.equals(deletionTime, that.deletionTime) &&
|
||||
Objects.equals(version, that.version) &&
|
||||
Objects.equals(customMetadata, that.customMetadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(createdTimeString, deletionTimeString, destroyed, version);
|
||||
return Objects.hash(createdTime, deletionTime, destroyed, version, customMetadata);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response.embedded;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -28,7 +29,7 @@ import java.util.Objects;
|
||||
* @since 1.1
|
||||
*/
|
||||
public class WrapInfo implements Serializable {
|
||||
private static final long serialVersionUID = -7764500642913116581L;
|
||||
private static final long serialVersionUID = 4864973237090355607L;
|
||||
|
||||
@JsonProperty("token")
|
||||
private String token;
|
||||
@ -37,7 +38,7 @@ public class WrapInfo implements Serializable {
|
||||
private Integer ttl;
|
||||
|
||||
@JsonProperty("creation_time")
|
||||
private String creationTime;
|
||||
private ZonedDateTime creationTime;
|
||||
|
||||
@JsonProperty("creation_path")
|
||||
private String creationPath;
|
||||
@ -59,7 +60,7 @@ public class WrapInfo implements Serializable {
|
||||
/**
|
||||
* @return Creation time
|
||||
*/
|
||||
public String getCreationTime() {
|
||||
public ZonedDateTime getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
@ -79,9 +80,9 @@ public class WrapInfo implements Serializable {
|
||||
}
|
||||
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);
|
||||
Objects.equals(ttl, that.ttl) &&
|
||||
Objects.equals(creationTime, that.creationTime) &&
|
||||
Objects.equals(creationPath, that.creationPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -30,7 +30,8 @@ module de.stklcode.jvault.connector {
|
||||
opens de.stklcode.jvault.connector.model.response to com.fasterxml.jackson.databind;
|
||||
opens de.stklcode.jvault.connector.model.response.embedded to com.fasterxml.jackson.databind;
|
||||
|
||||
requires java.base;
|
||||
requires java.net.http;
|
||||
requires com.fasterxml.jackson.annotation;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires com.fasterxml.jackson.datatype.jsr310;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,7 +25,10 @@ import org.junit.jupiter.api.io.TempDir;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@ -38,6 +41,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
*/
|
||||
class HTTPVaultConnectorBuilderTest {
|
||||
private static final String VAULT_ADDR = "https://localhost:8201";
|
||||
private static final String VAULT_ADDR_2 = "http://localhost";
|
||||
private static final String VAULT_ADDR_3 = "https://localhost/vault/";
|
||||
private static final Integer VAULT_MAX_RETRIES = 13;
|
||||
private static final String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||
|
||||
@ -112,6 +117,22 @@ class HTTPVaultConnectorBuilderTest {
|
||||
|
||||
return null;
|
||||
});
|
||||
withVaultEnv(VAULT_ADDR_2, null, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
assertEquals(VAULT_ADDR_2 + "/v1/", getRequestHelperPrivate(builder.build(), "baseURL"), "URL without port not set correctly");
|
||||
return null;
|
||||
});
|
||||
withVaultEnv(VAULT_ADDR_3, null, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
assertEquals(VAULT_ADDR_3, getRequestHelperPrivate(builder.build(), "baseURL"), "URL with custom path not set correctly");
|
||||
return null;
|
||||
});
|
||||
|
||||
// Provide address and number of retries.
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
@ -128,20 +149,6 @@ class HTTPVaultConnectorBuilderTest {
|
||||
return null;
|
||||
});
|
||||
|
||||
// Provide CA certificate.
|
||||
String VAULT_CACERT = tempDir.toString() + "/doesnotexist";
|
||||
withVaultEnv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
TlsException e = assertThrows(
|
||||
TlsException.class,
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Creation with unknown cert path failed"
|
||||
);
|
||||
assertTrue(e.getCause() instanceof NoSuchFileException);
|
||||
assertEquals(VAULT_CACERT, ((NoSuchFileException) e.getCause()).getFile());
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// Automatic authentication.
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
@ -165,11 +172,64 @@ class HTTPVaultConnectorBuilderTest {
|
||||
});
|
||||
}
|
||||
|
||||
private SystemLambda.WithEnvironmentVariables withVaultEnv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
|
||||
return withEnvironmentVariable("VAULT_ADDR", vault_addr)
|
||||
.and("VAULT_CACERT", vault_cacert)
|
||||
.and("VAULT_MAX_RETRIES", vault_max_retries)
|
||||
.and("VAULT_TOKEN", vault_token);
|
||||
/**
|
||||
* Test CA certificate handling from environment variables
|
||||
*/
|
||||
@Test
|
||||
void testCertificateFromEnv() throws Exception {
|
||||
// From direct PEM content
|
||||
String pem = Files.readString(Paths.get(getClass().getResource("/tls/ca.pem").toURI()));
|
||||
AtomicReference<Object> certFromPem = new AtomicReference<>();
|
||||
withVaultEnv(VAULT_ADDR, pem, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Builder with PEM certificate from environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
certFromPem.set(getRequestHelperPrivate(connector, "trustedCaCert"));
|
||||
assertNotNull(certFromPem.get(), "Trusted CA cert from PEM not set");
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// From file path
|
||||
String file = Paths.get(getClass().getResource("/tls/ca.pem").toURI()).toString();
|
||||
AtomicReference<Object> certFromFile = new AtomicReference<>();
|
||||
withVaultEnv(VAULT_ADDR, file, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Builder with certificate path from environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
certFromFile.set(getRequestHelperPrivate(connector, "trustedCaCert"));
|
||||
assertNotNull(certFromFile.get(), "Trusted CA cert from file not set");
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
assertEquals(certFromPem.get(), certFromFile.get(), "Certificates from PEM and file should be equal");
|
||||
|
||||
// Non-existing path CA certificate path
|
||||
String doesNotExist = tempDir.toString() + "/doesnotexist";
|
||||
withVaultEnv(VAULT_ADDR, doesNotExist, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
TlsException e = assertThrows(
|
||||
TlsException.class,
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Creation with unknown cert path failed"
|
||||
);
|
||||
assertEquals(doesNotExist, assertInstanceOf(NoSuchFileException.class, e.getCause()).getFile());
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private SystemLambda.WithEnvironmentVariables withVaultEnv(String vaultAddr, String vaultCacert, String vaultMaxRetries, String vaultToken) {
|
||||
return withEnvironmentVariable("VAULT_ADDR", vaultAddr)
|
||||
.and("VAULT_CACERT", vaultCacert)
|
||||
.and("VAULT_MAX_RETRIES", vaultMaxRetries)
|
||||
.and("VAULT_TOKEN", vaultToken);
|
||||
}
|
||||
|
||||
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,17 +25,18 @@ import de.stklcode.jvault.connector.model.response.*;
|
||||
import de.stklcode.jvault.connector.test.Credentials;
|
||||
import de.stklcode.jvault.connector.test.VaultConfiguration;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.apache.commons.io.FileUtils.copyDirectory;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
@ -51,7 +52,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
* @since 0.1
|
||||
*/
|
||||
class HTTPVaultConnectorIT {
|
||||
private static String VAULT_VERSION = "1.12.0"; // The vault version this test is supposed to run against.
|
||||
private static String VAULT_VERSION = "1.19.0"; // The vault version this test is supposed to run against.
|
||||
private static final String KEY1 = "E38bkCm0VhUvpdCKGQpcohhD9XmcHJ/2hreOSY019Lho";
|
||||
private static final String KEY2 = "O5OHwDleY3IiPdgw61cgHlhsrEm6tVJkrxhF6QAnILd1";
|
||||
private static final String KEY3 = "mw7Bm3nbt/UWa/juDjjL2EPQ04kiJ0saC5JEXwJvXYsB";
|
||||
@ -59,7 +60,6 @@ class HTTPVaultConnectorIT {
|
||||
private static final String USER_VALID = "validUser";
|
||||
private static final String PASS_VALID = "validPass";
|
||||
|
||||
private static boolean legacy;
|
||||
private Process vaultProcess;
|
||||
private VaultConnector connector;
|
||||
|
||||
@ -70,9 +70,6 @@ class HTTPVaultConnectorIT {
|
||||
VAULT_VERSION = System.getenv("VAULT_VERSION");
|
||||
System.out.println("Vault version set to " + VAULT_VERSION);
|
||||
}
|
||||
if (compareVersions(VAULT_VERSION, "1.12.0") < 0) {
|
||||
legacy = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,13 +126,11 @@ class HTTPVaultConnectorIT {
|
||||
@Test
|
||||
@Order(10)
|
||||
@DisplayName("Read secrets")
|
||||
@SuppressWarnings("deprecation")
|
||||
void readSecretTest() {
|
||||
authUser();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
// Try to read path user has no permission to read.
|
||||
SecretResponse res = null;
|
||||
final String invalidPath = "secret/invalid/path";
|
||||
|
||||
VaultConnectorException e = assertThrows(
|
||||
@ -151,7 +146,7 @@ class HTTPVaultConnectorIT {
|
||||
assertFalse(Pattern.compile("[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}").matcher(stackTrace(e)).find());
|
||||
|
||||
// Try to read accessible path with known value.
|
||||
res = assertDoesNotThrow(
|
||||
SecretResponse res = assertDoesNotThrow(
|
||||
() -> connector.read(SECRET_PATH + "/" + SECRET_KEY),
|
||||
"Valid secret path could not be read"
|
||||
);
|
||||
@ -216,7 +211,6 @@ class HTTPVaultConnectorIT {
|
||||
@Test
|
||||
@Order(30)
|
||||
@DisplayName("Write secrets")
|
||||
@SuppressWarnings("deprecation")
|
||||
void writeSecretTest() {
|
||||
authUser();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
@ -550,74 +544,6 @@ class HTTPVaultConnectorIT {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@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 {
|
||||
private static final String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA";
|
||||
private static final String USER_ID = "5ADF8218-D7FB-4089-9E38-287465DBF37E";
|
||||
|
||||
/**
|
||||
* App-ID authentication roundtrip.
|
||||
*/
|
||||
@Test
|
||||
@Order(10)
|
||||
@DisplayName("Authenticate with App-ID")
|
||||
void authAppIdTest() {
|
||||
// Try unauthorized access first.
|
||||
assumeFalse(connector.isAuthorized());
|
||||
|
||||
assertThrows(
|
||||
AuthorizationRequiredException.class,
|
||||
() -> connector.registerAppId("", "", ""),
|
||||
"Expected exception not thrown"
|
||||
);
|
||||
assertThrows(
|
||||
AuthorizationRequiredException.class,
|
||||
() -> connector.registerUserId("", ""),
|
||||
"Expected exception not thrown"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* App-ID authentication roundtrip.
|
||||
*/
|
||||
@Test
|
||||
@Order(20)
|
||||
@DisplayName("Register App-ID")
|
||||
void registerAppIdTest() {
|
||||
// Authorize.
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
// Register App-ID.
|
||||
boolean res = assertDoesNotThrow(
|
||||
() -> connector.registerAppId(APP_ID, "user", "App Name"),
|
||||
"Failed to register App-ID"
|
||||
);
|
||||
assertTrue(res, "Failed to register App-ID");
|
||||
|
||||
// Register User-ID.
|
||||
res = assertDoesNotThrow(
|
||||
() -> connector.registerUserId(APP_ID, USER_ID),
|
||||
"Failed to register App-ID"
|
||||
);
|
||||
assertTrue(res, "Failed to register App-ID");
|
||||
|
||||
connector.resetAuth();
|
||||
assumeFalse(connector.isAuthorized());
|
||||
|
||||
// Authenticate with created credentials.
|
||||
AuthResponse resp = assertDoesNotThrow(
|
||||
() -> connector.authAppId(APP_ID, USER_ID),
|
||||
"Failed to authenticate using App-ID"
|
||||
);
|
||||
assertTrue(connector.isAuthorized(), "Authorization flag not set after App-ID login");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("AppRole Tests")
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@ -909,7 +835,7 @@ class HTTPVaultConnectorIT {
|
||||
assertFalse(res.getAuth().isRenewable(), "Root token should not be renewable");
|
||||
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.
|
||||
// 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");
|
||||
|
||||
@ -1063,6 +989,75 @@ class HTTPVaultConnectorIT {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Transit Tests")
|
||||
class TransitTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Transit encryption")
|
||||
void transitEncryptTest() {
|
||||
assertDoesNotThrow(() -> connector.authToken(TOKEN_ROOT));
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitEncrypt("my-key", "dGVzdCBtZQ=="),
|
||||
"Failed to encrypt via transit"
|
||||
);
|
||||
assertNotNull(transitResponse.getCiphertext());
|
||||
assertTrue(transitResponse.getCiphertext().startsWith("vault:v1:"));
|
||||
|
||||
transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitEncrypt("my-key", "test me".getBytes(UTF_8)),
|
||||
"Failed to encrypt binary data via transit"
|
||||
);
|
||||
assertNotNull(transitResponse.getCiphertext());
|
||||
assertTrue(transitResponse.getCiphertext().startsWith("vault:v1:"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Transit decryption")
|
||||
void transitDecryptTest() {
|
||||
assertDoesNotThrow(() -> connector.authToken(TOKEN_ROOT));
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitDecrypt("my-key", "vault:v1:1mhLVkBAR2nrFtIkJF/qg57DWfRj0FWgR6tvkGO8XOnL6sw="),
|
||||
"Failed to decrypt via transit"
|
||||
);
|
||||
|
||||
assertEquals("dGVzdCBtZQ==", transitResponse.getPlaintext());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Transit hash")
|
||||
void transitHashText() {
|
||||
assertDoesNotThrow(() -> connector.authToken(TOKEN_ROOT));
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-512", "dGVzdCBtZQ=="),
|
||||
"Failed to hash via transit"
|
||||
);
|
||||
|
||||
assertEquals("7677af0ee4effaa9f35e9b1e82d182f79516ab8321786baa23002de7c06851059492dd37d5fc3791f17d81d4b58198d24a6fd8bbd62c42c1c30b371da500f193", transitResponse.getSum());
|
||||
|
||||
TransitResponse transitResponseBase64 = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-256", "dGVzdCBtZQ==", "base64"),
|
||||
"Failed to hash via transit with base64 output"
|
||||
);
|
||||
|
||||
assertEquals("5DfYkW7cvGLkfy36cXhqmZcygEy9HpnFNB4WWXKOl1M=", transitResponseBase64.getSum());
|
||||
|
||||
transitResponseBase64 = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-256", "test me".getBytes(UTF_8), "base64"),
|
||||
"Failed to hash binary data via transit"
|
||||
);
|
||||
|
||||
assertEquals("5DfYkW7cvGLkfy36cXhqmZcygEy9HpnFNB4WWXKOl1M=", transitResponseBase64.getSum());
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Misc Tests")
|
||||
class MiscTests {
|
||||
@ -1080,13 +1075,9 @@ class HTTPVaultConnectorIT {
|
||||
() -> connector.getAuthBackends(),
|
||||
"Could not list supported auth backends"
|
||||
);
|
||||
if (legacy) {
|
||||
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)));
|
||||
}
|
||||
|
||||
assertEquals(3, supportedBackends.size());
|
||||
assertTrue(supportedBackends.containsAll(List.of(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPROLE)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1212,11 +1203,7 @@ class HTTPVaultConnectorIT {
|
||||
*/
|
||||
private VaultConfiguration initializeVault(File dir, boolean tls) throws IllegalStateException, IOException {
|
||||
File dataDir = new File(dir, "data");
|
||||
if (legacy) {
|
||||
copyDirectory(new File(getClass().getResource("/data_dir_legacy").getPath()), dataDir);
|
||||
} else {
|
||||
copyDirectory(new File(getClass().getResource("/data_dir").getPath()), dataDir);
|
||||
}
|
||||
copyDirectory(new File(getClass().getResource("/data_dir").getPath()), dataDir);
|
||||
|
||||
// Generate vault local unencrypted configuration.
|
||||
VaultConfiguration config = new VaultConfiguration()
|
||||
@ -1234,15 +1221,17 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Write configuration file.
|
||||
File configFile = new File(dir, "vault.conf");
|
||||
try (BufferedWriter bw = new BufferedWriter(new FileWriter(configFile))) {
|
||||
bw.write(config.toString());
|
||||
try {
|
||||
Files.write(configFile.toPath(), config.toString().getBytes(UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unable to generate config file", e);
|
||||
}
|
||||
|
||||
// Start vault process.
|
||||
try {
|
||||
vaultProcess = Runtime.getRuntime().exec("vault server -config " + configFile);
|
||||
vaultProcess = new ProcessBuilder("vault", "server", "-config", configFile.toString())
|
||||
.directory(dir)
|
||||
.start();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unable to start vault. Make sure vault binary is in your executable path", e);
|
||||
}
|
||||
@ -1310,35 +1299,4 @@ class HTTPVaultConnectorIT {
|
||||
th.printStackTrace(new PrintWriter(sw, true));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,13 +17,13 @@
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
|
||||
import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -36,9 +36,7 @@ import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collections;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -48,26 +46,23 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@WireMockTest
|
||||
class HTTPVaultConnectorTest {
|
||||
@RegisterExtension
|
||||
static WireMockExtension wireMock = WireMockExtension.newInstance()
|
||||
.options(wireMockConfig().dynamicPort())
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Test exceptions thrown during request.
|
||||
*/
|
||||
@Test
|
||||
void requestExceptionTest() throws IOException, URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
void requestExceptionTest(WireMockRuntimeInfo wireMock) throws IOException, URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
|
||||
|
||||
// Test invalid response code.
|
||||
final int responseCode = 400;
|
||||
mockHttpResponse(responseCode, "", "application/json");
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
InvalidResponseException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message");
|
||||
assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception");
|
||||
@ -76,9 +71,9 @@ class HTTPVaultConnectorTest {
|
||||
// Simulate permission denied response.
|
||||
mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json");
|
||||
assertThrows(
|
||||
PermissionDeniedException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
PermissionDeniedException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
|
||||
// Test exception thrown during request.
|
||||
@ -86,22 +81,22 @@ class HTTPVaultConnectorTest {
|
||||
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build();
|
||||
}
|
||||
e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
assertTrue(e.getCause() instanceof IOException, "Unexpected cause");
|
||||
assertInstanceOf(IOException.class, e.getCause(), "Unexpected cause");
|
||||
|
||||
// Now simulate a failing request that succeeds on second try.
|
||||
connector = HTTPVaultConnector.builder(wireMock.url("/")).withNumberOfRetries(1).withTimeout(250).build();
|
||||
connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withNumberOfRetries(1).withTimeout(250).build();
|
||||
|
||||
wireMock.stubFor(
|
||||
WireMock.any(anyUrl())
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json"))
|
||||
stubFor(
|
||||
WireMock.any(anyUrl())
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json"))
|
||||
);
|
||||
assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly");
|
||||
}
|
||||
@ -164,9 +159,9 @@ class HTTPVaultConnectorTest {
|
||||
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort()).withTimeout(250).build();
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::sealStatus,
|
||||
"Querying seal status succeeded on invalid instance"
|
||||
ConnectionException.class,
|
||||
connector::sealStatus,
|
||||
"Querying seal status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
}
|
||||
@ -182,9 +177,9 @@ class HTTPVaultConnectorTest {
|
||||
connector = HTTPVaultConnector.builder("http://localhost:" + s.getLocalPort() + "/").withTimeout(250).build();
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
}
|
||||
@ -193,8 +188,8 @@ class HTTPVaultConnectorTest {
|
||||
* Test behavior on unparsable responses.
|
||||
*/
|
||||
@Test
|
||||
void parseExceptionTest() throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
void parseExceptionTest(WireMockRuntimeInfo wireMock) throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
@ -227,8 +222,8 @@ class HTTPVaultConnectorTest {
|
||||
* Test requests that expect an empty response with code 204, but receive a 200 body.
|
||||
*/
|
||||
@Test
|
||||
void nonEmpty204ResponseTest() throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
void nonEmpty204ResponseTest(WireMockRuntimeInfo wireMock) throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
@ -236,57 +231,45 @@ class HTTPVaultConnectorTest {
|
||||
|
||||
// Now test the methods expecting a 204.
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.registerAppId("appID", "policy", "displayName"),
|
||||
"registerAppId() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.createAppRole("appID", Collections.singletonList("policy")),
|
||||
"createAppRole() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.registerUserId("appID", "userID"),
|
||||
"registerUserId() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.deleteAppRole("roleName"),
|
||||
"deleteAppRole() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.createAppRole("appID", Collections.singletonList("policy")),
|
||||
"createAppRole() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.setAppRoleID("roleName", "roleID"),
|
||||
"setAppRoleID() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.deleteAppRole("roleName"),
|
||||
"deleteAppRole() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretID"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.setAppRoleID("roleName", "roleID"),
|
||||
"setAppRoleID() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretUD"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretID"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.delete("key"),
|
||||
"delete() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretUD"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.delete("key"),
|
||||
"delete() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.revoke("leaseID"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
InvalidResponseException.class,
|
||||
() -> connector.revoke("leaseID"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
);
|
||||
}
|
||||
|
||||
@ -300,7 +283,7 @@ class HTTPVaultConnectorTest {
|
||||
|
||||
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.isAccessible()) {
|
||||
if (field.canAccess(target)) {
|
||||
return field.get(target);
|
||||
}
|
||||
field.setAccessible(true);
|
||||
@ -312,7 +295,7 @@ class HTTPVaultConnectorTest {
|
||||
private void setPrivate(Object target, String fieldName, Object value) {
|
||||
try {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible = field.isAccessible();
|
||||
boolean accessible = field.canAccess(target);
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
field.setAccessible(accessible);
|
||||
@ -322,10 +305,10 @@ class HTTPVaultConnectorTest {
|
||||
}
|
||||
|
||||
private void mockHttpResponse(int status, String body, String contentType) {
|
||||
wireMock.stubFor(
|
||||
WireMock.any(anyUrl()).willReturn(
|
||||
aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType)
|
||||
)
|
||||
stubFor(
|
||||
WireMock.any(anyUrl()).willReturn(
|
||||
aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,10 @@
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -16,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||
*/
|
||||
public abstract class AbstractModelTest<T> {
|
||||
protected final Class<?> modelClass;
|
||||
protected final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Test case constructor.
|
||||
@ -24,6 +30,11 @@ public abstract class AbstractModelTest<T> {
|
||||
*/
|
||||
protected AbstractModelTest(Class<T> modelClass) {
|
||||
this.modelClass = modelClass;
|
||||
this.objectMapper = JsonMapper.builder()
|
||||
.addModule(new JavaTimeModule())
|
||||
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@ -116,16 +115,14 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
*/
|
||||
@Test
|
||||
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 afterward.
|
||||
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.
|
||||
String secretJson2 = commaSeparatedToList(secretJson);
|
||||
|
||||
AppRoleSecret secret2 = assertDoesNotThrow(
|
||||
() -> mapper.readValue(secretJson2, AppRoleSecret.class),
|
||||
() -> objectMapper.readValue(secretJson2, AppRoleSecret.class),
|
||||
"Deserialization failed"
|
||||
);
|
||||
assertEquals(secret2.getId(), secret.getId());
|
||||
@ -145,9 +142,9 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
assumeTrue(secret.getNumUses() == 678);
|
||||
setPrivateField(secret, "ttl", 12345);
|
||||
assumeTrue(secret.getTtl() == 12345);
|
||||
String secretJson3 = assertDoesNotThrow(() -> mapper.writeValueAsString(secret), "Serialization failed");
|
||||
String secretJson3 = assertDoesNotThrow(() -> objectMapper.writeValueAsString(secret), "Serialization failed");
|
||||
secret2 = assertDoesNotThrow(
|
||||
() -> mapper.readValue(commaSeparatedToList(secretJson3), AppRoleSecret.class),
|
||||
() -> objectMapper.readValue(commaSeparatedToList(secretJson3), AppRoleSecret.class),
|
||||
"Deserialization failed"
|
||||
);
|
||||
assertEquals(secret2.getId(), secret.getId());
|
||||
@ -165,7 +162,7 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
|
||||
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
|
||||
"\"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_CREATION", secret2.getCreationTime());
|
||||
assertEquals("TEST_EXPIRATION", secret2.getExpirationTime());
|
||||
@ -176,14 +173,14 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
|
||||
private static void setPrivateField(Object object, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = object.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible = field.isAccessible();
|
||||
boolean accessible = field.canAccess(object);
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
|
||||
private static String commaSeparatedToList(String json) {
|
||||
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":\\[$1\\]")
|
||||
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":[$1]")
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -44,7 +43,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final Integer SECRET_ID_NUM_USES = 10;
|
||||
private static final Integer SECRET_ID_TTL = 7200;
|
||||
private static final Boolean ENABLE_LOCAL_SECRET_IDS = false;
|
||||
private static final Boolean LOCAL_SECRET_IDS = false;
|
||||
private static final Integer TOKEN_TTL = 4800;
|
||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 14400;
|
||||
@ -53,8 +52,8 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
private static final Integer TOKEN_PERIOD = 1234;
|
||||
private static final Token.Type TOKEN_TYPE = Token.Type.DEFAULT_SERVICE;
|
||||
private static final String JSON_MIN = "{\"role_name\":\"" + NAME + "\"}";
|
||||
private static final String JSON_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());
|
||||
private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}",
|
||||
NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value());
|
||||
|
||||
AppRoleTest() {
|
||||
super(AppRole.class);
|
||||
@ -69,7 +68,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
|
||||
.withLocalSecretIds(LOCAL_SECRET_IDS)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
@ -99,7 +98,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
assertNull(role.getTokenPolicies());
|
||||
assertNull(role.getSecretIdNumUses());
|
||||
assertNull(role.getSecretIdTtl());
|
||||
assertNull(role.getEnableLocalSecretIds());
|
||||
assertNull(role.getLocalSecretIds());
|
||||
assertNull(role.getTokenTtl());
|
||||
assertNull(role.getTokenMaxTtl());
|
||||
assertNull(role.getTokenBoundCidrs());
|
||||
@ -110,7 +109,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +125,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
assertEquals(POLICIES, role.getTokenPolicies());
|
||||
assertEquals(SECRET_ID_NUM_USES, role.getSecretIdNumUses());
|
||||
assertEquals(SECRET_ID_TTL, role.getSecretIdTtl());
|
||||
assertEquals(ENABLE_LOCAL_SECRET_IDS, role.getEnableLocalSecretIds());
|
||||
assertEquals(LOCAL_SECRET_IDS, role.getLocalSecretIds());
|
||||
assertEquals(TOKEN_TTL, role.getTokenTtl());
|
||||
assertEquals(TOKEN_MAX_TTL, role.getTokenMaxTtl());
|
||||
assertEquals(BOUND_CIDR_LIST, role.getTokenBoundCidrs());
|
||||
@ -137,7 +136,7 @@ class AppRoleTest extends AbstractModelTest<AppRole> {
|
||||
assertEquals(TOKEN_TYPE.value(), role.getTokenType());
|
||||
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role));
|
||||
assertEquals(JSON_FULL, objectMapper.writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -35,7 +35,6 @@ class AuthBackendTest {
|
||||
@Test
|
||||
void forTypeTest() {
|
||||
assertEquals(AuthBackend.TOKEN, AuthBackend.forType("token"));
|
||||
assertEquals(AuthBackend.APPID, AuthBackend.forType("app-id"));
|
||||
assertEquals(AuthBackend.USERPASS, AuthBackend.forType("userpass"));
|
||||
assertEquals(AuthBackend.GITHUB, AuthBackend.forType("github"));
|
||||
assertEquals(AuthBackend.UNKNOWN, AuthBackend.forType(""));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -133,7 +132,7 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
// Optional fields should be ignored, so JSON string should be empty.
|
||||
assertEquals("{}", new ObjectMapper().writeValueAsString(role));
|
||||
assertEquals("{}", objectMapper.writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,10 +173,10 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
// Empty builder should be equal to no-arg construction.
|
||||
assertEquals(role, new TokenRole());
|
||||
assertEquals(new TokenRole(), role);
|
||||
|
||||
// Optional fields should be ignored, so JSON string should be empty.
|
||||
assertEquals("{}", new ObjectMapper().writeValueAsString(role));
|
||||
assertEquals("{}", objectMapper.writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,6 +207,6 @@ class TokenRoleTest extends AbstractModelTest<TokenRole> {
|
||||
assertEquals(TOKEN_TYPE.value(), role.getTokenType());
|
||||
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role));
|
||||
assertEquals(JSON_FULL, objectMapper.writeValueAsString(role));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -103,10 +102,10 @@ class TokenTest extends AbstractModelTest<Token> {
|
||||
assertNull(token.getEntityAlias());
|
||||
|
||||
// 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());
|
||||
assertEquals(new Token(), token);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +128,7 @@ class TokenTest extends AbstractModelTest<Token> {
|
||||
assertEquals(PERIOD, token.getPeriod());
|
||||
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(token));
|
||||
assertEquals(JSON_FULL, objectMapper.writeValueAsString(token));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import de.stklcode.jvault.connector.model.AppRole;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -69,7 +68,7 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
|
||||
@Override
|
||||
protected AppRoleResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class);
|
||||
return objectMapper.readValue(RES_JSON, AppRoleResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -92,7 +91,7 @@ class AppRoleResponseTest extends AbstractModelTest<AppRoleResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
AppRoleResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class),
|
||||
() -> objectMapper.readValue(RES_JSON, AppRoleResponse.class),
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
@ -47,7 +46,10 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
|
||||
private static final String TK_ACCESSOR = "auth_token_ac0dd95a";
|
||||
private static final String TK_DESCR = "token based credentials";
|
||||
private static final Integer TK_LEASE_TTL = 0;
|
||||
private static final Boolean TK_FORCE_NO_CACHE = false;
|
||||
private static final Integer TK_MAX_LEASE_TTL = 0;
|
||||
private static final String TK_TOKEN_TYPE = "default-service";
|
||||
private static final String TK_RUNNING_PLUGIN_VERSION = "v1.15.3+builtin.vault";
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"data\": {" +
|
||||
@ -63,9 +65,15 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
|
||||
" \"" + TK_PATH + "\": {\n" +
|
||||
" \"config\": {\n" +
|
||||
" \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" +
|
||||
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + "\n" +
|
||||
" \"force_no_cache\": " + TK_FORCE_NO_CACHE + ",\n" +
|
||||
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + ",\n" +
|
||||
" \"token_type\": \"" + TK_TOKEN_TYPE + "\"\n" +
|
||||
" },\n" +
|
||||
" \"description\": \"" + TK_DESCR + "\",\n" +
|
||||
" \"options\": null,\n" +
|
||||
" \"plugin_version\": \"\",\n" +
|
||||
" \"running_plugin_version\": \"" + TK_RUNNING_PLUGIN_VERSION + "\",\n" +
|
||||
" \"running_sha256\": \"\",\n" +
|
||||
" \"type\": \"" + TK_TYPE + "\",\n" +
|
||||
" \"uuid\": \"" + TK_UUID + "\",\n" +
|
||||
" \"accessor\": \"" + TK_ACCESSOR + "\",\n" +
|
||||
@ -83,7 +91,7 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
|
||||
@Override
|
||||
protected AuthMethodsResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class);
|
||||
return objectMapper.readValue(RES_JSON, AuthMethodsResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -106,7 +114,7 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
AuthMethodsResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class),
|
||||
() -> objectMapper.readValue(RES_JSON, AuthMethodsResponse.class),
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
@ -138,15 +146,16 @@ class AuthMethodsResponseTest extends AbstractModelTest<AuthMethodsResponse> {
|
||||
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");
|
||||
assertEquals("", method.getPluginVersion(), "Unexpected plugin version");
|
||||
assertEquals(TK_RUNNING_PLUGIN_VERSION, method.getRunningPluginVersion(), "Unexpected running plugin version");
|
||||
assertEquals("", method.getRunningSha256(), "Unexpected running SHA256");
|
||||
|
||||
assertNotNull(method.getConfig(), "Missing config for Token");
|
||||
assertEquals(
|
||||
Map.of(
|
||||
"default_lease_ttl", TK_LEASE_TTL.toString(),
|
||||
"max_lease_ttl", TK_MAX_LEASE_TTL.toString()
|
||||
),
|
||||
method.getConfig(),
|
||||
"Unexpected config for Token"
|
||||
);
|
||||
assertEquals(TK_LEASE_TTL, method.getConfig().getDefaultLeaseTtl(), "Unexpected default TTL");
|
||||
assertEquals(TK_MAX_LEASE_TTL, method.getConfig().getMaxLeaseTtl(), "Unexpected max TTL");
|
||||
assertEquals(TK_FORCE_NO_CACHE, method.getConfig().getForceNoCache(), "Unexpected force no cache flag");
|
||||
assertEquals(TK_TOKEN_TYPE, method.getConfig().getTokenType(), "Unexpected token type");
|
||||
|
||||
assertNull(method.getOptions(), "Unexpected options");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,9 +17,12 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.MfaConstraintAny;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.MfaMethodId;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.MfaRequirement;
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
@ -45,29 +48,52 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
|
||||
private static final String AUTH_ENTITY_ID = "";
|
||||
private static final String AUTH_TOKEN_TYPE = "service";
|
||||
private static final Boolean AUTH_ORPHAN = false;
|
||||
private static final Integer AUTH_NUM_USES = 42;
|
||||
private static final String MFA_REQUEST_ID = "d0c9eec7-6921-8cc0-be62-202b289ef163";
|
||||
private static final String MFA_KEY = "enforcementConfigUserpass";
|
||||
private static final String MFA_METHOD_TYPE = "totp";
|
||||
private static final String MFA_METHOD_ID = "820997b3-110e-c251-7e8b-ff4aa428a6e1";
|
||||
private static final Boolean MFA_METHOD_USES_PASSCODE = true;
|
||||
private static final String MFA_METHOD_NAME = "sample_mfa_method_name";
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"auth\": {\n" +
|
||||
" \"accessor\": \"" + AUTH_ACCESSOR + "\",\n" +
|
||||
" \"client_token\": \"" + AUTH_CLIENT_TOKEN + "\",\n" +
|
||||
" \"policies\": [\n" +
|
||||
" \"" + AUTH_POLICY_1 + "\", \n" +
|
||||
" \"" + AUTH_POLICY_2 + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"token_policies\": [\n" +
|
||||
" \"" + AUTH_POLICY_2 + "\",\n" +
|
||||
" \"" + AUTH_POLICY_1 + "\" \n" +
|
||||
" ],\n" +
|
||||
" \"metadata\": {\n" +
|
||||
" \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" +
|
||||
" },\n" +
|
||||
" \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" +
|
||||
" \"renewable\": " + AUTH_RENEWABLE + ",\n" +
|
||||
" \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" +
|
||||
" \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" +
|
||||
" \"orphan\": " + AUTH_ORPHAN + "\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
" \"auth\": {\n" +
|
||||
" \"accessor\": \"" + AUTH_ACCESSOR + "\",\n" +
|
||||
" \"client_token\": \"" + AUTH_CLIENT_TOKEN + "\",\n" +
|
||||
" \"policies\": [\n" +
|
||||
" \"" + AUTH_POLICY_1 + "\", \n" +
|
||||
" \"" + AUTH_POLICY_2 + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"token_policies\": [\n" +
|
||||
" \"" + AUTH_POLICY_2 + "\",\n" +
|
||||
" \"" + AUTH_POLICY_1 + "\" \n" +
|
||||
" ],\n" +
|
||||
" \"metadata\": {\n" +
|
||||
" \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" +
|
||||
" },\n" +
|
||||
" \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" +
|
||||
" \"renewable\": " + AUTH_RENEWABLE + ",\n" +
|
||||
" \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" +
|
||||
" \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" +
|
||||
" \"orphan\": " + AUTH_ORPHAN + ",\n" +
|
||||
" \"num_uses\": " + AUTH_NUM_USES + ",\n" +
|
||||
" \"mfa_requirement\": {\n" +
|
||||
" \"mfa_request_id\": \"" + MFA_REQUEST_ID + "\",\n" +
|
||||
" \"mfa_constraints\": {\n" +
|
||||
" \"" + MFA_KEY + "\": {\n" +
|
||||
" \"any\": [\n" +
|
||||
" {\n" +
|
||||
" \"type\": \"" + MFA_METHOD_TYPE + "\",\n" +
|
||||
" \"id\": \"" + MFA_METHOD_ID + "\",\n" +
|
||||
" \"uses_passcode\": " + MFA_METHOD_USES_PASSCODE + ",\n" +
|
||||
" \"name\": \"" + MFA_METHOD_NAME + "\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
AuthResponseTest() {
|
||||
super(AuthResponse.class);
|
||||
@ -76,20 +102,27 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
|
||||
@Override
|
||||
protected AuthResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_JSON, AuthResponse.class);
|
||||
return objectMapper.readValue(RES_JSON, AuthResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqualsHashcodeMfa() {
|
||||
EqualsVerifier.simple().forClass(MfaRequirement.class).verify();
|
||||
EqualsVerifier.simple().forClass(MfaConstraintAny.class).verify();
|
||||
EqualsVerifier.simple().forClass(MfaMethodId.class).verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||
*/
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
AuthResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AuthResponse.class),
|
||||
() -> objectMapper.readValue(RES_JSON, AuthResponse.class),
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
@ -103,10 +136,20 @@ class AuthResponseTest extends AbstractModelTest<AuthResponse> {
|
||||
assertEquals(AUTH_ORPHAN, data.isOrphan(), "Incorrect auth orphan flag");
|
||||
assertEquals(AUTH_TOKEN_TYPE, data.getTokenType(), "Incorrect auth token type");
|
||||
assertEquals(AUTH_ENTITY_ID, data.getEntityId(), "Incorrect auth entity id");
|
||||
assertEquals(AUTH_NUM_USES, data.getNumUses(), "Incorrect auth num uses");
|
||||
assertEquals(2, data.getPolicies().size(), "Incorrect number of policies");
|
||||
assertTrue(data.getPolicies().containsAll(Set.of(AUTH_POLICY_1, AUTH_POLICY_2)));
|
||||
assertEquals(2, data.getTokenPolicies().size(), "Incorrect number of token policies");
|
||||
assertTrue(data.getTokenPolicies().containsAll(Set.of(AUTH_POLICY_2, AUTH_POLICY_1)), "Incorrect token policies");
|
||||
assertEquals(Map.of(AUTH_META_KEY, AUTH_META_VALUE), data.getMetadata(), "Incorrect auth metadata");
|
||||
|
||||
assertEquals(MFA_REQUEST_ID, data.getMfaRequirement().getMfaRequestId(), "Incorrect MFA request ID");
|
||||
assertEquals(Set.of(MFA_KEY), data.getMfaRequirement().getMfaConstraints().keySet(), "Incorrect MFA constraint keys");
|
||||
var mfaConstraint = data.getMfaRequirement().getMfaConstraints().get(MFA_KEY);
|
||||
assertEquals(1, mfaConstraint.getAny().size(), "Incorrect number of any constraints");
|
||||
assertEquals(MFA_METHOD_TYPE, mfaConstraint.getAny().get(0).getType(), "Incorrect MFA method type");
|
||||
assertEquals(MFA_METHOD_ID, mfaConstraint.getAny().get(0).getId(), "Incorrect MFA method type");
|
||||
assertEquals(MFA_METHOD_USES_PASSCODE, mfaConstraint.getAny().get(0).getUsesPasscode(), "Incorrect MFA method uses passcode");
|
||||
assertEquals(MFA_METHOD_NAME, mfaConstraint.getAny().get(0).getName(), "Incorrect MFA method uses passcode");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,8 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -52,7 +50,7 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
|
||||
@Override
|
||||
protected CredentialsResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(JSON, CredentialsResponse.class);
|
||||
return objectMapper.readValue(JSON, CredentialsResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -61,18 +59,16 @@ class CredentialsResponseTest extends AbstractModelTest<CredentialsResponse> {
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*
|
||||
* @throws InvalidResponseException Should not occur
|
||||
*/
|
||||
@Test
|
||||
void getCredentialsTest() throws InvalidResponseException {
|
||||
void getCredentialsTest() {
|
||||
// Create empty Object.
|
||||
CredentialsResponse res = new CredentialsResponse();
|
||||
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");
|
||||
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(JSON, CredentialsResponse.class),
|
||||
() -> objectMapper.readValue(JSON, CredentialsResponse.class),
|
||||
"Deserialization of CredentialsResponse failed"
|
||||
);
|
||||
assertEquals(VAL_USER, res.getUsername(), "Incorrect username");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -44,7 +43,7 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
|
||||
@Override
|
||||
protected ErrorResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(JSON, ErrorResponse.class);
|
||||
return objectMapper.readValue(JSON, ErrorResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -56,16 +55,15 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
|
||||
*/
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
ErrorResponse res = assertDoesNotThrow(
|
||||
() -> om.readValue(JSON, ErrorResponse.class),
|
||||
() -> 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(() -> om.writeValueAsString(res), "ErrorResponse serialization failed"),
|
||||
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "ErrorResponse serialization failed"),
|
||||
"Unexpected JSON string after serialization"
|
||||
);
|
||||
}
|
||||
@ -74,13 +72,13 @@ class ErrorResponseTest extends AbstractModelTest<ErrorResponse> {
|
||||
@Test
|
||||
void testToString() {
|
||||
ErrorResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(JSON, ErrorResponse.class),
|
||||
() -> objectMapper.readValue(JSON, ErrorResponse.class),
|
||||
"ErrorResponse deserialization failed"
|
||||
);
|
||||
assertEquals(ERROR_1, res.toString());
|
||||
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(JSON_EMPTY, ErrorResponse.class),
|
||||
() -> objectMapper.readValue(JSON_EMPTY, ErrorResponse.class),
|
||||
"ErrorResponse deserialization failed with empty list"
|
||||
);
|
||||
assertEquals("error response", res.toString());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -32,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228";
|
||||
private static final String CLUSTER_NAME = "vault-cluster-5515c810";
|
||||
private static final String VERSION = "0.9.2";
|
||||
private static final String VERSION = "0.17.0";
|
||||
private static final Long SERVER_TIME_UTC = 1469555798L;
|
||||
private static final Boolean STANDBY = false;
|
||||
private static final Boolean SEALED = false;
|
||||
@ -40,6 +39,10 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
private static final Boolean PERF_STANDBY = false;
|
||||
private static final String REPL_PERF_MODE = "disabled";
|
||||
private static final String REPL_DR_MODE = "disabled";
|
||||
private static final Long ECHO_DURATION = 1L;
|
||||
private static final Long CLOCK_SKEW = 0L;
|
||||
private static final Long REPL_PRIM_CANARY_AGE = 2L;
|
||||
private static final Boolean ENTERPRISE = false;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||
@ -51,7 +54,11 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
" \"initialized\": " + INITIALIZED + ",\n" +
|
||||
" \"replication_performance_mode\": \"" + REPL_PERF_MODE + "\",\n" +
|
||||
" \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" +
|
||||
" \"performance_standby\": " + PERF_STANDBY + "\n" +
|
||||
" \"performance_standby\": " + PERF_STANDBY + ",\n" +
|
||||
" \"echo_duration_ms\": " + ECHO_DURATION + ",\n" +
|
||||
" \"clock_skew_ms\": " + CLOCK_SKEW + ",\n" +
|
||||
" \"replication_primary_canary_age_ms\": " + REPL_PRIM_CANARY_AGE + ",\n" +
|
||||
" \"enterprise\": " + ENTERPRISE + "\n" +
|
||||
"}";
|
||||
|
||||
HealthResponseTest() {
|
||||
@ -61,7 +68,7 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
@Override
|
||||
protected HealthResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_JSON, HealthResponse.class);
|
||||
return objectMapper.readValue(RES_JSON, HealthResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -74,7 +81,7 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
HealthResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, HealthResponse.class),
|
||||
() -> objectMapper.readValue(RES_JSON, HealthResponse.class),
|
||||
"Health deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
@ -88,5 +95,9 @@ class HealthResponseTest extends AbstractModelTest<HealthResponse> {
|
||||
assertEquals(PERF_STANDBY, res.isPerformanceStandby(), "Incorrect performance standby state");
|
||||
assertEquals(REPL_PERF_MODE, res.getReplicationPerfMode(), "Incorrect replication perf mode");
|
||||
assertEquals(REPL_DR_MODE, res.getReplicationDrMode(), "Incorrect replication DR mode");
|
||||
assertEquals(ECHO_DURATION, res.getEchoDurationMs(), "Incorrect echo duration");
|
||||
assertEquals(CLOCK_SKEW, res.getClockSkewMs(), "Incorrect clock skew");
|
||||
assertEquals(REPL_PRIM_CANARY_AGE, res.getReplicationPrimaryCanaryAgeMs(), "Incorrect canary age");
|
||||
assertEquals(ENTERPRISE, res.isEnterprise(), "Incorrect enterprise flag");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -40,7 +39,7 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
|
||||
@Override
|
||||
protected HelpResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(JSON, HelpResponse.class);
|
||||
return objectMapper.readValue(JSON, HelpResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -52,16 +51,15 @@ class HelpResponseTest extends AbstractModelTest<HelpResponse> {
|
||||
*/
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
HelpResponse res = assertDoesNotThrow(
|
||||
() -> om.readValue(JSON, HelpResponse.class),
|
||||
() -> objectMapper.readValue(JSON, HelpResponse.class),
|
||||
"HelpResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(HELP, res.getHelp(), "Unexpected help text");
|
||||
assertEquals(
|
||||
JSON,
|
||||
assertDoesNotThrow(() -> om.writeValueAsString(res), "HelpResponse serialization failed"),
|
||||
assertDoesNotThrow(() -> objectMapper.writeValueAsString(res), "HelpResponse serialization failed"),
|
||||
"Unexpected JSON string after serialization"
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,11 +17,11 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@ -43,6 +43,9 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
|
||||
private static final String SECRET_META_CREATED = "2018-03-22T02:24:06.945319214Z";
|
||||
private static final String SECRET_META_DELETED = "2018-03-23T03:25:07.056420325Z";
|
||||
private static final List<String> SECRET_WARNINGS = null;
|
||||
private static final String CUSTOM_META_KEY = "foo";
|
||||
private static final String CUSTOM_META_VAL = "bar";
|
||||
|
||||
private static final String SECRET_JSON_V2 = "{\n" +
|
||||
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
||||
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
|
||||
@ -55,6 +58,7 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
|
||||
" },\n" +
|
||||
" \"metadata\": {\n" +
|
||||
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
|
||||
" \"custom_metadata\": null,\n" +
|
||||
" \"deletion_time\": \"\",\n" +
|
||||
" \"destroyed\": false,\n" +
|
||||
" \"version\": 1\n" +
|
||||
@ -74,6 +78,9 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
|
||||
" },\n" +
|
||||
" \"metadata\": {\n" +
|
||||
" \"created_time\": \"" + SECRET_META_CREATED + "\",\n" +
|
||||
" \"custom_metadata\": {" +
|
||||
" \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" +
|
||||
" },\n" +
|
||||
" \"deletion_time\": \"" + SECRET_META_DELETED + "\",\n" +
|
||||
" \"destroyed\": true,\n" +
|
||||
" \"version\": 2\n" +
|
||||
@ -89,7 +96,7 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
|
||||
@Override
|
||||
protected MetaSecretResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(SECRET_JSON_V2, MetaSecretResponse.class);
|
||||
return objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -103,31 +110,29 @@ class MetaSecretResponseTest extends AbstractModelTest<MetaSecretResponse> {
|
||||
void jsonRoundtrip() {
|
||||
// KV v2 secret.
|
||||
MetaSecretResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON_V2, MetaSecretResponse.class),
|
||||
() -> objectMapper.readValue(SECRET_JSON_V2, MetaSecretResponse.class),
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
assertSecretData(res);
|
||||
assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata");
|
||||
assertEquals(SECRET_META_CREATED, res.getMetadata().getCreatedTimeString(), "Incorrect creation date string");
|
||||
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
|
||||
assertEquals("", res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
|
||||
assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
|
||||
assertFalse(res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
|
||||
assertEquals(1, res.getMetadata().getVersion(), "Incorrect secret version");
|
||||
assertNull(res.getMetadata().getCustomMetadata(), "Incorrect custom metadata");
|
||||
|
||||
// Deleted KV v2 secret.
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON_V2_2, MetaSecretResponse.class),
|
||||
() -> objectMapper.readValue(SECRET_JSON_V2_2, MetaSecretResponse.class),
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
assertSecretData(res);
|
||||
assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata");
|
||||
assertEquals(SECRET_META_CREATED, res.getMetadata().getCreatedTimeString(), "Incorrect creation date string");
|
||||
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
|
||||
assertEquals(SECRET_META_DELETED, res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
|
||||
assertNotNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
|
||||
assertTrue(res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
|
||||
assertEquals(2, res.getMetadata().getVersion(), "Incorrect secret version");
|
||||
assertEquals(Map.of(CUSTOM_META_KEY, CUSTOM_META_VAL), res.getMetadata().getCustomMetadata(), "Incorrect custom metadata");
|
||||
}
|
||||
|
||||
private void assertSecretData(SecretResponse res) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,10 +17,11 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -36,11 +37,20 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
|
||||
private static final Integer CURRENT_VERSION = 3;
|
||||
private static final Integer MAX_VERSIONS = 0;
|
||||
private static final Integer OLDEST_VERSION = 1;
|
||||
private static final Boolean CAS_REQUIRED = false;
|
||||
private static final String CUSTOM_META_KEY = "test";
|
||||
private static final String CUSTOM_META_VAL = "123";
|
||||
private static final String DELETE_VERSION_AFTER = "0s";
|
||||
|
||||
private static final String META_JSON = "{\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"cas_required\": " + CAS_REQUIRED + ",\n" +
|
||||
" \"created_time\": \"" + V1_TIME + "\",\n" +
|
||||
" \"current_version\": " + CURRENT_VERSION + ",\n" +
|
||||
" \"custom_metadata\": {" +
|
||||
" \"" + CUSTOM_META_KEY + "\": \"" + CUSTOM_META_VAL + "\"" +
|
||||
" },\n" +
|
||||
" \"delete_version_after\": \"" + DELETE_VERSION_AFTER + "\"," +
|
||||
" \"max_versions\": " + MAX_VERSIONS + ",\n" +
|
||||
" \"oldest_version\": " + OLDEST_VERSION + ",\n" +
|
||||
" \"updated_time\": \"" + V3_TIME + "\",\n" +
|
||||
@ -71,7 +81,7 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
|
||||
@Override
|
||||
protected MetadataResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(META_JSON, MetadataResponse.class);
|
||||
return objectMapper.readValue(META_JSON, MetadataResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -84,23 +94,22 @@ class MetadataResponseTest extends AbstractModelTest<MetadataResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
MetadataResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(META_JSON, MetadataResponse.class),
|
||||
() -> objectMapper.readValue(META_JSON, MetadataResponse.class),
|
||||
"MetadataResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertNotNull(res.getMetadata(), "Parsed metadata is NULL");
|
||||
assertEquals(V1_TIME, res.getMetadata().getCreatedTimeString(), "Incorrect created time");
|
||||
assertEquals(CAS_REQUIRED, res.getMetadata().isCasRequired(), "Incorrect CAS required flag");
|
||||
assertNotNull(res.getMetadata().getCreatedTime(), "Parting created time failed");
|
||||
assertEquals(CURRENT_VERSION, res.getMetadata().getCurrentVersion(), "Incorrect current version");
|
||||
assertEquals(MAX_VERSIONS, res.getMetadata().getMaxVersions(), "Incorrect max versions");
|
||||
assertEquals(OLDEST_VERSION, res.getMetadata().getOldestVersion(), "Incorrect oldest version");
|
||||
assertEquals(V3_TIME, res.getMetadata().getUpdatedTimeString(), "Incorrect updated time");
|
||||
assertEquals(Map.of(CUSTOM_META_KEY, CUSTOM_META_VAL), res.getMetadata().getCustomMetadata(), "Incorrect custom metadata");
|
||||
assertEquals(DELETE_VERSION_AFTER, res.getMetadata().getDeleteVersionAfter(), "Incorrect delete version after");
|
||||
assertNotNull(res.getMetadata().getUpdatedTime(), "Parting updated time failed");
|
||||
assertEquals(3, res.getMetadata().getVersions().size(), "Incorrect number of versions");
|
||||
assertEquals(V2_TIME, res.getMetadata().getVersions().get(1).getDeletionTimeString(), "Incorrect version 1 delete time");
|
||||
assertNotNull(res.getMetadata().getVersions().get(1).getDeletionTime(), "Parsing version delete time failed");
|
||||
assertTrue(res.getMetadata().getVersions().get(1).isDestroyed(), "Incorrect version 1 destroyed state");
|
||||
assertEquals(V2_TIME, res.getMetadata().getVersions().get(2).getCreatedTimeString(), "Incorrect version 2 created time");
|
||||
assertNotNull(res.getMetadata().getVersions().get(2).getCreatedTime(), "Parsing version created failed");
|
||||
assertFalse(res.getMetadata().getVersions().get(3).isDestroyed(), "Incorrect version 3 destroyed state");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,12 +16,13 @@
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@ -60,7 +61,7 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
|
||||
@Override
|
||||
protected PlainSecretResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(SECRET_JSON, PlainSecretResponse.class);
|
||||
return objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -73,7 +74,7 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
SecretResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON, PlainSecretResponse.class),
|
||||
() -> objectMapper.readValue(SECRET_JSON, PlainSecretResponse.class),
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
|
||||
@ -86,4 +87,137 @@ class PlainSecretResponseTest extends AbstractModelTest<PlainSecretResponse> {
|
||||
assertEquals(SECRET_DATA_V1, res.get(SECRET_DATA_K1), "Response does not contain correct data");
|
||||
assertEquals(SECRET_DATA_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,10 +17,11 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -35,7 +36,8 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
private static final Integer SHARES = 5;
|
||||
private static final Integer PROGRESS_SEALED = 2;
|
||||
private static final Integer PROGRESS_UNSEALED = 0;
|
||||
private static final String VERSION = "1.8.2";
|
||||
private static final String VERSION = "1.15.4";
|
||||
private static final String BUILD_DATE = "2023-11-22T20:59:54Z";
|
||||
private static final String CLUSTER_NAME = "vault-cluster-d6ec3c7f";
|
||||
private static final String CLUSTER_ID = "3e8b3fec-3749-e056-ba41-b62a63b997e8";
|
||||
private static final String NONCE = "ef05d55d-4d2c-c594-a5e8-55bc88604c24";
|
||||
@ -52,6 +54,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
" \"progress\": " + PROGRESS_SEALED + ",\n" +
|
||||
" \"nonce\": \"\",\n" +
|
||||
" \"version\": \"" + VERSION + "\",\n" +
|
||||
" \"build_date\": \"" + BUILD_DATE + "\",\n" +
|
||||
" \"migration\": \"" + MIGRATION + "\",\n" +
|
||||
" \"recovery_seal\": \"" + RECOVERY_SEAL + "\",\n" +
|
||||
" \"storage_type\": \"" + STORAGE_TYPE + "\"\n" +
|
||||
@ -65,6 +68,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
" \"n\": " + SHARES + ",\n" +
|
||||
" \"progress\": " + PROGRESS_UNSEALED + ",\n" +
|
||||
" \"version\": \"" + VERSION + "\",\n" +
|
||||
" \"build_date\": \"" + BUILD_DATE + "\",\n" +
|
||||
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
|
||||
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||
" \"nonce\": \"" + NONCE + "\",\n" +
|
||||
@ -80,7 +84,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
@Override
|
||||
protected SealResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class);
|
||||
return objectMapper.readValue(RES_UNSEALED, SealResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -94,7 +98,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
void jsonRoundtripSealed() {
|
||||
// First test sealed Vault's response.
|
||||
SealResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_SEALED, SealResponse.class),
|
||||
() -> objectMapper.readValue(RES_SEALED, SealResponse.class),
|
||||
"SealResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
@ -106,6 +110,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
assertEquals(PROGRESS_SEALED, res.getProgress(), "Incorrect progress");
|
||||
assertEquals("", res.getNonce(), "Nonce not empty");
|
||||
assertEquals(VERSION, res.getVersion(), "Incorrect version");
|
||||
assertEquals(ZonedDateTime.parse(BUILD_DATE), res.getBuildDate(), "Incorrect build date");
|
||||
assertEquals(MIGRATION, res.getMigration(), "Incorrect migration");
|
||||
assertEquals(RECOVERY_SEAL, res.getRecoverySeal(), "Incorrect recovery seal");
|
||||
assertEquals(STORAGE_TYPE, res.getStorageType(), "Incorrect storage type");
|
||||
@ -116,7 +121,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
|
||||
// Not test unsealed Vault's response.
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class),
|
||||
() -> objectMapper.readValue(RES_UNSEALED, SealResponse.class),
|
||||
"SealResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
@ -128,6 +133,7 @@ class SealResponseTest extends AbstractModelTest<SealResponse> {
|
||||
assertEquals(PROGRESS_UNSEALED, res.getProgress(), "Incorrect progress");
|
||||
assertEquals(NONCE, res.getNonce(), "Incorrect nonce");
|
||||
assertEquals(VERSION, res.getVersion(), "Incorrect version");
|
||||
assertEquals(ZonedDateTime.parse(BUILD_DATE), res.getBuildDate(), "Incorrect build date");
|
||||
assertEquals(CLUSTER_NAME, res.getClusterName(), "Incorrect cluster name");
|
||||
assertEquals(CLUSTER_ID, res.getClusterId(), "Incorrect cluster ID");
|
||||
assertEquals(MIGRATION, res.getMigration(), "Incorrect migration");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -54,7 +53,7 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
|
||||
@Override
|
||||
protected SecretListResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(JSON, SecretListResponse.class);
|
||||
return objectMapper.readValue(JSON, SecretListResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -67,7 +66,7 @@ class SecretListResponseTest extends AbstractModelTest<SecretListResponse> {
|
||||
@Test
|
||||
void getKeysTest() {
|
||||
SecretListResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(JSON, SecretListResponse.class),
|
||||
() -> objectMapper.readValue(JSON, SecretListResponse.class),
|
||||
"SecretListResponse deserialization failed"
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -50,7 +49,7 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
|
||||
@Override
|
||||
protected SecretVersionResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class);
|
||||
return objectMapper.readValue(META_JSON, SecretVersionResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -63,13 +62,11 @@ class SecretVersionResponseTest extends AbstractModelTest<SecretVersionResponse>
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
SecretVersionResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class),
|
||||
() -> objectMapper.readValue(META_JSON, SecretVersionResponse.class),
|
||||
"SecretVersionResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertNotNull(res.getMetadata(), "Parsed metadata is NULL");
|
||||
assertEquals(CREATION_TIME, res.getMetadata().getCreatedTimeString(), "Incorrect created time");
|
||||
assertEquals(DELETION_TIME, res.getMetadata().getDeletionTimeString(), "Incorrect deletion time");
|
||||
assertFalse(res.getMetadata().isDestroyed(), "Incorrect destroyed state");
|
||||
assertEquals(VERSION, res.getMetadata().getVersion(), "Incorrect version");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -56,6 +55,7 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
|
||||
private static final String TOKEN_ID = "my-token";
|
||||
private static final String TOKEN_ISSUE_TIME = "2018-04-17T11:35:54.466476078-04:00";
|
||||
private static final String TOKEN_TYPE = "service";
|
||||
private static final String MOUNT_TYPE = "token";
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"lease_id\": \"\",\n" +
|
||||
@ -86,7 +86,8 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
|
||||
" \"type\": \"" + TOKEN_TYPE + "\"\n" +
|
||||
" },\n" +
|
||||
" \"warnings\": null,\n" +
|
||||
" \"auth\": null\n" +
|
||||
" \"auth\": null,\n" +
|
||||
" \"mount_type\": \"" + MOUNT_TYPE + "\"\n" +
|
||||
"}";
|
||||
|
||||
TokenResponseTest() {
|
||||
@ -96,7 +97,7 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
|
||||
@Override
|
||||
protected TokenResponse createFull() {
|
||||
try {
|
||||
return new ObjectMapper().readValue(RES_JSON, TokenResponse.class);
|
||||
return objectMapper.readValue(RES_JSON, TokenResponse.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
@ -119,13 +120,14 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
TokenResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, TokenResponse.class),
|
||||
() -> objectMapper.readValue(RES_JSON, TokenResponse.class),
|
||||
"TokenResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(RES_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration");
|
||||
assertEquals(RES_RENEWABLE, res.isRenewable(), "Incorrect response renewable flag");
|
||||
assertEquals(RES_LEASE_DURATION, res.getLeaseDuration(), "Incorrect response lease duration");
|
||||
assertEquals(MOUNT_TYPE, res.getMountType(), "Incorrect mount type");
|
||||
// Extract token data.
|
||||
TokenData data = res.getData();
|
||||
assertNotNull(data, "Token data is NULL");
|
||||
@ -134,11 +136,9 @@ class TokenResponseTest extends AbstractModelTest<TokenResponse> {
|
||||
assertEquals(TOKEN_TTL, data.getCreationTtl(), "Incorrect token creation TTL");
|
||||
assertEquals(TOKEN_DISPLAY_NAME, data.getName(), "Incorrect token display name");
|
||||
assertEquals(TOKEN_ENTITY_ID, data.getEntityId(), "Incorrect token entity ID");
|
||||
assertEquals(TOKEN_EXPIRE_TIME, data.getExpireTimeString(), "Incorrect token expire time");
|
||||
assertEquals(ZonedDateTime.parse(TOKEN_EXPIRE_TIME), data.getExpireTime(), "Incorrect parsed token expire time");
|
||||
assertEquals(TOKEN_EXPLICIT_MAX_TTL, data.getExplicitMaxTtl(), "Incorrect token explicit max TTL");
|
||||
assertEquals(TOKEN_ID, data.getId(), "Incorrect token ID");
|
||||
assertEquals(TOKEN_ISSUE_TIME, data.getIssueTimeString(), "Incorrect token issue time");
|
||||
assertEquals(ZonedDateTime.parse(TOKEN_ISSUE_TIME), data.getIssueTime(), "Incorrect parsed token issue time");
|
||||
assertEquals(Map.of(TOKEN_META_KEY, TOKEN_META_VALUE), data.getMeta(), "Incorrect token metadata");
|
||||
assertEquals(TOKEN_NUM_USES, data.getNumUses(), "Incorrect token number of uses");
|
||||
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.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 TransitResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class TransitResponseTest extends AbstractModelTest<TransitResponse> {
|
||||
private static final String CIPHERTEXT = "vault:v1:XjsPWPjqPrBi1N2Ms2s1QM798YyFWnO4TR4lsFA=";
|
||||
private static final String PLAINTEXT = "dGhlIHF1aWNrIGJyb3duIGZveAo=";
|
||||
private static final String SUM = "dGhlIHF1aWNrIGJyb3duIGZveAo=";
|
||||
|
||||
TransitResponseTest() {
|
||||
super(TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransitResponse createFull() {
|
||||
try {
|
||||
return objectMapper.readValue(
|
||||
json(
|
||||
"\"ciphertext\": \"" + CIPHERTEXT + "\", " +
|
||||
"\"plaintext\": \"" + PLAINTEXT + "\", " +
|
||||
"\"sum\": \"" + SUM + "\""
|
||||
),
|
||||
TransitResponse.class
|
||||
);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void encryptionTest() {
|
||||
TransitResponse res = assertDoesNotThrow(
|
||||
() -> objectMapper.readValue(
|
||||
json("\"ciphertext\": \"" + CIPHERTEXT + "\""),
|
||||
TransitResponse.class
|
||||
),
|
||||
"TransitResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals("987c6daf-b0e2-4142-a970-1e61fdb249d7", res.getRequestId(), "Incorrect request id");
|
||||
assertEquals("", res.getLeaseId(), "Unexpected lease id");
|
||||
assertFalse(res.isRenewable(), "Unexpected renewable flag");
|
||||
assertEquals(0, res.getLeaseDuration(), "Unexpected lease duration");
|
||||
assertEquals(CIPHERTEXT, res.getCiphertext(), "Incorrect ciphertext");
|
||||
assertNull(res.getPlaintext(), "Unexpected plaintext");
|
||||
assertNull(res.getSum(), "Unexpected sum");
|
||||
assertNull(res.getWrapInfo(), "Unexpected wrap info");
|
||||
assertNull(res.getWarnings(), "Unexpected warnings");
|
||||
assertNull(res.getAuth(), "Unexpected auth");
|
||||
}
|
||||
|
||||
@Test
|
||||
void decryptionTest() {
|
||||
TransitResponse res = assertDoesNotThrow(
|
||||
() -> objectMapper.readValue(
|
||||
json("\"plaintext\": \"" + PLAINTEXT + "\""),
|
||||
TransitResponse.class
|
||||
),
|
||||
"TransitResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals("987c6daf-b0e2-4142-a970-1e61fdb249d7", res.getRequestId(), "Incorrect request id");
|
||||
assertEquals("", res.getLeaseId(), "Unexpected lease id");
|
||||
assertFalse(res.isRenewable(), "Unexpected renewable flag");
|
||||
assertEquals(0, res.getLeaseDuration(), "Unexpected lease duration");
|
||||
assertNull(res.getCiphertext(), "Unexpected ciphertext");
|
||||
assertEquals(PLAINTEXT, res.getPlaintext(), "Incorrect plaintext");
|
||||
assertNull(res.getSum(), "Unexpected sum");
|
||||
assertNull(res.getWrapInfo(), "Unexpected wrap info");
|
||||
assertNull(res.getWarnings(), "Unexpected warnings");
|
||||
assertNull(res.getAuth(), "Unexpected auth");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashTest() {
|
||||
TransitResponse res = assertDoesNotThrow(
|
||||
() -> objectMapper.readValue(
|
||||
json("\"sum\": \"" + SUM + "\""),
|
||||
TransitResponse.class
|
||||
),
|
||||
"TransitResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals("987c6daf-b0e2-4142-a970-1e61fdb249d7", res.getRequestId(), "Incorrect request id");
|
||||
assertEquals("", res.getLeaseId(), "Unexpected lease id");
|
||||
assertFalse(res.isRenewable(), "Unexpected renewable flag");
|
||||
assertEquals(0, res.getLeaseDuration(), "Unexpected lease duration");
|
||||
assertNull(res.getCiphertext(), "Unexpected ciphertext");
|
||||
assertNull(res.getPlaintext(), "Unexpected plaintext");
|
||||
assertEquals(SUM, res.getSum(), "Incorrect sum");
|
||||
assertNull(res.getWrapInfo(), "Unexpected wrap info");
|
||||
assertNull(res.getWarnings(), "Unexpected warnings");
|
||||
assertNull(res.getAuth(), "Unexpected auth");
|
||||
}
|
||||
|
||||
private static String json(String data) {
|
||||
return "{\n" +
|
||||
" \"request_id\" : \"987c6daf-b0e2-4142-a970-1e61fdb249d7\",\n" +
|
||||
" \"lease_id\" : \"\",\n" +
|
||||
" \"renewable\" : false,\n" +
|
||||
" \"lease_duration\" : 0,\n" +
|
||||
" \"data\" : {\n" +
|
||||
" " + data + "\n" +
|
||||
" },\n" +
|
||||
" \"wrap_info\" : null,\n" +
|
||||
" \"warnings\" : null,\n" +
|
||||
" \"auth\" : null\n" +
|
||||
"}";
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import de.stklcode.jvault.connector.model.AbstractModelTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit test for {@link MountConfig}.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
class MountConfigTest extends AbstractModelTest<MountConfig> {
|
||||
private static final Integer DEFAULT_LEASE_TTL = 1800;
|
||||
private static final Integer MAX_LEASE_TTL = 3600;
|
||||
private static final Boolean FORCE_NO_CACHE = false;
|
||||
private static final String TOKEN_TYPE = "default-service";
|
||||
private static final String AUDIT_NON_HMAC_REQ_KEYS_1 = "req1";
|
||||
private static final String AUDIT_NON_HMAC_REQ_KEYS_2 = "req2";
|
||||
private static final String AUDIT_NON_HMAC_RES_KEYS_1 = "res1";
|
||||
private static final String AUDIT_NON_HMAC_RES_KEYS_2 = "res2";
|
||||
private static final String LISTING_VISIBILITY = "unauth";
|
||||
private static final String PT_REQ_HEADER_1 = "prh1";
|
||||
private static final String PT_REQ_HEADER_2 = "prh2";
|
||||
private static final String ALLOWED_RES_HEADER_1 = "arh1";
|
||||
private static final String ALLOWED_RES_HEADER_2 = "arh2";
|
||||
private static final String ALLOWED_MANAGED_KEY_1 = "amk1";
|
||||
private static final String ALLOWED_MANAGED_KEY_2 = "amk2";
|
||||
private static final String DEL_AUTH_ACCESSOR_1 = "daa1";
|
||||
private static final String DEL_AUTH_ACCESSOR_2 = "daa2";
|
||||
private static final Integer LOCKOUT_THRESH = 7200;
|
||||
private static final Integer LOCKOUT_DURATION = 86400;
|
||||
private static final Integer LOCKOUT_CNT_RESET_DURATION = 43200;
|
||||
private static final Boolean LOCKOUT_DISABLE = false;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"default_lease_ttl\": " + DEFAULT_LEASE_TTL + ",\n" +
|
||||
" \"force_no_cache\": " + FORCE_NO_CACHE + ",\n" +
|
||||
" \"max_lease_ttl\": " + MAX_LEASE_TTL + ",\n" +
|
||||
" \"token_type\": \"" + TOKEN_TYPE + "\",\n" +
|
||||
" \"audit_non_hmac_request_keys\": [\"" + AUDIT_NON_HMAC_REQ_KEYS_1 + "\", \"" + AUDIT_NON_HMAC_REQ_KEYS_2 + "\"],\n" +
|
||||
" \"audit_non_hmac_response_keys\": [\"" + AUDIT_NON_HMAC_RES_KEYS_1 + "\", \"" + AUDIT_NON_HMAC_RES_KEYS_2 + "\"],\n" +
|
||||
" \"listing_visibility\": \"" + LISTING_VISIBILITY + "\",\n" +
|
||||
" \"passthrough_request_headers\": [\"" + PT_REQ_HEADER_1 + "\", \"" + PT_REQ_HEADER_2 + "\"],\n" +
|
||||
" \"allowed_response_headers\": [\"" + ALLOWED_RES_HEADER_1 + "\", \"" + ALLOWED_RES_HEADER_2 + "\"],\n" +
|
||||
" \"allowed_managed_keys\": [\"" + ALLOWED_MANAGED_KEY_1 + "\", \"" + ALLOWED_MANAGED_KEY_2 + "\"],\n" +
|
||||
" \"delegated_auth_accessors\": [\"" + DEL_AUTH_ACCESSOR_1 + "\", \"" + DEL_AUTH_ACCESSOR_2 + "\"],\n" +
|
||||
" \"user_lockout_config\": {\n" +
|
||||
" \"lockout_threshold\": " + LOCKOUT_THRESH + ",\n" +
|
||||
" \"lockout_duration\": " + LOCKOUT_DURATION + ",\n" +
|
||||
" \"lockout_counter_reset_duration\": " + LOCKOUT_CNT_RESET_DURATION + ",\n" +
|
||||
" \"lockout_disable\": " + LOCKOUT_DISABLE + "\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
MountConfigTest() {
|
||||
super(MountConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MountConfig createFull() {
|
||||
try {
|
||||
return objectMapper.readValue(RES_JSON, MountConfig.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
fail("Creation of full model instance failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||
*/
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
MountConfig mountConfig = assertDoesNotThrow(
|
||||
() -> objectMapper.readValue(RES_JSON, MountConfig.class),
|
||||
"MountConfig deserialization failed"
|
||||
);
|
||||
assertNotNull(mountConfig, "Parsed response is NULL");
|
||||
|
||||
// Verify data.
|
||||
assertEquals(DEFAULT_LEASE_TTL, mountConfig.getDefaultLeaseTtl(), "Unexpected default lease TTL");
|
||||
assertEquals(MAX_LEASE_TTL, mountConfig.getMaxLeaseTtl(), "Unexpected max lease TTL");
|
||||
assertEquals(FORCE_NO_CACHE, mountConfig.getForceNoCache(), "Unexpected force no cache");
|
||||
assertEquals(TOKEN_TYPE, mountConfig.getTokenType(), "Unexpected token type");
|
||||
assertEquals(List.of(AUDIT_NON_HMAC_REQ_KEYS_1, AUDIT_NON_HMAC_REQ_KEYS_2), mountConfig.getAuditNonHmacRequestKeys(), "Unexpected audit no HMAC request keys");
|
||||
assertEquals(List.of(AUDIT_NON_HMAC_RES_KEYS_1, AUDIT_NON_HMAC_RES_KEYS_2), mountConfig.getAuditNonHmacResponseKeys(), "Unexpected audit no HMAC response keys");
|
||||
assertEquals(LISTING_VISIBILITY, mountConfig.getListingVisibility(), "Unexpected listing visibility");
|
||||
assertEquals(List.of(PT_REQ_HEADER_1, PT_REQ_HEADER_2), mountConfig.getPassthroughRequestHeaders(), "Unexpected passthrough request headers");
|
||||
assertEquals(List.of(ALLOWED_RES_HEADER_1, ALLOWED_RES_HEADER_2), mountConfig.getAllowedResponseHeaders(), "Unexpected allowed response headers");
|
||||
assertEquals(List.of(ALLOWED_MANAGED_KEY_1, ALLOWED_MANAGED_KEY_2), mountConfig.getAllowedManagedKeys(), "Unexpected allowed managed keys");
|
||||
assertEquals(List.of(DEL_AUTH_ACCESSOR_1, DEL_AUTH_ACCESSOR_2), mountConfig.getDelegatedAuthAccessors(), "Unexpected delegate auth accessors");
|
||||
assertNotNull(mountConfig.getUserLockoutConfig(), "Missing user lockout config");
|
||||
var ulc = mountConfig.getUserLockoutConfig();
|
||||
assertEquals(LOCKOUT_THRESH, ulc.getLockoutThreshold(), "Unexpected lockout threshold");
|
||||
assertEquals(LOCKOUT_DURATION, ulc.getLockoutDuration(), "Unexpected lockout duration");
|
||||
assertEquals(LOCKOUT_CNT_RESET_DURATION, ulc.getLockoutCounterResetDuration(), "Unexpected lockout counter reset duration");
|
||||
assertEquals(LOCKOUT_DISABLE, ulc.getLockoutDisable(), "Unexpected lockout disable");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2022 Stefan Kalscheuer
|
||||
* Copyright 2016-2025 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -103,4 +103,4 @@ public class VaultConfiguration {
|
||||
"}\n" +
|
||||
((disableMlock) ? "disable_mlock = true" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"Value":"AAAAAQIOTEuNxtf2ZfGu6k9+65GFonDBiaetJnyLYFk1qfWPrE/VqUunbxuTv/QyK4pgC/q14sqypdxPe4Ygp/5mxzzuY6JXB0VKiDMXe9R5BltTG7++rLmKH/j+G7nEh71LER1/qVktU6x8dmDmTbpTgl5xzAB5DIXLMMKjjWda/7qJ3ivNI0pEOQ3JyT27SkqjqM49Dp1JIgKnjIEVQORqKcsSP+aqIncMjIo2iGXOGlDYAesp5tZ4hln3VCwXaIlrU8z6Mmntgcg7NeK/O2WTl86K644dbJUh6frGFDujrjOh/Pgp9n9u0BI3E9K9GD1Z1S1wEb1MCqzT/e9oHG7I7D8ku8PH11wGWGH6BmYlESYUG/KRVqu0XOQEfroLHZQiLE00yHBdStW/UJ9y5pmGpu1aiQ88Q8fpjF5xmRey99b4c6KUIpHjw5Af0XA9ZKsEJUyjS/dbMKPM6PBOW21LYefXH5b0poXMWgLW6LJV0zLuVMyVZJqANbzCVtheDPSsEjkHHwR/CLa2zs2Z6wJF3j1GDZxUFf4nbnuXQzz3M3kVPPtS6htlb0d8RN0/dkOrqUue+c4UjnXhiacXyVUnQQzUVu0sGak4vrQi0020aBzMXM2ZG7rNgvw+wcYFS4txO90kwJL6aOMXT2BeJiQ3wjjHb7M74/sSd0ffRTUlJSODSDotO7Q7Dfcnc1FLrIhXPRFPavTjFoL5HRy77xuGG7U7jTMoGra+rK54v0sxqKbS5WZi1hADQmAVIO8bPb+jA1qoejRFygW6sLgAdmEFQQJOhCV/BoKP3A=="}
|
||||
{"Value":"AAAAAQJ7mykBIbHX5k81qdXEpvlLgRF1ZSlODETcB1JBZ7nj0Muskpvvl3jofN5XH1Td8ibJlrR0o5o/OUjZAz9t0Da+ZzCy4ga9G2SmgWkUAravTqfPO/ZxWh2hqTso2WPBXRM3/IeR0SAv/zh7m7JILxjKybJmnl9U6fkjPID/us0AscckZ9kgJ4g8jwaTzPfRp5U8jMebHYbABXZ65PeUOvNiDVcOvQDWPJrMxICz12xbeJ8mKs5MHpcNkLtPoRCQSpsh0YYTwkuF7NvpIciqIJ4/Yb7wYO+vp9AATbiIs3sSFBWxXEl0OAg/SAmOvaR27Y7/NHN//mg81jkMOHv62/Fxf11I8t1d63oyWFQhP0xR9eoq5hGNQ/30I2m1prhZtLRC2ieKASBDMxTzyNS5G5bsVXvhCsxn8tiC0Ma+ySOfxMQzBRfbx8rtoGmLFP+l/d6VMOPGFxmYqzLS5HvvpCryscCqLn7A8i6TMSrZiF7ZevyfEBpThqhJiYHzUxf07O5IAe6JBSGuNV9gLE+uJXaiYLedJwSfjRKwdQyzer730dU1IegW3KYTb/5hSW4eaETKkjc/alC536WlvAv+5FyckDBc3aVC+hHB7lKZG5YANkOUS3m5I8epemOmuKQ5pnXLOdDkQ14DyNCC79NwLltkp0d6sTNstQ44XAbs0HlLjs4EFwg5Hps9qHeXgTOXeAvwUerJgM20nKszlB+Oy+JzZm0xOK5xoJwy+z0/U3PtJ+7pwAipesIa2QEzqMt3EneuPuwEcv3bPUcowukq542sCEK0CuZjLqTUU9nNqiZan5f5pWuL0hYw4NFIkNfQyRlqgKpMaplDk/2fBqaV98yn0DWceEMWRY4NXpEMS+ysPDIeamX99auWqakb95AZ7tySpkRAkZYtq1nY5Nu0w7NyJrJZ1lhBHs2ZjW0tpXn2CL0MhMVArg=="}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Value":"AAAAAQIwsBgPcs7Hxl7UnB8OkTq9+5HERx4Fzn8jAzR8uIhoQZfpNG/15m2LEEsDJw1o+lxc6u+h7XcOB1QRqrKz8k7CFR15A+qsxD0UclHZdnk+MmMwXL9SSvYugp7XPiXmpG/uTZVf1QtigXQuehEEJeFfJVI7aFACu2AHEGVt+5b6yDQEgTUruo0seazRXuVU+J6NFCDU3ZvkR8e0al6OcMail59KamzjSCYiqDF4TeUuOQ6Zyr7zIG7gSaas1sog2JIlvrh+wkHW6I+OyD9SJSTinGEGRXl0tq15qoBJ4srfXdWODmKtExEupArbiDR5PyvSI3KlIHKIFduslJZKkJwiV3dBscdva4Rqb98FffMVYuM4G4s+VpvDDX+WVsqWF1ssoHRAFWCNAJGsenVDTxblzAF/4rGkJ7LC9yjLGsBtMOCkCZAKDQ3C9VFu+LGhbMRA5p2RKxNKWGem4Cyp5AqMmx62UzDAgMLGgm89A0g9s1/3FnCoLPdVmlWc6cg4QahN30qJCInJeAmH7T9NwIjv6/QxyJxyDVtdMtcfnMNxx15Q29lbyWTcbaI1iabHpc16iS/gwAPQeBTSbcvc4OxqwC5PDFThFq6bwZXaekYz4ghC13j9Ht79GVKH9cPZb5M="}
|
@ -0,0 +1 @@
|
||||
{"Value":"AAAAAQKfotDJ0SihB+f5i4PxZ6lq1kxtH4QMprGI7Hj8HimEwXsW0Gbj/1B7YM4DQt4t5JFD4gKwFVOwlJDyusaJj92ar0QLSreCWyJTKUadqZplMFyB/bAdK42QdH+ZS8Z9KHUNchbRpNhnvOFIahoDG8dZ+nbCIXblJONCaey4/ri3H+GQbk/jfre1VByh7zVIN0ISew5PzZRCTkbO1CvcQZhrRGoUGiPmLywKVbHEMsvimVuZY5py6OfL+70QmElBmN9O45bTgX9XPbfSmyQIcGrElO1foi0WwZLPsb/fZcAIgrhC768jOnzeimChoX4zc0DPxuyV1YPvsD1yAlsnsFuJW6CP7TGkszbJU+rwDpg0TgqKtvFr1Lgkxyfcxg0h++1BSiEgoJU7b2IgIWP7reJVjc1tbAsoR1tOBCSAAhvqWZVpn2oht5rfe9aN370bV3Jcu17hFWyhB+VhzbCCPRcofPXX3f2U2dcQ0X7bU4nMiq1v6NQP6u/D5GAPj4Jc0519tPW4KQrd9SNqR20ct6OvqxjMFWV4GZXVcsL4+3xup87Yib6EDb0+hhe6XEpC6isYgD3D5OTTOWphHlsglGkGFi9lUc+h8zNPM4FHwha6uVTLmaqaLGbLziwT9WXF1ATacwtNW0t3kZlFUBvMwSwWzoPqO1+jxs+id4ie/VI6ZTOeowi4ceK2eWJ1/t9MB/gjvadpgE+FYt5QG6dFav4ujQN5Ne/yY78PGF5tp0CT4koox0rMUuxyD1xOIXkm0NBpJm1y9/J06yqLpMKqS40/jGcSQaycRngXDb+6H9rj7mheiO4qxcFGqViqECCUjDG3PnLP/fy9py5kFq7mf0pq7L0Jq/lLWC+iKJF9UaZmCaz8DwlQ9zC03XOFqABPNe8gMFlb8zU09VKBbY+g5gukOonjcBeoFOTRqQxuaWwwwB2lj8XnZScOyIcVJGkH"}
|
@ -1 +0,0 @@
|
||||
{"Value":"AAAAAQINZKQEssY4IzHI/0k27nBtxSvnC6LkivYrqky6CblcjyAmQIg/4/cKQIBCXzmrWEv/SqMQbLw+4Lp63Xu1niF+U0NbyqDmFaPqnD2yfPs7meXvZr21+P9E/0APZMHQaSR7DIEY46zedHRjQ/pkhR2Axcjuy5gdfzBzC2XvUcNqdyR0pQwcDwGhAIdO0gxJfZCeBuvv8ceYS+aPs4gDHtIlA3szi+5qAQ8HvPBTDKQn1lHVYnzTdNbMS7v3mtzCyG8AeMkaUw=="}
|
@ -1 +0,0 @@
|
||||
{"Value":"AAAAAQJiN0bHxM8aNJpY7aHGZ/p3qOhJbd7JIXwFMEI4LtKmO6pP5Oa4P5z+2LK+2qzZhhX/iDeM4u+nR+lxt/GsBPKf"}
|
@ -1 +0,0 @@
|
||||
{"Value":"AAAAAQIZ5rvzLtBcBQvWqwwDoRADwUo6W0ECKgmcvXejbLKiYcbO0hP8fceCqB12J41wxcMViQ8vvWoIgyOX2HwcZS09GGCqQbjvyVfz/w+kyox9dJzr845f26tJjHVYlHX2YFsnxytwe5qCKdCsD5QP9kyz8J0="}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user