Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
fdda685f6f | |||
6e19e8514f | |||
1c31b7a5fe | |||
f918f85d20 | |||
7f153df136 | |||
7793b4fc77 | |||
7701f9f768 | |||
c60580481b | |||
1cd1b63f8d | |||
e81dd87fe1 | |||
f6037e31bb | |||
74092bba9a | |||
3c11fe912b | |||
71564e87e8 | |||
ce24de7347 | |||
f783286909 | |||
9ef709e3eb | |||
ce28b8eb60 | |||
587c6cde0a | |||
dab42816a7 | |||
9346619237 | |||
df466a4dd2 | |||
258a852f5c | |||
0f3ebc0bde | |||
ec4fbc5d3f | |||
4e2b8857e9 | |||
3485839553 | |||
36102326db | |||
60d94fc5bb | |||
8dfcf02a0a | |||
c45dbf014e | |||
f7d6f9384d |
10
.drone.yml
10
.drone.yml
@ -25,12 +25,12 @@ steps:
|
||||
- name: unit-integration-tests
|
||||
image: maven:3-jdk-11
|
||||
environment:
|
||||
VAULT_VERSION: 1.8.0
|
||||
VAULT_VERSION: 1.8.3
|
||||
commands:
|
||||
- curl -s -o vault_1.8.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.8.0/vault_1.8.0_linux_amd64.zip
|
||||
- curl -s https://releases.hashicorp.com/vault/1.8.0/vault_1.8.0_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||
- unzip vault_1.8.0_linux_amd64.zip
|
||||
- rm vault_1.8.0_linux_amd64.zip
|
||||
- curl -s -o vault_1.8.3_linux_amd64.zip https://releases.hashicorp.com/vault/1.8.3/vault_1.8.3_linux_amd64.zip
|
||||
- curl -s https://releases.hashicorp.com/vault/1.8.3/vault_1.8.3_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||
- unzip vault_1.8.3_linux_amd64.zip
|
||||
- rm vault_1.8.3_linux_amd64.zip
|
||||
- mv vault /bin/
|
||||
- mvn -B resources:testResources compiler:testCompile surefire:test
|
||||
when:
|
||||
|
49
.github/workflows/ci.yml
vendored
Normal file
49
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: CI
|
||||
on: [ push, pull_request ]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
jdk: [ 11, 17 ]
|
||||
vault: [ '1.8.3' ]
|
||||
include:
|
||||
- jdk: 11
|
||||
vault: '1.8.3'
|
||||
analysis: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
distribution: 'temurin'
|
||||
- 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
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')
|
||||
env:
|
||||
VAULT_VERSION: ${{ matrix.vault }}
|
||||
run: mvn -B -P coverage clean verify
|
||||
- name: Test (offline)
|
||||
if: github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/')
|
||||
run: mvn -B -P offline-tests -P coverage clean verify
|
||||
- name: Analysis
|
||||
if: matrix.analysis && github.event_name == 'push'
|
||||
run: >
|
||||
mvn -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 }}
|
47
.travis.yml
47
.travis.yml
@ -1,47 +0,0 @@
|
||||
language: java
|
||||
install: true
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "stklcode-github"
|
||||
token:
|
||||
secure: "sM9OfX5jW764pn9cb2LSXArnXucKMws+eGeg5NnZxHRcGYt4hpBKLSregBSsBNzUoWVj0zNzPCpnh+UQvgxQzUerOqwEdjTBpy3SNPaxSn7UpoSg+Wz3aUmL9ugmx01b51/wMG4UCHEwTZt2tpgTPVtw8K6uSO78e0dSICCBHDnRcdQwOjMEQHIJJ/qHVRwuy/MzLCAP3W1JPZlsphZg9QsFyhB4hW97dE90joZezfocQIv2xI/r6k+BLz0pY6MxYCul0RiDumaiaej0CPvEJI/uSu//BAQjUdHw+mQgnKUYIbrn2ONOviwNfwdr94JyoZEN2B6zASUmNLjPf4AbIojDeyS+CrpQpm17EVm/Qk/Ds+Xra4PPPIcsZhiWzV0KoDUz9xLfXuRJ526VT5tDPiaeI7oETf0+8l+JIS1b399FyqHi7smzjpvC6GuKflQrbuHK4MuKzDh7WTHiqokGG4SS0wOQIaaHB3dfdwwQzPh6IM24e8CETxh3DjMeqUTU4DWmv5po55jZ934TtxVQvVN78bTG9O0zS9u+JmRY04OZ+OaXuFam6MfMUFQi0EPZzdGul/oWSibGUu3bNfVEBp60CnJwYNM/dKG6U7pJthLHvSwiQFOdKzHZ+l1jZJ4gPaXaIGqpwqVGr28ntqA/El1rytPixr2driE6bYMt5jw="
|
||||
|
||||
env:
|
||||
- PATH=$PATH:. VAULT_VERSION=1.8.0 ANALYSIS=false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- '$HOME/.sonar/cache'
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- jdk: openjdk8
|
||||
- jdk: openjdk11
|
||||
env: PATH=$PATH:. VAULT_VERSION=1.8.0 ANALYSIS=true
|
||||
- jdk: openjdk16
|
||||
|
||||
before_script:
|
||||
- |
|
||||
if [[ "$TRAVIS_BRANCH" =~ ^main|(release\/.+)$ ]]; then
|
||||
wget -q https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
wget -q -O - https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c
|
||||
unzip vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
rm vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
fi
|
||||
|
||||
script:
|
||||
- mvn -B clean compile
|
||||
- |
|
||||
if [[ "$TRAVIS_BRANCH" =~ ^main|(release\/.+)$ ]]; then
|
||||
mvn -B resources:testResources compiler:testCompile surefire:test -P coverage
|
||||
else
|
||||
mvn -B resources:testResources compiler:testCompile surefire:test -P coverage -P offline-tests
|
||||
fi
|
||||
|
||||
after_success:
|
||||
- if [ "$ANALYSIS" == "true" ]; then mvn sonar:sonar; fi
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
secure: "YyE5GePOLkCVTtCy8j507BRmQrtrWhtvmUt4kY0Z2/ptf0LzfuDEJQ4ZbCxO5ri5IDJrrvyPAedjft818+bMzdFfxvi1oviIL+LZNhyev8gfeIBF/U2pvSLGKCRX4g4aZ6NKN3Untjdm8lmiVTltOyZ59JizQVwXzAl3LiOpnJugyBqbhOx4EIqBzwW3gaYAofMqY2LczW5W/M+99HJCst8Mb8H06GstCPEHCizAq7VRaUS68PstlxQMV0Q6bsSYMLFbLWmhuXs96WHqOrT+nNsl07ikr3N8c4HafhFutt2Jyc1+8gXO417+eSvVM0iBpHGwTmfGFfCqx/4Pf62DTJuvh8dR4fLgLDiqEeDrBEcRRDOs9cvXVOO22NN1HuBBJY8VRiFcwNAvuVMXCtnC+1RJRAZB2zubsANiFe+ygk/ywj37cVXY+NpqlBwcSph6jPHo2hD6cIl2rTWn1EnZH519Rh38xTSv6MRzAO9kWNVrAlX+UtvYS8Sk7Owrc0tET9Lc4zj6aI5tsA1wYbN3Jk6EbMhsF6K/XF2npt2qg09pxkj8wmxoUoR6/rGuSv55aSxTdLDmH+en4ahEm3uc4h1lYoVCk0yrZoTAas3zS4WpBCKnl+mweuKNxaejyy0Wv6NR9ZCTaS3yFgibNOjvDpxZxTAPdNBL7hn+k4LwgN4="
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,3 +1,25 @@
|
||||
## 1.0.0 (2021-10-02)
|
||||
|
||||
### Breaking
|
||||
* Requires Java 11 or later
|
||||
* Builder invocation has changed, use `HTTPVaultConnector.builder()....build()`
|
||||
|
||||
### Removal
|
||||
* Remove deprecated `VaultConnectorFactory` in favor of `VaultConnectorBuilder` with identical API
|
||||
* Remove deprecated `AppRoleBuilder` and `TokenBuilder` in favor of `AppRole.Builder` and `Token.Builder`
|
||||
* Remove deprecated `Period`, `Policy` and `Policies` methods from `AppRole` in favor of `Token`-prefixed versions
|
||||
* Remove deprecated `SecretResponse#getValue()` method, use `get("value")` instead
|
||||
* Remove deprecated convenience methods for interaction with "secret" mount
|
||||
|
||||
### Improvements
|
||||
* Use pre-sized map objects for fixed-size payloads
|
||||
* Remove Apache HTTP Client dependency in favor of Java 11 HTTP
|
||||
* Introduce Java module descriptor
|
||||
|
||||
### Test
|
||||
* Tested against Vault 1.8.3
|
||||
|
||||
|
||||
## 0.9.5 (2021-07-28)
|
||||
|
||||
### Deprecations
|
||||
|
112
CONTRIBUTING.md
Normal file
112
CONTRIBUTING.md
Normal file
@ -0,0 +1,112 @@
|
||||
# How to contribute
|
||||
|
||||
As for all great Open Source projects, contributions in form of bug reports and code are welcome and important to keep the project alive.
|
||||
|
||||
In general, this project follows the [GitHub Flow](https://guides.github.com/introduction/flow/).
|
||||
Fork the project, commit your changes to your branch, open a pull request and it will probably be merged.
|
||||
However, to ensure maintainability and quality of the code, there are some guidelines you might be more or less familiar with.
|
||||
For that purpose, this document describes the important points.
|
||||
|
||||
## Opening an Issue
|
||||
|
||||
If you experience any issues with the library or the code, don't hesitate to file an issue.
|
||||
|
||||
### Bug Reports
|
||||
|
||||
Think you found a bug?
|
||||
Please clearly state what happens and describe your environment to help tracking down the issue.
|
||||
|
||||
* Which version of the connector are you running?
|
||||
* Which version of Java (architecture and OS if relevant)?
|
||||
* Which version of Vault?
|
||||
|
||||
### Feature Requests
|
||||
|
||||
Missing a feature or like to have certain functionality enhanced?
|
||||
No problem, please open an issue and describe what and why you think this change is required.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
If you want to contribute your code to solve an issue or implement a desired feature yourself, you might open a pull request.
|
||||
If the changes introduce new functionality or affect major parts of existing code, please consider opening an issue for discussion first.
|
||||
|
||||
Extending or adapting JUnit test cases would be nice (no hard criterion though).
|
||||
|
||||
The `main` branch also be target for most pull requests.
|
||||
However, if it features new functionality you might want to target the `develop` branch instead (see next section for details on branches).
|
||||
|
||||
### Branches
|
||||
|
||||
The `main` branch represents the current, more or less stable state of development.
|
||||
Please ensure your initial code is up to date with it at the time you start development.
|
||||
|
||||
In addition, this project features a `develop` branch, which holds bleeding edge developments, not necessarily considered stable or even compatible.
|
||||
Do not expect this code to run smoothly, but you might have a look into the history to see if some work on an issue has already been started there.
|
||||
|
||||
For fixes and features, there might be additional branches, likely prefixed by `fix/` or `feature/` followed by an issue number (if applicable) and/or a title.
|
||||
Feel free to adapt this naming scheme to your forks.
|
||||
|
||||
### Merge Requirements
|
||||
|
||||
To be merged into the main branch, your code has to pass the automated continuous integration tests, to ensure compatibility.
|
||||
In addition, your code has to be approved by a project member.
|
||||
|
||||
#### What if my code fails the tests?
|
||||
|
||||
Don't worry, you can submit your PR anyway.
|
||||
The reviewing process might help you to solve remaining issues.
|
||||
|
||||
### Commit messages
|
||||
|
||||
Please use speaking titles and messages for your commits, to ensure a transparent history.
|
||||
If your patch fixes an issue, reference the ID in the first line.
|
||||
If you feel like you have to _briefly_ explain your changes, do it (for long explanations and discussion, consider opening an issue or describe in the PR).
|
||||
|
||||
**Example commit:**
|
||||
```text
|
||||
Fix nasty bug from #1337
|
||||
|
||||
This example commit fixes the issue that some people write non-speaking commit messages like 'done magic'.
|
||||
A short description is helpful sometimes.
|
||||
```
|
||||
|
||||
You might sign your work, although that's no must.
|
||||
|
||||
### When will it be merged?
|
||||
|
||||
Short answer: When it makes sense.
|
||||
|
||||
Bugfixes should be merged in time - assuming they pass the above criteria.
|
||||
New features might be assigned to a certain milestone and as a result of this be scheduled according to the planned release cycle.
|
||||
|
||||
## Compatibility
|
||||
|
||||
To ensure usability for a wide range of users, please take note on the software requirements stated in the `README`.
|
||||
This includes especially Java versions and a minimum version of _Vault_.
|
||||
|
||||
If you are unsure if your code matches these versions, the test will probably tell you.
|
||||
|
||||
In case you think, your change is more important than maintaining backwards compatibility, please start a discussion to see,
|
||||
if we might increase the minimum version or find a workaround for legacy systems.
|
||||
|
||||
## Build Environment
|
||||
|
||||
All you need to start off - besides your favorite IDE and a JDK of course - is [Maven](https://maven.apache.org/).
|
||||
|
||||
## Unit Tests
|
||||
|
||||
The code is tested by JUnit tests.
|
||||
For standalone testing against mocked APIs the _Maven_ profile `offline-test` should be used.
|
||||
Otherwise, there is a test suite that requires an actual _Vault_ binary in the executable path to start a real server instance.
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Automated tests are run using [GitHub Actions](https://github.com/features/actions) for every commit including pull requests.
|
||||
Tests usually run against the minimal supported version, all supported LTS versions and the latest version of Java.
|
||||
|
||||
There is an automated code quality analysis pushing results to [SonarCloud](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Ajvault-connector).
|
||||
|
||||
## Still Open Questions?
|
||||
|
||||
If anything is still left unanswered and you're unsure if you got it right, don't hesitate to contact a team member.
|
||||
In any case you might submit your request/issue anyway, we won't refuse good code only for formal reasons.
|
18
README.md
18
README.md
@ -1,6 +1,6 @@
|
||||
# Java Vault Connector
|
||||
|
||||
[](https://travis-ci.com/stklcode/jvaultconnector)
|
||||
[](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)
|
||||
@ -12,7 +12,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
## Features:
|
||||
|
||||
* HTTP(S) backend connector
|
||||
* Ability to provide or enforce custom CA certificate
|
||||
* Ability to provide or enforce custom CA certificate
|
||||
* Optional initialization from environment variables
|
||||
* Authorization methods
|
||||
* Token
|
||||
@ -32,7 +32,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
* SQL secret handling
|
||||
* KV v1 and v2 support
|
||||
* Connector Factory with builder pattern
|
||||
* Tested against Vault 1.8.0
|
||||
* Tested against Vault 1.8.3
|
||||
|
||||
|
||||
## 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>0.9.5</version>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@ -57,9 +57,7 @@ VaultConnector vault = HTTPVaultConnector.builder()
|
||||
.build();
|
||||
|
||||
// Instantiate with custom SSL context
|
||||
VaultConnector vault = HTTPVaultConnector.builder()
|
||||
.withHost("example.com")
|
||||
.withPort(8200)
|
||||
VaultConnector vault = HTTPVaultConnector.builder("https://example.com:8200/v1/")
|
||||
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
||||
.build();
|
||||
|
||||
@ -120,10 +118,10 @@ AppRoleSecretResponse secret = vault.createAppRoleSecret("testrole");
|
||||
|
||||
## Links
|
||||
|
||||
[Project Page](http://jvault.stklcode.de)
|
||||
[Project Page](https://jvault.stklcode.de)
|
||||
|
||||
[JavaDoc API](http://jvault.stklcode.de/apidocs/)
|
||||
[JavaDoc API](https://jvault.stklcode.de/apidocs/)
|
||||
|
||||
## License
|
||||
|
||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
The project is licensed under [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
70
pom.xml
70
pom.xml
@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>jvault-connector</artifactId>
|
||||
<version>0.9.5</version>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
|
||||
<url>https://www.apache.org/licenses/LICENSE-2.0.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
@ -52,8 +52,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@ -96,8 +96,16 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<configuration>
|
||||
<reuseForks>false</reuseForks>
|
||||
<argLine>@{argLine} --illegal-access=permit</argLine>
|
||||
<argLine>
|
||||
@{argLine}
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.exception=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response.embedded=ALL-UNNAMED
|
||||
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@ -105,39 +113,33 @@
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.12.4</version>
|
||||
<version>2.13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.7.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>3.11.2</version>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.12.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-lambda</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<version>2.27.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -194,9 +196,9 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<source>11</source>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@ -287,7 +289,7 @@
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>6.2.2</version>
|
||||
<version>6.3.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@ -300,26 +302,6 @@
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>jdk1.8</id>
|
||||
<activation>
|
||||
<jdk>1.8</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>sonatype</id>
|
||||
<distributionManagement>
|
||||
|
@ -24,7 +24,8 @@ import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -40,7 +41,6 @@ import static java.util.Collections.singletonMap;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class HTTPVaultConnector implements VaultConnector {
|
||||
private static final String PATH_PREFIX = "/v1/";
|
||||
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";
|
||||
@ -82,148 +82,44 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname and schema.
|
||||
* Get a new builder for a connector.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param baseURL Base URL.
|
||||
* @return Builder instance.
|
||||
* @throws URISyntaxException Invalid URI syntax.
|
||||
* @since 1.0
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS) {
|
||||
this(hostname, useTLS, null);
|
||||
public static HTTPVaultConnectorBuilder builder(String baseURL) throws URISyntaxException {
|
||||
return new HTTPVaultConnectorBuilder().withBaseURL(baseURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema and port.
|
||||
* Get a new builder for a connector.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
* @param baseURL Base URL.
|
||||
* @return Builder instance.
|
||||
* @since 1.0
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS, final Integer port) {
|
||||
this(hostname, useTLS, port, PATH_PREFIX);
|
||||
public static HTTPVaultConnectorBuilder builder(URI baseURL) {
|
||||
return new HTTPVaultConnectorBuilder().withBaseURL(baseURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema, port and path.
|
||||
* Create connector using a {@link HTTPVaultConnectorBuilder}.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param builder The builder.
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS, final Integer port, final String prefix) {
|
||||
this(((useTLS) ? "https" : "http")
|
||||
+ "://" + hostname
|
||||
+ ((port != null) ? ":" + port : "")
|
||||
+ prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema, port, path and trusted certificate.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname,
|
||||
final boolean useTLS,
|
||||
final Integer port,
|
||||
final String prefix,
|
||||
final X509Certificate trustedCaCert) {
|
||||
this(hostname, useTLS, DEFAULT_TLS_VERSION, port, prefix, trustedCaCert, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema, port, path and trusted certificate.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param tlsVersion TLS version
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname,
|
||||
final boolean useTLS,
|
||||
final String tlsVersion,
|
||||
final Integer port,
|
||||
final String prefix,
|
||||
final X509Certificate trustedCaCert,
|
||||
final int numberOfRetries,
|
||||
final Integer timeout) {
|
||||
this(((useTLS) ? "https" : "http")
|
||||
+ "://" + hostname
|
||||
+ ((port != null) ? ":" + port : "")
|
||||
+ prefix,
|
||||
trustedCaCert,
|
||||
numberOfRetries,
|
||||
timeout,
|
||||
tlsVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL) {
|
||||
this(baseURL, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL, final X509Certificate trustedCaCert) {
|
||||
this(baseURL, trustedCaCert, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL, final X509Certificate trustedCaCert, final int numberOfRetries) {
|
||||
this(baseURL, trustedCaCert, numberOfRetries, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL,
|
||||
final X509Certificate trustedCaCert,
|
||||
final int numberOfRetries,
|
||||
final Integer timeout) {
|
||||
this(baseURL, trustedCaCert, numberOfRetries, timeout, DEFAULT_TLS_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param trustedCaCert Trusted CA certificate
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||
* @param tlsVersion TLS Version.
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL,
|
||||
final X509Certificate trustedCaCert,
|
||||
final int numberOfRetries,
|
||||
final Integer timeout,
|
||||
final String tlsVersion) {
|
||||
this.request = new RequestHelper(baseURL, numberOfRetries, timeout, tlsVersion, trustedCaCert);
|
||||
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
|
||||
@ -256,13 +152,18 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
public HealthResponse getHealth() throws VaultConnectorException {
|
||||
/* Force status code to be 200, so we don't need to modify the request sequence. */
|
||||
Map<String, String> param = new HashMap<>(3, 1);
|
||||
param.put("standbycode", "200"); // Default: 429.
|
||||
param.put("sealedcode", "200"); // Default: 503.
|
||||
param.put("uninitcode", "200"); // Default: 501.
|
||||
|
||||
return request.get(PATH_HEALTH, param, token, HealthResponse.class);
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,12 +198,15 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>(2, 1);
|
||||
payload.put("app_id", appID);
|
||||
payload.put("user_id", userID);
|
||||
return queryAuth(PATH_AUTH_APPID + "login", payload);
|
||||
return queryAuth(
|
||||
PATH_AUTH_APPID + "login",
|
||||
Map.of(
|
||||
"app_id", appID,
|
||||
"user_id", userID
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -336,22 +240,26 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
Map<String, String> payload = new HashMap<>(2, 1);
|
||||
payload.put("value", policy);
|
||||
payload.put("display_name", displayName);
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(PATH_AUTH_APPID + "map/app-id/" + appID, payload, token);
|
||||
request.postWithoutResponse(
|
||||
PATH_AUTH_APPID + "map/app-id/" + appID,
|
||||
Map.of(
|
||||
"value", policy,
|
||||
"display_name", displayName
|
||||
),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
@ -550,17 +458,23 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
// Add CAS value to options map if present.
|
||||
Map<String, Object> options = new HashMap<>(1, 1);
|
||||
Map<String, Object> options;
|
||||
if (cas != null) {
|
||||
options.put("cas", cas);
|
||||
options = singletonMap("cas", cas);
|
||||
} else {
|
||||
options = emptyMap();
|
||||
}
|
||||
|
||||
Map<String, Object> payload = new HashMap<>(2, 1);
|
||||
payload.put("data", data);
|
||||
payload.put("options", options);
|
||||
|
||||
/* Issue request and parse metadata response */
|
||||
return request.post(mount + PATH_DATA + key, payload, token, SecretVersionResponse.class);
|
||||
return request.post(
|
||||
mount + PATH_DATA + key,
|
||||
Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
),
|
||||
token,
|
||||
SecretVersionResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -585,10 +499,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
// If options are given, split payload in two parts.
|
||||
if (options != null) {
|
||||
Map<String, Object> payloadMap = new HashMap<>(2, 1);
|
||||
payloadMap.put("data", data);
|
||||
payloadMap.put("options", options);
|
||||
payload = payloadMap;
|
||||
payload = Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
);
|
||||
}
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.builder.VaultConnectorBuilder;
|
||||
import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -31,6 +31,7 @@ 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.
|
||||
@ -39,7 +40,7 @@ import java.security.cert.X509Certificate;
|
||||
* @since 0.8.0
|
||||
* @since 0.9.5 Package {@link de.stklcode.jvault.connector}
|
||||
*/
|
||||
public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
public final class HTTPVaultConnectorBuilder {
|
||||
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
|
||||
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
|
||||
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
|
||||
@ -66,7 +67,7 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
* Default empty constructor.
|
||||
* Initializes factory with default values.
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder() {
|
||||
HTTPVaultConnectorBuilder() {
|
||||
host = DEFAULT_HOST;
|
||||
port = DEFAULT_PORT;
|
||||
tls = DEFAULT_TLS;
|
||||
@ -75,6 +76,32 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set base URL, e.g. "protocol://host:port/prefix".
|
||||
*
|
||||
* @param baseURL Base URL
|
||||
* @return self
|
||||
* @throws URISyntaxException Invalid URI syntax.
|
||||
* @since 1.0
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder withBaseURL(final String baseURL) throws URISyntaxException {
|
||||
return withBaseURL(new URI(baseURL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set base URL, e.g. "protocol://host:port/prefix".
|
||||
*
|
||||
* @param baseURL Base URL
|
||||
* @return self
|
||||
* @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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hostname (default: 127.0.0.1).
|
||||
*
|
||||
@ -86,17 +113,43 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hostname.
|
||||
*
|
||||
* @return Hostname or IP address
|
||||
*/
|
||||
String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port (default: 8200).
|
||||
* A value of {@code null} or {@code -1} indicates that no port is specified, i.e. the protocol default is used.
|
||||
* Otherwise a valid port number bwetween 1 and 65535 is expected.
|
||||
*
|
||||
* @param port Vault TCP port
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder withPort(final Integer port) {
|
||||
this.port = port;
|
||||
if (port < 0) {
|
||||
this.port = null;
|
||||
} else if (port < 1 || port > 65535) {
|
||||
throw new IllegalArgumentException("Port number " + port + " out of range");
|
||||
} else {
|
||||
this.port = port;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port..
|
||||
*
|
||||
* @return Vault TCP port
|
||||
*/
|
||||
Integer getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TLS usage (default: TRUE).
|
||||
*
|
||||
@ -108,6 +161,24 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TLS usage flag.
|
||||
*
|
||||
* @return use TLS or not
|
||||
*/
|
||||
boolean isWithTLS() {
|
||||
return this.tls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TLS version.
|
||||
*
|
||||
* @return TLS version.
|
||||
*/
|
||||
String getTlsVersion() {
|
||||
return this.tlsVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TLS usage (default: TRUE).
|
||||
*
|
||||
@ -154,7 +225,7 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
/**
|
||||
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
|
||||
*
|
||||
* @param prefix Vault API prefix (default: "/v1/"
|
||||
* @param prefix Vault API prefix (default: "/v1/")
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorBuilder withPrefix(final String prefix) {
|
||||
@ -162,6 +233,15 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get API prefix.
|
||||
*
|
||||
* @return Vault API prefix.
|
||||
*/
|
||||
String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trusted CA certificate for HTTPS connections.
|
||||
*
|
||||
@ -191,6 +271,15 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trusted CA certificate for HTTPS connections.
|
||||
*
|
||||
* @return path to certificate file, if specified.
|
||||
*/
|
||||
X509Certificate getTrustedCA() {
|
||||
return this.trustedCA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token for automatic authentication, using {@link #buildAndAuth()}.
|
||||
*
|
||||
@ -214,7 +303,7 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
/* Parse URL from environment variable */
|
||||
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
|
||||
try {
|
||||
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
|
||||
var url = new URL(System.getenv(ENV_VAULT_ADDR));
|
||||
this.host = url.getHost();
|
||||
this.port = url.getPort();
|
||||
this.tls = url.getProtocol().equals("https");
|
||||
@ -254,6 +343,15 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of retries to attempt on 5xx errors.
|
||||
*
|
||||
* @return The number of retries to attempt on 5xx errors (default: 0)
|
||||
*/
|
||||
int getNumberOfRetries() {
|
||||
return this.numberOfRetries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a custom timeout for the HTTP connection.
|
||||
*
|
||||
@ -266,12 +364,31 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector build() {
|
||||
return new HTTPVaultConnector(host, tls, tlsVersion, port, prefix, trustedCA, numberOfRetries, timeout);
|
||||
/**
|
||||
* Get custom timeout for the HTTP connection.
|
||||
*
|
||||
* @return Timeout value in milliseconds.
|
||||
*/
|
||||
Integer getTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Build command, produces connector after initialization.
|
||||
*
|
||||
* @return Vault Connector instance.
|
||||
*/
|
||||
public HTTPVaultConnector build() {
|
||||
return new HTTPVaultConnector(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build connector and authenticate with token set in factory or from environment.
|
||||
*
|
||||
* @return Authenticated Vault connector instance.
|
||||
* @throws VaultConnectorException if authentication failed
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||
if (token == null) {
|
||||
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
||||
@ -290,7 +407,7 @@ public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
|
||||
try (InputStream is = Files.newInputStream(certFile)) {
|
||||
try (var is = Files.newInputStream(certFile)) {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||
} catch (IOException | CertificateException e) {
|
||||
throw new TlsException("Unable to read certificate.", e);
|
||||
|
@ -16,13 +16,15 @@
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault Connector interface.
|
||||
@ -32,10 +34,6 @@ import java.util.*;
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
/**
|
||||
* Default sub-path for Vault secrets.
|
||||
*/
|
||||
String PATH_SECRET = "secret";
|
||||
|
||||
/**
|
||||
* Reset authorization information.
|
||||
@ -123,7 +121,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
@ -159,7 +157,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException;
|
||||
|
||||
@ -354,7 +352,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
* Consider using {@link #createAppRoleSecret} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
@ -368,7 +366,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since = "0.4", forRemoval = false)
|
||||
default boolean registerAppUserId(final String appID,
|
||||
final String policy,
|
||||
final String displayName,
|
||||
@ -393,36 +391,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
SecretResponse read(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to key.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #read(String)} instead with key prefix "secret/".
|
||||
*/
|
||||
@Deprecated
|
||||
default SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||
return read(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the latest secret data for specific version from Vault.
|
||||
* <br>
|
||||
* Prefix "secret/data" is automatically added to key.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
default SecretResponse readSecretData(final String key) throws VaultConnectorException {
|
||||
return readSecretVersion(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the latest secret data for specific version from Vault.
|
||||
* <br>
|
||||
@ -439,24 +407,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
return readSecretVersion(mount, key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param key Secret identifier.
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @return Metadata for the created/updated secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #writeSecretData(String, String, Map)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default SecretVersionResponse writeSecretData(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
return writeSecretData(PATH_SECRET, key, data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
@ -490,24 +440,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
SecretVersionResponse writeSecretData(final String mount, final String key, final Map<String, Object> data, final Integer cas) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret data from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #readSecretVersion(String, String, Integer)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default SecretResponse readSecretVersion(final String key, final Integer version) throws VaultConnectorException {
|
||||
return readSecretVersion(PATH_SECRET, key, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve secret data from Vault.
|
||||
* <br>
|
||||
@ -523,40 +455,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
SecretResponse readSecretVersion(final String mount, final String key, final Integer version) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret metadata from Vault.
|
||||
* Path {@code secret/metadata/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Metadata response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #readSecretMetadata(String, String)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default MetadataResponse readSecretMetadata(final String key) throws VaultConnectorException {
|
||||
return readSecretMetadata(PATH_SECRET, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update secret metadata.
|
||||
* <br>
|
||||
* Path {@code secret/metadata/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @param maxVersions Maximum number of versions (fallback to backend default if {@code null})
|
||||
* @param casRequired Specify if Check-And-Set is required for this secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #updateSecretMetadata(String, String, Integer, boolean)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void updateSecretMetadata(final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException {
|
||||
updateSecretMetadata(PATH_SECRET, key, maxVersions, casRequired);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve secret metadata from Vault.
|
||||
* <br>
|
||||
@ -596,21 +494,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
List<String> list(final String path) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available secrets from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
*
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #list(String)} instead with key prefix "secret/".
|
||||
*/
|
||||
@Deprecated
|
||||
default List<String> listSecrets(final String path) throws VaultConnectorException {
|
||||
return list(PATH_SECRET + "/" + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write simple value to Vault.
|
||||
*
|
||||
@ -646,40 +529,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void write(final String key, final Map<String, Object> data, final Map<String, Object> options) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param value Secret value
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #write(String, String)} instead with key prefix "secret/".
|
||||
*/
|
||||
@Deprecated
|
||||
default void writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||
writeSecret(key, Collections.singletonMap("value", value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #write(String, Map)} instead with key prefix "secret/".
|
||||
*/
|
||||
@Deprecated
|
||||
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
if (key == null || key.isEmpty()) {
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
}
|
||||
write(PATH_SECRET + "/" + key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete key from Vault.
|
||||
*
|
||||
@ -689,35 +538,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void delete(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #delete(String)} instead with key prefix "secret/".
|
||||
*/
|
||||
@Deprecated
|
||||
default void deleteSecret(final String key) throws VaultConnectorException {
|
||||
delete(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path. Only available for KV v2 stores.
|
||||
*
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteLatestSecretVersion(String, String)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void deleteLatestSecretVersion(final String key) throws VaultConnectorException {
|
||||
deleteLatestSecretVersion(PATH_SECRET, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
@ -730,22 +550,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteAllSecretVersions(String)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void deleteAllSecretVersions(final String key) throws VaultConnectorException {
|
||||
deleteAllSecretVersions(PATH_SECRET, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
@ -759,22 +563,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret versions from Vault.
|
||||
* <br>
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to delete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteSecretVersions(String, String, int...)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void deleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||
deleteSecretVersions(PATH_SECRET, key, versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete secret versions from Vault.
|
||||
* <br>
|
||||
@ -788,21 +576,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void deleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Undelete (restore) secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to undelete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #undeleteSecretVersions(String, String, int...)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void undeleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||
undeleteSecretVersions(PATH_SECRET, key, versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undelete (restore) secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
@ -815,21 +588,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void undeleteSecretVersions(final String mount, final String key, final int... versions) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to destroy.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
* @deprecated Convenience method will be removed in 1.0. Use {@link #destroySecretVersions(String, String, int...)} instead with mount parameter "secret".
|
||||
*/
|
||||
@Deprecated
|
||||
default void destroySecretVersions(final String key, final int... versions) throws VaultConnectorException {
|
||||
destroySecretVersions(PATH_SECRET, key, versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.builder;
|
||||
|
||||
/**
|
||||
* Vault Connector Builder implementation for HTTP Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8.0
|
||||
* @since 0.9.5 Extends new class for migration purposes only.
|
||||
* @deprecated Use {@link de.stklcode.jvault.connector.HTTPVaultConnectorBuilder} instead. Will be removed in 1.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class HTTPVaultConnectorBuilder extends de.stklcode.jvault.connector.HTTPVaultConnectorBuilder {
|
||||
public HTTPVaultConnectorBuilder() {
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.builder;
|
||||
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.VaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Abstract Vault Connector Builder interface.
|
||||
* Provides builder style for Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8.0
|
||||
*/
|
||||
public interface VaultConnectorBuilder {
|
||||
/**
|
||||
* Get Factory implementation for HTTP Vault Connector.
|
||||
*
|
||||
* @return HTTP Connector Factory
|
||||
* @deprecated Use {@link HTTPVaultConnector#builder()} instead. This interface will be removed in 1.0
|
||||
*/
|
||||
@Deprecated
|
||||
static HTTPVaultConnectorBuilder http() {
|
||||
return new HTTPVaultConnectorBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build command, produces connector after initialization.
|
||||
*
|
||||
* @return Vault Connector instance.
|
||||
*/
|
||||
VaultConnector build();
|
||||
|
||||
/**
|
||||
* Build connector and authenticate with token set in factory or from environment.
|
||||
*
|
||||
* @return Authenticated Vault connector instance.
|
||||
* @throws VaultConnectorException if authentication failed
|
||||
* @since 0.6.0
|
||||
*/
|
||||
VaultConnector buildAndAuth() throws VaultConnectorException;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the {@link de.stklcode.jvault.connector.builder.VaultConnectorBuilder} to initialize a
|
||||
* connector instance.
|
||||
*/
|
||||
package de.stklcode.jvault.connector.builder;
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
/**
|
||||
* Exception thrown trying to do a request without any authorization handles.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class AuthorizationRequiredException extends VaultConnectorException {
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
/**
|
||||
* Exception thrown when trying to send malformed request.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class InvalidRequestException extends VaultConnectorException {
|
||||
/**
|
||||
|
@ -136,30 +136,6 @@ public final class InvalidResponseException extends VaultConnectorException {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the HTTP status code. Can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param statusCode The status code
|
||||
* @return self
|
||||
* @deprecated as of 0.6.2, use constructor with status code argument instead
|
||||
*/
|
||||
@Deprecated
|
||||
public InvalidResponseException withStatusCode(final Integer statusCode) {
|
||||
return new InvalidResponseException(getMessage(), statusCode, getResponse(), getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the response string. Can be retrieved by {@link #getResponse()} later.
|
||||
*
|
||||
* @param response Response text
|
||||
* @return self
|
||||
* @deprecated use constructor with response argument instead
|
||||
*/
|
||||
@Deprecated
|
||||
public InvalidResponseException withResponse(final String response) {
|
||||
return new InvalidResponseException(getMessage(), getStatusCode(), response, getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the HTTP status code.
|
||||
*
|
||||
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
/**
|
||||
* Exception thrown when trying to access a path the current user/token does not have permission to access.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class PermissionDeniedException extends VaultConnectorException {
|
||||
/**
|
||||
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
/**
|
||||
* Exception thrown on errors with TLS connection.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TlsException extends VaultConnectorException {
|
||||
/**
|
||||
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
/**
|
||||
* Abstract Exception class for Vault Connector internal exceptions.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultConnectorException extends Exception {
|
||||
/**
|
||||
|
@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnectorBuilder;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Vault Connector Factory implementation for HTTP Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @deprecated As of 0.8.0 please refer to {@link de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder} with identical API.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
private final HTTPVaultConnectorBuilder delegate;
|
||||
|
||||
/**
|
||||
* Default empty constructor.
|
||||
* Initializes factory with default values.
|
||||
*/
|
||||
public HTTPVaultConnectorFactory() {
|
||||
delegate = new HTTPVaultConnectorBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hostname (default: 127.0.0.1).
|
||||
*
|
||||
* @param host Hostname or IP address
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withHost(final String host) {
|
||||
delegate.withHost(host);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port (default: 8200).
|
||||
*
|
||||
* @param port Vault TCP port
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withPort(final Integer port) {
|
||||
delegate.withPort(port);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TLS usage (default: TRUE).
|
||||
*
|
||||
* @param useTLS use TLS or not
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTLS(final boolean useTLS) {
|
||||
delegate.withTLS(useTLS);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience Method for TLS usage (enabled by default).
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTLS() {
|
||||
return withTLS(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience Method for NOT using TLS.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withoutTLS() {
|
||||
return withTLS(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
|
||||
*
|
||||
* @param prefix Vault API prefix (default: "/v1/"
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withPrefix(final String prefix) {
|
||||
delegate.withPrefix(prefix);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trusted CA certificate for HTTPS connections.
|
||||
*
|
||||
* @param cert path to certificate file
|
||||
* @return self
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||
delegate.withTrustedCA(cert);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trusted CA certificate for HTTPS connections.
|
||||
*
|
||||
* @param cert path to certificate file
|
||||
* @return self
|
||||
* @since 0.8.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTrustedCA(final X509Certificate cert) {
|
||||
delegate.withTrustedCA(cert);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom SSL context.
|
||||
* Overwrites certificates set by {@link #withTrustedCA}.
|
||||
*
|
||||
* @param sslContext the SSL context
|
||||
* @return self
|
||||
* @since 0.4.0
|
||||
* @deprecated As of 0.8.0 this is no longer supported, please use {@link #withTrustedCA(Path)} or {@link #withTrustedCA(X509Certificate)}.
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
||||
throw new UnsupportedOperationException("Use of deprecated method, please switch to withTrustedCA()");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token for automatic authentication, using {@link #buildAndAuth()}.
|
||||
*
|
||||
* @param token Vault token
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withToken(final String token) {
|
||||
delegate.withToken(token);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
|
||||
*
|
||||
* @return self
|
||||
* @throws VaultConnectorException if Vault address from environment variables is malformed
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException {
|
||||
delegate.fromEnv();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the number of retries to attempt on 5xx errors.
|
||||
*
|
||||
* @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0)
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) {
|
||||
delegate.withNumberOfRetries(numberOfRetries);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a custom timeout for the HTTP connection.
|
||||
*
|
||||
* @param milliseconds Timeout value in milliseconds.
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTimeout(final int milliseconds) {
|
||||
delegate.withTimeout(milliseconds);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector build() {
|
||||
return delegate.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||
return delegate.buildAndAuth();
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.builder.VaultConnectorBuilder;
|
||||
|
||||
/**
|
||||
* Abstract Vault Connector Factory interface.
|
||||
* Provides builder pattern style factory for Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder} with identical API.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class VaultConnectorFactory implements VaultConnectorBuilder {
|
||||
/**
|
||||
* Get Factory implementation for HTTP Vault Connector.
|
||||
*
|
||||
* @return HTTP Connector Factory
|
||||
* @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder#http()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static HTTPVaultConnectorFactory httpFactory() {
|
||||
return new HTTPVaultConnectorFactory();
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the {@link de.stklcode.jvault.connector.factory.VaultConnectorFactory} to initialize a
|
||||
* connector instance.
|
||||
*
|
||||
* @deprecated As of v0.8.0 please refer to {@link de.stklcode.jvault.connector.builder}.
|
||||
*/
|
||||
package de.stklcode.jvault.connector.factory;
|
@ -29,6 +29,7 @@ final class Error {
|
||||
static final String URI_FORMAT = "Invalid URI format";
|
||||
static final String RESPONSE_CODE = "Invalid response code";
|
||||
static final String INIT_SSL_CONTEXT = "Unable to initialize SSLContext";
|
||||
static final String CONNECTION = "Unable to connect to Vault server";
|
||||
|
||||
/**
|
||||
* Constructor hidden, this class should not be instantiated.
|
||||
|
@ -4,27 +4,29 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.*;
|
||||
import de.stklcode.jvault.connector.model.response.ErrorResponse;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Helper class to bundle Vault HTTP requests.
|
||||
*
|
||||
@ -55,7 +57,7 @@ public final class RequestHelper implements Serializable {
|
||||
final Integer timeout,
|
||||
final String tlsVersion,
|
||||
final X509Certificate trustedCaCert) {
|
||||
this.baseURL = baseURL;
|
||||
this.baseURL = baseURL + (baseURL.endsWith("/") ? "" : "/");
|
||||
this.retries = retries;
|
||||
this.timeout = timeout;
|
||||
this.tlsVersion = tlsVersion;
|
||||
@ -74,26 +76,24 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8 Added {@code token} parameter.
|
||||
*/
|
||||
public String post(final String path, final Object payload, final String token) throws VaultConnectorException {
|
||||
/* Initialize post */
|
||||
HttpPost post = new HttpPost(baseURL + path);
|
||||
// Initialize POST.
|
||||
var req = HttpRequest.newBuilder(URI.create(baseURL + path));
|
||||
|
||||
/* generate JSON from payload */
|
||||
StringEntity input;
|
||||
// Generate JSON from payload.
|
||||
try {
|
||||
input = new StringEntity(jsonMapper.writeValueAsString(payload), StandardCharsets.UTF_8);
|
||||
req.POST(HttpRequest.BodyPublishers.ofString(jsonMapper.writeValueAsString(payload), UTF_8));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new InvalidRequestException(Error.PARSE_RESPONSE, e);
|
||||
}
|
||||
input.setContentEncoding("UTF-8");
|
||||
input.setContentType("application/json");
|
||||
post.setEntity(input);
|
||||
|
||||
/* Set X-Vault-Token header */
|
||||
req.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
// Set X-Vault-Token header.
|
||||
if (token != null) {
|
||||
post.addHeader(HEADER_VAULT_TOKEN, token);
|
||||
req.setHeader(HEADER_VAULT_TOKEN, token);
|
||||
}
|
||||
|
||||
return request(post, retries);
|
||||
return request(req, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,26 +144,24 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8 Added {@code token} parameter.
|
||||
*/
|
||||
public String put(final String path, final Map<String, String> payload, final String token) throws VaultConnectorException {
|
||||
/* Initialize put */
|
||||
HttpPut put = new HttpPut(baseURL + path);
|
||||
// Initialize PUT.
|
||||
var req = HttpRequest.newBuilder(URI.create(baseURL + path));
|
||||
|
||||
/* generate JSON from payload */
|
||||
StringEntity entity = null;
|
||||
// Generate JSON from payload.
|
||||
try {
|
||||
entity = new StringEntity(jsonMapper.writeValueAsString(payload));
|
||||
} catch (UnsupportedEncodingException | JsonProcessingException e) {
|
||||
req.PUT(HttpRequest.BodyPublishers.ofString(jsonMapper.writeValueAsString(payload), UTF_8));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new InvalidRequestException("Payload serialization failed", e);
|
||||
}
|
||||
|
||||
/* Parse parameters */
|
||||
put.setEntity(entity);
|
||||
req.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
/* Set X-Vault-Token header */
|
||||
// Set X-Vault-Token header.
|
||||
if (token != null) {
|
||||
put.addHeader(HEADER_VAULT_TOKEN, token);
|
||||
req.setHeader(HEADER_VAULT_TOKEN, token);
|
||||
}
|
||||
|
||||
return request(put, retries);
|
||||
return request(req, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,15 +212,15 @@ public final class RequestHelper implements Serializable {
|
||||
* @since 0.8 Added {@code token} parameter.
|
||||
*/
|
||||
public String delete(final String path, final String token) throws VaultConnectorException {
|
||||
/* Initialize delete */
|
||||
HttpDelete delete = new HttpDelete(baseURL + path);
|
||||
// Initialize DELETE.
|
||||
HttpRequest.Builder req = HttpRequest.newBuilder(URI.create(baseURL + path)).DELETE();
|
||||
|
||||
/* Set X-Vault-Token header */
|
||||
// Set X-Vault-Token header.
|
||||
if (token != null) {
|
||||
delete.addHeader(HEADER_VAULT_TOKEN, token);
|
||||
req.setHeader(HEADER_VAULT_TOKEN, token);
|
||||
}
|
||||
|
||||
return request(delete, retries);
|
||||
return request(req, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,25 +249,31 @@ public final class RequestHelper implements Serializable {
|
||||
*/
|
||||
public String get(final String path, final Map<String, String> payload, final String token)
|
||||
throws VaultConnectorException {
|
||||
HttpGet get;
|
||||
try {
|
||||
/* Add parameters to URI */
|
||||
URIBuilder uriBuilder = new URIBuilder(baseURL + path);
|
||||
payload.forEach(uriBuilder::addParameter);
|
||||
// Add parameters to URI.
|
||||
var uriBuilder = new StringBuilder(baseURL + path);
|
||||
|
||||
/* Initialize request */
|
||||
get = new HttpGet(uriBuilder.build());
|
||||
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("&"))
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize GET.
|
||||
try {
|
||||
var req = HttpRequest.newBuilder(new URI(uriBuilder.toString()));
|
||||
|
||||
// Set X-Vault-Token header.
|
||||
if (token != null) {
|
||||
req.setHeader(HEADER_VAULT_TOKEN, token);
|
||||
}
|
||||
|
||||
return request(req, retries);
|
||||
} catch (URISyntaxException e) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException(Error.URI_FORMAT);
|
||||
}
|
||||
|
||||
/* Set X-Vault-Token header */
|
||||
if (token != null) {
|
||||
get.addHeader(HEADER_VAULT_TOKEN, token);
|
||||
}
|
||||
|
||||
return request(get, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,34 +301,40 @@ public final class RequestHelper implements Serializable {
|
||||
/**
|
||||
* Execute prepared HTTP request and return result.
|
||||
*
|
||||
* @param base Prepares Request
|
||||
* @param retries number of retries
|
||||
* @param requestBuilder Prepared request.
|
||||
* @param retries Number of retries.
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
*/
|
||||
private String request(final HttpRequestBase base, final int retries) throws VaultConnectorException {
|
||||
/* Set JSON Header */
|
||||
base.addHeader("accept", "application/json");
|
||||
private String request(final HttpRequest.Builder requestBuilder, final int retries) throws VaultConnectorException {
|
||||
// Set JSON Header.
|
||||
requestBuilder.setHeader("accept", "application/json");
|
||||
|
||||
CloseableHttpResponse response = null;
|
||||
var clientBuilder = HttpClient.newBuilder();
|
||||
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create()
|
||||
.setSSLSocketFactory(createSSLSocketFactory())
|
||||
.build()) {
|
||||
/* Set custom timeout, if defined */
|
||||
if (this.timeout != null) {
|
||||
base.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(timeout).build());
|
||||
}
|
||||
// Set custom timeout, if defined.
|
||||
if (this.timeout != null) {
|
||||
clientBuilder.connectTimeout(Duration.ofMillis(timeout));
|
||||
}
|
||||
|
||||
/* Execute request */
|
||||
response = httpClient.execute(base);
|
||||
// Set custom SSL context.
|
||||
clientBuilder.sslContext(createSSLContext());
|
||||
|
||||
HttpClient client = clientBuilder.build();
|
||||
|
||||
// Execute request.
|
||||
try {
|
||||
HttpResponse<InputStream> response = client.sendAsync(
|
||||
requestBuilder.build(),
|
||||
HttpResponse.BodyHandlers.ofInputStream()
|
||||
).join();
|
||||
|
||||
/* Check if response is valid */
|
||||
if (response == null) {
|
||||
throw new InvalidResponseException("Response unavailable");
|
||||
}
|
||||
|
||||
switch (response.getStatusLine().getStatusCode()) {
|
||||
switch (response.statusCode()) {
|
||||
case 200:
|
||||
return handleResult(response);
|
||||
case 204:
|
||||
@ -332,64 +342,50 @@ public final class RequestHelper implements Serializable {
|
||||
case 403:
|
||||
throw new PermissionDeniedException();
|
||||
default:
|
||||
if (response.getStatusLine().getStatusCode() >= 500
|
||||
&& response.getStatusLine().getStatusCode() < 600 && retries > 0) {
|
||||
/* Retry on 5xx errors */
|
||||
return request(base, retries - 1);
|
||||
if (response.statusCode() >= 500 && response.statusCode() < 600 && retries > 0) {
|
||||
// Retry on 5xx errors.
|
||||
return request(requestBuilder, retries - 1);
|
||||
} else {
|
||||
/* Fail on different error code and/or no retries left */
|
||||
// Fail on different error code and/or no retries left.
|
||||
handleError(response);
|
||||
|
||||
/* Throw exception without details, if response entity is empty. */
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
||||
response.getStatusLine().getStatusCode());
|
||||
// Throw exception without details, if response entity is empty.
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE, response.statusCode());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException(Error.READ_RESPONSE, e);
|
||||
} finally {
|
||||
if (response != null && response.getEntity() != null) {
|
||||
try {
|
||||
EntityUtils.consume(response.getEntity());
|
||||
} catch (IOException ignored) {
|
||||
// Exception ignored.
|
||||
}
|
||||
}
|
||||
} catch (CompletionException e) {
|
||||
throw new ConnectionException(Error.CONNECTION, e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom socket factory from trusted CA certificate.
|
||||
* Create a custom SSL context from trusted CA certificate.
|
||||
*
|
||||
* @return The factory.
|
||||
* @return The context.
|
||||
* @throws TlsException An error occurred during initialization of the SSL context.
|
||||
* @since 0.8.0
|
||||
* @since 0.10 Generate {@link SSLContext} instead of Apache {@code SSLConnectionSocketFactory}
|
||||
*/
|
||||
private SSLConnectionSocketFactory createSSLSocketFactory() throws TlsException {
|
||||
private SSLContext createSSLContext() throws TlsException {
|
||||
try {
|
||||
// Create context..
|
||||
SSLContext context = SSLContext.getInstance(tlsVersion);
|
||||
// Create context.
|
||||
var sslContext = SSLContext.getInstance(tlsVersion);
|
||||
|
||||
if (trustedCaCert != null) {
|
||||
// Create Keystore with trusted certificate.
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null, null);
|
||||
keyStore.setCertificateEntry("trustedCert", trustedCaCert);
|
||||
|
||||
// Initialize TrustManager.
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(keyStore);
|
||||
context.init(null, tmf.getTrustManagers(), null);
|
||||
sslContext.init(null, tmf.getTrustManagers(), null);
|
||||
} else {
|
||||
context.init(null, null, null);
|
||||
sslContext.init(null, null, null);
|
||||
}
|
||||
|
||||
return new SSLConnectionSocketFactory(
|
||||
context,
|
||||
null,
|
||||
null,
|
||||
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
|
||||
);
|
||||
return sslContext;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
|
||||
throw new TlsException(Error.INIT_SSL_CONTEXT, e);
|
||||
}
|
||||
@ -402,10 +398,9 @@ public final class RequestHelper implements Serializable {
|
||||
* @return Complete response body as String
|
||||
* @throws InvalidResponseException on reading errors
|
||||
*/
|
||||
private String handleResult(final HttpResponse response) throws InvalidResponseException {
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(response.getEntity().getContent()))) {
|
||||
return br.lines().collect(Collectors.joining("\n"));
|
||||
private String handleResult(final HttpResponse<InputStream> response) throws InvalidResponseException {
|
||||
try (var reader = new BufferedReader(new InputStreamReader(response.body()))) {
|
||||
return reader.lines().collect(Collectors.joining("\n"));
|
||||
} catch (IOException ignored) {
|
||||
throw new InvalidResponseException(Error.READ_RESPONSE, 200);
|
||||
}
|
||||
@ -417,18 +412,16 @@ public final class RequestHelper implements Serializable {
|
||||
* @param response The raw HTTP response (assuming status code 5xx)
|
||||
* @throws VaultConnectorException Expected exception with details to throw
|
||||
*/
|
||||
private void handleError(final HttpResponse response) throws VaultConnectorException {
|
||||
if (response.getEntity() != null) {
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(response.getEntity().getContent()))) {
|
||||
String responseString = br.lines().collect(Collectors.joining("\n"));
|
||||
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();
|
||||
}
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
||||
response.getStatusLine().getStatusCode(), er.toString());
|
||||
throw new InvalidResponseException(Error.RESPONSE_CODE, response.statusCode(), er.toString());
|
||||
} catch (IOException ignored) {
|
||||
// Exception ignored.
|
||||
}
|
||||
|
@ -105,53 +105,6 @@ public final class AppRole {
|
||||
public AppRole() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct complete {@link AppRole} object.
|
||||
* <p>
|
||||
* This constructor is used for transition from {@code bound_cidr_list} to {@code secret_id_bound_cidrs} only.
|
||||
*
|
||||
* @param name Role name (required)
|
||||
* @param id Role ID (optional)
|
||||
* @param bindSecretId Bind secret ID (optional)
|
||||
* @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional)
|
||||
* @param secretIdNumUses Maximum number of uses per secret (optional)
|
||||
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
|
||||
* @param enableLocalSecretIds Enable local secret IDs (optional)
|
||||
* @param tokenTtl Token TTL in seconds (optional)
|
||||
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
|
||||
* @param tokenPolicies List of token policies (optional)
|
||||
* @param tokenBoundCidrs Whitelist of subnets in CIDR notation for associated tokens (optional)
|
||||
* @param tokenExplicitMaxTtl Explicit maximum TTL for associated tokens (optional)
|
||||
* @param tokenNoDefaultPolicy Enable or disable default policy for associated tokens (optional)
|
||||
* @param tokenNumUses Number of uses for tokens (optional)
|
||||
* @param tokenPeriod Duration in seconds, if set the token is a periodic token (optional)
|
||||
* @param tokenType Token type (optional)
|
||||
* @deprecated As of 0.9 in favor of {@link #builder(String)}. Will be removed with next major release.
|
||||
*/
|
||||
@Deprecated
|
||||
AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> secretIdBoundCidrs,
|
||||
final Integer secretIdNumUses, final Integer secretIdTtl, final Boolean enableLocalSecretIds,
|
||||
final Integer tokenTtl, final Integer tokenMaxTtl, final List<String> tokenPolicies,
|
||||
final List<String> tokenBoundCidrs, final Integer tokenExplicitMaxTtl, final Boolean tokenNoDefaultPolicy,
|
||||
final Integer tokenNumUses, final Integer tokenPeriod, final String tokenType) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.bindSecretId = bindSecretId;
|
||||
this.secretIdBoundCidrs = secretIdBoundCidrs;
|
||||
this.tokenPolicies = tokenPolicies;
|
||||
this.secretIdNumUses = secretIdNumUses;
|
||||
this.secretIdTtl = secretIdTtl;
|
||||
this.enableLocalSecretIds = enableLocalSecretIds;
|
||||
this.tokenTtl = tokenTtl;
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
this.tokenBoundCidrs = tokenBoundCidrs;
|
||||
this.tokenExplicitMaxTtl = tokenExplicitMaxTtl;
|
||||
this.tokenNoDefaultPolicy = tokenNoDefaultPolicy;
|
||||
this.tokenNumUses = tokenNumUses;
|
||||
this.tokenPeriod = tokenPeriod;
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link AppRole} object from {@link AppRole.Builder}.
|
||||
*
|
||||
@ -265,16 +218,6 @@ public final class AppRole {
|
||||
return tokenPolicies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of token policies
|
||||
* @deprecated Use {@link #getTokenPolicies()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public List<String> getPolicies() {
|
||||
return getTokenPolicies();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tokenPolicies list of token policies
|
||||
* @since 0.9
|
||||
@ -284,16 +227,6 @@ public final class AppRole {
|
||||
this.tokenPolicies = tokenPolicies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policies list of policies
|
||||
* @deprecated Use {@link #setTokenPolicies(List)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public void setPolicies(final List<String> policies) {
|
||||
setTokenPolicies(policies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of policies as comma-separated {@link String}
|
||||
* @since 0.9
|
||||
@ -307,16 +240,6 @@ public final class AppRole {
|
||||
return String.join(",", tokenPolicies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of policies as comma-separated {@link String}
|
||||
* @deprecated Use {@link #getTokenPoliciesString()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public String getPoliciesString() {
|
||||
return getTokenPoliciesString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maximum number of uses per secret
|
||||
*/
|
||||
@ -385,16 +308,6 @@ public final class AppRole {
|
||||
return tokenPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return duration in seconds, if specified
|
||||
* @deprecated Use {@link #getTokenPeriod()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public Integer getPeriod() {
|
||||
return getTokenPeriod();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return duration in seconds, if specified
|
||||
* @since 0.9
|
||||
@ -536,18 +449,6 @@ public final class AppRole {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPolicies(List)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withPolicies(final List<String> policies) {
|
||||
return withTokenPolicies(policies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
@ -563,18 +464,6 @@ public final class AppRole {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPolicy(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withPolicy(final String policy) {
|
||||
return withTokenPolicy(policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of uses for sectet IDs.
|
||||
*
|
||||
@ -708,31 +597,6 @@ public final class AppRole {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param tokenPeriod period in seconds
|
||||
* @return self
|
||||
* @since 0.9
|
||||
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder wit0hTokenPeriod(final Integer tokenPeriod) {
|
||||
return withTokenPeriod(tokenPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param period period in seconds
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withPeriod(final Integer period) {
|
||||
return withTokenPeriod(period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type of generated token.
|
||||
*
|
||||
|
@ -1,378 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A builder for vault AppRole roles..
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
* @deprecated As of 0.9 in favor of {@link AppRole.Builder}.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class AppRoleBuilder {
|
||||
private String name;
|
||||
private String id;
|
||||
private Boolean bindSecretId;
|
||||
private List<String> secretIdBoundCidrs;
|
||||
private List<String> tokenPolicies;
|
||||
private Integer secretIdNumUses;
|
||||
private Integer secretIdTtl;
|
||||
private Boolean enableLocalSecretIds;
|
||||
private Integer tokenTtl;
|
||||
private Integer tokenMaxTtl;
|
||||
private List<String> tokenBoundCidrs;
|
||||
private Integer tokenExplicitMaxTtl;
|
||||
private Boolean tokenNoDefaultPolicy;
|
||||
private Integer tokenNumUses;
|
||||
private Integer tokenPeriod;
|
||||
private Token.Type tokenType;
|
||||
|
||||
/**
|
||||
* Construct {@link AppRoleBuilder} with only the role name set.
|
||||
*
|
||||
* @param name Role name
|
||||
*/
|
||||
public AppRoleBuilder(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom role ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if role is bound to secret ID.
|
||||
*
|
||||
* @param bindSecretId the display name
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID(final Boolean bindSecretId) {
|
||||
this.bindSecretId = bindSecretId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID() {
|
||||
return withBindSecretID(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withoutBindSecretID() {
|
||||
return withBindSecretID(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bound CIDR blocks.
|
||||
*
|
||||
* @param secretIdBoundCidrs List of CIDR blocks which can perform login
|
||||
* @return self
|
||||
* @since 0.8 replaces {@code withBoundCidrList(List)}
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdBoundCidrs(final List<String> secretIdBoundCidrs) {
|
||||
if (this.secretIdBoundCidrs == null) {
|
||||
this.secretIdBoundCidrs = new ArrayList<>();
|
||||
}
|
||||
this.secretIdBoundCidrs.addAll(secretIdBoundCidrs);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CIDR block to list of bound blocks for secret.
|
||||
*
|
||||
* @param secretBoundCidr the CIDR block
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withSecretBoundCidr(final String secretBoundCidr) {
|
||||
if (secretIdBoundCidrs == null) {
|
||||
secretIdBoundCidrs = new ArrayList<>();
|
||||
}
|
||||
secretIdBoundCidrs.add(secretBoundCidr);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param tokenPolicies the token policies
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenPolicies(final List<String> tokenPolicies) {
|
||||
if (this.tokenPolicies == null) {
|
||||
this.tokenPolicies = new ArrayList<>();
|
||||
}
|
||||
this.tokenPolicies.addAll(tokenPolicies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPolicies(List)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public AppRoleBuilder withPolicies(final List<String> policies) {
|
||||
return withTokenPolicies(policies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param tokenPolicy the token policy
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenPolicy(final String tokenPolicy) {
|
||||
if (this.tokenPolicies == null) {
|
||||
this.tokenPolicies = new ArrayList<>();
|
||||
}
|
||||
tokenPolicies.add(tokenPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPolicy(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public AppRoleBuilder withPolicy(final String policy) {
|
||||
return withTokenPolicy(policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of uses for secret IDs.
|
||||
*
|
||||
* @param secretIdNumUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdNumUses(final Integer secretIdNumUses) {
|
||||
this.secretIdNumUses = secretIdNumUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default secret ID TTL in seconds.
|
||||
*
|
||||
* @param secretIdTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdTtl(final Integer secretIdTtl) {
|
||||
this.secretIdTtl = secretIdTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable local secret IDs.
|
||||
*
|
||||
* @param enableLocalSecretIds Enable local secret IDs?
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) {
|
||||
this.enableLocalSecretIds = enableLocalSecretIds;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default token TTL in seconds.
|
||||
*
|
||||
* @param tokenTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenTtl(final Integer tokenTtl) {
|
||||
this.tokenTtl = tokenTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum token TTL in seconds.
|
||||
*
|
||||
* @param tokenMaxTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenMaxTtl(final Integer tokenMaxTtl) {
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bound CIDR blocks for associated tokens.
|
||||
*
|
||||
* @param tokenBoundCidrs List of CIDR blocks which can perform login
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenBoundCidrs(final List<String> tokenBoundCidrs) {
|
||||
if (this.tokenBoundCidrs == null) {
|
||||
this.tokenBoundCidrs = new ArrayList<>();
|
||||
}
|
||||
this.tokenBoundCidrs.addAll(tokenBoundCidrs);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CIDR block to list of bound blocks for token.
|
||||
*
|
||||
* @param tokenBoundCidr the CIDR block
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenBoundCidr(final String tokenBoundCidr) {
|
||||
if (tokenBoundCidrs == null) {
|
||||
tokenBoundCidrs = new ArrayList<>();
|
||||
}
|
||||
tokenBoundCidrs.add(tokenBoundCidr);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set explicit maximum token TTL in seconds.
|
||||
*
|
||||
* @param tokenExplicitMaxTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) {
|
||||
this.tokenExplicitMaxTtl = tokenExplicitMaxTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable default policy for generated token.
|
||||
*
|
||||
* @param tokenNoDefaultPolicy Enable default policy for token?
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenNoDefaultPolicy(final Boolean tokenNoDefaultPolicy) {
|
||||
this.tokenNoDefaultPolicy = tokenNoDefaultPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of uses for generated tokens.
|
||||
*
|
||||
* @param tokenNumUses number of uses for tokens
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenNumUses(final Integer tokenNumUses) {
|
||||
this.tokenNumUses = tokenNumUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param tokenPeriod period in seconds
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenPeriod(final Integer tokenPeriod) {
|
||||
this.tokenPeriod = tokenPeriod;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param tokenPeriod period in seconds
|
||||
* @return self
|
||||
* @since 0.9
|
||||
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public AppRoleBuilder wit0hTokenPeriod(final Integer tokenPeriod) {
|
||||
return withTokenPeriod(tokenPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param period period in seconds
|
||||
* @return self
|
||||
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public AppRoleBuilder withPeriod(final Integer period) {
|
||||
return withTokenPeriod(period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type of generated token.
|
||||
*
|
||||
* @param tokenType token type
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public AppRoleBuilder withTokenType(final Token.Type tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the AppRole role based on given parameters.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public AppRole build() {
|
||||
return new AppRole(
|
||||
name,
|
||||
id,
|
||||
bindSecretId,
|
||||
secretIdBoundCidrs,
|
||||
secretIdNumUses,
|
||||
secretIdTtl,
|
||||
enableLocalSecretIds,
|
||||
tokenTtl,
|
||||
tokenMaxTtl,
|
||||
tokenPolicies,
|
||||
tokenBoundCidrs,
|
||||
tokenExplicitMaxTtl,
|
||||
tokenNoDefaultPolicy,
|
||||
tokenNumUses,
|
||||
tokenPeriod,
|
||||
tokenType != null ? tokenType.value() : null
|
||||
);
|
||||
}
|
||||
}
|
@ -98,71 +98,6 @@ public final class Token {
|
||||
public Token() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct complete {@link Token} object with default type.
|
||||
*
|
||||
* @param id Token ID (optional)
|
||||
* @param displayName Token display name (optional)
|
||||
* @param noParent Token has no parent (optional)
|
||||
* @param noDefaultPolicy Do not add default policy (optional)
|
||||
* @param ttl Token TTL in seconds (optional)
|
||||
* @param numUses Number of uses (optional)
|
||||
* @param policies List of policies (optional)
|
||||
* @param meta Metadata (optional)
|
||||
* @param renewable Is the token renewable (optional)
|
||||
* @deprecated As of 0.9 in favor of {@link #builder()}. Will be removed with next major release.
|
||||
*/
|
||||
@Deprecated
|
||||
public Token(final String id,
|
||||
final String displayName,
|
||||
final Boolean noParent,
|
||||
final Boolean noDefaultPolicy,
|
||||
final Integer ttl,
|
||||
final Integer numUses,
|
||||
final List<String> policies,
|
||||
final Map<String, String> meta,
|
||||
final Boolean renewable) {
|
||||
this(id, Type.DEFAULT.value(), displayName, noParent, noDefaultPolicy, ttl, numUses, policies, meta, renewable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct complete {@link Token} object.
|
||||
*
|
||||
* @param id Token ID (optional)
|
||||
* @param type Token type (optional)
|
||||
* @param displayName Token display name (optional)
|
||||
* @param noParent Token has no parent (optional)
|
||||
* @param noDefaultPolicy Do not add default policy (optional)
|
||||
* @param ttl Token TTL in seconds (optional)
|
||||
* @param numUses Number of uses (optional)
|
||||
* @param policies List of policies (optional)
|
||||
* @param meta Metadata (optional)
|
||||
* @param renewable Is the token renewable (optional)
|
||||
* @deprecated As of 0.9 in favor of {@link #builder()}. Will be removed with next major release.
|
||||
*/
|
||||
@Deprecated
|
||||
public Token(final String id,
|
||||
final String type,
|
||||
final String displayName,
|
||||
final Boolean noParent,
|
||||
final Boolean noDefaultPolicy,
|
||||
final Integer ttl,
|
||||
final Integer numUses,
|
||||
final List<String> policies,
|
||||
final Map<String, String> meta,
|
||||
final Boolean renewable) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.displayName = displayName;
|
||||
this.ttl = ttl;
|
||||
this.numUses = numUses;
|
||||
this.noParent = noParent;
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
this.policies = policies;
|
||||
this.meta = meta;
|
||||
this.renewable = renewable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link Token} object from {@link Builder}.
|
||||
*
|
||||
|
@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A builder for vault tokens.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
* @deprecated As of 0.9 in favor of {@link Token.Builder}.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class TokenBuilder {
|
||||
private String id;
|
||||
private Token.Type type;
|
||||
private String displayName;
|
||||
private Boolean noParent;
|
||||
private Boolean noDefaultPolicy;
|
||||
private Integer ttl;
|
||||
private Integer numUses;
|
||||
private List<String> policies;
|
||||
private Map<String, String> meta;
|
||||
private Boolean renewable;
|
||||
|
||||
/**
|
||||
* Add token ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify token type.
|
||||
*
|
||||
* @param type the type
|
||||
* @return self
|
||||
* @since 0.9
|
||||
*/
|
||||
public TokenBuilder withType(final Token.Type type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add display name.
|
||||
*
|
||||
* @param displayName the display name
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDisplayName(final String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired time to live.
|
||||
*
|
||||
* @param ttl the ttl
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withTtl(final Integer ttl) {
|
||||
this.ttl = ttl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired number of uses.
|
||||
*
|
||||
* @param numUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNumUses(final Integer numUses) {
|
||||
this.numUses = numUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the token should be created without parent.
|
||||
*
|
||||
* @param noParent if TRUE, token is created as orphan
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoParent(final boolean noParent) {
|
||||
this.noParent = noParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token without parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder asOrphan() {
|
||||
return withNoParent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token with parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withParent() {
|
||||
return withNoParent(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the default policy should not be part of this token.
|
||||
*
|
||||
* @param noDefaultPolicy if TRUE, default policy is not attached
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoDefaultPolicy(final boolean noDefaultPolicy) {
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDefaultPolicy() {
|
||||
return withNoDefaultPolicy(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withoutDefaultPolicy() {
|
||||
return withNoDefaultPolicy(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
* @since 0.5.0
|
||||
*/
|
||||
public TokenBuilder withPolicies(final String... policies) {
|
||||
return withPolicies(Arrays.asList(policies));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicies(final List<String> policies) {
|
||||
if (this.policies == null) {
|
||||
this.policies = new ArrayList<>();
|
||||
}
|
||||
this.policies.addAll(policies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicy(final String policy) {
|
||||
if (this.policies == null) {
|
||||
this.policies = new ArrayList<>();
|
||||
}
|
||||
policies.add(policy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param meta the metadata
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final Map<String, String> meta) {
|
||||
if (this.meta == null) {
|
||||
this.meta = new HashMap<>();
|
||||
}
|
||||
this.meta.putAll(meta);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final String key, final String value) {
|
||||
if (this.meta == null) {
|
||||
this.meta = new HashMap<>();
|
||||
}
|
||||
this.meta.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if token is renewable.
|
||||
*
|
||||
* @param renewable TRUE, if renewable
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withRenewable(final Boolean renewable) {
|
||||
this.renewable = renewable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder renewable() {
|
||||
return withRenewable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be not renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder notRenewable() {
|
||||
return withRenewable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the token based on given parameters.
|
||||
*
|
||||
* @return the token
|
||||
*/
|
||||
public Token build() {
|
||||
return new Token(id,
|
||||
type != null ? type.value() : null,
|
||||
displayName,
|
||||
noParent,
|
||||
noDefaultPolicy,
|
||||
ttl,
|
||||
numUses,
|
||||
policies,
|
||||
meta,
|
||||
renewable);
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ public final class AppRoleResponse extends VaultDataResponse {
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
|
||||
|
@ -37,7 +37,7 @@ public final class AppRoleSecretResponse extends VaultDataResponse {
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
|
||||
|
@ -28,8 +28,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Authentication method response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethodsResponse extends VaultDataResponse {
|
||||
@ -44,7 +44,7 @@ public final class AuthMethodsResponse extends VaultDataResponse {
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
try {
|
||||
this.supportedMethods.put(entry.getKey(),
|
||||
|
@ -45,7 +45,7 @@ public final class AuthResponse extends VaultDataResponse {
|
||||
*/
|
||||
@JsonProperty("auth")
|
||||
public void setAuth(final Map<String, Object> auth) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
this.auth = mapper.readValue(mapper.writeValueAsString(auth), AuthData.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -21,8 +21,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
/**
|
||||
* Vault response from credentials lookup. Simple wrapper for data objects containing username and password fields.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class CredentialsResponse extends SecretResponse {
|
||||
|
@ -24,8 +24,8 @@ import java.util.List;
|
||||
/**
|
||||
* Vault response in case of errors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class ErrorResponse implements VaultResponse {
|
||||
|
@ -22,8 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
/**
|
||||
* Vault response for health query.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class HealthResponse implements VaultResponse {
|
||||
|
@ -22,8 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
/**
|
||||
* Vault response for help request.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class HelpResponse implements VaultResponse {
|
||||
|
@ -37,7 +37,7 @@ public class MetadataResponse extends VaultDataResponse {
|
||||
|
||||
@Override
|
||||
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
this.metadata = mapper.readValue(mapper.writeValueAsString(data), SecretMetadata.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -23,8 +23,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Simple Vault data response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class RawDataResponse extends VaultDataResponse {
|
||||
|
@ -44,7 +44,7 @@ public class SecretResponse extends VaultDataResponse {
|
||||
if (data.size() == 2
|
||||
&& data.containsKey(KEY_DATA) && data.get(KEY_DATA) instanceof Map
|
||||
&& data.containsKey(KEY_METADATA) && data.get(KEY_METADATA) instanceof Map) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
// This is apparently a KV v2 value.
|
||||
this.data = (Map<String, Object>) data.get(KEY_DATA);
|
||||
@ -95,37 +95,6 @@ public class SecretResponse extends VaultDataResponse {
|
||||
return getData().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data element for key "value".
|
||||
* Method for backwards compatibility in case of simple secrets.
|
||||
*
|
||||
* @return the value
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final String getValue() {
|
||||
Object value = get("value");
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON.
|
||||
*
|
||||
* @param type Class to parse response
|
||||
* @param <T> Class to parse response
|
||||
* @return Parsed object
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.3
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final <T> T getValue(final Class<T> type) throws InvalidResponseException {
|
||||
return get("value", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON.
|
||||
*
|
||||
|
@ -37,7 +37,7 @@ public class SecretVersionResponse extends VaultDataResponse {
|
||||
|
||||
@Override
|
||||
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
this.metadata = mapper.readValue(mapper.writeValueAsString(data), VersionMetadata.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -46,7 +46,7 @@ public final class TokenResponse extends VaultDataResponse {
|
||||
*/
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenData.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -43,7 +43,7 @@ public final class TokenRoleResponse extends VaultDataResponse {
|
||||
*/
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
try {
|
||||
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenRole.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.model.response;
|
||||
/**
|
||||
* Marker interface for responses from Vault backend.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface VaultResponse {
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Embedded authorization information inside Vault response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthData {
|
||||
|
@ -26,8 +26,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Embedded authentication method response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethod {
|
||||
|
@ -27,8 +27,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Embedded metadata for Key-Value v2 secrets.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class SecretMetadata {
|
||||
|
@ -26,8 +26,8 @@ import java.time.format.DateTimeParseException;
|
||||
/**
|
||||
* Embedded metadata for a single Key-Value v2 version.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class VersionMetadata {
|
||||
|
36
src/main/java/module-info.java
Normal file
36
src/main/java/module-info.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JVaultConnector module.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
module de.stklcode.jvault.connector {
|
||||
exports de.stklcode.jvault.connector;
|
||||
exports de.stklcode.jvault.connector.exception;
|
||||
exports de.stklcode.jvault.connector.model;
|
||||
exports de.stklcode.jvault.connector.model.response;
|
||||
exports de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
opens de.stklcode.jvault.connector.model to com.fasterxml.jackson.databind;
|
||||
opens de.stklcode.jvault.connector.model.response to com.fasterxml.jackson.databind;
|
||||
opens de.stklcode.jvault.connector.model.response.embedded to com.fasterxml.jackson.databind;
|
||||
|
||||
requires java.base;
|
||||
requires java.net.http;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import com.github.stefanbirkner.systemlambda.SystemLambda;
|
||||
import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
||||
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector factory
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8.0
|
||||
*/
|
||||
class HTTPVaultConnectorBuilderTest {
|
||||
private static final String VAULT_ADDR = "https://localhost:8201";
|
||||
private static final Integer VAULT_MAX_RETRIES = 13;
|
||||
private static final String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||
|
||||
@TempDir
|
||||
File tempDir;
|
||||
|
||||
/**
|
||||
* Test the builder.
|
||||
*/
|
||||
@Test
|
||||
void builderTest() throws Exception {
|
||||
// Minimal configuration.
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder().withHost("vault.example.com").build();
|
||||
|
||||
assertEquals("https://vault.example.com:8200/v1/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
|
||||
assertNull(getRequestHelperPrivate(connector, "trustedCaCert"), "Trusted CA cert set when no cert provided");
|
||||
assertEquals(0, getRequestHelperPrivate(connector, "retries"), "Number of retries unexpectedly set");
|
||||
|
||||
// Specify all options.
|
||||
HTTPVaultConnectorBuilder builder = HTTPVaultConnector.builder()
|
||||
.withHost("vault2.example.com")
|
||||
.withoutTLS()
|
||||
.withPort(1234)
|
||||
.withPrefix("/foo/")
|
||||
.withTimeout(5678)
|
||||
.withNumberOfRetries(9);
|
||||
connector = builder.build();
|
||||
|
||||
assertEquals("http://vault2.example.com:1234/foo/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
|
||||
assertNull(getRequestHelperPrivate(connector, "trustedCaCert"), "Trusted CA cert set when no cert provided");
|
||||
assertEquals(9, getRequestHelperPrivate(connector, "retries"), "Unexpected number of retries");
|
||||
assertEquals(5678, getRequestHelperPrivate(connector, "timeout"), "Number timeout value");
|
||||
assertThrows(ConnectionException.class, builder::buildAndAuth, "Immediate authentication should throw exception without token");
|
||||
|
||||
// Initialization from URL.
|
||||
assertThrows(
|
||||
URISyntaxException.class,
|
||||
() -> HTTPVaultConnector.builder().withBaseURL("foo:/\\1nv4l1d_UrL"),
|
||||
"Initialization from invalid URL should fail"
|
||||
);
|
||||
connector = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().withBaseURL("https://vault3.example.com:5678/bar/").build(),
|
||||
"Initialization from valid URL should not fail"
|
||||
);
|
||||
assertEquals("https://vault3.example.com:5678/bar/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
|
||||
|
||||
// Port numbers.
|
||||
assertThrows(IllegalArgumentException.class, () -> HTTPVaultConnector.builder().withPort(65536), "Too large port number should throw an exception");
|
||||
assertThrows(IllegalArgumentException.class, () -> HTTPVaultConnector.builder().withPort(0), "Port number 0 should throw an exception");
|
||||
builder = assertDoesNotThrow(() -> HTTPVaultConnector.builder().withPort(-1), "Port number -1 should not throw an exception");
|
||||
assertNull(builder.getPort(), "Port number -1 should be omitted");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test building from environment variables
|
||||
*/
|
||||
@Test
|
||||
void testFromEnv() throws Exception {
|
||||
// Provide address only should be enough.
|
||||
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
assertEquals(VAULT_ADDR + "/v1/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
|
||||
assertNull(getRequestHelperPrivate(connector, "trustedCaCert"), "Trusted CA cert set when no cert provided");
|
||||
assertEquals(0, getRequestHelperPrivate(connector, "retries"), "Non-default number of retries, when none set");
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// Provide address and number of retries.
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
assertEquals(VAULT_ADDR + "/v1/", getRequestHelperPrivate(connector, "baseURL"), "URL not set correctly");
|
||||
assertNull(getRequestHelperPrivate(connector, "trustedCaCert"), "Trusted CA cert set when no cert provided");
|
||||
assertEquals(VAULT_MAX_RETRIES, getRequestHelperPrivate(connector, "retries"), "Number of retries not set correctly");
|
||||
|
||||
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(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
assertEquals(VAULT_TOKEN, getPrivate(builder, "token"), "Token not set correctly");
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// Invalid URL.
|
||||
withVaultEnv("This is not a valid URL!", null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
|
||||
assertThrows(
|
||||
ConnectionException.class,
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Invalid URL from environment should raise an exception"
|
||||
);
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||
}
|
||||
|
||||
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.canAccess(target)) {
|
||||
return field.get(target);
|
||||
}
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
field.setAccessible(false);
|
||||
return value;
|
||||
}
|
||||
}
|
@ -16,37 +16,31 @@
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
|
||||
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.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector.
|
||||
@ -56,52 +50,43 @@ import static org.mockito.Mockito.*;
|
||||
* @since 0.7.0
|
||||
*/
|
||||
class HTTPVaultConnectorOfflineTest {
|
||||
private static final String INVALID_URL = "foo:/\\1nv4l1d_UrL";
|
||||
|
||||
private static MockedStatic<HttpClientBuilder> hcbMock;
|
||||
private static CloseableHttpClient httpMock;
|
||||
private final CloseableHttpResponse responseMock = mock(CloseableHttpResponse.class);
|
||||
private static WireMockServer wireMock;
|
||||
|
||||
@BeforeAll
|
||||
static void prepare() {
|
||||
// Mock the static HTTPClient creation.
|
||||
hcbMock = mockStatic(HttpClientBuilder.class);
|
||||
hcbMock.when(HttpClientBuilder::create).thenReturn(new MockedHttpClientBuilder());
|
||||
// Initialize HTTP mock.
|
||||
wireMock = new WireMockServer(WireMockConfiguration.options().dynamicPort());
|
||||
wireMock.start();
|
||||
WireMock.configureFor("localhost", wireMock.port());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
hcbMock.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
// Re-initialize HTTP mock to ensure fresh (empty) results.
|
||||
httpMock = mock(CloseableHttpClient.class);
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
wireMock.stop();
|
||||
wireMock = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test exceptions thrown during request.
|
||||
*/
|
||||
@Test
|
||||
void requestExceptionTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("http://127.0.0.1", null, 0, 250);
|
||||
void requestExceptionTest() throws IOException, URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
|
||||
// Test invalid response code.
|
||||
final int responseCode = 400;
|
||||
mockResponse(responseCode, "", ContentType.APPLICATION_JSON);
|
||||
InvalidResponseException e = assertThrows(
|
||||
mockHttpResponse(responseCode, "", "application/json");
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Invalid response code"));
|
||||
assertThat("Unexpected status code in exception", ((InvalidResponseException) e).getStatusCode(), is(responseCode));
|
||||
assertThat("Response message where none was expected", ((InvalidResponseException) e).getResponse(), is(nullValue()));
|
||||
assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message");
|
||||
assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception");
|
||||
assertNull(((InvalidResponseException) e).getResponse(), "Response message where none was expected");
|
||||
|
||||
// Simulate permission denied response.
|
||||
mockResponse(responseCode, "{\"errors\":[\"permission denied\"]}", ContentType.APPLICATION_JSON);
|
||||
mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json");
|
||||
assertThrows(
|
||||
PermissionDeniedException.class,
|
||||
connector::getHealth,
|
||||
@ -109,25 +94,27 @@ class HTTPVaultConnectorOfflineTest {
|
||||
);
|
||||
|
||||
// Test exception thrown during request.
|
||||
when(httpMock.execute(any())).thenThrow(new IOException("Test Exception"));
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build();
|
||||
}
|
||||
e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Unable to read response"));
|
||||
assertThat("Unexpected cause", e.getCause(), instanceOf(IOException.class));
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
assertTrue(e.getCause() instanceof IOException, "Unexpected cause");
|
||||
|
||||
// Now simulate a failing request that succeeds on second try.
|
||||
connector = new HTTPVaultConnector("https://127.0.0.1", null, 1, 250);
|
||||
doReturn(responseMock).doReturn(responseMock).when(httpMock).execute(any());
|
||||
doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, ""))
|
||||
.when(responseMock).getStatusLine();
|
||||
when(responseMock.getEntity()).thenReturn(new StringEntity("{}", ContentType.APPLICATION_JSON));
|
||||
connector = HTTPVaultConnector.builder(wireMock.url("/")).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"))
|
||||
);
|
||||
assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly");
|
||||
}
|
||||
|
||||
@ -135,13 +122,13 @@ class HTTPVaultConnectorOfflineTest {
|
||||
* Test constructors of the {@link HTTPVaultConnector} class.
|
||||
*/
|
||||
@Test
|
||||
void constructorTest() throws IOException, CertificateException {
|
||||
void constructorTest() throws IOException, CertificateException, URISyntaxException {
|
||||
final String url = "https://vault.example.net/test/";
|
||||
final String hostname = "vault.example.com";
|
||||
final Integer port = 1337;
|
||||
final String prefix = "/custom/prefix/";
|
||||
final int retries = 42;
|
||||
final String expectedNoTls = "http://" + hostname + "/v1/";
|
||||
final String expectedNoTls = "http://" + hostname + ":8200/v1/";
|
||||
final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/";
|
||||
final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix;
|
||||
X509Certificate trustedCaCert;
|
||||
@ -151,94 +138,79 @@ class HTTPVaultConnectorOfflineTest {
|
||||
}
|
||||
|
||||
// Most basic constructor expects complete URL.
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector(url);
|
||||
assertThat("Unexpected base URL", getRequestHelperPrivate(connector, "baseURL"), is(url));
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(url).build();
|
||||
assertEquals(url, getRequestHelperPrivate(connector, "baseURL"), "Unexpected base URL");
|
||||
|
||||
// Now override TLS usage.
|
||||
connector = new HTTPVaultConnector(hostname, false);
|
||||
assertThat("Unexpected base URL with TLS disabled", getRequestHelperPrivate(connector, "baseURL"), is(expectedNoTls));
|
||||
connector = HTTPVaultConnector.builder().withHost(hostname).withoutTLS().build();
|
||||
assertEquals(expectedNoTls, getRequestHelperPrivate(connector, "baseURL"), "Unexpected base URL with TLS disabled");
|
||||
|
||||
// Specify custom port.
|
||||
connector = new HTTPVaultConnector(hostname, true, port);
|
||||
assertThat("Unexpected base URL with custom port", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPort));
|
||||
connector = HTTPVaultConnector.builder().withHost(hostname).withTLS().withPort(port).build();
|
||||
assertEquals(expectedCustomPort, getRequestHelperPrivate(connector, "baseURL"), "Unexpected base URL with custom port");
|
||||
|
||||
// Specify custom prefix.
|
||||
connector = new HTTPVaultConnector(hostname, true, port, prefix);
|
||||
assertThat("Unexpected base URL with custom prefix", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||
assertThat("Trusted CA cert set, but not specified", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||
|
||||
// Provide custom SSL context.
|
||||
connector = new HTTPVaultConnector(hostname, true, port, prefix, trustedCaCert);
|
||||
assertThat("Unexpected base URL with custom prefix", getRequestHelperPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||
assertThat("Trusted CA cert not filled correctly", getRequestHelperPrivate(connector, "trustedCaCert"), is(trustedCaCert));
|
||||
connector = HTTPVaultConnector.builder().withHost(hostname).withTLS().withPort(port).withPrefix(prefix).build();
|
||||
assertEquals(expectedCustomPrefix, getRequestHelperPrivate(connector, "baseURL"), "Unexpected base URL with custom prefix");
|
||||
assertNull(getRequestHelperPrivate(connector, "trustedCaCert"), "Trusted CA cert set, but not specified");
|
||||
|
||||
// Specify number of retries.
|
||||
connector = new HTTPVaultConnector(url, trustedCaCert, retries);
|
||||
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(retries));
|
||||
connector = HTTPVaultConnector.builder(url).withTrustedCA(trustedCaCert).withNumberOfRetries(retries).build();
|
||||
assertEquals(retries, getRequestHelperPrivate(connector, "retries"), "Number of retries not set correctly");
|
||||
|
||||
// Test TLS version (#22).
|
||||
assertThat("TLS version should be 1.2 if not specified", getRequestHelperPrivate(connector, "tlsVersion"), is("TLSv1.2"));
|
||||
assertEquals("TLSv1.2", getRequestHelperPrivate(connector, "tlsVersion"), "TLS version should be 1.2 if not specified");
|
||||
// Now override.
|
||||
connector = new HTTPVaultConnector(url, trustedCaCert, retries, null, "TLSv1.1");
|
||||
assertThat("Overridden TLS version 1.1 not correct", getRequestHelperPrivate(connector, "tlsVersion"), is("TLSv1.1"));
|
||||
connector = HTTPVaultConnector.builder(url).withTrustedCA(trustedCaCert).withNumberOfRetries(retries).withTLS("TLSv1.1").build();
|
||||
assertEquals("TLSv1.1", getRequestHelperPrivate(connector, "tlsVersion"), "Overridden TLS version 1.1 not correct");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||
*/
|
||||
@Test
|
||||
void sealExceptionTest() {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidRequestException.class,
|
||||
connector::sealStatus,
|
||||
"Querying seal status succeeded on invalid URL"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
|
||||
|
||||
// Simulate NULL response (mock not supplied with data).
|
||||
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
void sealExceptionTest() throws IOException, URISyntaxException {
|
||||
// Simulate no connection.
|
||||
VaultConnector connector;
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort()).withTimeout(250).build();
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::sealStatus,
|
||||
"Querying seal status succeeded on invalid instance"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||
*/
|
||||
@Test
|
||||
void healthExceptionTest() {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidRequestException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid URL"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
|
||||
|
||||
// Simulate NULL response (mock not supplied with data).
|
||||
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
void healthExceptionTest() throws IOException, URISyntaxException {
|
||||
// Simulate no connection.
|
||||
HTTPVaultConnector connector;
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
connector = HTTPVaultConnector.builder("http://localhost:" + s.getLocalPort() + "/").withTimeout(250).build();
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behavior on unparsable responses.
|
||||
*/
|
||||
@Test
|
||||
void parseExceptionTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
void parseExceptionTest() throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
mockResponse(200, "invalid", ContentType.APPLICATION_JSON);
|
||||
mockHttpResponse(200, "invalid", "application/json");
|
||||
|
||||
// Now test the methods.
|
||||
assertParseError(connector::sealStatus, "sealStatus() succeeded on invalid instance");
|
||||
@ -260,19 +232,19 @@ class HTTPVaultConnectorOfflineTest {
|
||||
|
||||
private void assertParseError(Executable executable, String message) {
|
||||
InvalidResponseException e = assertThrows(InvalidResponseException.class, executable, message);
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Unable to parse response"));
|
||||
assertEquals("Unable to parse response", e.getMessage(), "Unexpected exception message");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test requests that expect an empty response with code 204, but receive a 200 body.
|
||||
*/
|
||||
@Test
|
||||
void nonEmpty204ResponseTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
void nonEmpty204ResponseTest() throws URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.url("/")).withTimeout(250).build();
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
mockResponse(200, "{}", ContentType.APPLICATION_JSON);
|
||||
mockHttpResponse(200, "{}", "application/json");
|
||||
|
||||
// Now test the methods expecting a 204.
|
||||
assertThrows(
|
||||
@ -361,20 +333,11 @@ class HTTPVaultConnectorOfflineTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void mockResponse(int status, String body, ContentType type) throws IOException {
|
||||
when(httpMock.execute(any())).thenReturn(responseMock);
|
||||
when(responseMock.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), status, ""));
|
||||
when(responseMock.getEntity()).thenReturn(new StringEntity(body, type));
|
||||
private void mockHttpResponse(int status, String body, String contentType) {
|
||||
WireMock.stubFor(
|
||||
WireMock.any(anyUrl()).willReturn(
|
||||
aResponse().withStatus(status).withBody(body).withHeader("Content-Type", contentType)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocked {@link HttpClientBuilder} that always returns the mocked client.
|
||||
*/
|
||||
private static class MockedHttpClientBuilder extends HttpClientBuilder {
|
||||
@Override
|
||||
public CloseableHttpClient build() {
|
||||
return httpMock;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.builder;
|
||||
|
||||
import com.github.stefanbirkner.systemlambda.SystemLambda;
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnectorBuilder;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
||||
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector factory
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.8.0
|
||||
*/
|
||||
class HTTPVaultConnectorBuilderTest {
|
||||
private static final String VAULT_ADDR = "https://localhost:8201";
|
||||
private static final Integer VAULT_MAX_RETRIES = 13;
|
||||
private static final String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||
|
||||
@TempDir
|
||||
File tempDir;
|
||||
|
||||
/**
|
||||
* Test building from environment variables
|
||||
*/
|
||||
@Test
|
||||
void testFromEnv() throws Exception {
|
||||
/* Provide address only should be enough */
|
||||
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||
assertThat("Non-default number of retries, when none set", getRequestHelperPrivate(connector, "retries"), is(0));
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
/* Provide address and number of retries */
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = builder.build();
|
||||
|
||||
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||
|
||||
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."
|
||||
);
|
||||
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
||||
assertThat(((NoSuchFileException) e.getCause()).getFile(), is(VAULT_CACERT));
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
/* Automatic authentication */
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
|
||||
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
|
||||
() -> HTTPVaultConnector.builder().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
assertThat("Token nor set correctly", getPrivate(builder, "token"), is(equalTo(VAULT_TOKEN)));
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||
}
|
||||
|
||||
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.isAccessible()) {
|
||||
return field.get(target);
|
||||
}
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
field.setAccessible(false);
|
||||
return value;
|
||||
}
|
||||
}
|
@ -18,10 +18,8 @@ package de.stklcode.jvault.connector.exception;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
/**
|
||||
* Common JUnit test for Exceptions extending {@link VaultConnectorException}.
|
||||
@ -65,42 +63,39 @@ class VaultConnectorExceptionTest {
|
||||
|
||||
// Constructor with message and status code.
|
||||
InvalidResponseException e = new InvalidResponseException(MSG, STATUS_CODE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(nullValue()));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertNull(e.getCause());
|
||||
assertEquals(STATUS_CODE, e.getStatusCode());
|
||||
assertNull(e.getResponse());
|
||||
|
||||
// Constructor with message, status code and cause.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, CAUSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(nullValue()));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertEquals(CAUSE, e.getCause());
|
||||
assertEquals(STATUS_CODE, e.getStatusCode());
|
||||
assertNull(e.getResponse());
|
||||
|
||||
// Constructor with message, status code and response.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, RESPONSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(RESPONSE));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertNull(e.getCause());
|
||||
assertEquals(STATUS_CODE, e.getStatusCode());
|
||||
assertEquals(RESPONSE, e.getResponse());
|
||||
|
||||
// Constructor with message, status code, response and cause.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, RESPONSE, CAUSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(RESPONSE));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertEquals(CAUSE, e.getCause());
|
||||
assertEquals(STATUS_CODE, e.getStatusCode());
|
||||
assertEquals(RESPONSE, e.getResponse());
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionDeniedExceptionTest() {
|
||||
// Default message overwritten.
|
||||
PermissionDeniedException e = new PermissionDeniedException();
|
||||
assertThat(e, is(instanceOf(VaultConnectorException.class)));
|
||||
assertThat(e, is(instanceOf(Exception.class)));
|
||||
assertThat(e, is(instanceOf(Throwable.class)));
|
||||
assertThat(e.getMessage(), is("Permission denied"));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertEquals("Permission denied", e.getMessage());
|
||||
assertNull(e.getCause());
|
||||
|
||||
assertMsgConstructor(new PermissionDeniedException(MSG));
|
||||
assertCauseConstructor(new PermissionDeniedException(CAUSE));
|
||||
@ -121,11 +116,8 @@ class VaultConnectorExceptionTest {
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertEmptyConstructor(VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(VaultConnectorException.class)));
|
||||
assertThat(e, is(instanceOf(Exception.class)));
|
||||
assertThat(e, is(instanceOf(Throwable.class)));
|
||||
assertThat(e.getMessage(), is(nullValue()));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertNull(e.getMessage());
|
||||
assertNull(e.getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,8 +126,8 @@ class VaultConnectorExceptionTest {
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertMsgConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertNull(e.getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,8 +136,8 @@ class VaultConnectorExceptionTest {
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertCauseConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(CAUSE.toString()));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertEquals(CAUSE.toString(), e.getMessage());
|
||||
assertEquals(CAUSE, e.getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +146,7 @@ class VaultConnectorExceptionTest {
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertMsgCauseConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertEquals(MSG, e.getMessage());
|
||||
assertEquals(CAUSE, e.getCause());
|
||||
}
|
||||
}
|
||||
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import com.github.stefanbirkner.systemlambda.SystemLambda;
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
||||
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector factory
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.0
|
||||
*/
|
||||
class HTTPVaultConnectorFactoryTest {
|
||||
private static String VAULT_ADDR = "https://localhost:8201";
|
||||
private static Integer VAULT_MAX_RETRIES = 13;
|
||||
private static String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777";
|
||||
|
||||
@TempDir
|
||||
File tempDir;
|
||||
|
||||
/**
|
||||
* Test building from environment variables
|
||||
*/
|
||||
@Test
|
||||
void testFromEnv() throws Exception {
|
||||
/* Provide address only should be enough */
|
||||
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
|
||||
HTTPVaultConnectorFactory factory = assertDoesNotThrow(
|
||||
() -> VaultConnectorFactory.httpFactory().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = factory.build();
|
||||
|
||||
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||
assertThat("Non-default number of retries, when none set", getRequestHelperPrivate(connector, "retries"), is(0));
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
/* Provide address and number of retries */
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
|
||||
HTTPVaultConnectorFactory factory = assertDoesNotThrow(
|
||||
() -> VaultConnectorFactory.httpFactory().fromEnv(),
|
||||
"Factory creation from environment failed"
|
||||
);
|
||||
HTTPVaultConnector connector = factory.build();
|
||||
|
||||
assertThat("URL nor set correctly", getRequestHelperPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("Trusted CA cert set when no cert provided", getRequestHelperPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||
assertThat("Number of retries not set correctly", getRequestHelperPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||
|
||||
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,
|
||||
() -> VaultConnectorFactory.httpFactory().fromEnv(),
|
||||
"Creation with unknown cert path failed."
|
||||
);
|
||||
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
||||
assertThat(((NoSuchFileException) e.getCause()).getFile(), is(VAULT_CACERT));
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
/* Automatic authentication */
|
||||
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
|
||||
HTTPVaultConnectorFactory factory = assertDoesNotThrow(
|
||||
() -> VaultConnectorFactory.httpFactory().fromEnv(),
|
||||
"Factory creation from minimal environment failed"
|
||||
);
|
||||
assertThat("Token nor set correctly", getPrivate(getPrivate(factory, "delegate"), "token"), is(equalTo(VAULT_TOKEN)));
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getPrivate(getPrivate(connector, "request"), fieldName);
|
||||
}
|
||||
|
||||
private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.isAccessible()) {
|
||||
return field.get(target);
|
||||
}
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
field.setAccessible(false);
|
||||
return value;
|
||||
}
|
||||
}
|
@ -1,299 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for AppRole Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
class AppRoleBuilderTest {
|
||||
private static final String NAME = "TestRole";
|
||||
private static final String ID = "test-id";
|
||||
private static final Boolean BIND_SECRET_ID = true;
|
||||
private static final List<String> BOUND_CIDR_LIST = new ArrayList<>();
|
||||
private static final String CIDR_1 = "192.168.1.0/24";
|
||||
private static final String CIDR_2 = "172.16.0.0/16";
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
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 Integer TOKEN_TTL = 4800;
|
||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 14400;
|
||||
private static final Boolean TOKEN_NO_DEFAULT_POLICY = false;
|
||||
private static final Integer TOKEN_NUM_USES = 42;
|
||||
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());
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
BOUND_CIDR_LIST.add(CIDR_1);
|
||||
POLICIES.add(POLICY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build role with only a name.
|
||||
*/
|
||||
@Test
|
||||
void buildDefaultTest() throws JsonProcessingException {
|
||||
AppRole role = AppRole.builder(NAME).build();
|
||||
assertThat(role.getId(), is(nullValue()));
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
assertThat(role.getSecretIdBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenPolicies(), is(nullValue()));
|
||||
assertThat(role.getPolicies(), is(nullValue()));
|
||||
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
||||
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
||||
assertThat(role.getEnableLocalSecretIds(), is(nullValue()));
|
||||
assertThat(role.getTokenTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(role.getTokenNumUses(), is(nullValue()));
|
||||
assertThat(role.getTokenPeriod(), is(nullValue()));
|
||||
assertThat(role.getPeriod(), is(nullValue()));
|
||||
assertThat(role.getTokenType(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should only contain role_name */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build role with only a name.
|
||||
*/
|
||||
@Test
|
||||
void legacyBuildDefaultTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getId(), is(nullValue()));
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
assertThat(role.getSecretIdBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenPolicies(), is(nullValue()));
|
||||
assertThat(role.getPolicies(), is(nullValue()));
|
||||
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
||||
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
||||
assertThat(role.getEnableLocalSecretIds(), is(nullValue()));
|
||||
assertThat(role.getTokenTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(role.getTokenNumUses(), is(nullValue()));
|
||||
assertThat(role.getTokenPeriod(), is(nullValue()));
|
||||
assertThat(role.getPeriod(), is(nullValue()));
|
||||
assertThat(role.getTokenType(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should only contain role_name */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void buildFullTest() throws JsonProcessingException {
|
||||
AppRole role = AppRole.builder(NAME)
|
||||
.withId(ID)
|
||||
.withBindSecretID(BIND_SECRET_ID)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
|
||||
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
|
||||
.withTokenNumUses(TOKEN_NUM_USES)
|
||||
.withTokenPeriod(TOKEN_PERIOD)
|
||||
.withTokenType(TOKEN_TYPE)
|
||||
.build();
|
||||
assertThat(role.getName(), is(NAME));
|
||||
assertThat(role.getId(), is(ID));
|
||||
assertThat(role.getBindSecretId(), is(BIND_SECRET_ID));
|
||||
assertThat(role.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST));
|
||||
assertThat(role.getTokenPolicies(), is(POLICIES));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
||||
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
||||
assertThat(role.getEnableLocalSecretIds(), is(ENABLE_LOCAL_SECRET_IDS));
|
||||
assertThat(role.getTokenTtl(), is(TOKEN_TTL));
|
||||
assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL));
|
||||
assertThat(role.getTokenBoundCidrs(), is(BOUND_CIDR_LIST));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY));
|
||||
assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES));
|
||||
assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD));
|
||||
assertThat(role.getPeriod(), is(TOKEN_PERIOD));
|
||||
assertThat(role.getTokenType(), is(TOKEN_TYPE.value()));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void legacyBuildFullTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME)
|
||||
.withId(ID)
|
||||
.withBindSecretID(BIND_SECRET_ID)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
|
||||
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
|
||||
.withTokenNumUses(TOKEN_NUM_USES)
|
||||
.withTokenPeriod(TOKEN_PERIOD)
|
||||
.withTokenType(TOKEN_TYPE)
|
||||
.build();
|
||||
assertThat(role.getName(), is(NAME));
|
||||
assertThat(role.getId(), is(ID));
|
||||
assertThat(role.getBindSecretId(), is(BIND_SECRET_ID));
|
||||
assertThat(role.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST));
|
||||
assertThat(role.getTokenPolicies(), is(POLICIES));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
||||
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
||||
assertThat(role.getEnableLocalSecretIds(), is(ENABLE_LOCAL_SECRET_IDS));
|
||||
assertThat(role.getTokenTtl(), is(TOKEN_TTL));
|
||||
assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL));
|
||||
assertThat(role.getTokenBoundCidrs(), is(BOUND_CIDR_LIST));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY));
|
||||
assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES));
|
||||
assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD));
|
||||
assertThat(role.getPeriod(), is(TOKEN_PERIOD));
|
||||
assertThat(role.getTokenType(), is(TOKEN_TYPE.value()));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void convenienceMethodsTest() {
|
||||
/* bind_secret_id */
|
||||
AppRole role = AppRole.builder(NAME).build();
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
role = AppRole.builder(NAME).withBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(true));
|
||||
role = AppRole.builder(NAME).withoutBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(false));
|
||||
|
||||
/* Add single CIDR subnet */
|
||||
role = AppRole.builder(NAME).withSecretBoundCidr(CIDR_2).withTokenBoundCidr(CIDR_2).build();
|
||||
assertThat(role.getSecretIdBoundCidrs(), hasSize(1));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_2));
|
||||
assertThat(role.getTokenBoundCidrs(), hasSize(1));
|
||||
assertThat(role.getTokenBoundCidrs(), contains(CIDR_2));
|
||||
role = AppRole.builder(NAME)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withSecretBoundCidr(CIDR_2)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenBoundCidr(CIDR_2)
|
||||
.build();
|
||||
assertThat(role.getSecretIdBoundCidrs(), hasSize(2));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2));
|
||||
assertThat(role.getTokenBoundCidrs(), hasSize(2));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2));
|
||||
|
||||
/* Add single policy */
|
||||
role = AppRole.builder(NAME).withTokenPolicy(POLICY_2).build();
|
||||
assertThat(role.getTokenPolicies(), hasSize(1));
|
||||
assertThat(role.getTokenPolicies(), contains(POLICY_2));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
role = AppRole.builder(NAME)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withTokenPolicy(POLICY_2)
|
||||
.build();
|
||||
assertThat(role.getTokenPolicies(), hasSize(2));
|
||||
assertThat(role.getTokenPolicies(), contains(POLICY, POLICY_2));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void legacyConvenienceMethodsTest() {
|
||||
/* bind_secret_id */
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
role = new AppRoleBuilder(NAME).withBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(true));
|
||||
role = new AppRoleBuilder(NAME).withoutBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(false));
|
||||
|
||||
/* Add single CIDR subnet */
|
||||
role = new AppRoleBuilder(NAME).withSecretBoundCidr(CIDR_2).withTokenBoundCidr(CIDR_2).build();
|
||||
assertThat(role.getSecretIdBoundCidrs(), hasSize(1));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_2));
|
||||
assertThat(role.getTokenBoundCidrs(), hasSize(1));
|
||||
assertThat(role.getTokenBoundCidrs(), contains(CIDR_2));
|
||||
role = new AppRoleBuilder(NAME)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withSecretBoundCidr(CIDR_2)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenBoundCidr(CIDR_2)
|
||||
.build();
|
||||
assertThat(role.getSecretIdBoundCidrs(), hasSize(2));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2));
|
||||
assertThat(role.getTokenBoundCidrs(), hasSize(2));
|
||||
assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2));
|
||||
|
||||
/* Add single policy */
|
||||
role = new AppRoleBuilder(NAME).withTokenPolicy(POLICY_2).build();
|
||||
assertThat(role.getTokenPolicies(), hasSize(1));
|
||||
assertThat(role.getTokenPolicies(), contains(POLICY_2));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
role = new AppRoleBuilder(NAME)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withTokenPolicy(POLICY_2)
|
||||
.build();
|
||||
assertThat(role.getTokenPolicies(), hasSize(2));
|
||||
assertThat(role.getTokenPolicies(), contains(POLICY, POLICY_2));
|
||||
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
|
||||
}
|
||||
}
|
@ -25,9 +25,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
|
||||
@ -38,7 +36,6 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
* @since 0.5.0
|
||||
*/
|
||||
class AppRoleSecretTest {
|
||||
|
||||
private static final String TEST_ID = "abc123";
|
||||
private static final Map<String, Object> TEST_META = new HashMap<>();
|
||||
private static final List<String> TEST_CIDR = Arrays.asList("203.0.113.0/24", "198.51.100.0/24");
|
||||
@ -53,44 +50,44 @@ class AppRoleSecretTest {
|
||||
*/
|
||||
@Test
|
||||
void constructorTest() {
|
||||
/* Empty constructor */
|
||||
// Empty constructor.
|
||||
AppRoleSecret secret = new AppRoleSecret();
|
||||
assertThat(secret.getId(), is(nullValue()));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
assertNull(secret.getId());
|
||||
assertNull(secret.getAccessor());
|
||||
assertNull(secret.getMetadata());
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
assertNull(secret.getNumUses());
|
||||
assertNull(secret.getTtl());
|
||||
|
||||
/* Constructor with ID */
|
||||
// Constructor with ID.
|
||||
secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
assertEquals(TEST_ID, secret.getId());
|
||||
assertNull(secret.getAccessor());
|
||||
assertNull(secret.getMetadata());
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
assertNull(secret.getNumUses());
|
||||
assertNull(secret.getTtl());
|
||||
|
||||
/* Constructor with Metadata and CIDR bindings */
|
||||
// Constructor with Metadata and CIDR bindings.
|
||||
secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(TEST_META));
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
assertEquals(TEST_ID, secret.getId());
|
||||
assertNull(secret.getAccessor());
|
||||
assertEquals(TEST_META, secret.getMetadata());
|
||||
assertEquals(TEST_CIDR, secret.getCidrList());
|
||||
assertEquals(String.join(",", TEST_CIDR), secret.getCidrListString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
assertNull(secret.getNumUses());
|
||||
assertNull(secret.getTtl());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,14 +96,14 @@ class AppRoleSecretTest {
|
||||
@Test
|
||||
void setterTest() {
|
||||
AppRoleSecret secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
secret.setCidrList(TEST_CIDR);
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
assertEquals(TEST_CIDR, secret.getCidrList());
|
||||
assertEquals(String.join(",", TEST_CIDR), secret.getCidrListString());
|
||||
secret.setCidrList(null);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,21 +113,21 @@ class AppRoleSecretTest {
|
||||
void jsonTest() throws NoSuchFieldException, IllegalAccessException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
/* A simple roundtrip first. All set fields should be present afterwards. */
|
||||
// A simple roundtrip first. All set fields should be present afterwards..
|
||||
AppRoleSecret secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
|
||||
String secretJson = assertDoesNotThrow(() -> mapper.writeValueAsString(secret), "Serialization failed");
|
||||
/* CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list */
|
||||
// CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list.
|
||||
String secretJson2 = commaSeparatedToList(secretJson);
|
||||
|
||||
AppRoleSecret secret2 = assertDoesNotThrow(
|
||||
() -> mapper.readValue(secretJson2, AppRoleSecret.class),
|
||||
"Deserialization failed"
|
||||
);
|
||||
assertThat(secret.getId(), is(secret2.getId()));
|
||||
assertThat(secret.getMetadata(), is(secret2.getMetadata()));
|
||||
assertThat(secret.getCidrList(), is(secret2.getCidrList()));
|
||||
assertEquals(secret2.getId(), secret.getId());
|
||||
assertEquals(secret2.getMetadata(), secret.getMetadata());
|
||||
assertEquals(secret2.getCidrList(), secret.getCidrList());
|
||||
|
||||
/* Test fields, that should not be written to JSON */
|
||||
// Test fields, that should not be written to JSON.
|
||||
setPrivateField(secret, "accessor", "TEST_ACCESSOR");
|
||||
assumeTrue("TEST_ACCESSOR".equals(secret.getAccessor()));
|
||||
setPrivateField(secret, "creationTime", "TEST_CREATION");
|
||||
@ -148,28 +145,28 @@ class AppRoleSecretTest {
|
||||
() -> mapper.readValue(commaSeparatedToList(secretJson3), AppRoleSecret.class),
|
||||
"Deserialization failed"
|
||||
);
|
||||
assertThat(secret.getId(), is(secret2.getId()));
|
||||
assertThat(secret.getMetadata(), is(secret2.getMetadata()));
|
||||
assertThat(secret.getCidrList(), is(secret2.getCidrList()));
|
||||
assertThat(secret2.getAccessor(), is(nullValue()));
|
||||
assertThat(secret2.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret2.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret2.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret2.getNumUses(), is(nullValue()));
|
||||
assertThat(secret2.getTtl(), is(nullValue()));
|
||||
assertEquals(secret2.getId(), secret.getId());
|
||||
assertEquals(secret2.getMetadata(), secret.getMetadata());
|
||||
assertEquals(secret2.getCidrList(), secret.getCidrList());
|
||||
assertNull(secret2.getAccessor());
|
||||
assertNull(secret2.getCreationTime());
|
||||
assertNull(secret2.getExpirationTime());
|
||||
assertNull(secret2.getLastUpdatedTime());
|
||||
assertNull(secret2.getNumUses());
|
||||
assertNull(secret2.getTtl());
|
||||
|
||||
/* Those fields should be deserialized from JSON though */
|
||||
// Those fields should be deserialized from JSON though.
|
||||
String secretJson4 = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
|
||||
"\"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");
|
||||
assertThat(secret2.getAccessor(), is("TEST_ACCESSOR"));
|
||||
assertThat(secret2.getCreationTime(), is("TEST_CREATION"));
|
||||
assertThat(secret2.getExpirationTime(), is("TEST_EXPIRATION"));
|
||||
assertThat(secret2.getLastUpdatedTime(), is("TEST_LASTUPDATE"));
|
||||
assertThat(secret2.getNumUses(), is(678));
|
||||
assertThat(secret2.getTtl(), is(12345));
|
||||
assertEquals("TEST_ACCESSOR", secret2.getAccessor());
|
||||
assertEquals("TEST_CREATION", secret2.getCreationTime());
|
||||
assertEquals("TEST_EXPIRATION", secret2.getExpirationTime());
|
||||
assertEquals("TEST_LASTUPDATE", secret2.getLastUpdatedTime());
|
||||
assertEquals(678, secret2.getNumUses());
|
||||
assertEquals(12345, secret2.getTtl());
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AppRole} and {@link AppRole.Builder}.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
class AppRoleTest {
|
||||
private static final String NAME = "TestRole";
|
||||
private static final String ID = "test-id";
|
||||
private static final Boolean BIND_SECRET_ID = true;
|
||||
private static final List<String> BOUND_CIDR_LIST = new ArrayList<>();
|
||||
private static final String CIDR_1 = "192.168.1.0/24";
|
||||
private static final String CIDR_2 = "172.16.0.0/16";
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
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 Integer TOKEN_TTL = 4800;
|
||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 14400;
|
||||
private static final Boolean TOKEN_NO_DEFAULT_POLICY = false;
|
||||
private static final Integer TOKEN_NUM_USES = 42;
|
||||
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());
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
BOUND_CIDR_LIST.add(CIDR_1);
|
||||
POLICIES.add(POLICY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build role with only a name.
|
||||
*/
|
||||
@Test
|
||||
void buildDefaultTest() throws JsonProcessingException {
|
||||
AppRole role = AppRole.builder(NAME).build();
|
||||
assertNull(role.getId());
|
||||
assertNull(role.getBindSecretId());
|
||||
assertNull(role.getSecretIdBoundCidrs());
|
||||
assertNull(role.getTokenPolicies());
|
||||
assertNull(role.getSecretIdNumUses());
|
||||
assertNull(role.getSecretIdTtl());
|
||||
assertNull(role.getEnableLocalSecretIds());
|
||||
assertNull(role.getTokenTtl());
|
||||
assertNull(role.getTokenMaxTtl());
|
||||
assertNull(role.getTokenBoundCidrs());
|
||||
assertNull(role.getTokenExplicitMaxTtl());
|
||||
assertNull(role.getTokenNoDefaultPolicy());
|
||||
assertNull(role.getTokenNumUses());
|
||||
assertNull(role.getTokenPeriod());
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
// Optional fields should be ignored, so JSON string should only contain role_name.
|
||||
assertEquals(JSON_MIN, new ObjectMapper().writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void buildFullTest() throws JsonProcessingException {
|
||||
AppRole role = AppRole.builder(NAME)
|
||||
.withId(ID)
|
||||
.withBindSecretID(BIND_SECRET_ID)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
|
||||
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
|
||||
.withTokenNumUses(TOKEN_NUM_USES)
|
||||
.withTokenPeriod(TOKEN_PERIOD)
|
||||
.withTokenType(TOKEN_TYPE)
|
||||
.build();
|
||||
assertEquals(NAME, role.getName());
|
||||
assertEquals(ID, role.getId());
|
||||
assertEquals(BIND_SECRET_ID, role.getBindSecretId());
|
||||
assertEquals(BOUND_CIDR_LIST, role.getSecretIdBoundCidrs());
|
||||
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(TOKEN_TTL, role.getTokenTtl());
|
||||
assertEquals(TOKEN_MAX_TTL, role.getTokenMaxTtl());
|
||||
assertEquals(BOUND_CIDR_LIST, role.getTokenBoundCidrs());
|
||||
assertEquals(TOKEN_EXPLICIT_MAX_TTL, role.getTokenExplicitMaxTtl());
|
||||
assertEquals(TOKEN_NO_DEFAULT_POLICY, role.getTokenNoDefaultPolicy());
|
||||
assertEquals(TOKEN_NUM_USES, role.getTokenNumUses());
|
||||
assertEquals(TOKEN_PERIOD, role.getTokenPeriod());
|
||||
assertEquals(TOKEN_TYPE.value(), role.getTokenType());
|
||||
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void convenienceMethodsTest() {
|
||||
// bind_secret_id.
|
||||
AppRole role = AppRole.builder(NAME).build();
|
||||
assertNull(role.getBindSecretId());
|
||||
role = AppRole.builder(NAME).withBindSecretID().build();
|
||||
assertEquals(true, role.getBindSecretId());
|
||||
role = AppRole.builder(NAME).withoutBindSecretID().build();
|
||||
assertEquals(false, role.getBindSecretId());
|
||||
|
||||
// Add single CIDR subnet.
|
||||
role = AppRole.builder(NAME).withSecretBoundCidr(CIDR_2).withTokenBoundCidr(CIDR_2).build();
|
||||
assertEquals(1, role.getSecretIdBoundCidrs().size());
|
||||
assertEquals(CIDR_2, role.getSecretIdBoundCidrs().get(0));
|
||||
assertEquals(1, role.getTokenBoundCidrs().size());
|
||||
assertEquals(CIDR_2, role.getTokenBoundCidrs().get(0));
|
||||
role = AppRole.builder(NAME)
|
||||
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withSecretBoundCidr(CIDR_2)
|
||||
.withTokenBoundCidrs(BOUND_CIDR_LIST)
|
||||
.withTokenBoundCidr(CIDR_2)
|
||||
.build();
|
||||
assertEquals(2, role.getSecretIdBoundCidrs().size());
|
||||
assertTrue(role.getSecretIdBoundCidrs().containsAll(List.of(CIDR_1, CIDR_2)));
|
||||
assertEquals(2, role.getTokenBoundCidrs().size());
|
||||
assertTrue(role.getSecretIdBoundCidrs().containsAll(List.of(CIDR_1, CIDR_2)));
|
||||
|
||||
// Add single policy.
|
||||
role = AppRole.builder(NAME).withTokenPolicy(POLICY_2).build();
|
||||
assertEquals(1, role.getTokenPolicies().size());
|
||||
assertEquals(POLICY_2, role.getTokenPolicies().get(0));
|
||||
role = AppRole.builder(NAME)
|
||||
.withTokenPolicies(POLICIES)
|
||||
.withTokenPolicy(POLICY_2)
|
||||
.build();
|
||||
assertEquals(2, role.getTokenPolicies().size());
|
||||
assertTrue(role.getTokenPolicies().containsAll(List.of(POLICY, POLICY_2)));
|
||||
}
|
||||
}
|
@ -18,8 +18,8 @@ package de.stklcode.jvault.connector.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/**
|
||||
* JUnit Test for AuthBackend model.
|
||||
@ -34,12 +34,11 @@ class AuthBackendTest {
|
||||
*/
|
||||
@Test
|
||||
void forTypeTest() {
|
||||
assertThat(AuthBackend.forType("token"), is(AuthBackend.TOKEN));
|
||||
assertThat(AuthBackend.forType("app-id"), is(AuthBackend.APPID));
|
||||
assertThat(AuthBackend.forType("userpass"), is(AuthBackend.USERPASS));
|
||||
assertThat(AuthBackend.forType("github"), is(AuthBackend.GITHUB));
|
||||
assertThat(AuthBackend.forType(""), is(AuthBackend.UNKNOWN));
|
||||
assertThat(AuthBackend.forType("foobar"), is(AuthBackend.UNKNOWN));
|
||||
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(""));
|
||||
assertEquals(AuthBackend.UNKNOWN, AuthBackend.forType("foobar"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,276 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for Token Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
class TokenBuilderTest {
|
||||
private static final String ID = "test-id";
|
||||
private static final String DISPLAY_NAME = "display-name";
|
||||
private static final Boolean NO_PARENT = false;
|
||||
private static final Boolean NO_DEFAULT_POLICY = false;
|
||||
private static final Integer TTL = 123;
|
||||
private static final Integer EXPLICIT_MAX_TTL = 456;
|
||||
private static final Integer NUM_USES = 4;
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final String POLICY_3 = "policy3";
|
||||
private static final Map<String, String> META = new HashMap<>();
|
||||
private static final String META_KEY = "key";
|
||||
private static final String META_VALUE = "value";
|
||||
private static final String META_KEY_2 = "key2";
|
||||
private static final String META_VALUE_2 = "value2";
|
||||
private static final Boolean RENEWABLE = true;
|
||||
private static final Integer PERIOD = 3600;
|
||||
private static final String ENTITY_ALIAS = "alias-value";
|
||||
private static final String LEGACY_JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}";
|
||||
private static final String JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"explicit_max_ttl\":456,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true,\"period\":3600,\"entity_alias\":\"alias-value\"}";
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
POLICIES.add(POLICY);
|
||||
META.put(META_KEY, META_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without any parameters.
|
||||
*/
|
||||
@Test
|
||||
void buildDefaultTest() throws JsonProcessingException {
|
||||
Token token = Token.builder().build();
|
||||
assertThat(token.getId(), is(nullValue()));
|
||||
assertThat(token.getType(), is(nullValue()));
|
||||
assertThat(token.getDisplayName(), is(nullValue()));
|
||||
assertThat(token.getNoParent(), is(nullValue()));
|
||||
assertThat(token.getNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(token.getTtl(), is(nullValue()));
|
||||
assertThat(token.getExplicitMaxTtl(), is(nullValue()));
|
||||
assertThat(token.getNumUses(), is(nullValue()));
|
||||
assertThat(token.getPolicies(), is(nullValue()));
|
||||
assertThat(token.getMeta(), is(nullValue()));
|
||||
assertThat(token.isRenewable(), is(nullValue()));
|
||||
assertThat(token.getPeriod(), is(nullValue()));
|
||||
assertThat(token.getEntityAlias(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without any parameters.
|
||||
*/
|
||||
@Test
|
||||
void legacyBuildDefaultTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder().build();
|
||||
assertThat(token.getId(), is(nullValue()));
|
||||
assertThat(token.getType(), is(nullValue()));
|
||||
assertThat(token.getDisplayName(), is(nullValue()));
|
||||
assertThat(token.getNoParent(), is(nullValue()));
|
||||
assertThat(token.getNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(token.getTtl(), is(nullValue()));
|
||||
assertThat(token.getNumUses(), is(nullValue()));
|
||||
assertThat(token.getPolicies(), is(nullValue()));
|
||||
assertThat(token.getMeta(), is(nullValue()));
|
||||
assertThat(token.isRenewable(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void buildFullTest() throws JsonProcessingException {
|
||||
Token token = Token.builder()
|
||||
.withId(ID)
|
||||
.withType(Token.Type.SERVICE)
|
||||
.withDisplayName(DISPLAY_NAME)
|
||||
.withNoParent(NO_PARENT)
|
||||
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
|
||||
.withTtl(TTL)
|
||||
.withExplicitMaxTtl(EXPLICIT_MAX_TTL)
|
||||
.withNumUses(NUM_USES)
|
||||
.withPolicies(POLICIES)
|
||||
.withMeta(META)
|
||||
.withRenewable(RENEWABLE)
|
||||
.withPeriod(PERIOD)
|
||||
.withEntityAlias(ENTITY_ALIAS)
|
||||
.build();
|
||||
assertThat(token.getId(), is(ID));
|
||||
assertThat(token.getType(), is(Token.Type.SERVICE.value()));
|
||||
assertThat(token.getDisplayName(), is(DISPLAY_NAME));
|
||||
assertThat(token.getNoParent(), is(NO_PARENT));
|
||||
assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY));
|
||||
assertThat(token.getTtl(), is(TTL));
|
||||
assertThat(token.getExplicitMaxTtl(), is(EXPLICIT_MAX_TTL));
|
||||
assertThat(token.getNumUses(), is(NUM_USES));
|
||||
assertThat(token.getPolicies(), is(POLICIES));
|
||||
assertThat(token.getMeta(), is(META));
|
||||
assertThat(token.isRenewable(), is(RENEWABLE));
|
||||
assertThat(token.getPeriod(), is(PERIOD));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void legacyBuildFullTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder()
|
||||
.withId(ID)
|
||||
.withType(Token.Type.SERVICE)
|
||||
.withDisplayName(DISPLAY_NAME)
|
||||
.withNoParent(NO_PARENT)
|
||||
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
|
||||
.withTtl(TTL)
|
||||
.withNumUses(NUM_USES)
|
||||
.withPolicies(POLICIES)
|
||||
.withMeta(META)
|
||||
.withRenewable(RENEWABLE)
|
||||
.build();
|
||||
assertThat(token.getId(), is(ID));
|
||||
assertThat(token.getType(), is(Token.Type.SERVICE.value()));
|
||||
assertThat(token.getDisplayName(), is(DISPLAY_NAME));
|
||||
assertThat(token.getNoParent(), is(NO_PARENT));
|
||||
assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY));
|
||||
assertThat(token.getTtl(), is(TTL));
|
||||
assertThat(token.getNumUses(), is(NUM_USES));
|
||||
assertThat(token.getPolicies(), is(POLICIES));
|
||||
assertThat(token.getMeta(), is(META));
|
||||
assertThat(token.isRenewable(), is(RENEWABLE));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is(LEGACY_JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void convenienceMethodsTest() {
|
||||
/* Parent */
|
||||
Token token = Token.builder().asOrphan().build();
|
||||
assertThat(token.getNoParent(), is(true));
|
||||
token = Token.builder().withParent().build();
|
||||
assertThat(token.getNoParent(), is(false));
|
||||
|
||||
/* Default policy */
|
||||
token = Token.builder().withDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(false));
|
||||
token = Token.builder().withoutDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(true));
|
||||
|
||||
/* Renewability */
|
||||
token = Token.builder().renewable().build();
|
||||
assertThat(token.isRenewable(), is(true));
|
||||
token = Token.builder().notRenewable().build();
|
||||
assertThat(token.isRenewable(), is(false));
|
||||
|
||||
/* Add single policy */
|
||||
token = Token.builder().withPolicy(POLICY_2).build();
|
||||
assertThat(token.getPolicies(), hasSize(1));
|
||||
assertThat(token.getPolicies(), contains(POLICY_2));
|
||||
token = Token.builder()
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertThat(token.getPolicies(), hasSize(3));
|
||||
assertThat(token.getPolicies(), contains(POLICY, POLICY_2, POLICY_3));
|
||||
|
||||
/* Add single metadata */
|
||||
token = Token.builder().withMeta(META_KEY_2, META_VALUE_2).build();
|
||||
assertThat(token.getMeta().size(), is(1));
|
||||
assertThat(token.getMeta().keySet(), contains(META_KEY_2));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
token = Token.builder()
|
||||
.withMeta(META)
|
||||
.withMeta(META_KEY_2, META_VALUE_2)
|
||||
.build();
|
||||
assertThat(token.getMeta().size(), is(2));
|
||||
assertThat(token.getMeta().get(META_KEY), is(META_VALUE));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void legacyConvenienceMethodsTest() {
|
||||
/* Parent */
|
||||
Token token = new TokenBuilder().asOrphan().build();
|
||||
assertThat(token.getNoParent(), is(true));
|
||||
token = new TokenBuilder().withParent().build();
|
||||
assertThat(token.getNoParent(), is(false));
|
||||
|
||||
/* Default policy */
|
||||
token = new TokenBuilder().withDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(false));
|
||||
token = new TokenBuilder().withoutDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(true));
|
||||
|
||||
/* Renewability */
|
||||
token = new TokenBuilder().renewable().build();
|
||||
assertThat(token.isRenewable(), is(true));
|
||||
token = new TokenBuilder().notRenewable().build();
|
||||
assertThat(token.isRenewable(), is(false));
|
||||
|
||||
/* Add single policy */
|
||||
token = new TokenBuilder().withPolicy(POLICY_2).build();
|
||||
assertThat(token.getPolicies(), hasSize(1));
|
||||
assertThat(token.getPolicies(), contains(POLICY_2));
|
||||
token = new TokenBuilder()
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertThat(token.getPolicies(), hasSize(3));
|
||||
assertThat(token.getPolicies(), contains(POLICY, POLICY_2, POLICY_3));
|
||||
|
||||
/* Add single metadata */
|
||||
token = new TokenBuilder().withMeta(META_KEY_2, META_VALUE_2).build();
|
||||
assertThat(token.getMeta().size(), is(1));
|
||||
assertThat(token.getMeta().keySet(), contains(META_KEY_2));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
token = new TokenBuilder()
|
||||
.withMeta(META)
|
||||
.withMeta(META_KEY_2, META_VALUE_2)
|
||||
.build();
|
||||
assertThat(token.getMeta().size(), is(2));
|
||||
assertThat(token.getMeta().get(META_KEY), is(META_VALUE));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
}
|
||||
}
|
@ -23,8 +23,7 @@ import org.junit.jupiter.api.Test;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit Test for {@link Token.Builder}
|
||||
@ -80,20 +79,20 @@ class TokenRoleBuilderTest {
|
||||
@Test
|
||||
void buildDefaultTest() throws JsonProcessingException {
|
||||
TokenRole role = TokenRole.builder().build();
|
||||
assertThat(role.getAllowedPolicies(), is(nullValue()));
|
||||
assertThat(role.getDisallowedPolicies(), is(nullValue()));
|
||||
assertThat(role.getOrphan(), is(nullValue()));
|
||||
assertThat(role.getRenewable(), is(nullValue()));
|
||||
assertThat(role.getAllowedEntityAliases(), is(nullValue()));
|
||||
assertThat(role.getTokenBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(role.getTokenNumUses(), is(nullValue()));
|
||||
assertThat(role.getTokenPeriod(), is(nullValue()));
|
||||
assertThat(role.getTokenType(), is(nullValue()));
|
||||
assertNull(role.getAllowedPolicies());
|
||||
assertNull(role.getDisallowedPolicies());
|
||||
assertNull(role.getOrphan());
|
||||
assertNull(role.getRenewable());
|
||||
assertNull(role.getAllowedEntityAliases());
|
||||
assertNull(role.getTokenBoundCidrs());
|
||||
assertNull(role.getTokenExplicitMaxTtl());
|
||||
assertNull(role.getTokenNoDefaultPolicy());
|
||||
assertNull(role.getTokenNumUses());
|
||||
assertNull(role.getTokenPeriod());
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is("{}"));
|
||||
// Optional fields should be ignored, so JSON string should be empty.
|
||||
assertEquals("{}", new ObjectMapper().writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,20 +120,20 @@ class TokenRoleBuilderTest {
|
||||
.withTokenType(null)
|
||||
.build();
|
||||
|
||||
assertThat(role.getAllowedPolicies(), is(nullValue()));
|
||||
assertThat(role.getDisallowedPolicies(), is(nullValue()));
|
||||
assertThat(role.getOrphan(), is(nullValue()));
|
||||
assertThat(role.getRenewable(), is(nullValue()));
|
||||
assertThat(role.getAllowedEntityAliases(), is(nullValue()));
|
||||
assertThat(role.getTokenBoundCidrs(), is(nullValue()));
|
||||
assertThat(role.getTokenExplicitMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(role.getTokenNumUses(), is(nullValue()));
|
||||
assertThat(role.getTokenPeriod(), is(nullValue()));
|
||||
assertThat(role.getTokenType(), is(nullValue()));
|
||||
assertNull(role.getAllowedPolicies());
|
||||
assertNull(role.getDisallowedPolicies());
|
||||
assertNull(role.getOrphan());
|
||||
assertNull(role.getRenewable());
|
||||
assertNull(role.getAllowedEntityAliases());
|
||||
assertNull(role.getTokenBoundCidrs());
|
||||
assertNull(role.getTokenExplicitMaxTtl());
|
||||
assertNull(role.getTokenNoDefaultPolicy());
|
||||
assertNull(role.getTokenNumUses());
|
||||
assertNull(role.getTokenPeriod());
|
||||
assertNull(role.getTokenType());
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is("{}"));
|
||||
// Optional fields should be ignored, so JSON string should be empty.
|
||||
assertEquals("{}", new ObjectMapper().writeValueAsString(role));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,24 +160,24 @@ class TokenRoleBuilderTest {
|
||||
.withTokenPeriod(TOKEN_PERIOD)
|
||||
.withTokenType(TOKEN_TYPE)
|
||||
.build();
|
||||
assertThat(role.getName(), is(NAME));
|
||||
assertThat(role.getAllowedPolicies(), hasSize(ALLOWED_POLICIES.size() + 1));
|
||||
assertThat(role.getAllowedPolicies(), containsInAnyOrder(ALLOWED_POLICY_1, ALLOWED_POLICY_2, ALLOWED_POLICY_3));
|
||||
assertThat(role.getDisallowedPolicies(), hasSize(DISALLOWED_POLICIES.size() + 1));
|
||||
assertThat(role.getDisallowedPolicies(), containsInAnyOrder(DISALLOWED_POLICY_1, DISALLOWED_POLICY_2, DISALLOWED_POLICY_3));
|
||||
assertThat(role.getOrphan(), is(ORPHAN));
|
||||
assertThat(role.getRenewable(), is(RENEWABLE));
|
||||
assertThat(role.getPathSuffix(), is(PATH_SUFFIX));
|
||||
assertThat(role.getAllowedEntityAliases(), hasSize(ALLOWED_ENTITY_ALIASES.size() + 1));
|
||||
assertThat(role.getAllowedEntityAliases(), containsInAnyOrder(ALLOWED_ENTITY_ALIAS_1, ALLOWED_ENTITY_ALIAS_2, ALLOWED_ENTITY_ALIAS_3));
|
||||
assertThat(role.getTokenBoundCidrs(), hasSize(TOKEN_BOUND_CIDRS.size() + 1));
|
||||
assertThat(role.getTokenBoundCidrs(), containsInAnyOrder(TOKEN_BOUND_CIDR_1, TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_3));
|
||||
assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY));
|
||||
assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES));
|
||||
assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD));
|
||||
assertThat(role.getTokenType(), is(TOKEN_TYPE.value()));
|
||||
assertEquals(NAME, role.getName());
|
||||
assertEquals(ALLOWED_POLICIES.size() + 1, role.getAllowedPolicies().size());
|
||||
assertTrue(role.getAllowedPolicies().containsAll(List.of(ALLOWED_POLICY_1, ALLOWED_POLICY_2, ALLOWED_POLICY_3)));
|
||||
assertEquals(DISALLOWED_POLICIES.size() + 1, role.getDisallowedPolicies().size());
|
||||
assertTrue(role.getDisallowedPolicies().containsAll(List.of(DISALLOWED_POLICY_1, DISALLOWED_POLICY_2, DISALLOWED_POLICY_3)));
|
||||
assertEquals(ORPHAN, role.getOrphan());
|
||||
assertEquals(RENEWABLE, role.getRenewable());
|
||||
assertEquals(PATH_SUFFIX, role.getPathSuffix());
|
||||
assertEquals(ALLOWED_ENTITY_ALIASES.size() + 1, role.getAllowedEntityAliases().size());
|
||||
assertTrue(role.getAllowedEntityAliases().containsAll(List.of(ALLOWED_ENTITY_ALIAS_1, ALLOWED_ENTITY_ALIAS_2, ALLOWED_ENTITY_ALIAS_3)));
|
||||
assertEquals(TOKEN_BOUND_CIDRS.size() + 1, role.getTokenBoundCidrs().size());
|
||||
assertTrue(role.getTokenBoundCidrs().containsAll(List.of(TOKEN_BOUND_CIDR_1, TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_3)));
|
||||
assertEquals(TOKEN_NO_DEFAULT_POLICY, role.getTokenNoDefaultPolicy());
|
||||
assertEquals(TOKEN_NUM_USES, role.getTokenNumUses());
|
||||
assertEquals(TOKEN_PERIOD, role.getTokenPeriod());
|
||||
assertEquals(TOKEN_TYPE.value(), role.getTokenType());
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(role));
|
||||
}
|
||||
}
|
||||
|
170
src/test/java/de/stklcode/jvault/connector/model/TokenTest.java
Normal file
170
src/test/java/de/stklcode/jvault/connector/model/TokenTest.java
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link Token} and {@link Token.Builder}.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
class TokenTest {
|
||||
private static final String ID = "test-id";
|
||||
private static final String DISPLAY_NAME = "display-name";
|
||||
private static final Boolean NO_PARENT = false;
|
||||
private static final Boolean NO_DEFAULT_POLICY = false;
|
||||
private static final Integer TTL = 123;
|
||||
private static final Integer EXPLICIT_MAX_TTL = 456;
|
||||
private static final Integer NUM_USES = 4;
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final String POLICY_3 = "policy3";
|
||||
private static final Map<String, String> META = new HashMap<>();
|
||||
private static final String META_KEY = "key";
|
||||
private static final String META_VALUE = "value";
|
||||
private static final String META_KEY_2 = "key2";
|
||||
private static final String META_VALUE_2 = "value2";
|
||||
private static final Boolean RENEWABLE = true;
|
||||
private static final Integer PERIOD = 3600;
|
||||
private static final String ENTITY_ALIAS = "alias-value";
|
||||
private static final String JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"explicit_max_ttl\":456,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true,\"period\":3600,\"entity_alias\":\"alias-value\"}";
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
POLICIES.add(POLICY);
|
||||
META.put(META_KEY, META_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without any parameters.
|
||||
*/
|
||||
@Test
|
||||
void buildDefaultTest() throws JsonProcessingException {
|
||||
Token token = Token.builder().build();
|
||||
assertNull(token.getId());
|
||||
assertNull(token.getType());
|
||||
assertNull(token.getDisplayName());
|
||||
assertNull(token.getNoParent());
|
||||
assertNull(token.getNoDefaultPolicy());
|
||||
assertNull(token.getTtl());
|
||||
assertNull(token.getExplicitMaxTtl());
|
||||
assertNull(token.getNumUses());
|
||||
assertNull(token.getPolicies());
|
||||
assertNull(token.getMeta());
|
||||
assertNull(token.isRenewable());
|
||||
assertNull(token.getPeriod());
|
||||
assertNull(token.getEntityAlias());
|
||||
|
||||
// Optional fields should be ignored, so JSON string should be empty.
|
||||
assertEquals("{}", new ObjectMapper().writeValueAsString(token));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
void buildFullTest() throws JsonProcessingException {
|
||||
Token token = Token.builder()
|
||||
.withId(ID)
|
||||
.withType(Token.Type.SERVICE)
|
||||
.withDisplayName(DISPLAY_NAME)
|
||||
.withNoParent(NO_PARENT)
|
||||
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
|
||||
.withTtl(TTL)
|
||||
.withExplicitMaxTtl(EXPLICIT_MAX_TTL)
|
||||
.withNumUses(NUM_USES)
|
||||
.withPolicies(POLICIES)
|
||||
.withMeta(META)
|
||||
.withRenewable(RENEWABLE)
|
||||
.withPeriod(PERIOD)
|
||||
.withEntityAlias(ENTITY_ALIAS)
|
||||
.build();
|
||||
assertEquals(ID, token.getId());
|
||||
assertEquals(Token.Type.SERVICE.value(), token.getType());
|
||||
assertEquals(DISPLAY_NAME, token.getDisplayName());
|
||||
assertEquals(NO_PARENT, token.getNoParent());
|
||||
assertEquals(NO_DEFAULT_POLICY, token.getNoDefaultPolicy());
|
||||
assertEquals(TTL, token.getTtl());
|
||||
assertEquals(EXPLICIT_MAX_TTL, token.getExplicitMaxTtl());
|
||||
assertEquals(NUM_USES, token.getNumUses());
|
||||
assertEquals(POLICIES, token.getPolicies());
|
||||
assertEquals(META, token.getMeta());
|
||||
assertEquals(RENEWABLE, token.isRenewable());
|
||||
assertEquals(PERIOD, token.getPeriod());
|
||||
|
||||
// Verify that all parameters are included in JSON string.
|
||||
assertEquals(JSON_FULL, new ObjectMapper().writeValueAsString(token));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
void convenienceMethodsTest() {
|
||||
// Parent.
|
||||
Token token = Token.builder().asOrphan().build();
|
||||
assertEquals(true, token.getNoParent());
|
||||
token = Token.builder().withParent().build();
|
||||
assertEquals(false, token.getNoParent());
|
||||
|
||||
// Default policy.
|
||||
token = Token.builder().withDefaultPolicy().build();
|
||||
assertEquals(false, token.getNoDefaultPolicy());
|
||||
token = Token.builder().withoutDefaultPolicy().build();
|
||||
assertEquals(true, token.getNoDefaultPolicy());
|
||||
|
||||
// Renewability.
|
||||
token = Token.builder().renewable().build();
|
||||
assertEquals(true, token.isRenewable());
|
||||
token = Token.builder().notRenewable().build();
|
||||
assertEquals(false, token.isRenewable());
|
||||
|
||||
// Add single policy.
|
||||
token = Token.builder().withPolicy(POLICY_2).build();
|
||||
assertEquals(1, token.getPolicies().size());
|
||||
assertEquals(List.of(POLICY_2), token.getPolicies());
|
||||
token = Token.builder()
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertEquals(3, token.getPolicies().size());
|
||||
assertTrue(token.getPolicies().containsAll(List.of(POLICY, POLICY_2, POLICY_3)));
|
||||
|
||||
// Add single metadata.
|
||||
token = Token.builder().withMeta(META_KEY_2, META_VALUE_2).build();
|
||||
assertEquals(1, token.getMeta().size());
|
||||
assertEquals(Set.of(META_KEY_2), token.getMeta().keySet());
|
||||
assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2));
|
||||
token = Token.builder()
|
||||
.withMeta(META)
|
||||
.withMeta(META_KEY_2, META_VALUE_2)
|
||||
.build();
|
||||
assertEquals(2, token.getMeta().size());
|
||||
assertEquals(META_VALUE, token.getMeta().get(META_KEY));
|
||||
assertEquals(META_VALUE_2, token.getMeta().get(META_KEY_2));
|
||||
}
|
||||
}
|
@ -22,12 +22,10 @@ import de.stklcode.jvault.connector.model.AppRole;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AppRoleResponse} model.
|
||||
@ -78,7 +76,7 @@ class AppRoleResponseTest {
|
||||
void getDataRoundtrip() {
|
||||
// Create empty Object.
|
||||
AppRoleResponse res = new AppRoleResponse();
|
||||
assertThat("Initial data should be empty", res.getRole(), is(nullValue()));
|
||||
assertNull(res.getRole(), "Initial data should be empty");
|
||||
|
||||
// Parsing invalid auth data map should fail.
|
||||
assertThrows(
|
||||
@ -95,24 +93,20 @@ class AppRoleResponseTest {
|
||||
void jsonRoundtrip() {
|
||||
AppRoleResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class),
|
||||
"AuthResponse deserialization failed."
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
// Extract role data.
|
||||
AppRole role = res.getRole();
|
||||
assertThat("Role data is NULL", role, is(notNullValue()));
|
||||
assertThat("Incorrect token TTL", role.getTokenTtl(), is(ROLE_TOKEN_TTL));
|
||||
assertThat("Incorrect token max TTL", role.getTokenMaxTtl(), is(ROLE_TOKEN_MAX_TTL));
|
||||
assertThat("Incorrect secret ID TTL", role.getSecretIdTtl(), is(ROLE_SECRET_TTL));
|
||||
assertThat("Incorrect secret ID umber of uses", role.getSecretIdNumUses(), is(ROLE_SECRET_NUM_USES));
|
||||
assertThat("Incorrect number of policies", role.getTokenPolicies(), hasSize(1));
|
||||
assertThat("Incorrect role policies", role.getTokenPolicies(), contains(ROLE_POLICY));
|
||||
assertThat("Incorrect number of policies", role.getPolicies(), hasSize(1));
|
||||
assertThat("Incorrect role policies", role.getPolicies(), contains(ROLE_POLICY));
|
||||
assertThat("Incorrect role period", role.getTokenPeriod(), is(ROLE_PERIOD));
|
||||
assertThat("Incorrect role period", role.getPeriod(), is(ROLE_PERIOD));
|
||||
assertThat("Incorrect role bind secret ID flag", role.getBindSecretId(), is(ROLE_BIND_SECRET));
|
||||
assertThat("Incorrect bound CIDR list", role.getTokenBoundCidrs(), is(nullValue()));
|
||||
assertThat("Incorrect bound CIDR list string", role.getTokenBoundCidrsString(), is(emptyString()));
|
||||
assertNotNull(role, "Role data is NULL");
|
||||
assertEquals(ROLE_TOKEN_TTL, role.getTokenTtl(), "Incorrect token TTL");
|
||||
assertEquals(ROLE_TOKEN_MAX_TTL, role.getTokenMaxTtl(), "Incorrect token max TTL");
|
||||
assertEquals(ROLE_SECRET_TTL, role.getSecretIdTtl(), "Incorrect secret ID TTL");
|
||||
assertEquals(ROLE_SECRET_NUM_USES, role.getSecretIdNumUses(), "Incorrect secret ID umber of uses");
|
||||
assertEquals(List.of(ROLE_POLICY), role.getTokenPolicies(), "Incorrect policies");
|
||||
assertEquals(ROLE_PERIOD, role.getTokenPeriod(), "Incorrect role period");
|
||||
assertEquals(ROLE_BIND_SECRET, role.getBindSecretId(), "Incorrect role bind secret ID flag");
|
||||
assertNull(role.getTokenBoundCidrs(), "Incorrect bound CIDR list");
|
||||
assertEquals("", role.getTokenBoundCidrsString(), "Incorrect bound CIDR list string");
|
||||
}
|
||||
}
|
||||
|
@ -22,13 +22,12 @@ import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthMethodsResponse} model.
|
||||
@ -76,7 +75,7 @@ class AuthMethodsResponseTest {
|
||||
void getDataRoundtrip() {
|
||||
// Create empty Object.
|
||||
AuthMethodsResponse res = new AuthMethodsResponse();
|
||||
assertThat("Initial method map should be empty", res.getSupportedMethods(), is(anEmptyMap()));
|
||||
assertEquals(Collections.emptyMap(), res.getSupportedMethods(), "Initial method map should be empty");
|
||||
|
||||
// Parsing invalid data map should fail.
|
||||
assertThrows(
|
||||
@ -95,29 +94,29 @@ class AuthMethodsResponseTest {
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class),
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
// Extract auth data.
|
||||
Map<String, AuthMethod> supported = res.getSupportedMethods();
|
||||
assertThat("Auth data is NULL", supported, is(notNullValue()));
|
||||
assertThat("Incorrect number of supported methods", supported.entrySet(), hasSize(2));
|
||||
assertThat("Incorrect method paths", supported.keySet(), containsInAnyOrder(GH_PATH, TK_PATH));
|
||||
assertNotNull(supported, "Auth data is NULL");
|
||||
assertEquals(2, supported.size(), "Incorrect number of supported methods");
|
||||
assertTrue(supported.keySet().containsAll(Set.of(GH_PATH, TK_PATH)), "Incorrect method paths");
|
||||
|
||||
// Verify first method.
|
||||
AuthMethod method = supported.get(GH_PATH);
|
||||
assertThat("Incorrect raw type for GitHub", method.getRawType(), is(GH_TYPE));
|
||||
assertThat("Incorrect parsed type for GitHub", method.getType(), is(AuthBackend.GITHUB));
|
||||
assertThat("Incorrect description for GitHub", method.getDescription(), is(GH_DESCR));
|
||||
assertThat("Unexpected config for GitHub", method.getConfig(), is(nullValue()));
|
||||
assertEquals(GH_TYPE, method.getRawType(), "Incorrect raw type for GitHub");
|
||||
assertEquals(AuthBackend.GITHUB, method.getType(), "Incorrect parsed type for GitHub");
|
||||
assertEquals(GH_DESCR, method.getDescription(), "Incorrect description for GitHub");
|
||||
assertNull(method.getConfig(), "Unexpected config for GitHub");
|
||||
|
||||
// Verify first method.
|
||||
method = supported.get(TK_PATH);
|
||||
assertThat("Incorrect raw type for Token", method.getRawType(), is(TK_TYPE));
|
||||
assertThat("Incorrect parsed type for Token", method.getType(), is(AuthBackend.TOKEN));
|
||||
assertThat("Incorrect description for Token", method.getDescription(), is(TK_DESCR));
|
||||
assertThat("Missing config for Token", method.getConfig(), is(notNullValue()));
|
||||
assertThat("Unexpected config size for Token", method.getConfig().keySet(), hasSize(2));
|
||||
assertThat("Incorrect lease TTL config", method.getConfig().get("default_lease_ttl"), is(TK_LEASE_TTL.toString()));
|
||||
assertThat("Incorrect max lease TTL config", method.getConfig().get("max_lease_ttl"), is(TK_MAX_LEASE_TTL.toString()));
|
||||
assertEquals(TK_TYPE, method.getRawType(), "Incorrect raw type for Token");
|
||||
assertEquals(AuthBackend.TOKEN, method.getType(), "Incorrect parsed type for Token");
|
||||
assertEquals(TK_DESCR, method.getDescription(), "Incorrect description for Token");
|
||||
assertNotNull(method.getConfig(), "Missing config for Token");
|
||||
assertEquals(2, method.getConfig().size(), "Unexpected config size for Token");
|
||||
assertEquals(TK_LEASE_TTL.toString(), method.getConfig().get("default_lease_ttl"), "Incorrect lease TTL config");
|
||||
assertEquals(TK_MAX_LEASE_TTL.toString(), method.getConfig().get("max_lease_ttl"), "Incorrect max lease TTL config");
|
||||
}
|
||||
|
||||
private static class Dummy {
|
||||
|
@ -23,11 +23,9 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthResponse} model.
|
||||
@ -84,7 +82,7 @@ class AuthResponseTest {
|
||||
void getDataRoundtrip() {
|
||||
// Create empty Object.
|
||||
AuthResponse res = new AuthResponse();
|
||||
assertThat("Initial data should be empty", res.getData(), is(nullValue()));
|
||||
assertNull(res.getData(), "Initial data should be empty");
|
||||
|
||||
// Parsing invalid auth data map should fail.
|
||||
assertThrows(
|
||||
@ -95,7 +93,7 @@ class AuthResponseTest {
|
||||
|
||||
// Data method should be agnostic.
|
||||
res.setData(INVALID_AUTH_DATA);
|
||||
assertThat("Data not passed through", res.getData(), is(INVALID_AUTH_DATA));
|
||||
assertEquals(INVALID_AUTH_DATA, res.getData(), "Data not passed through");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,26 +101,25 @@ class AuthResponseTest {
|
||||
*/
|
||||
@Test
|
||||
void jsonRoundtrip() {
|
||||
AuthResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AuthResponse.class),
|
||||
"AuthResponse deserialization failed."
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
// Extract auth data.
|
||||
AuthData data = res.getAuth();
|
||||
assertThat("Auth data is NULL", data, is(notNullValue()));
|
||||
assertThat("Incorrect auth accessor", data.getAccessor(), is(AUTH_ACCESSOR));
|
||||
assertThat("Incorrect auth client token", data.getClientToken(), is(AUTH_CLIENT_TOKEN));
|
||||
assertThat("Incorrect auth lease duration", data.getLeaseDuration(), is(AUTH_LEASE_DURATION));
|
||||
assertThat("Incorrect auth renewable flag", data.isRenewable(), is(AUTH_RENEWABLE));
|
||||
assertThat("Incorrect auth orphan flag", data.isOrphan(), is(AUTH_ORPHAN));
|
||||
assertThat("Incorrect auth token type", data.getTokenType(), is(AUTH_TOKEN_TYPE));
|
||||
assertThat("Incorrect auth entity id", data.getEntityId(), is(AUTH_ENTITY_ID));
|
||||
assertThat("Incorrect number of policies", data.getPolicies(), hasSize(2));
|
||||
assertThat("Incorrect auth policies", data.getPolicies(), containsInRelativeOrder(AUTH_POLICY_1, AUTH_POLICY_2));
|
||||
assertThat("Incorrect number of token policies", data.getTokenPolicies(), hasSize(2));
|
||||
assertThat("Incorrect token policies", data.getTokenPolicies(), containsInRelativeOrder(AUTH_POLICY_2, AUTH_POLICY_1));
|
||||
assertThat("Incorrect auth metadata size", data.getMetadata().entrySet(), hasSize(1));
|
||||
assertThat("Incorrect auth metadata", data.getMetadata().get(AUTH_META_KEY), is(AUTH_META_VALUE));
|
||||
AuthResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, AuthResponse.class),
|
||||
"AuthResponse deserialization failed"
|
||||
);
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
// Extract auth data.
|
||||
AuthData data = res.getAuth();
|
||||
assertNotNull(data, "Auth data is NULL");
|
||||
assertEquals(AUTH_ACCESSOR, data.getAccessor(), "Incorrect auth accessor");
|
||||
assertEquals(AUTH_CLIENT_TOKEN, data.getClientToken(), "Incorrect auth client token");
|
||||
assertEquals(AUTH_LEASE_DURATION, data.getLeaseDuration(), "Incorrect auth lease duration");
|
||||
assertEquals(AUTH_RENEWABLE, data.isRenewable(), "Incorrect auth renewable flag");
|
||||
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(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");
|
||||
}
|
||||
}
|
||||
|
@ -16,18 +16,14 @@
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link CredentialsResponse} model.
|
||||
@ -55,12 +51,12 @@ class CredentialsResponseTest {
|
||||
void getCredentialsTest() throws InvalidResponseException {
|
||||
// Create empty Object.
|
||||
CredentialsResponse res = new CredentialsResponse();
|
||||
assertThat("Username not present in data map should not return anything", res.getUsername(), is(nullValue()));
|
||||
assertThat("Password not present in data map should not return anything", res.getPassword(), is(nullValue()));
|
||||
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");
|
||||
|
||||
// Fill data map.
|
||||
res.setData(DATA);
|
||||
assertThat("Incorrect username", res.getUsername(), is(VAL_USER));
|
||||
assertThat("Incorrect password", res.getPassword(), is(VAL_PASS));
|
||||
assertEquals(VAL_USER, res.getUsername(), "Incorrect username");
|
||||
assertEquals(VAL_PASS, res.getPassword(), "Incorrect password");
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthResponse} model.
|
||||
@ -62,18 +59,18 @@ class HealthResponseTest {
|
||||
void jsonRoundtrip() {
|
||||
HealthResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, HealthResponse.class),
|
||||
"Health deserialization failed."
|
||||
"Health deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect cluster ID", res.getClusterID(), is(CLUSTER_ID));
|
||||
assertThat("Incorrect cluster name", res.getClusterName(), is(CLUSTER_NAME));
|
||||
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||
assertThat("Incorrect server time", res.getServerTimeUTC(), is(SERVER_TIME_UTC));
|
||||
assertThat("Incorrect standby state", res.isStandby(), is(STANDBY));
|
||||
assertThat("Incorrect seal state", res.isSealed(), is(SEALED));
|
||||
assertThat("Incorrect initialization state", res.isInitialized(), is(INITIALIZED));
|
||||
assertThat("Incorrect performance standby state", res.isPerformanceStandby(), is(PERF_STANDBY));
|
||||
assertThat("Incorrect replication perf mode", res.getReplicationPerfMode(), is(REPL_PERF_MODE));
|
||||
assertThat("Incorrect replication DR mode", res.getReplicationDrMode(), is(REPL_DR_MODE));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(CLUSTER_ID, res.getClusterID(), "Incorrect cluster ID");
|
||||
assertEquals(CLUSTER_NAME, res.getClusterName(), "Incorrect cluster name");
|
||||
assertEquals(VERSION, res.getVersion(), "Incorrect version");
|
||||
assertEquals(SERVER_TIME_UTC, res.getServerTimeUTC(), "Incorrect server time");
|
||||
assertEquals(STANDBY, res.isStandby(), "Incorrect standby state");
|
||||
assertEquals(SEALED, res.isSealed(), "Incorrect seal state");
|
||||
assertEquals(INITIALIZED, res.isInitialized(), "Incorrect initialization state");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link MetadataResponse} model.
|
||||
@ -72,23 +69,23 @@ class MetadataResponseTest {
|
||||
void jsonRoundtrip() {
|
||||
MetadataResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(META_JSON, MetadataResponse.class),
|
||||
"MetadataResponse deserialization failed."
|
||||
"MetadataResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Parsed metadata is NULL", res.getMetadata(), is(notNullValue()));
|
||||
assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(V1_TIME));
|
||||
assertThat("Parting created time failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||
assertThat("Incorrect current version", res.getMetadata().getCurrentVersion(), is(CURRENT_VERSION));
|
||||
assertThat("Incorrect max versions", res.getMetadata().getMaxVersions(), is(MAX_VERSIONS));
|
||||
assertThat("Incorrect oldest version", res.getMetadata().getOldestVersion(), is(OLDEST_VERSION));
|
||||
assertThat("Incorrect updated time", res.getMetadata().getUpdatedTimeString(), is(V3_TIME));
|
||||
assertThat("Parting updated time failed", res.getMetadata().getUpdatedTime(), is(notNullValue()));
|
||||
assertThat("Incorrect number of versions", res.getMetadata().getVersions().size(), is(3));
|
||||
assertThat("Incorrect version 1 delete time", res.getMetadata().getVersions().get(1).getDeletionTimeString(), is(V2_TIME));
|
||||
assertThat("Parsing version delete time failed", res.getMetadata().getVersions().get(1).getDeletionTime(), is(notNullValue()));
|
||||
assertThat("Incorrect version 1 destroyed state", res.getMetadata().getVersions().get(1).isDestroyed(), is(true));
|
||||
assertThat("Incorrect version 2 created time", res.getMetadata().getVersions().get(2).getCreatedTimeString(), is(V2_TIME));
|
||||
assertThat("Parsing version created failed", res.getMetadata().getVersions().get(2).getCreatedTime(), is(notNullValue()));
|
||||
assertThat("Incorrect version 3 destroyed state", res.getMetadata().getVersions().get(3).isDestroyed(), is(false));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertNotNull(res.getMetadata(), "Parsed metadata is NULL");
|
||||
assertEquals(V1_TIME, res.getMetadata().getCreatedTimeString(), "Incorrect created time");
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link SealResponse} model.
|
||||
@ -72,37 +70,37 @@ class SealResponseTest {
|
||||
// First test sealed Vault's response.
|
||||
SealResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_SEALED, SealResponse.class),
|
||||
"TokenResponse deserialization failed."
|
||||
"TokenResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect seal type", res.getType(), is(TYPE));
|
||||
assertThat("Incorrect seal status", res.isSealed(), is(true));
|
||||
assertThat("Incorrect initialization status", res.isInitialized(), is(true));
|
||||
assertThat("Incorrect threshold", res.getThreshold(), is(THRESHOLD));
|
||||
assertThat("Incorrect number of shares", res.getNumberOfShares(), is(SHARES));
|
||||
assertThat("Incorrect progress", res.getProgress(), is(PROGRESS_SEALED));
|
||||
assertThat("Nonce not empty", res.getNonce(), is(""));
|
||||
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(TYPE, res.getType(), "Incorrect seal type");
|
||||
assertTrue(res.isSealed(), "Incorrect seal status");
|
||||
assertTrue(res.isInitialized(), "Incorrect initialization status");
|
||||
assertEquals(THRESHOLD, res.getThreshold(), "Incorrect threshold");
|
||||
assertEquals(SHARES, res.getNumberOfShares(), "Incorrect number of shares");
|
||||
assertEquals(PROGRESS_SEALED, res.getProgress(), "Incorrect progress");
|
||||
assertEquals("", res.getNonce(), "Nonce not empty");
|
||||
assertEquals(VERSION, res.getVersion(), "Incorrect version");
|
||||
// And the fields, that should not be filled.
|
||||
assertThat("Cluster name should not be populated", res.getClusterName(), is(nullValue()));
|
||||
assertThat("Cluster ID should not be populated", res.getClusterId(), is(nullValue()));
|
||||
assertNull(res.getClusterName(), "Cluster name should not be populated");
|
||||
assertNull(res.getClusterId(), "Cluster ID should not be populated");
|
||||
|
||||
|
||||
// Not test unsealed Vault's response.
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class),
|
||||
"TokenResponse deserialization failed."
|
||||
"TokenResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect seal type", res.getType(), is(TYPE));
|
||||
assertThat("Incorrect seal status", res.isSealed(), is(false));
|
||||
assertThat("Incorrect initialization status", res.isInitialized(), is(true));
|
||||
assertThat("Incorrect threshold", res.getThreshold(), is(THRESHOLD));
|
||||
assertThat("Incorrect number of shares", res.getNumberOfShares(), is(SHARES));
|
||||
assertThat("Incorrect progress", res.getProgress(), is(PROGRESS_UNSEALED));
|
||||
assertThat("Incorrect nonce", res.getNonce(), is(NONCE));
|
||||
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||
assertThat("Incorrect cluster name", res.getClusterName(), is(CLUSTER_NAME));
|
||||
assertThat("Incorrect cluster ID", res.getClusterId(), is(CLUSTER_ID));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(TYPE, res.getType(), "Incorrect seal type");
|
||||
assertFalse(res.isSealed(), "Incorrect seal status");
|
||||
assertTrue(res.isInitialized(), "Incorrect initialization status");
|
||||
assertEquals(THRESHOLD, res.getThreshold(), "Incorrect threshold");
|
||||
assertEquals(SHARES, res.getNumberOfShares(), "Incorrect number of shares");
|
||||
assertEquals(PROGRESS_UNSEALED, res.getProgress(), "Incorrect progress");
|
||||
assertEquals(NONCE, res.getNonce(), "Incorrect nonce");
|
||||
assertEquals(VERSION, res.getVersion(), "Incorrect version");
|
||||
assertEquals(CLUSTER_NAME, res.getClusterName(), "Incorrect cluster name");
|
||||
assertEquals(CLUSTER_ID, res.getClusterId(), "Incorrect cluster ID");
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,9 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link SecretListResponse} model.
|
||||
@ -53,7 +48,7 @@ class SecretListResponseTest {
|
||||
void getKeysTest() throws InvalidResponseException {
|
||||
// Create empty Object.
|
||||
SecretListResponse res = new SecretListResponse();
|
||||
assertThat("Keys should be null without initialization", res.getKeys(), is(nullValue()));
|
||||
assertNull(res.getKeys(), "Keys should be null without initialization");
|
||||
|
||||
// Provoke internal ClassCastException.
|
||||
Map<String, Object> invalidData = new HashMap<>();
|
||||
@ -66,8 +61,8 @@ class SecretListResponseTest {
|
||||
|
||||
// Fill correct data.
|
||||
res.setData(DATA);
|
||||
assertThat("Keys should be filled here", res.getKeys(), is(notNullValue()));
|
||||
assertThat("Unexpected number of keys", res.getKeys(), hasSize(2));
|
||||
assertThat("Unexpected keys", res.getKeys(), contains(KEY1, KEY2));
|
||||
assertNotNull(res.getKeys(), "Keys should be filled here");
|
||||
assertEquals(2, res.getKeys().size(), "Unexpected number of keys");
|
||||
assertTrue(res.getKeys().containsAll(Set.of(KEY1, KEY2)), "Unexpected keys");
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,9 @@ import org.junit.jupiter.api.Test;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link SecretResponse} model.
|
||||
@ -123,31 +121,31 @@ class SecretResponseTest {
|
||||
void getDataRoundtrip() throws InvalidResponseException {
|
||||
// Create empty Object.
|
||||
SecretResponse res = new SecretResponse();
|
||||
assertThat("Initial data should be Map", res.getData(), is(instanceOf(Map.class)));
|
||||
assertThat("Initial data should be empty", res.getData().entrySet(), empty());
|
||||
assertThat("Getter should return NULL on empty data map", res.get(KEY_STRING), is(nullValue()));
|
||||
assertNotNull(res.getData(), "Initial data should be Map");
|
||||
assertTrue(res.getData().isEmpty(), "Initial data should be empty");
|
||||
assertNull(res.get(KEY_STRING), "Getter should return NULL on empty data map");
|
||||
|
||||
// Fill data map.
|
||||
res.setData(DATA);
|
||||
assertThat("Data setter/getter not transparent", res.getData(), is(DATA));
|
||||
assertThat("Data size modified", res.getData().keySet(), hasSize(DATA.size()));
|
||||
assertThat("Data keys not passed correctly", res.getData().keySet(), containsInAnyOrder(KEY_STRING, KEY_INTEGER, KEY_LIST));
|
||||
assertThat("Data values not passed correctly", res.get(KEY_STRING), is(VAL_STRING));
|
||||
assertThat("Data values not passed correctly", res.get(KEY_INTEGER), is(VAL_INTEGER));
|
||||
assertThat("Non-Null returned on unknown key", res.get(KEY_UNKNOWN), is(nullValue()));
|
||||
assertEquals(DATA, res.getData(), "Data setter/getter not transparent");
|
||||
assertEquals(DATA.size(), res.getData().keySet().size(), "Data size modified");
|
||||
assertTrue(res.getData().keySet().containsAll(Set.of(KEY_STRING, KEY_INTEGER, KEY_LIST)), "Data keys not passed correctly");
|
||||
assertEquals(VAL_STRING, res.get(KEY_STRING), "Data values not passed correctly");
|
||||
assertEquals(VAL_INTEGER, res.get(KEY_INTEGER), "Data values not passed correctly");
|
||||
assertNull(res.get(KEY_UNKNOWN), "Non-Null returned on unknown key");
|
||||
|
||||
// Try explicit JSON conversion.
|
||||
final List<?> list = res.get(KEY_LIST, List.class);
|
||||
assertThat("JSON parsing of list failed", list, is(notNullValue()));
|
||||
assertThat("JSON parsing of list returned incorrect size", list.size(), is(2));
|
||||
assertThat("JSON parsing of list returned incorrect elements", list, contains("first", "second"));
|
||||
assertThat("Non-Null returned on unknown key", res.get(KEY_UNKNOWN, Object.class), is(nullValue()));
|
||||
assertNotNull(list, "JSON parsing of list failed");
|
||||
assertEquals(2, list.size(), "JSON parsing of list returned incorrect size");
|
||||
assertTrue(list.containsAll(List.of("first", "second")), "JSON parsing of list returned incorrect elements");
|
||||
assertNull(res.get(KEY_UNKNOWN, Object.class), "Non-Null returned on unknown key");
|
||||
|
||||
// Requesting invalid class should result in Exception.
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> res.get(KEY_LIST, Double.class),
|
||||
"JSON parsing to incorrect type succeeded."
|
||||
"JSON parsing to incorrect type succeeded"
|
||||
);
|
||||
}
|
||||
|
||||
@ -158,46 +156,46 @@ class SecretResponseTest {
|
||||
void jsonRoundtrip() {
|
||||
SecretResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class),
|
||||
"SecretResponse deserialization failed."
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
assertSecretData(res);
|
||||
|
||||
// KV v2 secret.
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON_V2, SecretResponse.class),
|
||||
"SecretResponse deserialization failed."
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
assertSecretData(res);
|
||||
assertThat("SecretResponse does not contain metadata", res.getMetadata(), is(notNullValue()));
|
||||
assertThat("Incorrect creation date string", res.getMetadata().getCreatedTimeString(), is(SECRET_META_CREATED));
|
||||
assertThat("Creation date parsing failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||
assertThat("Incorrect deletion date string", res.getMetadata().getDeletionTimeString(), is(emptyString()));
|
||||
assertThat("Incorrect deletion date", res.getMetadata().getDeletionTime(), is(nullValue()));
|
||||
assertThat("Secret destroyed when not expected", res.getMetadata().isDestroyed(), is(false));
|
||||
assertThat("Incorrect secret version", res.getMetadata().getVersion(), is(1));
|
||||
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");
|
||||
assertEquals(false, res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
|
||||
assertEquals(1, res.getMetadata().getVersion(), "Incorrect secret version");
|
||||
|
||||
// Deleted KV v2 secret.
|
||||
res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(SECRET_JSON_V2_2, SecretResponse.class),
|
||||
"SecretResponse deserialization failed."
|
||||
"SecretResponse deserialization failed"
|
||||
);
|
||||
assertSecretData(res);
|
||||
assertThat("SecretResponse does not contain metadata", res.getMetadata(), is(notNullValue()));
|
||||
assertThat("Incorrect creation date string", res.getMetadata().getCreatedTimeString(), is(SECRET_META_CREATED));
|
||||
assertThat("Creation date parsing failed", res.getMetadata().getCreatedTime(), is(notNullValue()));
|
||||
assertThat("Incorrect deletion date string", res.getMetadata().getDeletionTimeString(), is(SECRET_META_DELETED));
|
||||
assertThat("Incorrect deletion date", res.getMetadata().getDeletionTime(), is(notNullValue()));
|
||||
assertThat("Secret destroyed when not expected", res.getMetadata().isDestroyed(), is(true));
|
||||
assertThat("Incorrect secret version", res.getMetadata().getVersion(), is(2));
|
||||
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");
|
||||
assertEquals(true, res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
|
||||
assertEquals(2, res.getMetadata().getVersion(), "Incorrect secret version");
|
||||
}
|
||||
|
||||
private void assertSecretData(SecretResponse res) {
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect lease ID", res.getLeaseId(), is(SECRET_LEASE_ID));
|
||||
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(SECRET_LEASE_DURATION));
|
||||
assertThat("Incorrect renewable status", res.isRenewable(), is(SECRET_RENEWABLE));
|
||||
assertThat("Incorrect warnings", res.getWarnings(), is(SECRET_WARNINGS));
|
||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K1), is(SECRET_DATA_V1));
|
||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K2), is(SECRET_DATA_V2));
|
||||
assertNotNull(res, "Parsed response is NULL");
|
||||
assertEquals(SECRET_LEASE_ID, res.getLeaseId(), "Incorrect lease ID");
|
||||
assertEquals(SECRET_LEASE_DURATION, res.getLeaseDuration(), "Incorrect lease duration");
|
||||
assertEquals(SECRET_RENEWABLE, res.isRenewable(), "Incorrect renewable status");
|
||||
assertEquals(SECRET_WARNINGS, res.getWarnings(), "Incorrect warnings");
|
||||
assertEquals(SECRET_DATA_V1, res.get(SECRET_DATA_K1), "Response does not contain correct data");
|
||||
assertEquals(SECRET_DATA_V2, res.get(SECRET_DATA_K2), "Response does not contain correct data");
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,7 @@ package de.stklcode.jvault.connector.model.response;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link SecretVersionResponse} model.
|
||||
@ -53,11 +50,11 @@ class SecretVersionResponseTest {
|
||||
() -> new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class),
|
||||
"SecretVersionResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Parsed metadata is NULL", res.getMetadata(), is(notNullValue()));
|
||||
assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(CREATION_TIME));
|
||||
assertThat("Incorrect deletion time", res.getMetadata().getDeletionTimeString(), is(DELETION_TIME));
|
||||
assertThat("Incorrect destroyed state", res.getMetadata().isDestroyed(), is(false));
|
||||
assertThat("Incorrect version", res.getMetadata().getVersion(), is(VERSION));
|
||||
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");
|
||||
assertEquals(false, res.getMetadata().isDestroyed(), "Incorrect destroyed state");
|
||||
assertEquals(VERSION, res.getMetadata().getVersion(), "Incorrect version");
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link TokenResponse} model.
|
||||
@ -104,7 +102,7 @@ class TokenResponseTest {
|
||||
void getDataRoundtrip() {
|
||||
// Create empty Object.
|
||||
TokenResponse res = new TokenResponse();
|
||||
assertThat("Initial data should be empty", res.getData(), is(nullValue()));
|
||||
assertNull(res.getData(), "Initial data should be empty");
|
||||
|
||||
// Parsing invalid data map should fail.
|
||||
assertThrows(
|
||||
@ -121,35 +119,34 @@ class TokenResponseTest {
|
||||
void jsonRoundtrip() {
|
||||
TokenResponse res = assertDoesNotThrow(
|
||||
() -> new ObjectMapper().readValue(RES_JSON, TokenResponse.class),
|
||||
"TokenResponse deserialization failed."
|
||||
"TokenResponse deserialization failed"
|
||||
);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION));
|
||||
assertThat("Incorrect response renewable flag", res.isRenewable(), is(RES_RENEWABLE));
|
||||
assertThat("Incorrect response lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION));
|
||||
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");
|
||||
// Extract token data.
|
||||
TokenData data = res.getData();
|
||||
assertThat("Token data is NULL", data, is(notNullValue()));
|
||||
assertThat("Incorrect token accessor", data.getAccessor(), is(TOKEN_ACCESSOR));
|
||||
assertThat("Incorrect token creation time", data.getCreationTime(), is(TOKEN_CREATION_TIME));
|
||||
assertThat("Incorrect token creation TTL", data.getCreationTtl(), is(TOKEN_TTL));
|
||||
assertThat("Incorrect token display name", data.getName(), is(TOKEN_DISPLAY_NAME));
|
||||
assertThat("Incorrect token entity ID", data.getEntityId(), is(TOKEN_ENTITY_ID));
|
||||
assertThat("Incorrect token expire time", data.getExpireTimeString(), is(TOKEN_EXPIRE_TIME));
|
||||
assertThat("Incorrect parsed token expire time", data.getExpireTime(), is(ZonedDateTime.parse(TOKEN_EXPIRE_TIME)));
|
||||
assertThat("Incorrect token explicit max TTL", data.getExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL));
|
||||
assertThat("Incorrect token ID", data.getId(), is(TOKEN_ID));
|
||||
assertThat("Incorrect token issue time", data.getIssueTimeString(), is(TOKEN_ISSUE_TIME));
|
||||
assertThat("Incorrect parsed token issue time", data.getIssueTime(), is(ZonedDateTime.parse(TOKEN_ISSUE_TIME)));
|
||||
assertThat("Incorrect token metadata size", data.getMeta().entrySet(), hasSize(1));
|
||||
assertThat("Incorrect token metadata", data.getMeta().get(TOKEN_META_KEY), is(TOKEN_META_VALUE));
|
||||
assertThat("Incorrect token number of uses", data.getNumUses(), is(TOKEN_NUM_USES));
|
||||
assertThat("Incorrect token orphan flag", data.isOrphan(), is(TOKEN_ORPHAN));
|
||||
assertThat("Incorrect token path", data.getPath(), is(TOKEN_PATH));
|
||||
assertThat("Incorrect number of token policies", data.getPolicies(), hasSize(2));
|
||||
assertThat("Incorrect token policies", data.getPolicies(), contains(TOKEN_POLICY_1, TOKEN_POLICY_2));
|
||||
assertThat("Incorrect token renewable flag", data.isRenewable(), is(TOKEN_RENEWABLE));
|
||||
assertThat("Incorrect token TTL", data.getTtl(), is(RES_TTL));
|
||||
assertThat("Incorrect token type", data.getType(), is(TOKEN_TYPE));
|
||||
assertNotNull(data, "Token data is NULL");
|
||||
assertEquals(TOKEN_ACCESSOR, data.getAccessor(), "Incorrect token accessor");
|
||||
assertEquals(TOKEN_CREATION_TIME, data.getCreationTime(), "Incorrect token creation time");
|
||||
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");
|
||||
assertEquals(TOKEN_ORPHAN, data.isOrphan(), "Incorrect token orphan flag");
|
||||
assertEquals(TOKEN_PATH, data.getPath(), "Incorrect token path");
|
||||
assertEquals(2, data.getPolicies().size(), "Incorrect number of token policies");
|
||||
assertTrue(data.getPolicies().containsAll(List.of(TOKEN_POLICY_1, TOKEN_POLICY_2)), "Incorrect token policies");
|
||||
assertEquals(TOKEN_RENEWABLE, data.isRenewable(), "Incorrect token renewable flag");
|
||||
assertEquals(RES_TTL, data.getTtl(), "Incorrect token TTL");
|
||||
assertEquals(TOKEN_TYPE, data.getType(), "Incorrect token type");
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
/**
|
||||
* Simple credentials class for JSON testing.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class Credentials {
|
||||
@JsonProperty("username")
|
||||
|
Reference in New Issue
Block a user