63 Commits

Author SHA1 Message Date
5f9950e048 prepare release 0.9.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:22:13 +02:00
e2c439379e switch to "main" as default branch name
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:09:28 +02:00
ce33d37396 minor dependency updates; test against Vault 1.7.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:07:02 +02:00
bdf4fc4b83 fix typo in method AppRole.Builder#wit0hTokenPeriod (#49) 2021-06-06 12:02:01 +02:00
50d485fab8 clean up unused imports
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-02 11:27:24 +02:00
5b508374d9 prepare release 0.9.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-02 11:16:04 +02:00
fbc61e065f fix argline for JDK 1.8 unit tests
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-29 21:13:34 +02:00
56a52cb22a fix argline for JDK 16 unit tests
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-29 20:50:16 +02:00
c43ec190ca use SystemLambda instead of custom environment mocks 2021-03-29 20:49:44 +02:00
639d0e3c5b Jackson 2.12.2, test against Vault 1.7.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-29 18:56:24 +02:00
8e97f3c1dd build with JDK 16, test against Vault 1.6.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-20 12:13:19 +01:00
c04d940a80 test: close static mocks
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-28 13:03:25 +01:00
76a5ea4fe9 test: use assertThrows instead of try-catch blocks
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-28 12:59:06 +01:00
2b0f458da3 use pre-sized maps for fixed-size payloads
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-28 10:52:36 +01:00
63278c09c8 constructors of abstract VaultConnectorException protected
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-24 14:57:14 +01:00
600f3d0d0f test classes package-private; use mockStatic()
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-24 14:52:48 +01:00
1a19eaa87d release 0.9.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-24 12:26:29 +01:00
a2dde38348 Jackson 2.12.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-24 12:24:09 +01:00
dfb6d0a37c only initialize trust managers if CA certificate is provided (#43)
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-24 12:20:45 +01:00
b46b59e4a0 update copyright notice to 2021
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-03 11:56:33 +01:00
79ec536876 prepare release of v0.9.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-03 11:48:51 +01:00
00d4e9acef test against Vault 1.6.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-03 11:46:40 +01:00
48eccedad0 introduce maven profile for dependency analysis 2021-01-03 11:44:34 +01:00
ec4c4ac868 rework Travis CI configuration
Separate stages do not work as intended.
Add LTS and latest JDK (8, 11, 15) to build roster and run analysis with JDK 11 only.
2020-12-12 11:52:43 +01:00
90835aea92 dependency updates
All checks were successful
continuous-integration/drone/push Build is passing
Jackson 2.12, HTTPClient 4.5.13 and some test dependencies
2020-12-12 11:18:17 +01:00
32eed75de8 use batch mode in CI builds
All checks were successful
continuous-integration/drone/push Build is passing
Do not bloat the log with progress output.
2020-12-02 10:14:16 +01:00
c8ca5c4091 test against Vault 1.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2020-11-12 19:48:08 +01:00
4ba81492d5 docs: update Travis CI badge
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 21:28:16 +02:00
84b9877ca9 test against Vault 1.5.0 2020-07-26 14:12:13 +02:00
b5c9a3b35b minor CI configuration adjustments
All checks were successful
continuous-integration/drone/push Build is passing
2020-04-29 16:44:55 +02:00
9d7f501b1a Merge branch 'release/0.9.0' 2020-04-29 15:53:06 +02:00
aab76273a5 last minute JavaDoc corrections 2020-04-29 15:47:20 +02:00
4fb63f0977 prepare release 0.9.0 2020-04-29 15:24:16 +02:00
1d5db0c365 add missing fields to Token model and builder (#41)
* explicit_max_ttl
* period
* entity_alias
2020-04-26 18:04:35 +02:00
9f80a7dada typo fixes 2020-04-25 13:04:39 +02:00
46461f482a add coverage profile to maven project 2020-04-25 12:33:22 +02:00
be7aa865d8 rework CI configuration for multi-stage job 2020-04-25 11:39:50 +02:00
fa7036921a move builders into model classes and deprecate constructors
Enforces use of builder pattern in future releases. Builder API is
unchanged despite the class itself.
2020-04-15 17:29:50 +02:00
e0cbe34881 minor JavaDoc correction
[skip ci]
2020-04-15 16:29:42 +02:00
dcb8d6067a update AppRole model and builder to current API
Add missing JSON fields and remove unprefixed, already deprecated fields
2020-04-15 16:28:14 +02:00
fc9e429bd1 add support for token roles (#27) (#37) 2020-04-13 17:12:55 +02:00
94d1d2c80b test against Vault 1.4.0 2020-04-08 14:25:16 +02:00
edb9194153 Update copyright notice to 2020
Better late than never, at least before the next release... [skip ci]
2020-04-08 14:23:48 +02:00
c0708bd288 implement methods for token role handling (#27)
Create, update, read, delete and list token roles is now possible.
2020-04-06 18:36:42 +02:00
f54ba38cf5 implement TokenRole metamodel and corresponding builder 2020-04-06 17:58:11 +02:00
8f10bbfed7 add missing fields to token data
* entity_id
* expire_time
* explicit_max_ttl
* issue_time
* renewable
* type
2020-03-29 14:29:06 +02:00
a4a0e13904 add missing fields to auth response
* token_policies
* entity_id
* token_type
* orphan
2020-03-29 14:29:06 +02:00
df696e9f17 add token type to model and builder classes 2020-03-29 14:29:06 +02:00
83a05fcd40 correctly map token policies on lookup (close #35)
Remove superfluous "role" flag and add "policies" list instead.
2020-03-29 13:59:06 +02:00
d564ba9365 update dependencies and plugins for JDK 14 build environments 2020-03-29 13:01:25 +02:00
071eeda423 correclty map token meta in lookup response (fix #34) 2020-03-29 12:56:06 +02:00
4788fa7272 Test against Vault 1.4.0-rc1 2020-03-25 10:21:10 +01:00
21d544c2c7 Test against Vault 1.3.0 2019-11-20 09:43:44 +01:00
a944fce6c5 Test against Vault 1.3.0 2019-11-20 09:43:11 +01:00
9710d59821 prepare release of v0.8.2 2019-10-20 14:04:47 +02:00
30d426303e add distribution profiles to POM 2019-10-20 14:04:47 +02:00
ca9da6bd0f minor dependency updated and cleanup 2019-10-20 13:49:14 +02:00
9fedb3f88b replace legacy JUnit 4 rule for system mock by custom helper 2019-10-20 13:48:41 +02:00
596a097707 fix API endpoint for token lookup 2019-10-16 18:00:45 +02:00
d51421cb14 update Jackson dependency to 2.10 2019-10-03 11:45:08 +02:00
ffea9bfbfe update test environment for JDK 13 builds 2019-10-03 11:42:14 +02:00
ffdc0f6a27 Test against Vault 1.2.2 2019-10-03 11:09:39 +02:00
9b5c537e55 fix SonarCloud link in ReadMe [skip ci] 2019-08-17 14:57:24 +02:00
80 changed files with 4150 additions and 1874 deletions

View File

@ -2,25 +2,38 @@ kind: pipeline
name: default
steps:
- name: test-online
- name: compile
image: maven:3-jdk-11
environment:
VAULT_VERSION: 1.2.2
commands:
- curl -o vault_1.2.2_linux_amd64.zip https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_linux_amd64.zip
- curl -s https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_SHA256SUMS | grep linux_amd64 | sha256sum -c
- unzip vault_1.2.2_linux_amd64.zip
- rm vault_1.2.2_linux_amd64.zip
- mv vault /bin/
- mvn clean test
- mvn -B clean compile
when:
branch:
- master
- name: test-offline
- main
- develop
- feature/*
- fix/*
- release/*
- name: unit-tests
image: maven:3-jdk-11
commands:
- mvn clean test -P offline-tests
- mvn -B resources:testResources compiler:testCompile surefire:test -P offline-tests
when:
branch:
- develop
- feature/*
- fix/*
- name: unit-integration-tests
image: maven:3-jdk-11
environment:
VAULT_VERSION: 1.7.2
commands:
- curl -s -o vault_1.7.2_linux_amd64.zip https://releases.hashicorp.com/vault/1.7.2/vault_1.7.2_linux_amd64.zip
- curl -s https://releases.hashicorp.com/vault/1.7.2/vault_1.7.2_SHA256SUMS | grep linux_amd64 | sha256sum -c
- unzip vault_1.7.2_linux_amd64.zip
- rm vault_1.7.2_linux_amd64.zip
- mv vault /bin/
- mvn -B resources:testResources compiler:testCompile surefire:test
when:
branch:
- main
- release/*

View File

@ -1,33 +1,47 @@
language: java
jdk:
- openjdk11
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.2.2
before_script:
- |
if [ "$TRAVIS_BRANCH" = "master" ]; then
wget 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
- PATH=$PATH:. VAULT_VERSION=1.7.2 ANALYSIS=false
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.sonar/cache'
script:
jobs:
include:
- jdk: openjdk8
- jdk: openjdk11
env: PATH=$PATH:. VAULT_VERSION=1.7.2 ANALYSIS=true
- jdk: openjdk16
before_script:
- |
if [ "$TRAVIS_BRANCH" = "master" ]; then
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
else
mvn clean test -P offline-tests
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="

View File

@ -1,9 +1,85 @@
## 0.9.4 (2021-06-06)
### Deprecations
* `AppRole.Builder#wit0hTokenPeriod()` is deprecated in favor of `#withTokenPeriod()` (#49)
### Improvements
* Minor dependency updates
### Test
* Tested against Vault 1.7.2
## 0.9.3 (2021-04-02)
### Improvements
* Use pre-sized map objects for fixed-size payloads
* Minor dependency updates
* Unit test adjustments for JDK 16 build environments
### Test
* Tested against Vault 1.7.0
## 0.9.2 (2021-01-24)
### Fixes
* Only initialize custom trust managers, if CA certificate is actually provided (#43)
### Improvements
* Minor dependency updates
## 0.9.1 (2021-01-03)
### Improvements
* Dependency updates
### Test
* Tested against Vault 1.6.1
## 0.9.0 (2020-04-29)
### Fixes
* Correctly parse Map field for token metadata (#34)
* Correctly map token policies on token lookup (#35)
### Features
* Support for token types (#26)
* Support for token role handling (#27) (#37)
### Improvements
* Added `entity_id`, `token_policies`, `token_type` and `orphan` flags to auth response
* Added `entity_id`, `expire_time`, `explicit_max_ttl`, `issue_time`, `renewable` and `type` flags to token data
* Added `explicit_max_ttl`, `period` and `entity_alias` flags to _Token_ model (#41)
* Added `enable_local_secret_ids`, `token_bound_cidrs`, `token_explicit_max_ttl`, `token_no_default_policy`,
`token_num_uses`, `token_period` and `token_type` flags to _AppRole_ model
* Minor dependency updates
### Deprecations
* `AppRole#getPolicies()` and `#setPolicies()` are deprecated in favor of `#getTokenPolicies()` and `#setTokenPolicies()`
* `AppRole#getPeriod()` is deprecated in favor of `#getTokenPeriod()`
* `AppRoleBuilder` and `TokenBuilder` in favor of `AppRole.Builder` and `Token.Builder`
* All-arg constructors of `AppRole` and `Token` in favor of `.builder()....build()` introduced in 0.8
### Removals
* Deprecated methods `AppRole#getBoundCidrList()`, `#setBoundCidrList()` and `getBoundCidrListString()` have been removed.
### Test
* Tested against Vault 1.4.0
## 0.8.2 (2019-10-20)
### Fixes
* Fixed token lookup (#31)
### Improvements
* Updated dependencies
## 0.8.1 (2019-08-16)
### Fixes
* Removed compile dependency to JUnit library (#30)
### Improvements
* Updated ependencies
* Updated dependencies
### Test
* Tested against Vault 1.2.2

View File

@ -1,11 +1,11 @@
# Java Vault Connector
[![Build Status](https://travis-ci.org/stklcode/jvaultconnector.svg?branch=master)](https://travis-ci.org/stklcode/jvaultconnector)
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=de.stklcode.jvault%3Ajvault-connector&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Aconnector)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
[![Build Status](https://travis-ci.com/stklcode/jvaultconnector.svg?branch=main)](https://travis-ci.com/stklcode/jvaultconnector)
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=de.stklcode.jvault%3Ajvault-connector&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Ajvault-connector)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/stklcode/jvaultconnector/blob/main/LICENSE.txt)
[![Maven Central](https://img.shields.io/maven-central/v/de.stklcode.jvault/jvault-connector.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22jvault-connector%22)
![Logo](https://raw.githubusercontent.com/stklcode/jvaultconnector/master/assets/logo.png)
![Logo](https://raw.githubusercontent.com/stklcode/jvaultconnector/main/assets/logo.png)
Java Vault Connector is a connector library for [Vault](https://www.vaultproject.io) by [Hashicorp](https://www.hashicorp.com) written in Java. The connector allows simple usage of Vault's secret store in own applications.
@ -20,8 +20,8 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
* AppRole (register and authenticate)
* AppID (register and authenticate) [_deprecated_]
* Tokens
* Creation and lookup of tokens
* TokenBuilder for speaking creation of complex configuraitons
* Creation and lookup of tokens and token roles
* TokenBuilder for speaking creation of complex configurations
* Secrets
* Read secrets
* Write secrets
@ -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.2.2
* Tested against Vault 1.7.2
## 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.8.1</version>
<version>0.9.4</version>
</dependency>
```
@ -86,20 +86,20 @@ vault.authAppRole("01234567-89ab-cdef-0123-456789abcdef", "fedcba98-7654-3210-fe
```java
// Retrieve secret (prefix "secret/" assumed, use read() to read arbitrary paths)
String secret = vault.readSecret("some/secret/key").get("value", String.class);
String secret = vault.read("secret/some/key").get("value", String.class);
// Complex secret.
Map<String, Object> secretData = vault.readSecret("another/secret/key").getData();
Map<String, Object> secretData = vault.read("secret/another/key").getData();
// Write simple secret.
vault.writeSecret("new/secret/key", "secret value");
vault.write("secret/new/key", "secret value");
// Write complex data to arbitraty path.
// Write complex data.
Map<String, Object> map = ...;
vault.write("any/path/to/write", map);
vault.write("path/to/write", map);
// Delete secret.
vault.delete("any/path/to/write");
vault.delete("path/to/delete");
```
### Token and role creation

191
pom.xml
View File

@ -4,7 +4,7 @@
<groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId>
<version>0.8.1</version>
<version>0.9.4</version>
<packaging>jar</packaging>
@ -23,6 +23,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<argLine></argLine>
</properties>
<developers>
@ -66,12 +67,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>
@ -85,12 +86,18 @@
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<reuseForks>false</reuseForks>
<argLine>@{argLine} --illegal-access=permit</argLine>
</configuration>
</plugin>
</plugins>
@ -98,71 +105,65 @@
</build>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.11</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.3</version>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>5.5.1</version>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-junit</artifactId>
<version>2.0.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.17.2</version>
<artifactId>hamcrest</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.0.0</version>
<version>3.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.0.0</version>
<version>3.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.0.2155</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
@ -175,7 +176,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
@ -199,7 +200,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
<configuration>
<source>1.8</source>
</configuration>
@ -216,6 +217,58 @@
</build>
</profile>
<profile>
<id>sign</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<keyname>${gpg.keyname}</keyname>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>offline-tests</id>
<build>
@ -232,5 +285,73 @@
</pluginManagement>
</build>
</profile>
<profile>
<id>dependency-check</id>
<build>
<plugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.2.0</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</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>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>local</id>
<distributionManagement>
<repository>
<id>stklcode</id>
<url>${dist.repo.local}</url>
</repository>
<snapshotRepository>
<id>stklcode</id>
<url>${dist.repo.local.snapshot}</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
</project>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -20,10 +20,7 @@ import de.stklcode.jvault.connector.exception.AuthorizationRequiredException;
import de.stklcode.jvault.connector.exception.InvalidRequestException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import de.stklcode.jvault.connector.internal.RequestHelper;
import de.stklcode.jvault.connector.model.AppRole;
import de.stklcode.jvault.connector.model.AppRoleSecret;
import de.stklcode.jvault.connector.model.AuthBackend;
import de.stklcode.jvault.connector.model.Token;
import de.stklcode.jvault.connector.model.*;
import de.stklcode.jvault.connector.model.response.*;
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
@ -33,8 +30,11 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
/**
* Vault Connector implementatin using Vault's HTTP API.
* Vault Connector implementation using Vault's HTTP API.
*
* @author Stefan Kalscheuer
* @since 0.1
@ -49,6 +49,7 @@ public class HTTPVaultConnector implements VaultConnector {
private static final String PATH_TOKEN = "auth/token";
private static final String PATH_LOOKUP = "/lookup";
private static final String PATH_CREATE = "/create";
private static final String PATH_ROLES = "/roles";
private static final String PATH_CREATE_ORPHAN = "/create-orphan";
private static final String PATH_AUTH_USERPASS = "auth/userpass/login/";
private static final String PATH_AUTH_APPID = "auth/app-id/";
@ -224,17 +225,17 @@ public class HTTPVaultConnector implements VaultConnector {
@Override
public final SealResponse sealStatus() throws VaultConnectorException {
return request.get(PATH_SEAL_STATUS, new HashMap<>(), token, SealResponse.class);
return request.get(PATH_SEAL_STATUS, emptyMap(), token, SealResponse.class);
}
@Override
public final void seal() throws VaultConnectorException {
request.put(PATH_SEAL, new HashMap<>(), token);
request.put(PATH_SEAL, emptyMap(), token);
}
@Override
public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException {
Map<String, String> param = new HashMap<>();
Map<String, String> param = new HashMap<>(2, 1);
param.put("key", key);
if (reset != null) {
param.put("reset", reset.toString());
@ -246,7 +247,7 @@ 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<>();
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.
@ -262,7 +263,7 @@ public class HTTPVaultConnector implements VaultConnector {
@Override
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
/* Issue request and parse response */
AuthMethodsResponse amr = request.get(PATH_AUTH, new HashMap<>(), token, AuthMethodsResponse.class);
AuthMethodsResponse amr = request.get(PATH_AUTH, emptyMap(), token, AuthMethodsResponse.class);
return amr.getSupportedMethods().values().stream().map(AuthMethod::getType).collect(Collectors.toList());
}
@ -272,7 +273,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* set token */
this.token = token;
this.tokenTTL = 0;
TokenResponse res = request.post(PATH_TOKEN + PATH_LOOKUP, new HashMap<>(), token, TokenResponse.class);
TokenResponse res = request.post(PATH_TOKEN + PATH_LOOKUP, emptyMap(), token, TokenResponse.class);
authorized = true;
return res;
@ -281,15 +282,14 @@ public class HTTPVaultConnector implements VaultConnector {
@Override
public final AuthResponse authUserPass(final String username, final String password)
throws VaultConnectorException {
final Map<String, String> payload = new HashMap<>();
payload.put("password", password);
final Map<String, String> payload = singletonMap("password", password);
return queryAuth(PATH_AUTH_USERPASS + username, payload);
}
@Override
@Deprecated
public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
final Map<String, String> payload = new HashMap<>();
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);
@ -297,7 +297,7 @@ public class HTTPVaultConnector implements VaultConnector {
@Override
public final AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
final Map<String, String> payload = new HashMap<>();
final Map<String, String> payload = new HashMap<>(2, 1);
payload.put("role_id", roleID);
if (secretID != null) {
payload.put("secret_id", secretID);
@ -330,7 +330,7 @@ public class HTTPVaultConnector implements VaultConnector {
public final boolean registerAppId(final String appID, final String policy, final String displayName)
throws VaultConnectorException {
requireAuth();
Map<String, String> payload = new HashMap<>();
Map<String, String> payload = new HashMap<>(2, 1);
payload.put("value", policy);
payload.put("display_name", displayName);
@ -344,11 +344,13 @@ public class HTTPVaultConnector implements VaultConnector {
@Deprecated
public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
requireAuth();
Map<String, String> payload = new HashMap<>();
payload.put("value", appID);
/* Issue request and expect code 204 with empty response */
request.postWithoutResponse(PATH_AUTH_APPID + "map/user-id/" + userID, payload, token);
request.postWithoutResponse(
PATH_AUTH_APPID + "map/user-id/" + userID,
singletonMap("value", appID),
token
);
return true;
}
@ -368,7 +370,12 @@ public class HTTPVaultConnector implements VaultConnector {
public final AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
requireAuth();
/* Request HTTP response and parse Secret */
return request.get(String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""), new HashMap<>(), token, AppRoleResponse.class);
return request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, ""),
emptyMap(),
token,
AppRoleResponse.class
);
}
@Override
@ -387,7 +394,7 @@ public class HTTPVaultConnector implements VaultConnector {
/* Issue request, parse response and extract Role ID */
return request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
new HashMap<>(),
emptyMap(),
token,
RawDataResponse.class
).getData().get("role_id").toString();
@ -396,12 +403,13 @@ public class HTTPVaultConnector implements VaultConnector {
@Override
public final boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException {
requireAuth();
/* Request HTTP response and parse Secret */
Map<String, String> payload = new HashMap<>();
payload.put("role_id", roleID);
/* Issue request and expect code 204 with empty response */
request.postWithoutResponse(String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"), payload, token);
request.postWithoutResponse(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/role-id"),
singletonMap("role_id", roleID),
token
);
return true;
}
@ -459,7 +467,13 @@ public class HTTPVaultConnector implements VaultConnector {
public final List<String> listAppRoles() throws VaultConnectorException {
requireAuth();
SecretListResponse secrets = request.get(PATH_AUTH_APPROLE + "role?list=true", new HashMap<>(), token, SecretListResponse.class);
SecretListResponse secrets = request.get(
PATH_AUTH_APPROLE + "role?list=true",
emptyMap(),
token,
SecretListResponse.class
);
return secrets.getKeys();
}
@ -469,7 +483,7 @@ public class HTTPVaultConnector implements VaultConnector {
SecretListResponse secrets = request.get(
String.format(PATH_AUTH_APPROLE_ROLE, roleName, "/secret-id?list=true"),
new HashMap<>(),
emptyMap(),
token,
SecretListResponse.class
);
@ -481,14 +495,14 @@ public class HTTPVaultConnector implements VaultConnector {
public final SecretResponse read(final String key) throws VaultConnectorException {
requireAuth();
/* Issue request and parse secret response */
return request.get(key, new HashMap<>(), token, SecretResponse.class);
return request.get(key, emptyMap(), token, SecretResponse.class);
}
@Override
public final SecretResponse readSecretVersion(final String mount, final String key, final Integer version) throws VaultConnectorException {
requireAuth();
/* Request HTTP response and parse secret metadata */
Map<String, String> args = new HashMap<>();
Map<String, String> args = new HashMap<>(1, 1);
if (version != null) {
args.put("version", version.toString());
}
@ -501,14 +515,14 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth();
/* Request HTTP response and parse secret metadata */
return request.get(mount + PATH_METADATA + key, new HashMap<>(), token, MetadataResponse.class);
return request.get(mount + PATH_METADATA + key, emptyMap(), token, MetadataResponse.class);
}
@Override
public void updateSecretMetadata(final String mount, final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException {
requireAuth();
Map<String, Object> payload = new HashMap<>();
Map<String, Object> payload = new HashMap<>(2, 1);
if (maxVersions != null) {
payload.put("max_versions", maxVersions);
}
@ -526,12 +540,12 @@ public class HTTPVaultConnector implements VaultConnector {
}
// Add CAS value to options map if present.
Map<String, Object> options = new HashMap<>();
Map<String, Object> options = new HashMap<>(1, 1);
if (cas != null) {
options.put("cas", cas);
}
Map<String, Object> payload = new HashMap<>();
Map<String, Object> payload = new HashMap<>(2, 1);
payload.put("data", data);
payload.put("options", options);
@ -543,7 +557,7 @@ public class HTTPVaultConnector implements VaultConnector {
public final List<String> list(final String path) throws VaultConnectorException {
requireAuth();
SecretListResponse secrets = request.get(path + "/?list=true", new HashMap<>(), token, SecretListResponse.class);
SecretListResponse secrets = request.get(path + "/?list=true", emptyMap(), token, SecretListResponse.class);
return secrets.getKeys();
}
@ -561,7 +575,7 @@ public class HTTPVaultConnector implements VaultConnector {
// If options are given, split payload in two parts.
if (options != null) {
Map<String, Object> payloadMap = new HashMap<>();
Map<String, Object> payloadMap = new HashMap<>(2, 1);
payloadMap.put("data", data);
payloadMap.put("options", options);
payload = payloadMap;
@ -607,7 +621,7 @@ public class HTTPVaultConnector implements VaultConnector {
/**
* Common method to bundle secret version operations.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param pathPart Path part to query.
* @param key Secret key.
* @param versions Versions to handle.
@ -618,8 +632,7 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth();
/* Request HTTP response and expect empty result */
Map<String, Object> payload = new HashMap<>();
payload.put("versions", versions);
Map<String, Object> payload = singletonMap("versions", versions);
/* Issue request and expect code 204 with empty response */
request.postWithoutResponse(mount + pathPart + key, payload, token);
@ -630,14 +643,14 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth();
/* Issue request and expect code 204 with empty response */
request.putWithoutResponse(PATH_REVOKE + leaseID, new HashMap<>(), token);
request.putWithoutResponse(PATH_REVOKE + leaseID, emptyMap(), token);
}
@Override
public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException {
requireAuth();
Map<String, String> payload = new HashMap<>();
Map<String, String> payload = new HashMap<>(2, 1);
payload.put("lease_id", leaseID);
if (increment != null) {
payload.put("increment", increment.toString());
@ -696,7 +709,57 @@ public class HTTPVaultConnector implements VaultConnector {
requireAuth();
/* Request HTTP response and parse Secret */
return request.get(PATH_TOKEN + "/lookup/" + token, new HashMap<>(), token, TokenResponse.class);
return request.get(
PATH_TOKEN + PATH_LOOKUP,
singletonMap("token", token),
token,
TokenResponse.class
);
}
@Override
public boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException {
requireAuth();
if (name == null) {
throw new InvalidRequestException("Role name must be provided.");
} else if (role == null) {
throw new InvalidRequestException("Role must be provided.");
}
// Issue request and expect code 204 with empty response.
request.postWithoutResponse(PATH_TOKEN + PATH_ROLES + "/" + name, role, token);
return true;
}
@Override
public TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException {
requireAuth();
// Request HTTP response and parse response.
return request.get(PATH_TOKEN + PATH_ROLES + "/" + name, emptyMap(), token, TokenRoleResponse.class);
}
@Override
public List<String> listTokenRoles() throws VaultConnectorException {
requireAuth();
return list(PATH_TOKEN + PATH_ROLES);
}
@Override
public boolean deleteTokenRole(final String name) throws VaultConnectorException {
requireAuth();
if (name == null) {
throw new InvalidRequestException("Role name must be provided.");
}
// Issue request and expect code 204 with empty response.
request.deleteWithoutResponse(PATH_TOKEN + PATH_ROLES + "/" + name, token);
return true;
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -22,10 +22,7 @@ import de.stklcode.jvault.connector.model.*;
import de.stklcode.jvault.connector.model.response.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Vault Connector interface.
@ -91,7 +88,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
HealthResponse getHealth() throws VaultConnectorException;
/**
* Get all availale authentication backends.
* Get all available authentication backends.
*
* @return List of backends
* @throws VaultConnectorException on error
@ -226,14 +223,14 @@ public interface VaultConnector extends AutoCloseable, Serializable {
*/
default boolean createAppRole(final String roleName, final List<String> policies, final String roleID)
throws VaultConnectorException {
return createAppRole(new AppRoleBuilder(roleName).withPolicies(policies).withId(roleID).build());
return createAppRole(AppRole.builder(roleName).withTokenPolicies(policies).withId(roleID).build());
}
/**
* Delete AppRole role from Vault.
*
* @param roleName The role anme
* @return {@code true} on succevss
* @param roleName The role name
* @return {@code true} on success
* @throws VaultConnectorException on error
*/
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
@ -430,7 +427,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/data/<key>} is read here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret identifier
* @return Secret response
* @throws VaultConnectorException on error
@ -446,7 +443,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Prefix {@code secret/} is automatically added to path.
* Only available for KV v2 secrets.
*
* @param key Secret identifier.
* @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
@ -462,9 +459,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/data/<key>} is written here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param key Secret identifier
* @param data Secret content. Value must be be JSON serializable.
* @param mount Secret store mount point (without leading or trailing slash).
* @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
@ -479,10 +476,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/data/<key>} is written here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param key Secret identifier
* @param data Secret content. Value must be be JSON serializable.
* @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value.
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret identifier
* @param data Secret content. Value must be be JSON serializable.
* @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value.
* @return Metadata for the created/updated secret.
* @throws VaultConnectorException on error
* @since 0.8
@ -511,10 +508,10 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/data/<key>} is read here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret identifier
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
* @return Secret responsef
* @return Secret response.
* @throws VaultConnectorException on error
* @since 0.8
*/
@ -540,7 +537,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code secret/metadata/<key>} is read here.
* Only available for KV v2 secrets.
*
* @param key Secret identifier
* @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
@ -556,7 +553,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/metadata/<key>} is read here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret identifier
* @return Metadata response
* @throws VaultConnectorException on error
@ -570,7 +567,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Path {@code <mount>/metadata/<key>} is written here.
* Only available for KV v2 secrets.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @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.
@ -611,9 +608,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @since 0.5.0
*/
default void write(final String key, final String value) throws VaultConnectorException {
Map<String, Object> param = new HashMap<>();
param.put("value", value);
write(key, param);
write(key, Collections.singletonMap("value", value));
}
/**
@ -649,9 +644,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @throws VaultConnectorException on error
*/
default void writeSecret(final String key, final String value) throws VaultConnectorException {
Map<String, Object> param = new HashMap<>();
param.put("value", value);
writeSecret(key, param);
writeSecret(key, Collections.singletonMap("value", value));
}
/**
@ -710,7 +703,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* <br>
* Only available for KV v2 stores.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret path.
* @throws VaultConnectorException on error
* @since 0.8
@ -737,8 +730,8 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Prefix {@code secret/} is automatically added to path.
* Only available for KV v2 stores.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param key Secret path.
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret path.
* @throws VaultConnectorException on error
* @since 0.8
*/
@ -763,7 +756,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* <br>
* Only available for KV v2 stores.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret path.
* @param versions Versions of the secret to delete.
* @throws VaultConnectorException on error
@ -788,7 +781,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Undelete (restore) secret versions from Vault.
* Only available for KV v2 stores.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret path.
* @param versions Versions of the secret to undelete.
* @throws VaultConnectorException on error
@ -813,7 +806,7 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* Destroy secret versions from Vault.
* Only available for KV v2 stores.
*
* @param mount Secret store mountpoint (without leading or trailing slash).
* @param mount Secret store mount point (without leading or trailing slash).
* @param key Secret path.
* @param versions Versions of the secret to destroy.
* @throws VaultConnectorException on error
@ -888,7 +881,57 @@ public interface VaultConnector extends AutoCloseable, Serializable {
*/
TokenResponse lookupToken(final String token) throws VaultConnectorException;
/**
* Create a new or update an existing token role.
*
* @param role the role entity (name must be set)
* @return {@code true} on success
* @throws VaultConnectorException on error
* @since 0.9
*/
default boolean createOrUpdateTokenRole(final TokenRole role) throws VaultConnectorException {
return createOrUpdateTokenRole(role.getName(), role);
}
/**
* Create a new or update an existing token role.
*
* @param name the role name (overrides name possibly set in role entity)
* @param role the role entity
* @return {@code true} on success
* @throws VaultConnectorException on error
* @since 0.9
*/
boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException;
/**
* Lookup token information.
*
* @param name the role name
* @return the result response
* @throws VaultConnectorException on error
* @since 0.9
*/
TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException;
/**
* List available token roles from Vault.
*
* @return List of token roles
* @throws VaultConnectorException on error
* @since 0.9
*/
List<String> listTokenRoles() throws VaultConnectorException;
/**
* Delete a token role.
*
* @param name the role name to delete
* @return {@code true} on success
* @throws VaultConnectorException on error
* @since 0.9
*/
boolean deleteTokenRole(final String name) throws VaultConnectorException;
/**
* Read credentials for MySQL backend at default mount point.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -33,7 +33,7 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Vault Connector Factory implementation for HTTP Vault connectors.
* Vault Connector Builder implementation for HTTP Vault connectors.
*
* @author Stefan Kalscheuer
* @since 0.8.0
@ -162,7 +162,7 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
}
/**
* Add a trusted CA certifiate for HTTPS connections.
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
@ -179,7 +179,7 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
}
/**
* Add a trusted CA certifiate for HTTPS connections.
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -26,7 +26,7 @@ public abstract class VaultConnectorException extends Exception {
/**
* Constructs a new empty exception.
*/
public VaultConnectorException() {
protected VaultConnectorException() {
}
/**
@ -34,7 +34,7 @@ public abstract class VaultConnectorException extends Exception {
*
* @param message the detail message
*/
public VaultConnectorException(final String message) {
protected VaultConnectorException(final String message) {
super(message);
}
@ -43,7 +43,7 @@ public abstract class VaultConnectorException extends Exception {
*
* @param cause the cause
*/
public VaultConnectorException(final Throwable cause) {
protected VaultConnectorException(final Throwable cause) {
super(cause);
}
@ -53,7 +53,7 @@ public abstract class VaultConnectorException extends Exception {
* @param message the detail message
* @param cause the cause
*/
public VaultConnectorException(final String message, final Throwable cause) {
protected VaultConnectorException(final String message, final Throwable cause) {
super(message, cause);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -107,7 +107,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
}
/**
* Add a trusted CA certifiate for HTTPS connections.
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
@ -120,7 +120,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
}
/**
* Add a trusted CA certifiate for HTTPS connections.
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -28,7 +28,7 @@ final class Error {
static final String UNEXPECTED_RESPONSE = "Received response where none was expected";
static final String URI_FORMAT = "Invalid URI format";
static final String RESPONSE_CODE = "Invalid response code";
static final String INIT_SSL_CONTEXT = "Unable to intialize SSLContext";
static final String INIT_SSL_CONTEXT = "Unable to initialize SSLContext";
/**
* Constructor hidden, this class should not be instantiated.

View File

@ -340,7 +340,7 @@ public final class RequestHelper implements Serializable {
/* Fail on different error code and/or no retries left */
handleError(response);
/* Throw exception withoud details, if response entity is empty. */
/* Throw exception without details, if response entity is empty. */
throw new InvalidResponseException(Error.RESPONSE_CODE,
response.getStatusLine().getStatusCode());
}
@ -362,23 +362,27 @@ public final class RequestHelper implements Serializable {
* Create a custom socket factory from trusted CA certificate.
*
* @return The factory.
* @throws TlsException An error occured during initialization of the SSL context.
* @throws TlsException An error occurred during initialization of the SSL context.
* @since 0.8.0
*/
private SSLConnectionSocketFactory createSSLSocketFactory() throws TlsException {
try {
// Create Keystore with trusted certificate.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("trustedCert", trustedCaCert);
// Initialize TrustManager.
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// Create context usint this TrustManager.
// Create context..
SSLContext context = SSLContext.getInstance(tlsVersion);
context.init(null, tmf.getTrustManagers(), new SecureRandom());
if (trustedCaCert != null) {
// Create Keystore with trusted certificate.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("trustedCert", trustedCaCert);
// Initialize TrustManager.
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
context.init(null, tmf.getTrustManagers(), null);
} else {
context.init(null, null, null);
}
return new SSLConnectionSocketFactory(
context,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -18,6 +18,7 @@ package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
@ -29,14 +30,14 @@ import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public final class AppRole {
/**
* Get {@link AppRoleBuilder} instance.
* Get {@link Builder} instance.
*
* @param name Role name.
* @return AppRole Builder.
* @since 0.8
*/
public static AppRoleBuilder builder(final String name) {
return new AppRoleBuilder(name);
public static Builder builder(final String name) {
return new Builder(name);
}
@JsonProperty("role_name")
@ -50,12 +51,8 @@ public final class AppRole {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean bindSecretId;
private List<String> boundCidrList;
private List<String> secretIdBoundCidrs;
private List<String> policies;
@JsonProperty("secret_id_num_uses")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer secretIdNumUses;
@ -64,6 +61,10 @@ public final class AppRole {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer secretIdTtl;
@JsonProperty("enable_local_secret_ids")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean enableLocalSecretIds;
@JsonProperty("token_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenTtl;
@ -72,44 +73,36 @@ public final class AppRole {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenMaxTtl;
@JsonProperty("period")
private List<String> tokenPolicies;
@JsonProperty("token_bound_cidrs")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer period;
private List<String> tokenBoundCidrs;
@JsonProperty("token_explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenExplicitMaxTtl;
@JsonProperty("token_no_default_policy")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean tokenNoDefaultPolicy;
@JsonProperty("token_num_uses")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenNumUses;
@JsonProperty("token_period")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenPeriod;
@JsonProperty("token_type")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String tokenType;
/**
* Construct empty {@link AppRole} object.
*/
public AppRole() {
}
/**
* Construct complete {@link AppRole} object.
*
* @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 policies List of policies (optional)
* @param secretIdNumUses Maximum number of uses per secret (optional)
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
* @param tokenTtl Token TTL in seconds (optional)
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
* @param period Duration in seconds, if set the token is a periodic token (optional)
*/
public AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> secretIdBoundCidrs,
final List<String> policies, final Integer secretIdNumUses, final Integer secretIdTtl,
final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) {
this.name = name;
this.id = id;
this.bindSecretId = bindSecretId;
this.secretIdBoundCidrs = secretIdBoundCidrs;
this.policies = policies;
this.secretIdNumUses = secretIdNumUses;
this.secretIdTtl = secretIdTtl;
this.tokenTtl = tokenTtl;
this.tokenMaxTtl = tokenMaxTtl;
this.period = period;
}
/**
@ -117,32 +110,70 @@ public final class AppRole {
* <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 boundCidrList Whitelist of subnets in CIDR notation (optional)
* @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional)
* @param policies List of policies (optional)
* @param secretIdNumUses Maximum number of uses per secret (optional)
* @param secretIdTtl Maximum TTL in seconds for secrets (optional)
* @param tokenTtl Token TTL in seconds (optional)
* @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional)
* @param period Duration in seconds, if set the token is a periodic token (optional)
* @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.
*/
AppRole(final String name, final String id, final Boolean bindSecretId, final List<String> boundCidrList,
final List<String> secretIdBoundCidrs, final List<String> policies, final Integer secretIdNumUses,
final Integer secretIdTtl, final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) {
@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.boundCidrList = boundCidrList;
this.secretIdBoundCidrs = secretIdBoundCidrs;
this.policies = policies;
this.tokenPolicies = tokenPolicies;
this.secretIdNumUses = secretIdNumUses;
this.secretIdTtl = secretIdTtl;
this.enableLocalSecretIds = enableLocalSecretIds;
this.tokenTtl = tokenTtl;
this.tokenMaxTtl = tokenMaxTtl;
this.period = period;
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}.
*
* @param builder AppRole builder.
*/
public AppRole(final Builder builder) {
this.name = builder.name;
this.id = builder.id;
this.bindSecretId = builder.bindSecretId;
this.secretIdBoundCidrs = builder.secretIdBoundCidrs;
this.secretIdNumUses = builder.secretIdNumUses;
this.secretIdTtl = builder.secretIdTtl;
this.enableLocalSecretIds = builder.enableLocalSecretIds;
this.tokenTtl = builder.tokenTtl;
this.tokenMaxTtl = builder.tokenMaxTtl;
this.tokenPolicies = builder.tokenPolicies;
this.tokenBoundCidrs = builder.tokenBoundCidrs;
this.tokenExplicitMaxTtl = builder.tokenExplicitMaxTtl;
this.tokenNoDefaultPolicy = builder.tokenNoDefaultPolicy;
this.tokenNumUses = builder.tokenNumUses;
this.tokenPeriod = builder.tokenPeriod;
this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null;
}
/**
@ -167,41 +198,38 @@ public final class AppRole {
}
/**
* @return list of bound CIDR subnets
* @deprecated Use {@link #getSecretIdBoundCidrs()} instead, as this parameter is deprecated in Vault.
* @return list of bound CIDR subnets of associated tokens
* @since 0.9
*/
@Deprecated
public List<String> getBoundCidrList() {
return boundCidrList;
public List<String> getTokenBoundCidrs() {
return tokenBoundCidrs;
}
/**
* @param boundCidrList list of subnets in CIDR notation to bind role to
* @deprecated Use {@link #setSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault.
* @since 0.9
*/
@Deprecated
@JsonSetter("bound_cidr_list")
public void setBoundCidrList(final List<String> boundCidrList) {
this.boundCidrList = boundCidrList;
@JsonSetter("token_bound_cidrs")
public void setBoundCidrs(final List<String> boundCidrList) {
this.tokenBoundCidrs = boundCidrList;
}
/**
* @return list of subnets in CIDR notation as comma-separated {@link String}
* @deprecated Use {@link #getSecretIdBoundCidrsString()} instead, as this parameter is deprecated in Vault.
* @since 0.9
*/
@Deprecated
@JsonGetter("bound_cidr_list")
@JsonGetter("token_bound_cidrs")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getBoundCidrListString() {
if (boundCidrList == null || boundCidrList.isEmpty()) {
public String getTokenBoundCidrsString() {
if (tokenBoundCidrs == null || tokenBoundCidrs.isEmpty()) {
return "";
}
return String.join(",", boundCidrList);
return String.join(",", tokenBoundCidrs);
}
/**
* @return list of bound CIDR subnets
* @since 0.8 replaces {@link #getBoundCidrList()}
* @since 0.8 replaces {@code getBoundCidrList()}
*/
public List<String> getSecretIdBoundCidrs() {
return secretIdBoundCidrs;
@ -209,7 +237,7 @@ public final class AppRole {
/**
* @param secretIdBoundCidrs List of subnets in CIDR notation to bind secrets of this role to.
* @since 0.8 replaces {@link #setBoundCidrList(List)}
* @since 0.8 replaces {@code setBoundCidrList(List)}
*/
@JsonSetter("secret_id_bound_cidrs")
public void setSecretIdBoundCidrs(final List<String> secretIdBoundCidrs) {
@ -218,7 +246,7 @@ public final class AppRole {
/**
* @return List of subnets in CIDR notation as comma-separated {@link String}
* @since 0.8 replaces {@link #getBoundCidrListString()} ()}
* @since 0.8 replaces {@code getBoundCidrListString()} ()}
*/
@JsonGetter("secret_id_bound_cidrs")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@ -230,30 +258,63 @@ public final class AppRole {
}
/**
* @return list of policies
* @return list of token policies
* @since 0.9
*/
public List<String> getTokenPolicies() {
return tokenPolicies;
}
/**
* @return list of token policies
* @deprecated Use {@link #getTokenPolicies()} instead.
*/
@Deprecated
@JsonIgnore
public List<String> getPolicies() {
return policies;
return getTokenPolicies();
}
/**
* @param tokenPolicies list of token policies
* @since 0.9
*/
@JsonSetter("token_policies")
public void setTokenPolicies(final List<String> tokenPolicies) {
this.tokenPolicies = tokenPolicies;
}
/**
* @param policies list of policies
* @deprecated Use {@link #setTokenPolicies(List)} instead.
*/
@JsonSetter("policies")
@Deprecated
@JsonIgnore
public void setPolicies(final List<String> policies) {
this.policies = policies;
setTokenPolicies(policies);
}
/**
* @return list of policies as comma-separated {@link String}
* @since 0.9
*/
@JsonGetter("policies")
@JsonGetter("token_policies")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getPoliciesString() {
if (policies == null || policies.isEmpty()) {
public String getTokenPoliciesString() {
if (tokenPolicies == null || tokenPolicies.isEmpty()) {
return "";
}
return String.join(",", policies);
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();
}
/**
@ -270,6 +331,14 @@ public final class AppRole {
return secretIdTtl;
}
/**
* @return Enable local secret IDs?
* @since 0.9
*/
public Boolean getEnableLocalSecretIds() {
return enableLocalSecretIds;
}
/**
* @return token TTL in seconds
*/
@ -285,9 +354,404 @@ public final class AppRole {
}
/**
* @return duration in seconds, if specified
* @return explicit maximum token TTL in seconds, including renewals
* @since 0.9
*/
public Integer getTokenExplicitMaxTtl() {
return tokenExplicitMaxTtl;
}
/**
* @return enable default policy for token?
* @since 0.9
*/
public Boolean getTokenNoDefaultPolicy() {
return tokenNoDefaultPolicy;
}
/**
* @return number of uses for token
* @since 0.9
*/
public Integer getTokenNumUses() {
return tokenNumUses;
}
/**
* @return duration in seconds, if specified
* @since 0.9
*/
public Integer getTokenPeriod() {
return tokenPeriod;
}
/**
* @return duration in seconds, if specified
* @deprecated Use {@link #getTokenPeriod()} instead.
*/
@Deprecated
@JsonIgnore
public Integer getPeriod() {
return period;
return getTokenPeriod();
}
/**
* @return duration in seconds, if specified
* @since 0.9
*/
public String getTokenType() {
return tokenType;
}
/**
* A builder for vault AppRole roles..
*
* @author Stefan Kalscheuer
* @since 0.4.0
* @since 0.9 Moved into subclass of {@link AppRole}.
*/
public static final class Builder {
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 Builder} with only the role name set.
*
* @param name Role name
*/
public Builder(final String name) {
this.name = name;
}
/**
* Add role name.
*
* @param name Role name
* @return self
*/
public Builder withName(final String name) {
this.name = name;
return this;
}
/**
* Add custom role ID. (optional)
*
* @param id the ID
* @return self
*/
public Builder 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 Builder withBindSecretID(final Boolean bindSecretId) {
this.bindSecretId = bindSecretId;
return this;
}
/**
* Bind role to secret ID.
* Convenience method for {@link #withBindSecretID(Boolean)}
*
* @return self
*/
public Builder withBindSecretID() {
return withBindSecretID(true);
}
/**
* Do not bind role to secret ID.
* Convenience method for {@link #withBindSecretID(Boolean)}
*
* @return self
*/
public Builder 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 Builder 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 Builder 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 Builder 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 Builder withPolicies(final List<String> policies) {
return withTokenPolicies(policies);
}
/**
* Add a single policy.
*
* @param tokenPolicy the token policy
* @return self
* @since 0.9
*/
public Builder 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 Builder withPolicy(final String policy) {
return withTokenPolicy(policy);
}
/**
* Set number of uses for sectet IDs.
*
* @param secretIdNumUses the number of uses
* @return self
*/
public Builder withSecretIdNumUses(final Integer secretIdNumUses) {
this.secretIdNumUses = secretIdNumUses;
return this;
}
/**
* Set default sectet ID TTL in seconds.
*
* @param secretIdTtl the TTL
* @return self
*/
public Builder 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 Builder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) {
this.enableLocalSecretIds = enableLocalSecretIds;
return this;
}
/**
* Set default token TTL in seconds.
*
* @param tokenTtl the TTL
* @return self
*/
public Builder withTokenTtl(final Integer tokenTtl) {
this.tokenTtl = tokenTtl;
return this;
}
/**
* Set maximum token TTL in seconds.
*
* @param tokenMaxTtl the TTL
* @return self
*/
public Builder 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 Builder 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 Builder 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 Builder 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 Builder 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 Builder 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 Builder 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 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.
*
* @param tokenType token type
* @return self
* @since 0.9
*/
public Builder 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(this);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -24,19 +24,26 @@ import java.util.List;
*
* @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> boundCidrList;
private List<String> secretIdBoundCidrs;
private List<String> policies;
private List<String> tokenPolicies;
private Integer secretIdNumUses;
private Integer secretIdTtl;
private Boolean enableLocalSecretIds;
private Integer tokenTtl;
private Integer tokenMaxTtl;
private Integer period;
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.
@ -89,47 +96,48 @@ public final class AppRoleBuilder {
return withBindSecretID(false);
}
/**
* Set bound CIDR blocks.
*
* @param boundCidrList List of CIDR blocks which can perform login
* @return self
* @deprecated Use {@link #withSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault.
*/
@Deprecated
public AppRoleBuilder withBoundCidrList(final List<String> boundCidrList) {
this.boundCidrList = boundCidrList;
return this;
}
/**
* Set bound CIDR blocks.
*
* @param secretIdBoundCidrs List of CIDR blocks which can perform login
* @return self
* @since 0.8 replaces {@link #withBoundCidrList(List)}
* @since 0.8 replaces {@code withBoundCidrList(List)}
*/
public AppRoleBuilder withSecretIdBoundCidrs(final List<String> secretIdBoundCidrs) {
this.secretIdBoundCidrs = secretIdBoundCidrs;
if (this.secretIdBoundCidrs == null) {
this.secretIdBoundCidrs = new ArrayList<>();
}
this.secretIdBoundCidrs.addAll(secretIdBoundCidrs);
return this;
}
/**
* Add a CIDR block to list of bound blocks.
* Add a CIDR block to list of bound blocks for secret.
*
* @param cidrBlock the CIDR block
* @param secretBoundCidr the CIDR block
* @return self
* @since 0.9
*/
public AppRoleBuilder withCidrBlock(final String cidrBlock) {
if (boundCidrList == null) {
boundCidrList = new ArrayList<>();
}
boundCidrList.add(cidrBlock);
public AppRoleBuilder withSecretBoundCidr(final String secretBoundCidr) {
if (secretIdBoundCidrs == null) {
secretIdBoundCidrs = new ArrayList<>();
}
secretIdBoundCidrs.add(cidrBlock);
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;
}
@ -138,12 +146,25 @@ public final class AppRoleBuilder {
*
* @param policies the policies
* @return self
* @deprecated Use {@link #withTokenPolicies(List)} instead.
*/
@Deprecated
public AppRoleBuilder withPolicies(final List<String> policies) {
if (this.policies == null) {
this.policies = new ArrayList<>();
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<>();
}
this.policies.addAll(policies);
tokenPolicies.add(tokenPolicy);
return this;
}
@ -152,34 +173,44 @@ public final class AppRoleBuilder {
*
* @param policy the policy
* @return self
* @deprecated Use {@link #withTokenPolicy(String)} instead.
*/
@Deprecated
public AppRoleBuilder withPolicy(final String policy) {
if (this.policies == null) {
this.policies = new ArrayList<>();
}
policies.add(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 number of uses for sectet IDs.
* Set default secret ID TTL in seconds.
*
* @param secredIdNumUses the number of uses
* @param secretIdTtl the TTL
* @return self
*/
public AppRoleBuilder withSecretIdNumUses(final Integer secredIdNumUses) {
this.secretIdNumUses = secredIdNumUses;
public AppRoleBuilder withSecretIdTtl(final Integer secretIdTtl) {
this.secretIdTtl = secretIdTtl;
return this;
}
/**
* Set default sectet ID TTL in seconds.
* Enable or disable local secret IDs.
*
* @param secredIdTtl the TTL
* @param enableLocalSecretIds Enable local secret IDs?
* @return self
* @since 0.9
*/
public AppRoleBuilder withSecretIdTtl(final Integer secredIdTtl) {
this.secretIdTtl = secredIdTtl;
public AppRoleBuilder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) {
this.enableLocalSecretIds = enableLocalSecretIds;
return this;
}
@ -205,17 +236,119 @@ public final class AppRoleBuilder {
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) {
this.period = period;
return this;
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.
@ -223,16 +356,23 @@ public final class AppRoleBuilder {
* @return the role
*/
public AppRole build() {
return new AppRole(name,
return new AppRole(
name,
id,
bindSecretId,
boundCidrList,
secretIdBoundCidrs,
policies,
secretIdNumUses,
secretIdTtl,
enableLocalSecretIds,
tokenTtl,
tokenMaxTtl,
period);
tokenPolicies,
tokenBoundCidrs,
tokenExplicitMaxTtl,
tokenNoDefaultPolicy,
tokenNumUses,
tokenPeriod,
tokenType != null ? tokenType.value() : null
);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -20,8 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Vault Token metamodel.
@ -32,19 +31,23 @@ import java.util.Map;
@JsonIgnoreProperties(ignoreUnknown = true)
public final class Token {
/**
* Get {@link TokenBuilder} instance.
* Get {@link Builder} instance.
*
* @return Token Builder.
* @since 0.8
*/
public static TokenBuilder builder() {
return new TokenBuilder();
public static Builder builder() {
return new Builder();
}
@JsonProperty("id")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String id;
@JsonProperty("type")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String type;
@JsonProperty("display_name")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String displayName;
@ -61,6 +64,10 @@ public final class Token {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer ttl;
@JsonProperty("explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer explicitMaxTtl;
@JsonProperty("num_uses")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer numUses;
@ -77,8 +84,22 @@ public final class Token {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean renewable;
@JsonProperty("period")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer period;
@JsonProperty("entity_alias")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String entityAlias;
/**
* Construct complete {@link Token} object.
* Construct empty {@link Token} object.
*/
public Token() {
}
/**
* Construct complete {@link Token} object with default type.
*
* @param id Token ID (optional)
* @param displayName Token display name (optional)
@ -89,7 +110,9 @@ public final class Token {
* @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,
@ -99,7 +122,37 @@ public final class Token {
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;
@ -110,6 +163,27 @@ public final class Token {
this.renewable = renewable;
}
/**
* Construct {@link Token} object from {@link Builder}.
*
* @param builder Token builder.
*/
public Token(final Builder builder) {
this.id = builder.id;
this.type = builder.type != null ? builder.type.value() : null;
this.displayName = builder.displayName;
this.noParent = builder.noParent;
this.noDefaultPolicy = builder.noDefaultPolicy;
this.ttl = builder.ttl;
this.explicitMaxTtl = builder.explicitMaxTtl;
this.numUses = builder.numUses;
this.policies = builder.policies;
this.meta = builder.meta;
this.renewable = builder.renewable;
this.period = builder.period;
this.entityAlias = builder.entityAlias;
}
/**
* @return Token ID
*/
@ -117,6 +191,14 @@ public final class Token {
return id;
}
/**
* @return Token type
* @since 0.9
*/
public String getType() {
return type;
}
/**
* @return Token display name
*/
@ -145,6 +227,14 @@ public final class Token {
return ttl;
}
/**
* @return Explicit maximum time-to-live in seconds
* @since 0.9
*/
public Integer getExplicitMaxTtl() {
return explicitMaxTtl;
}
/**
* @return Number of uses
*/
@ -172,4 +262,325 @@ public final class Token {
public Boolean isRenewable() {
return renewable;
}
/**
* @return Token period.
* @since 0.9
*/
public Integer getPeriod() {
return period;
}
/**
* @return Token entity alias.
* @since 0.9
*/
public String getEntityAlias() {
return entityAlias;
}
/**
* Constants for token types.
*/
public enum Type {
DEFAULT("default"),
BATCH("batch"),
SERVICE("service"),
DEFAULT_SERVICE("default-service"),
DEFAULT_BATCH("default-batch");
private final String value;
Type(String value) {
this.value = value;
}
public String value() {
return value;
}
}
/**
* A builder for vault tokens.
*
* @author Stefan Kalscheuer
* @since 0.4.0
* @since 0.9 Moved into subclass of {@link Token}.
*/
public static final class Builder {
private String id;
private Type type;
private String displayName;
private Boolean noParent;
private Boolean noDefaultPolicy;
private Integer ttl;
private Integer explicitMaxTtl;
private Integer numUses;
private List<String> policies;
private Map<String, String> meta;
private Boolean renewable;
private Integer period;
private String entityAlias;
/**
* Add token ID. (optional)
*
* @param id the ID
* @return self
*/
public Builder withId(final String id) {
this.id = id;
return this;
}
/**
* Specify token type.
*
* @param type the type
* @return self
* @since 0.9
*/
public Builder withType(final Token.Type type) {
this.type = type;
return this;
}
/**
* Add display name.
*
* @param displayName the display name
* @return self
*/
public Builder withDisplayName(final String displayName) {
this.displayName = displayName;
return this;
}
/**
* Set desired time to live.
*
* @param ttl the ttl
* @return self
*/
public Builder withTtl(final Integer ttl) {
this.ttl = ttl;
return this;
}
/**
* Set desired explicit maximum time to live.
*
* @param explicitMaxTtl the explicit max. TTL
* @return self
*/
public Builder withExplicitMaxTtl(final Integer explicitMaxTtl) {
this.explicitMaxTtl = explicitMaxTtl;
return this;
}
/**
* Set desired number of uses.
*
* @param numUses the number of uses
* @return self
*/
public Builder 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 Builder withNoParent(final boolean noParent) {
this.noParent = noParent;
return this;
}
/**
* Create token without parent.
* Convenience method for withNoParent()
*
* @return self
*/
public Builder asOrphan() {
return withNoParent(true);
}
/**
* Create token with parent.
* Convenience method for withNoParent()
*
* @return self
*/
public Builder 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 Builder withNoDefaultPolicy(final boolean noDefaultPolicy) {
this.noDefaultPolicy = noDefaultPolicy;
return this;
}
/**
* Attach default policy to token.
* Convenience method for withNoDefaultPolicy()
*
* @return self
*/
public Builder withDefaultPolicy() {
return withNoDefaultPolicy(false);
}
/**
* Do not attach default policy to token.
* Convenience method for withNoDefaultPolicy()
*
* @return self
*/
public Builder withoutDefaultPolicy() {
return withNoDefaultPolicy(true);
}
/**
* Add given policies.
*
* @param policies the policies
* @return self
* @since 0.5.0
*/
public Builder withPolicies(final String... policies) {
return withPolicies(Arrays.asList(policies));
}
/**
* Add given policies.
*
* @param policies the policies
* @return self
*/
public Builder 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 Builder 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 Builder 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 Builder 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 Builder withRenewable(final Boolean renewable) {
this.renewable = renewable;
return this;
}
/**
* Set token to be renewable.
* Convenience method for withRenewable()
*
* @return self
*/
public Builder renewable() {
return withRenewable(true);
}
/**
* Set token to be not renewable.
* Convenience method for withRenewable()
*
* @return self
*/
public Builder notRenewable() {
return withRenewable(false);
}
/**
* Set token period (former lease time).
*
* @param period Period in seconds.
* @return self
*/
public Builder withPeriod(final Integer period) {
this.period = period;
return this;
}
/**
* Set entity alias for token.
* Only works in combination with an associated token role.
*
* @param entityAlias Entity alias.
* @return self
*/
public Builder withEntityAlias(final String entityAlias) {
this.entityAlias = entityAlias;
return this;
}
/**
* Build the token based on given parameters.
*
* @return the token
*/
public Token build() {
return new Token(this);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -23,9 +23,12 @@ import java.util.*;
*
* @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;
@ -46,6 +49,18 @@ public final class TokenBuilder {
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.
*
@ -247,6 +262,7 @@ public final class TokenBuilder {
*/
public Token build() {
return new Token(id,
type != null ? type.value() : null,
displayName,
noParent,
noDefaultPolicy,

View File

@ -0,0 +1,465 @@
/*
* 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.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
/**
* Vault Token Role metamodel.
*
* @author Stefan Kalscheuer
* @since 0.9
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenRole {
/**
* Get {@link Builder} instance.
*
* @return Token Role Builder.
*/
public static Builder builder() {
return new Builder();
}
@JsonProperty("name")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String name;
@JsonProperty("allowed_policies")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> allowedPolicies;
@JsonProperty("disallowed_policies")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> disallowedPolicies;
@JsonProperty("orphan")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean orphan;
@JsonProperty("renewable")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean renewable;
@JsonProperty("path_suffix")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String pathSuffix;
@JsonProperty("allowed_entity_aliases")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> allowedEntityAliases;
@JsonProperty("token_bound_cidrs")
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> tokenBoundCidrs;
@JsonProperty("token_explicit_max_ttl")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenExplicitMaxTtl;
@JsonProperty("token_no_default_policy")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean tokenNoDefaultPolicy;
@JsonProperty("token_num_uses")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenNumUses;
@JsonProperty("token_period")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer tokenPeriod;
@JsonProperty("token_type")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String tokenType;
/**
* Construct empty {@link TokenRole} object.
*/
public TokenRole() {
}
public TokenRole(final Builder builder) {
this.name = builder.name;
this.allowedPolicies = builder.allowedPolicies;
this.disallowedPolicies = builder.disallowedPolicies;
this.orphan = builder.orphan;
this.renewable = builder.renewable;
this.pathSuffix = builder.pathSuffix;
this.allowedEntityAliases = builder.allowedEntityAliases;
this.tokenBoundCidrs = builder.tokenBoundCidrs;
this.tokenExplicitMaxTtl = builder.tokenExplicitMaxTtl;
this.tokenNoDefaultPolicy = builder.tokenNoDefaultPolicy;
this.tokenNumUses = builder.tokenNumUses;
this.tokenPeriod = builder.tokenPeriod;
this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null;
}
/**
* @return Token Role name
*/
public String getName() {
return name;
}
/**
* @return List of allowed policies
*/
public List<String> getAllowedPolicies() {
return allowedPolicies;
}
/**
* @return List of disallowed policies
*/
public List<String> getDisallowedPolicies() {
return disallowedPolicies;
}
/**
* @return Is Token Role orphan?
*/
public Boolean getOrphan() {
return orphan;
}
/**
* @return Is Token Role renewable?
*/
public Boolean getRenewable() {
return renewable;
}
/**
* @return Path suffix
*/
public String getPathSuffix() {
return pathSuffix;
}
/**
* @return List of allowed entity aliases
*/
public List<String> getAllowedEntityAliases() {
return allowedEntityAliases;
}
/**
* @return Token bound CIDR blocks
*/
public List<String> getTokenBoundCidrs() {
return tokenBoundCidrs;
}
/**
* @return Token explicit maximum TTL
*/
public Integer getTokenExplicitMaxTtl() {
return tokenExplicitMaxTtl;
}
/**
* @return Token without default policy?
*/
public Boolean getTokenNoDefaultPolicy() {
return tokenNoDefaultPolicy;
}
/**
* @return Token number of uses
*/
public Integer getTokenNumUses() {
return tokenNumUses;
}
/**
* @return Token period
*/
public Integer getTokenPeriod() {
return tokenPeriod;
}
/**
* @return Token type
*/
public String getTokenType() {
return tokenType;
}
/**
* A builder for vault token roles.
*
* @author Stefan Kalscheuer
* @since 0.9
*/
public static final class Builder {
private String name;
private List<String> allowedPolicies;
private List<String> disallowedPolicies;
private Boolean orphan;
private Boolean renewable;
private String pathSuffix;
private List<String> allowedEntityAliases;
private List<String> tokenBoundCidrs;
private Integer tokenExplicitMaxTtl;
private Boolean tokenNoDefaultPolicy;
private Integer tokenNumUses;
private Integer tokenPeriod;
private Token.Type tokenType;
/**
* Add token role name.
*
* @param name role name
* @return self
*/
public Builder forName(final String name) {
this.name = name;
return this;
}
/**
* Add an allowed policy.
*
* @param allowedPolicy allowed policy to add
* @return self
*/
public Builder withAllowedPolicy(final String allowedPolicy) {
if (allowedPolicy != null) {
if (this.allowedPolicies == null) {
this.allowedPolicies = new ArrayList<>();
}
this.allowedPolicies.add(allowedPolicy);
}
return this;
}
/**
* Add allowed policies.
*
* @param allowedPolicies list of allowed policies
* @return self
*/
public Builder withAllowedPolicies(final List<String> allowedPolicies) {
if (allowedPolicies != null) {
if (this.allowedPolicies == null) {
this.allowedPolicies = new ArrayList<>();
}
this.allowedPolicies.addAll(allowedPolicies);
}
return this;
}
/**
* Add a disallowed policy.
*
* @param disallowedPolicy disallowed policy to add
* @return self
*/
public Builder withDisallowedPolicy(final String disallowedPolicy) {
if (disallowedPolicy != null) {
if (this.disallowedPolicies == null) {
this.disallowedPolicies = new ArrayList<>();
}
this.disallowedPolicies.add(disallowedPolicy);
}
return this;
}
/**
* Add disallowed policies.
*
* @param disallowedPolicies list of disallowed policies
* @return self
*/
public Builder withDisallowedPolicies(final List<String> disallowedPolicies) {
if (disallowedPolicies != null) {
if (this.disallowedPolicies == null) {
this.disallowedPolicies = new ArrayList<>();
}
this.disallowedPolicies.addAll(disallowedPolicies);
}
return this;
}
/**
* Set TRUE if the token role should be created orphan.
*
* @param orphan if TRUE, token role is created as orphan
* @return self
*/
public Builder orphan(final Boolean orphan) {
this.orphan = orphan;
return this;
}
/**
* Set TRUE if the token role should be created renewable.
*
* @param renewable if TRUE, token role is created renewable
* @return self
*/
public Builder renewable(final Boolean renewable) {
this.renewable = renewable;
return this;
}
/**
* Set token role path suffix.
*
* @param pathSuffix path suffix to use
* @return self
*/
public Builder withPathSuffix(final String pathSuffix) {
this.pathSuffix = pathSuffix;
return this;
}
/**
* Add an allowed entity alias.
*
* @param allowedEntityAlias allowed entity alias to add
* @return self
*/
public Builder withAllowedEntityAlias(final String allowedEntityAlias) {
if (allowedEntityAlias != null) {
if (this.allowedEntityAliases == null) {
this.allowedEntityAliases = new ArrayList<>();
}
this.allowedEntityAliases.add(allowedEntityAlias);
}
return this;
}
/**
* Add allowed entity aliases.
*
* @param allowedEntityAliases list of allowed entity aliases to add
* @return self
*/
public Builder withAllowedEntityAliases(final List<String> allowedEntityAliases) {
if (allowedEntityAliases != null) {
if (this.allowedEntityAliases == null) {
this.allowedEntityAliases = new ArrayList<>();
}
this.allowedEntityAliases.addAll(allowedEntityAliases);
}
return this;
}
/**
* Add a single bound CIDR.
*
* @param tokenBoundCidr bound CIDR to add
* @return self
*/
public Builder withTokenBoundCidr(final String tokenBoundCidr) {
if (tokenBoundCidr != null) {
if (this.tokenBoundCidrs == null) {
this.tokenBoundCidrs = new ArrayList<>();
}
this.tokenBoundCidrs.add(tokenBoundCidr);
}
return this;
}
/**
* Add a list of bound CIDRs.
*
* @param tokenBoundCidrs list of bound CIDRs to add
* @return self
*/
public Builder withTokenBoundCidrs(final List<String> tokenBoundCidrs) {
if (tokenBoundCidrs != null) {
if (this.tokenBoundCidrs == null) {
this.tokenBoundCidrs = new ArrayList<>();
}
this.tokenBoundCidrs.addAll(tokenBoundCidrs);
}
return this;
}
/**
* Set explicit max. TTL for token.
*
* @param tokenExplicitMaxTtl explicit maximum TTL
* @return self
*/
public Builder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) {
this.tokenExplicitMaxTtl = tokenExplicitMaxTtl;
return this;
}
/**
* Set TRUE if the token role should be created renewable.
*
* @param tokenNoDefaultPolicy if TRUE, token is created without default policy.
* @return self
*/
public Builder withTokenNoDefaultPolicy(final Boolean tokenNoDefaultPolicy) {
this.tokenNoDefaultPolicy = tokenNoDefaultPolicy;
return this;
}
/**
* Set number of uses for tokens.
*
* @param tokenNumUses number of uses for associated tokens.
* @return self
*/
public Builder withTokenNumUses(final Integer tokenNumUses) {
this.tokenNumUses = tokenNumUses;
return this;
}
/**
* Set token period.
*
* @param tokenPeriod token period
* @return self
*/
public Builder withTokenPeriod(final Integer tokenPeriod) {
this.tokenPeriod = tokenPeriod;
return this;
}
/**
* Set token type.
*
* @param tokenType token type
* @return self
*/
public Builder withTokenType(final Token.Type tokenType) {
this.tokenType = tokenType;
return this;
}
/**
* Build the token based on given parameters.
*
* @return the token
*/
public TokenRole build() {
return new TokenRole(this);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -40,7 +40,7 @@ public final class AppRoleResponse extends VaultDataResponse {
ObjectMapper mapper = new ObjectMapper();
try {
/* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>();
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
data.forEach((k, v) -> {
if (!(v instanceof String && ((String) v).isEmpty())) {
filteredData.put(k, v);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -40,7 +40,7 @@ public final class AppRoleSecretResponse extends VaultDataResponse {
ObjectMapper mapper = new ObjectMapper();
try {
/* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>();
Map<String, Object> filteredData = new HashMap<>(data.size(), 1);
data.forEach((k, v) -> {
if (!(v instanceof String && ((String) v).isEmpty())) {
filteredData.put(k, v);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -22,7 +22,7 @@ import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
import java.io.IOException;
import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
/**
@ -66,7 +66,7 @@ public class SecretResponse extends VaultDataResponse {
*/
public final Map<String, Object> getData() {
if (data == null) {
return new HashMap<>();
return Collections.emptyMap();
}
return data;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -25,7 +25,7 @@ import java.io.IOException;
import java.util.Map;
/**
* Vault response for a single secret version metatada, i.e. after update (KV v2).
* Vault response for a single secret version metadata, i.e. after update (KV v2).
*
* @author Stefan Kalscheuer
* @since 0.8

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -0,0 +1,60 @@
/*
* Copyright 2016-2021 Stefan Kalscheuer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.TokenRole;
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import java.io.IOException;
import java.util.Map;
/**
* Vault response from token role lookup providing Token information in {@link TokenData} field.
*
* @author Stefan Kalscheuer
* @since 0.9
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenRoleResponse extends VaultDataResponse {
private TokenRole data;
/**
* Set data. Parses response data map to {@link TokenRole}.
*
* @param data Raw response data
* @throws InvalidResponseException on parsing errors
*/
@Override
public void setData(final Map<String, Object> data) throws InvalidResponseException {
ObjectMapper mapper = new ObjectMapper();
try {
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenRole.class);
} catch (IOException e) {
throw new InvalidResponseException("Failed deserializing response", e);
}
}
/**
* @return TokenRole data
*/
public TokenRole getData() {
return data;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -39,6 +39,9 @@ public final class AuthData {
@JsonProperty("policies")
private List<String> policies;
@JsonProperty("token_policies")
private List<String> tokenPolicies;
@JsonProperty("metadata")
private Map<String, Object> metadata;
@ -48,6 +51,15 @@ public final class AuthData {
@JsonProperty("renewable")
private boolean renewable;
@JsonProperty("entity_id")
private String entityId;
@JsonProperty("token_type")
private String tokenType;
@JsonProperty("orphan")
private boolean orphan;
/**
* @return Client token
*/
@ -56,10 +68,11 @@ public final class AuthData {
}
/**
* @return Token accessor
* @return Token type
* @since 0.9
*/
public String getAccessor() {
return accessor;
public String getTokenType() {
return tokenType;
}
/**
@ -69,6 +82,14 @@ public final class AuthData {
return policies;
}
/**
* @return List of policies associated with the token
* @since 0.9
*/
public List<String> getTokenPolicies() {
return tokenPolicies;
}
/**
* @return Metadata
*/
@ -89,4 +110,27 @@ public final class AuthData {
public boolean isRenewable() {
return renewable;
}
/**
* @return Entity ID
* @since 0.9
*/
public String getEntityId() {
return entityId;
}
/**
* @return Token accessor
*/
public String getAccessor() {
return accessor;
}
/**
* @return Token is orphan
* @since 0.9
*/
public boolean isOrphan() {
return orphan;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -19,11 +19,15 @@ package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
/**
* Embedded token information inside Vault response.
*
* @author Stefan Kalscheuer
* @since 0.1
* @author Stefan Kalscheuer
* @since 0.1
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenData {
@ -39,11 +43,23 @@ public final class TokenData {
@JsonProperty("display_name")
private String name;
@JsonProperty("entity_id")
private String entityId;
@JsonProperty("expire_time")
private String expireTime;
@JsonProperty("explicit_max_ttl")
private Integer explicitMaxTtl;
@JsonProperty("id")
private String id;
@JsonProperty("issue_time")
private String issueTime;
@JsonProperty("meta")
private String meta;
private Map<String, Object> meta;
@JsonProperty("num_uses")
private Integer numUses;
@ -54,12 +70,18 @@ public final class TokenData {
@JsonProperty("path")
private String path;
@JsonProperty("role")
private String role;
@JsonProperty("policies")
private List<String> policies;
@JsonProperty("renewable")
private boolean renewable;
@JsonProperty("ttl")
private Integer ttl;
@JsonProperty("type")
private String type;
/**
* @return Token accessor
*/
@ -88,6 +110,42 @@ public final class TokenData {
return name;
}
/**
* @return Entity ID
* @since 0.9
*/
public String getEntityId() {
return entityId;
}
/**
* @return Expire time as raw string value
* @since 0.9
*/
public String getExpireTimeString() {
return expireTime;
}
/**
* @return Expire time (parsed)
* @since 0.9
*/
public ZonedDateTime getExpireTime() {
if (expireTime == null) {
return null;
} else {
return ZonedDateTime.parse(expireTime);
}
}
/**
* @return Explicit maximum TTL
* @since 0.9
*/
public Integer getExplicitMaxTtl() {
return explicitMaxTtl;
}
/**
* @return Token ID
*/
@ -95,6 +153,34 @@ public final class TokenData {
return id;
}
/**
* @return Issue time as raw string value
* @since 0.9
*/
public String getIssueTimeString() {
return issueTime;
}
/**
* @return Expire time (parsed)
* @since 0.9
*/
public ZonedDateTime getIssueTime() {
if (issueTime == null) {
return null;
} else {
return ZonedDateTime.parse(issueTime);
}
}
/**
* @return Token type
* @since 0.9
*/
public String getType() {
return type;
}
/**
* @return Number of uses
*/
@ -117,10 +203,19 @@ public final class TokenData {
}
/**
* @return Token role
* @return Token policies
* @since 0.9
*/
public String getRole() {
return role;
public List<String> getPolicies() {
return policies;
}
/**
* @return Token is renewable
* @since 0.9
*/
public boolean isRenewable() {
return renewable;
}
/**
@ -133,7 +228,7 @@ public final class TokenData {
/**
* @return Metadata
*/
public String getMeta() {
public Map<String, Object> getMeta() {
return meta;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -20,9 +20,6 @@ import de.stklcode.jvault.connector.exception.InvalidRequestException;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.entity.ContentType;
@ -30,9 +27,9 @@ 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.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.function.Executable;
import org.mockito.MockedStatic;
import java.io.IOException;
import java.io.InputStream;
@ -42,13 +39,12 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collections;
import static net.bytebuddy.implementation.MethodDelegation.to;
import static net.bytebuddy.matcher.ElementMatchers.named;
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.fail;
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.*;
@ -59,79 +55,68 @@ import static org.mockito.Mockito.*;
* @author Stefan Kalscheuer
* @since 0.7.0
*/
public class HTTPVaultConnectorOfflineTest {
class HTTPVaultConnectorOfflineTest {
private static final String INVALID_URL = "foo:/\\1nv4l1d_UrL";
private static CloseableHttpClient httpMock = mock(CloseableHttpClient.class);
private CloseableHttpResponse responseMock = mock(CloseableHttpResponse.class);
private static MockedStatic<HttpClientBuilder> hcbMock;
private static CloseableHttpClient httpMock;
private final CloseableHttpResponse responseMock = mock(CloseableHttpResponse.class);
@BeforeAll
public static void initByteBuddy() {
// Install ByteBuddy Agent.
ByteBuddyAgent.install();
static void prepare() {
// Mock the static HTTPClient creation.
hcbMock = mockStatic(HttpClientBuilder.class);
hcbMock.when(HttpClientBuilder::create).thenReturn(new MockedHttpClientBuilder());
}
/**
* Helper method for redefinition of {@link HttpClientBuilder#create()} from {@link #initHttpMock()}.
*
* @return Mocked HTTP client builder.
*/
public static HttpClientBuilder create() {
return new MockedHttpClientBuilder();
}
@AfterAll
static void tearDown() {
hcbMock.close();
}
@BeforeEach
public void initHttpMock() {
// Redefine static method to return Mock on HttpClientBuilder creation.
new ByteBuddy().redefine(HttpClientBuilder.class)
.method(named("create"))
.intercept(to(HTTPVaultConnectorOfflineTest.class))
.make()
.load(HttpClientBuilder.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
void init() {
// Re-initialize HTTP mock to ensure fresh (empty) results.
httpMock = mock(CloseableHttpClient.class);
}
/**
* Test exceptions thrown during request.
*/
@Test
public void requestExceptionTest() throws IOException {
void requestExceptionTest() throws IOException {
HTTPVaultConnector connector = new HTTPVaultConnector("http://127.0.0.1", null, 0, 250);
// Test invalid response code.
final int responseCode = 400;
mockResponse(responseCode, "", ContentType.APPLICATION_JSON);
try {
connector.getHealth();
fail("Querying health status succeeded on invalid instance");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
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()));
}
InvalidResponseException 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()));
// Simulate permission denied response.
mockResponse(responseCode, "{\"errors\":[\"permission denied\"]}", ContentType.APPLICATION_JSON);
try {
connector.getHealth();
fail("Querying health status succeeded on invalid instance");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(PermissionDeniedException.class));
}
assertThrows(
PermissionDeniedException.class,
connector::getHealth,
"Querying health status succeeded on invalid instance"
);
// Test exception thrown during request.
when(httpMock.execute(any())).thenThrow(new IOException("Test Exception"));
try {
connector.getHealth();
fail("Querying health status succeeded on invalid instance");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
assertThat("Unexpected exception message", e.getMessage(), is("Unable to read response"));
assertThat("Unexpected cause", e.getCause(), instanceOf(IOException.class));
}
e = assertThrows(
InvalidResponseException.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));
// Now simulate a failing request that succeeds on second try.
connector = new HTTPVaultConnector("https://127.0.0.1", null, 1, 250);
@ -143,18 +128,14 @@ public class HTTPVaultConnectorOfflineTest {
.when(responseMock).getStatusLine();
when(responseMock.getEntity()).thenReturn(new StringEntity("{}", ContentType.APPLICATION_JSON));
try {
connector.getHealth();
} catch (Exception e) {
fail("Request failed unexpectedly: " + e.getMessage());
}
assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly");
}
/**
* Test constductors of the {@link HTTPVaultConnector} class.
* Test constructors of the {@link HTTPVaultConnector} class.
*/
@Test
public void constructorTest() throws IOException, CertificateException {
void constructorTest() throws IOException, CertificateException {
final String url = "https://vault.example.net/test/";
final String hostname = "vault.example.com";
final Integer port = 1337;
@ -206,60 +187,53 @@ public class HTTPVaultConnectorOfflineTest {
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
*/
@Test
public void sealExceptionTest() throws IOException {
void sealExceptionTest() {
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
try {
connector.sealStatus();
fail("Querying seal status succeeded on invalid URL");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidRequestException.class));
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
}
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
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).
try {
connector.sealStatus();
fail("Querying seal status succeeded on invalid instance");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
}
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
e = assertThrows(
InvalidResponseException.class,
connector::sealStatus,
"Querying seal status succeeded on invalid instance"
);
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
}
/**
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
*/
@Test
public void healthExceptionTest() throws IOException {
void healthExceptionTest() {
HTTPVaultConnector connector = new HTTPVaultConnector(INVALID_URL);
try {
connector.getHealth();
fail("Querying health status succeeded on invalid URL");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidRequestException.class));
assertThat("Unexpected exception message", e.getMessage(), is("Invalid URI format"));
}
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
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).
try {
connector.getHealth();
fail("Querying health status succeeded on invalid instance");
} catch (Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
}
connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
e = assertThrows(
InvalidResponseException.class,
connector::getHealth,
"Querying health status succeeded on invalid instance"
);
assertThat("Unexpected exception message", e.getMessage(), is("Response unavailable"));
}
/**
* Test behavior on unparsable responses.
*/
@Test
public void parseExceptionTest() throws IOException {
void parseExceptionTest() throws IOException {
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
// Mock authorization.
setPrivate(connector, "authorized", true);
@ -267,114 +241,25 @@ public class HTTPVaultConnectorOfflineTest {
mockResponse(200, "invalid", ContentType.APPLICATION_JSON);
// Now test the methods.
try {
connector.sealStatus();
fail("sealStatus() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.unseal("key");
fail("unseal() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.getHealth();
fail("getHealth() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.getAuthBackends();
fail("getAuthBackends() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.authToken("token");
fail("authToken() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.lookupAppRole("roleName");
fail("lookupAppRole() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.getAppRoleID("roleName");
fail("getAppRoleID() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.createAppRoleSecret("roleName");
fail("createAppRoleSecret() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.lookupAppRoleSecret("roleName", "secretID");
fail("lookupAppRoleSecret() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.listAppRoles();
fail("listAppRoles() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.listAppRoleSecrets("roleName");
fail("listAppRoleSecrets() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.read("key");
fail("read() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.list("path");
fail("list() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.renew("leaseID");
fail("renew() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
try {
connector.lookupToken("token");
fail("lookupToken() succeeded on invalid instance");
} catch (Exception e) {
assertParseError(e);
}
assertParseError(connector::sealStatus, "sealStatus() succeeded on invalid instance");
assertParseError(() -> connector.unseal("key"), "unseal() succeeded on invalid instance");
assertParseError(connector::getHealth, "getHealth() succeeded on invalid instance");
assertParseError(connector::getAuthBackends, "getAuthBackends() succeeded on invalid instance");
assertParseError(() -> connector.authToken("token"), "authToken() succeeded on invalid instance");
assertParseError(() -> connector.lookupAppRole("roleName"), "lookupAppRole() succeeded on invalid instance");
assertParseError(() -> connector.getAppRoleID("roleName"), "getAppRoleID() succeeded on invalid instance");
assertParseError(() -> connector.createAppRoleSecret("roleName"), "createAppRoleSecret() succeeded on invalid instance");
assertParseError(() -> connector.lookupAppRoleSecret("roleName", "secretID"), "lookupAppRoleSecret() succeeded on invalid instance");
assertParseError(connector::listAppRoles, "listAppRoles() succeeded on invalid instance");
assertParseError(() -> connector.listAppRoleSecrets("roleName"), "listAppRoleSecrets() succeeded on invalid instance");
assertParseError(() -> connector.read("key"), "read() succeeded on invalid instance");
assertParseError(() -> connector.list("path"), "list() succeeded on invalid instance");
assertParseError(() -> connector.renew("leaseID"), "renew() succeeded on invalid instance");
assertParseError(() -> connector.lookupToken("token"), "lookupToken() succeeded on invalid instance");
}
private void assertParseError(Exception e) {
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
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"));
}
@ -382,7 +267,7 @@ public class HTTPVaultConnectorOfflineTest {
* Test requests that expect an empty response with code 204, but receive a 200 body.
*/
@Test
public void nonEmpty204ResponseTest() throws IOException {
void nonEmpty204ResponseTest() throws IOException {
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
// Mock authorization.
setPrivate(connector, "authorized", true);
@ -390,71 +275,62 @@ public class HTTPVaultConnectorOfflineTest {
mockResponse(200, "{}", ContentType.APPLICATION_JSON);
// Now test the methods expecting a 204.
try {
connector.registerAppId("appID", "policy", "displayName");
fail("registerAppId() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.registerAppId("appID", "policy", "displayName"),
"registerAppId() with 200 response succeeded"
);
try {
connector.registerUserId("appID", "userID");
fail("registerUserId() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.registerUserId("appID", "userID"),
"registerUserId() with 200 response succeeded"
);
try {
connector.createAppRole("appID", Collections.singletonList("policy"));
fail("createAppRole() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.createAppRole("appID", Collections.singletonList("policy")),
"createAppRole() with 200 response succeeded"
);
try {
connector.deleteAppRole("roleName");
fail("deleteAppRole() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.deleteAppRole("roleName"),
"deleteAppRole() with 200 response succeeded"
);
try {
connector.setAppRoleID("roleName", "roleID");
fail("setAppRoleID() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.setAppRoleID("roleName", "roleID"),
"setAppRoleID() with 200 response succeeded"
);
try {
connector.destroyAppRoleSecret("roleName", "secretID");
fail("destroyAppRoleSecret() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.destroyAppRoleSecret("roleName", "secretID"),
"destroyAppRoleSecret() with 200 response succeeded"
);
try {
connector.destroyAppRoleSecret("roleName", "secretUD");
fail("destroyAppRoleSecret() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.destroyAppRoleSecret("roleName", "secretUD"),
"destroyAppRoleSecret() with 200 response succeeded"
);
try {
connector.delete("key");
fail("delete() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.delete("key"),
"delete() with 200 response succeeded"
);
try {
connector.revoke("leaseID");
fail("destroyAppRoleSecret() with 200 response succeeded");
} catch (VaultConnectorException e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
assertThrows(
InvalidResponseException.class,
() -> connector.revoke("leaseID"),
"destroyAppRoleSecret() with 200 response succeeded"
);
}
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) {
private Object getRequestHelperPrivate(HTTPVaultConnector connector, String fieldName) {
try {
return getPrivate(getPrivate(connector, "request"), fieldName);
} catch (NoSuchFieldException | IllegalAccessException e) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -16,23 +16,22 @@
package de.stklcode.jvault.connector.builder;
import com.github.stefanbirkner.systemlambda.SystemLambda;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.exception.TlsException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import org.junit.Rule;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.NoSuchFileException;
import java.util.concurrent.Callable;
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.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit test for HTTP Vault connector factory
@ -40,8 +39,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.8.0
*/
@EnableRuleMigrationSupport
public class HTTPVaultConnectorBuilderTest {
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";
@ -49,73 +47,72 @@ public class HTTPVaultConnectorBuilderTest {
@TempDir
File tempDir;
@Rule
public final EnvironmentVariables environment = new EnvironmentVariables();
/**
* Test building from environment variables
*/
@Test
void testFromEnv() throws NoSuchFieldException, IllegalAccessException, IOException {
void testFromEnv() throws Exception {
/* Provide address only should be enough */
setenv(VAULT_ADDR, null, null, null);
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
"Factory creation from minimal environment failed"
);
HTTPVaultConnector connector = builder.build();
HTTPVaultConnectorBuilder factory = null;
HTTPVaultConnector connector;
try {
factory = VaultConnectorBuilder.http().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from minimal environment failed");
}
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));
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 */
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
"Factory creation from environment failed"
);
HTTPVaultConnector connector = builder.build();
try {
factory = VaultConnectorBuilder.http().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from environment failed");
}
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));
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";
setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null);
try {
VaultConnectorBuilder.http().fromEnv();
fail("Creation with unknown cert path failed.");
} catch (VaultConnectorException e) {
assertThat(e, is(instanceOf(TlsException.class)));
withVaultEnv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
TlsException e = assertThrows(
TlsException.class,
() -> VaultConnectorBuilder.http().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 */
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN);
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
"Factory creation from minimal environment failed"
);
assertThat("Token nor set correctly", getPrivate(builder, "token"), is(equalTo(VAULT_TOKEN)));
try {
factory = VaultConnectorBuilder.http().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from minimal environment failed");
}
assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN)));
return null;
});
}
private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
environment.set("VAULT_ADDR", vault_addr);
environment.set("VAULT_CACERT", vault_cacert);
environment.set("VAULT_MAX_RETRIES", vault_max_retries);
environment.set("VAULT_TOKEN", vault_token);
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 {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -29,19 +29,19 @@ import static org.hamcrest.core.Is.is;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class VaultConnectorExceptionTest {
class VaultConnectorExceptionTest {
private static final String MSG = "This is a test exception!";
private static final Throwable CAUSE = new Exception("Test-Cause");
private static final Integer STATUS_CODE = 1337;
private static final String RESPONSE = "Dummy response";
@Test
public void authorizationRequiredExceptionTest() {
void authorizationRequiredExceptionTest() {
assertEmptyConstructor(new AuthorizationRequiredException());
}
@Test
public void connectionExceptionTest() {
void connectionExceptionTest() {
assertEmptyConstructor(new ConnectionException());
assertMsgConstructor(new ConnectionException(MSG));
assertCauseConstructor(new ConnectionException(CAUSE));
@ -49,7 +49,7 @@ public class VaultConnectorExceptionTest {
}
@Test
public void invalidRequestExceptionTest() {
void invalidRequestExceptionTest() {
assertEmptyConstructor(new InvalidRequestException());
assertMsgConstructor(new InvalidRequestException(MSG));
assertCauseConstructor(new InvalidRequestException(CAUSE));
@ -57,7 +57,7 @@ public class VaultConnectorExceptionTest {
}
@Test
public void invalidResponseExceptionTest() {
void invalidResponseExceptionTest() {
assertEmptyConstructor(new InvalidResponseException());
assertMsgConstructor(new InvalidResponseException(MSG));
assertCauseConstructor(new InvalidResponseException(CAUSE));
@ -93,7 +93,7 @@ public class VaultConnectorExceptionTest {
}
@Test
public void permissionDeniedExceptionTest() {
void permissionDeniedExceptionTest() {
// Default message overwritten.
PermissionDeniedException e = new PermissionDeniedException();
assertThat(e, is(instanceOf(VaultConnectorException.class)));
@ -108,7 +108,7 @@ public class VaultConnectorExceptionTest {
}
@Test
public void tlsExceptionTest() {
void tlsExceptionTest() {
assertEmptyConstructor(new TlsException());
assertMsgConstructor(new TlsException(MSG));
assertCauseConstructor(new TlsException(CAUSE));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -16,23 +16,21 @@
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 de.stklcode.jvault.connector.exception.VaultConnectorException;
import org.junit.Rule;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
import java.io.File;
import java.io.IOException;
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.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit test for HTTP Vault connector factory
@ -40,8 +38,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.0
*/
@EnableRuleMigrationSupport
public class HTTPVaultConnectorFactoryTest {
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";
@ -49,73 +46,72 @@ public class HTTPVaultConnectorFactoryTest {
@TempDir
File tempDir;
@Rule
public final EnvironmentVariables environment = new EnvironmentVariables();
/**
* Test building from environment variables
*/
@Test
public void testFromEnv() throws NoSuchFieldException, IllegalAccessException, IOException {
void testFromEnv() throws Exception {
/* Provide address only should be enough */
setenv(VAULT_ADDR, null, null, null);
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
HTTPVaultConnectorFactory factory = assertDoesNotThrow(
() -> VaultConnectorFactory.httpFactory().fromEnv(),
"Factory creation from minimal environment failed"
);
HTTPVaultConnector connector = factory.build();
HTTPVaultConnectorFactory factory = null;
HTTPVaultConnector connector;
try {
factory = VaultConnectorFactory.httpFactory().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from minimal environment failed");
}
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));
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 */
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
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();
try {
factory = VaultConnectorFactory.httpFactory().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from environment failed");
}
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));
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";
setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null);
try {
VaultConnectorFactory.httpFactory().fromEnv();
fail("Creation with unknown cert path failed.");
} catch (VaultConnectorException e) {
assertThat(e, is(instanceOf(TlsException.class)));
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 */
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN);
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)));
try {
factory = VaultConnectorFactory.httpFactory().fromEnv();
} catch (VaultConnectorException e) {
fail("Factory creation from minimal environment failed");
}
assertThat("Token nor set correctly", getPrivate(getPrivate(factory, "delegate"), "token"), is(equalTo(VAULT_TOKEN)));
return null;
});
}
private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {
environment.set("VAULT_ADDR", vault_addr);
environment.set("VAULT_CACERT", vault_cacert);
environment.set("VAULT_MAX_RETRIES", vault_max_retries);
environment.set("VAULT_TOKEN", vault_token);
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 {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -33,9 +33,7 @@ import static org.hamcrest.Matchers.*;
* @author Stefan Kalscheuer
* @since 0.4.0
*/
public class AppRoleBuilderTest {
class AppRoleBuilderTest {
private static final String NAME = "TestRole";
private static final String ID = "test-id";
private static final Boolean BIND_SECRET_ID = true;
@ -47,15 +45,20 @@ public class AppRoleBuilderTest {
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 PERIOD = 1234;
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,\"bound_cidr_list\":\"%s\",\"secret_id_bound_cidrs\":\"%s\",\"policies\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"token_ttl\":%d,\"token_max_ttl\":%d,\"period\":%d}",
NAME, ID, BIND_SECRET_ID, CIDR_1, CIDR_1, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD);
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
public static void init() {
static void init() {
BOUND_CIDR_LIST.add(CIDR_1);
POLICIES.add(POLICY);
}
@ -64,18 +67,53 @@ public class AppRoleBuilderTest {
* Build role with only a name.
*/
@Test
public void buildDefaultTest() throws JsonProcessingException {
AppRole role = new AppRoleBuilder(NAME).build();
void buildDefaultTest() throws JsonProcessingException {
AppRole role = AppRole.builder(NAME).build();
assertThat(role.getId(), is(nullValue()));
assertThat(role.getBindSecretId(), is(nullValue()));
assertThat(role.getBoundCidrList(), 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));
@ -85,30 +123,87 @@ public class AppRoleBuilderTest {
* Build token without all parameters set.
*/
@Test
public void buildFullTest() throws JsonProcessingException {
AppRole role = new AppRoleBuilder(NAME)
void buildFullTest() throws JsonProcessingException {
AppRole role = AppRole.builder(NAME)
.withId(ID)
.withBindSecretID(BIND_SECRET_ID)
.withBoundCidrList(BOUND_CIDR_LIST)
.withSecretIdBoundCidrs(BOUND_CIDR_LIST)
.withPolicies(POLICIES)
.withTokenPolicies(POLICIES)
.withSecretIdNumUses(SECRET_ID_NUM_USES)
.withSecretIdTtl(SECRET_ID_TTL)
.withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS)
.withTokenTtl(TOKEN_TTL)
.withTokenMaxTtl(TOKEN_MAX_TTL)
.withPeriod(PERIOD)
.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.getBoundCidrList(), is(BOUND_CIDR_LIST));
assertThat(role.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST));
assertThat(role.getPolicies(), is(POLICIES));
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.getPeriod(), is(PERIOD));
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));
@ -118,7 +213,51 @@ public class AppRoleBuilderTest {
* Test convenience methods
*/
@Test
public void convenienceMethodsTest() {
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()));
@ -128,29 +267,33 @@ public class AppRoleBuilderTest {
assertThat(role.getBindSecretId(), is(false));
/* Add single CIDR subnet */
role = new AppRoleBuilder(NAME).withCidrBlock(CIDR_2).build();
assertThat(role.getBoundCidrList(), hasSize(1));
assertThat(role.getBoundCidrList(), contains(CIDR_2));
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)
.withCidrBlock(CIDR_2)
.withSecretBoundCidr(CIDR_2)
.withTokenBoundCidrs(BOUND_CIDR_LIST)
.withTokenBoundCidr(CIDR_2)
.build();
assertThat(role.getBoundCidrList(), hasSize(1));
assertThat(role.getBoundCidrList(), contains(CIDR_2));
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).withPolicy(POLICY_2).build();
assertThat(role.getPolicies(), hasSize(1));
assertThat(role.getPolicies(), contains(POLICY_2));
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)
.withPolicies(POLICIES)
.withPolicy(POLICY_2)
.withTokenPolicies(POLICIES)
.withTokenPolicy(POLICY_2)
.build();
assertThat(role.getPolicies(), hasSize(2));
assertThat(role.getPolicies(), contains(POLICY, POLICY_2));
assertThat(role.getTokenPolicies(), hasSize(2));
assertThat(role.getTokenPolicies(), contains(POLICY, POLICY_2));
assertThat(role.getPolicies(), is(role.getTokenPolicies()));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -16,11 +16,9 @@
package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
@ -29,8 +27,8 @@ import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.junit.MatcherAssume.assumeThat;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
@ -39,7 +37,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.5.0
*/
public class AppRoleSecretTest {
class AppRoleSecretTest {
private static final String TEST_ID = "abc123";
private static final Map<String, Object> TEST_META = new HashMap<>();
@ -54,7 +52,7 @@ public class AppRoleSecretTest {
* Test constructors.
*/
@Test
public void constructorTest() {
void constructorTest() {
/* Empty constructor */
AppRoleSecret secret = new AppRoleSecret();
assertThat(secret.getId(), is(nullValue()));
@ -99,7 +97,7 @@ public class AppRoleSecretTest {
* Test setter.
*/
@Test
public void setterTest() {
void setterTest() {
AppRoleSecret secret = new AppRoleSecret(TEST_ID);
assertThat(secret.getCidrList(), is(nullValue()));
assertThat(secret.getCidrListString(), is(emptyString()));
@ -115,84 +113,63 @@ public class AppRoleSecretTest {
* Test JSON (de)serialization.
*/
@Test
public void jsonTest() throws NoSuchFieldException, IllegalAccessException {
void jsonTest() throws NoSuchFieldException, IllegalAccessException {
ObjectMapper mapper = new ObjectMapper();
/* A simple roundtrip first. All set fields should be present afterwards. */
AppRoleSecret secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
String secretJson = "";
try {
secretJson = mapper.writeValueAsString(secret);
} catch (JsonProcessingException e) {
e.printStackTrace();
fail("Serialization failed");
}
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 */
secretJson = commaSeparatedToList(secretJson);
String secretJson2 = commaSeparatedToList(secretJson);
AppRoleSecret secret2;
try {
secret2 = mapper.readValue(secretJson, AppRoleSecret.class);
assertThat(secret.getId(), is(secret2.getId()));
assertThat(secret.getMetadata(), is(secret2.getMetadata()));
assertThat(secret.getCidrList(), is(secret2.getCidrList()));
} catch (IOException e) {
e.printStackTrace();
fail("Deserialization failed");
}
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()));
/* Test fields, that should not be written to JSON */
setPrivateField(secret, "accessor", "TEST_ACCESSOR");
assumeThat(secret.getAccessor(), is("TEST_ACCESSOR"));
assumeTrue("TEST_ACCESSOR".equals(secret.getAccessor()));
setPrivateField(secret, "creationTime", "TEST_CREATION");
assumeThat(secret.getCreationTime(), is("TEST_CREATION"));
assumeTrue("TEST_CREATION".equals(secret.getCreationTime()));
setPrivateField(secret, "expirationTime", "TEST_EXPIRATION");
assumeThat(secret.getExpirationTime(), is("TEST_EXPIRATION"));
assumeTrue("TEST_EXPIRATION".equals(secret.getExpirationTime()));
setPrivateField(secret, "lastUpdatedTime", "TEST_UPDATETIME");
assumeThat(secret.getLastUpdatedTime(), is("TEST_UPDATETIME"));
assumeTrue("TEST_UPDATETIME".equals(secret.getLastUpdatedTime()));
setPrivateField(secret, "numUses", 678);
assumeThat(secret.getNumUses(), is(678));
assumeTrue(secret.getNumUses() == 678);
setPrivateField(secret, "ttl", 12345);
assumeThat(secret.getTtl(), is(12345));
try {
secretJson = mapper.writeValueAsString(secret);
} catch (JsonProcessingException e) {
e.printStackTrace();
fail("Serialization failed");
}
try {
secret2 = mapper.readValue(commaSeparatedToList(secretJson), AppRoleSecret.class);
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()));
} catch (IOException e) {
e.printStackTrace();
fail("Deserialization failed");
}
assumeTrue(secret.getTtl() == 12345);
String secretJson3 = assertDoesNotThrow(() -> mapper.writeValueAsString(secret), "Serialization failed");
secret2 = assertDoesNotThrow(
() -> 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()));
/* Those fields should be deserialized from JSON though */
secretJson = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
String secretJson4 = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}";
try {
secret2 = mapper.readValue(secretJson, AppRoleSecret.class);
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));
} catch (IOException e) {
e.printStackTrace();
fail("Deserialization failed");
}
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));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -27,13 +27,13 @@ import static org.hamcrest.Matchers.is;
* @author Stefan Kalscheuer
* @since 0.4.0
*/
public class AuthBackendTest {
class AuthBackendTest {
/**
* Test forType() method.
*/
@Test
public void forTypeTest() {
void forTypeTest() {
assertThat(AuthBackend.forType("token"), is(AuthBackend.TOKEN));
assertThat(AuthBackend.forType("app-id"), is(AuthBackend.APPID));
assertThat(AuthBackend.forType("userpass"), is(AuthBackend.USERPASS));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -35,13 +35,13 @@ import static org.hamcrest.Matchers.*;
* @author Stefan Kalscheuer
* @since 0.4.0
*/
public class TokenBuilderTest {
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";
@ -53,10 +53,13 @@ public class TokenBuilderTest {
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 String JSON_FULL = "{\"id\":\"test-id\",\"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 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
public static void init() {
static void init() {
POLICIES.add(POLICY);
META.put(META_KEY, META_VALUE);
}
@ -65,9 +68,34 @@ public class TokenBuilderTest {
* Build token without any parameters.
*/
@Test
public void buildDefaultTest() throws JsonProcessingException {
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()));
@ -85,9 +113,47 @@ public class TokenBuilderTest {
* Build token without all parameters set.
*/
@Test
public void buildFullTest() throws JsonProcessingException {
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)
@ -98,6 +164,7 @@ public class TokenBuilderTest {
.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));
@ -108,14 +175,62 @@ public class TokenBuilderTest {
assertThat(token.isRenewable(), is(RENEWABLE));
/* Verify that all parameters are included in JSON string */
assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL));
assertThat(new ObjectMapper().writeValueAsString(token), is(LEGACY_JSON_FULL));
}
/**
* Test convenience methods
*/
@Test
public void convenienceMethodsTest() {
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));

View File

@ -0,0 +1,184 @@
/*
* 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.Test;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
/**
* Unit Test for {@link Token.Builder}
*
* @author Stefan Kalscheuer
* @since 0.9
*/
class TokenRoleBuilderTest {
private static final String NAME = "test-role";
private static final String ALLOWED_POLICY_1 = "apol-1";
private static final String ALLOWED_POLICY_2 = "apol-2";
private static final String ALLOWED_POLICY_3 = "apol-3";
private static final List<String> ALLOWED_POLICIES = Arrays.asList(ALLOWED_POLICY_1, ALLOWED_POLICY_2);
private static final String DISALLOWED_POLICY_1 = "dpol-1";
private static final String DISALLOWED_POLICY_2 = "dpol-2";
private static final String DISALLOWED_POLICY_3 = "dpol-3";
private static final List<String> DISALLOWED_POLICIES = Arrays.asList(DISALLOWED_POLICY_2, DISALLOWED_POLICY_3);
private static final Boolean ORPHAN = false;
private static final Boolean RENEWABLE = true;
private static final String PATH_SUFFIX = "ps";
private static final String ALLOWED_ENTITY_ALIAS_1 = "alias-1";
private static final String ALLOWED_ENTITY_ALIAS_2 = "alias-2";
private static final String ALLOWED_ENTITY_ALIAS_3 = "alias-3";
private static final List<String> ALLOWED_ENTITY_ALIASES = Arrays.asList(ALLOWED_ENTITY_ALIAS_1, ALLOWED_ENTITY_ALIAS_3);
private static final String TOKEN_BOUND_CIDR_1 = "192.0.2.0/24";
private static final String TOKEN_BOUND_CIDR_2 = "198.51.100.0/24";
private static final String TOKEN_BOUND_CIDR_3 = "203.0.113.0/24";
private static final List<String> TOKEN_BOUND_CIDRS = Arrays.asList(TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_1);
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 1234;
private static final Boolean TOKEN_NO_DEFAULT_POLICY = false;
private static final Integer TOKEN_NUM_USES = 5;
private static final Integer TOKEN_PERIOD = 2345;
private static final Token.Type TOKEN_TYPE = Token.Type.SERVICE;
private static final String JSON_FULL = "{" +
"\"name\":\"" + NAME + "\"," +
"\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," +
"\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," +
"\"orphan\":" + ORPHAN + "," +
"\"renewable\":" + RENEWABLE + "," +
"\"path_suffix\":\"" + PATH_SUFFIX + "\"," +
"\"allowed_entity_aliases\":[\"" + ALLOWED_ENTITY_ALIAS_1 + "\",\"" + ALLOWED_ENTITY_ALIAS_3 + "\",\"" + ALLOWED_ENTITY_ALIAS_2 + "\"]," +
"\"token_bound_cidrs\":[\"" + TOKEN_BOUND_CIDR_3 + "\",\"" + TOKEN_BOUND_CIDR_2 + "\",\"" + TOKEN_BOUND_CIDR_1 + "\"]," +
"\"token_explicit_max_ttl\":" + TOKEN_EXPLICIT_MAX_TTL + "," +
"\"token_no_default_policy\":" + TOKEN_NO_DEFAULT_POLICY + "," +
"\"token_num_uses\":" + TOKEN_NUM_USES + "," +
"\"token_period\":" + TOKEN_PERIOD + "," +
"\"token_type\":\"" + TOKEN_TYPE.value() + "\"}";
/**
* Build token without any parameters.
*/
@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()));
/* optional fields should be ignored, so JSON string should be empty */
assertThat(new ObjectMapper().writeValueAsString(role), is("{}"));
}
/**
* Build token without all parameters NULL.
*/
@Test
void buildNullTest() throws JsonProcessingException {
TokenRole role = TokenRole.builder()
.forName(null)
.withAllowedPolicies(null)
.withAllowedPolicy(null)
.withDisallowedPolicy(null)
.withDisallowedPolicies(null)
.orphan(null)
.renewable(null)
.withPathSuffix(null)
.withAllowedEntityAliases(null)
.withAllowedEntityAlias(null)
.withTokenBoundCidr(null)
.withTokenBoundCidrs(null)
.withTokenExplicitMaxTtl(null)
.withTokenNoDefaultPolicy(null)
.withTokenNumUses(null)
.withTokenPeriod(null)
.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()));
/* optional fields should be ignored, so JSON string should be empty */
assertThat(new ObjectMapper().writeValueAsString(role), is("{}"));
}
/**
* Build token without all parameters set.
*/
@Test
void buildFullTest() throws JsonProcessingException {
TokenRole role = TokenRole.builder()
.forName(NAME)
.withAllowedPolicies(ALLOWED_POLICIES)
.withAllowedPolicy(ALLOWED_POLICY_3)
.withDisallowedPolicy(DISALLOWED_POLICY_1)
.withDisallowedPolicies(DISALLOWED_POLICIES)
.orphan(ORPHAN)
.renewable(RENEWABLE)
.withPathSuffix(PATH_SUFFIX)
.withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES)
.withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2)
.withTokenBoundCidr(TOKEN_BOUND_CIDR_3)
.withTokenBoundCidrs(TOKEN_BOUND_CIDRS)
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
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()));
/* Verify that all parameters are included in JSON string */
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -21,13 +21,13 @@ import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AppRole;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
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.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link AppRoleResponse} model.
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class AppRoleResponseTest {
class AppRoleResponseTest {
private static final Integer ROLE_TOKEN_TTL = 1200;
private static final Integer ROLE_TOKEN_MAX_TTL = 1800;
private static final Integer ROLE_SECRET_TTL = 600;
@ -53,10 +53,10 @@ public class AppRoleResponseTest {
" \"token_max_ttl\": " + ROLE_TOKEN_MAX_TTL + ",\n" +
" \"secret_id_ttl\": " + ROLE_SECRET_TTL + ",\n" +
" \"secret_id_num_uses\": " + ROLE_SECRET_NUM_USES + ",\n" +
" \"policies\": [\n" +
" \"token_policies\": [\n" +
" \"" + ROLE_POLICY + "\"\n" +
" ],\n" +
" \"period\": " + ROLE_PERIOD + ",\n" +
" \"token_period\": " + ROLE_PERIOD + ",\n" +
" \"bind_secret_id\": " + ROLE_BIND_SECRET + ",\n" +
" \"bound_cidr_list\": \"\"\n" +
" },\n" +
@ -68,50 +68,51 @@ public class AppRoleResponseTest {
private static final Map<String, Object> INVALID_DATA = new HashMap<>();
static {
INVALID_DATA.put("policies", "fancy-policy");
INVALID_DATA.put("token_policies", "fancy-policy");
}
/**
* Test getter, setter and get-methods for response data.
*/
@Test
public void getDataRoundtrip() {
void getDataRoundtrip() {
// Create empty Object.
AppRoleResponse res = new AppRoleResponse();
assertThat("Initial data should be empty", res.getRole(), is(nullValue()));
// Parsing invalid auth data map should fail.
try {
res.setData(INVALID_DATA);
fail("Parsing invalid data succeeded");
} catch (Exception e) {
assertThat(e, is(instanceOf(InvalidResponseException.class)));
}
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_DATA),
"Parsing invalid data succeeded"
);
}
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
AppRoleResponse res = new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class);
assertThat("Parsed response is NULL", res, is(notNullValue()));
// 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.getPolicies(), hasSize(1));
assertThat("Incorrect role policies", role.getPolicies(), contains(ROLE_POLICY));
assertThat("Incorrect role period", role.getPeriod(), is(ROLE_PERIOD));
assertThat("Incorrect role bind secret ID flag", role.getBindSecretId(), is(ROLE_BIND_SECRET));
assertThat("Incorrect biund CIDR list", role.getBoundCidrList(), is(nullValue()));
assertThat("Incorrect biund CIDR list string", role.getBoundCidrListString(), is(emptyString()));
} catch (IOException e) {
fail("AuthResponse deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
AppRoleResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_JSON, AppRoleResponse.class),
"AuthResponse deserialization failed."
);
assertThat("Parsed response is NULL", res, is(notNullValue()));
// 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()));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -22,13 +22,13 @@ import de.stklcode.jvault.connector.model.AuthBackend;
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
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.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link AuthMethodsResponse} model.
@ -36,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class AuthMethodsResponseTest {
class AuthMethodsResponseTest {
private static final String GH_PATH = "github/";
private static final String GH_TYPE = "github";
private static final String GH_DESCR = "GitHub auth";
@ -73,53 +73,51 @@ public class AuthMethodsResponseTest {
* Test getter, setter and get-methods for response data.
*/
@Test
public void getDataRoundtrip() {
void getDataRoundtrip() {
// Create empty Object.
AuthMethodsResponse res = new AuthMethodsResponse();
assertThat("Initial method map should be empty", res.getSupportedMethods(), is(anEmptyMap()));
// Parsing invalid data map should fail.
try {
res.setData(INVALID_DATA);
fail("Parsing invalid data succeeded");
} catch (Exception e) {
assertThat(e, is(instanceOf(InvalidResponseException.class)));
}
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_DATA),
"Parsing invalid data succeeded"
);
}
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
AuthMethodsResponse res = new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class);
assertThat("Parsed response is NULL", res, is(notNullValue()));
// 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));
void jsonRoundtrip() {
AuthMethodsResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_JSON, AuthMethodsResponse.class),
"AuthResponse deserialization failed"
);
assertThat("Parsed response is NULL", res, is(notNullValue()));
// 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));
// 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()));
// 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()));
// 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()));
} catch (IOException e) {
fail("AuthResponse deserialization failed: " + e.getMessage());
}
// 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()));
}
private static class Dummy {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -21,13 +21,13 @@ import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
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.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link AuthResponse} model.
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class AuthResponseTest {
class AuthResponseTest {
private static final String AUTH_ACCESSOR = "2c84f488-2133-4ced-87b0-570f93a76830";
private static final String AUTH_CLIENT_TOKEN = "ABCD";
private static final String AUTH_POLICY_1 = "web";
@ -44,6 +44,9 @@ public class AuthResponseTest {
private static final String AUTH_META_VALUE = "armon";
private static final Integer AUTH_LEASE_DURATION = 3600;
private static final Boolean AUTH_RENEWABLE = true;
private static final String AUTH_ENTITY_ID = "";
private static final String AUTH_TOKEN_TYPE = "service";
private static final Boolean AUTH_ORPHAN = false;
private static final String RES_JSON = "{\n" +
" \"auth\": {\n" +
@ -53,11 +56,18 @@ public class AuthResponseTest {
" \"" + AUTH_POLICY_1 + "\", \n" +
" \"" + AUTH_POLICY_2 + "\"\n" +
" ],\n" +
" \"token_policies\": [\n" +
" \"" + AUTH_POLICY_2 + "\",\n" +
" \"" + AUTH_POLICY_1 + "\" \n" +
" ],\n" +
" \"metadata\": {\n" +
" \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" +
" },\n" +
" \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" +
" \"renewable\": " + AUTH_RENEWABLE + "\n" +
" \"renewable\": " + AUTH_RENEWABLE + ",\n" +
" \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" +
" \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" +
" \"orphan\": " + AUTH_ORPHAN + "\n" +
" }\n" +
"}";
@ -71,18 +81,17 @@ public class AuthResponseTest {
* Test getter, setter and get-methods for response data.
*/
@Test
public void getDataRoundtrip() {
void getDataRoundtrip() {
// Create empty Object.
AuthResponse res = new AuthResponse();
assertThat("Initial data should be empty", res.getData(), is(nullValue()));
// Parsing invalid auth data map should fail.
try {
res.setAuth(INVALID_AUTH_DATA);
fail("Parsing invalid auth data succeeded");
} catch (Exception e) {
assertThat(e, is(instanceOf(InvalidResponseException.class)));
}
assertThrows(
InvalidResponseException.class,
() -> res.setAuth(INVALID_AUTH_DATA),
"Parsing invalid auth data succeeded"
);
// Data method should be agnostic.
res.setData(INVALID_AUTH_DATA);
@ -93,9 +102,11 @@ public class AuthResponseTest {
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
AuthResponse res = new ObjectMapper().readValue(RES_JSON, AuthResponse.class);
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();
@ -104,10 +115,14 @@ public class AuthResponseTest {
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(), containsInAnyOrder(AUTH_POLICY_1, AUTH_POLICY_2));
} catch (IOException e) {
fail("AuthResponse deserialization failed: " + e.getMessage());
}
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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.8
*/
public class CredentialsResponseTest {
class CredentialsResponseTest {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String VAL_USER = "testUserName";
private static final String VAL_PASS = "5up3r5ecr3tP455";
@ -52,7 +52,7 @@ public class CredentialsResponseTest {
*/
@Test
@SuppressWarnings("unchecked")
public void getCredentialsTest() throws InvalidResponseException {
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()));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -19,12 +19,10 @@ package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.io.IOException;
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.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* JUnit Test for {@link AuthResponse} model.
@ -32,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.7.0
*/
public class HealthResponseTest {
class HealthResponseTest {
private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228";
private static final String CLUSTER_NAME = "vault-cluster-5515c810";
private static final String VERSION = "0.9.2";
@ -56,26 +54,26 @@ public class HealthResponseTest {
" \"replication_dr_mode\": \"" + REPL_DR_MODE + "\",\n" +
" \"performance_standby\": " + PERF_STANDBY + "\n" +
"}";
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
HealthResponse res = new ObjectMapper().readValue(RES_JSON, HealthResponse.class);
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));
} catch (IOException e) {
fail("Health deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
HealthResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_JSON, HealthResponse.class),
"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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -17,16 +17,12 @@
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.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.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* JUnit Test for {@link MetadataResponse} model.
@ -34,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.8
*/
public class MetadataResponseTest {
class MetadataResponseTest {
private static final String V1_TIME = "2018-03-22T02:24:06.945319214Z";
private static final String V3_TIME = "2018-03-22T02:36:43.986212308Z";
private static final String V2_TIME = "2018-03-22T02:36:33.954880664Z";
@ -73,28 +69,26 @@ public class MetadataResponseTest {
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
MetadataResponse res = new ObjectMapper().readValue(META_JSON, MetadataResponse.class);
assertThat("Parsed response is NULL", res, is(notNullValue()));
assertThat("Parsed metadatra 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("Parsion 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("Parsion 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));
} catch (IOException e) {
fail("MetadataResoponse deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
MetadataResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(META_JSON, MetadataResponse.class),
"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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -19,11 +19,9 @@ package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.io.IOException;
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.assertDoesNotThrow;
/**
* JUnit Test for {@link SealResponse} model.
@ -31,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.8
*/
public class SealResponseTest {
class SealResponseTest {
private static final String TYPE = "shamir";
private static final Integer THRESHOLD = 3;
private static final Integer SHARES = 5;
@ -70,43 +68,41 @@ public class SealResponseTest {
* Test creation from JSON value as returned by Vault when sealed (JSON example close to Vault documentation).
*/
@Test
public void jsonRoundtripSealed() {
void jsonRoundtripSealed() {
// First test sealed Vault's response.
try {
SealResponse res = new ObjectMapper().readValue(RES_SEALED, SealResponse.class);
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));
// 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()));
} catch (IOException e) {
fail("TokenResponse deserialization failed: " + e.getMessage());
}
SealResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_SEALED, SealResponse.class),
"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));
// 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()));
// Not test unsealed Vault's response.
try {
SealResponse res = new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class);
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));
} catch (IOException e) {
fail("TokenResponse deserialization failed: " + e.getMessage());
}
res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_UNSEALED, SealResponse.class),
"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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -26,7 +26,7 @@ import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link SecretListResponse} model.
@ -34,7 +34,7 @@ import static org.junit.Assert.fail;
* @author Stefan Kalscheuer
* @since 0.8
*/
public class SecretListResponseTest {
class SecretListResponseTest {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String KEY1 = "key1";
private static final String KEY2 = "key-2";
@ -50,21 +50,19 @@ public class SecretListResponseTest {
* @throws InvalidResponseException Should not occur
*/
@Test
@SuppressWarnings("unchecked")
public void getKeysTest() throws InvalidResponseException {
void getKeysTest() throws InvalidResponseException {
// Create empty Object.
SecretListResponse res = new SecretListResponse();
assertThat("Keys should be null without initialization", res.getKeys(), is(nullValue()));
// Provoke internal ClassCastException.
try {
Map<String, Object> invalidData = new HashMap<>();
invalidData.put("keys", "some string");
res.setData(invalidData);
fail("Setting incorrect class succeeded");
} catch (Exception e) {
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
}
Map<String, Object> invalidData = new HashMap<>();
invalidData.put("keys", "some string");
assertThrows(
InvalidResponseException.class,
() -> res.setData(invalidData),
"Setting incorrect class succeeded"
);
// Fill correct data.
res.setData(DATA);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -20,14 +20,14 @@ 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.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link SecretResponse} model.
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class SecretResponseTest {
class SecretResponseTest {
private static final Map<String, Object> DATA = new HashMap<>();
private static final String KEY_UNKNOWN = "unknown";
private static final String KEY_STRING = "test1";
@ -120,7 +120,7 @@ public class SecretResponseTest {
*/
@Test
@SuppressWarnings("unchecked")
public void getDataRoundtrip() throws InvalidResponseException {
void getDataRoundtrip() throws InvalidResponseException {
// Create empty Object.
SecretResponse res = new SecretResponse();
assertThat("Initial data should be Map", res.getData(), is(instanceOf(Map.class)));
@ -137,61 +137,58 @@ public class SecretResponseTest {
assertThat("Non-Null returned on unknown key", res.get(KEY_UNKNOWN), is(nullValue()));
// Try explicit JSON conversion.
final List list = res.get(KEY_LIST, List.class);
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<Object>)list, contains("first", "second"));
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()));
// Requesting invalid class should result in Exception.
try {
res.get(KEY_LIST, Double.class);
fail("JSON parsing to incorrect type succeeded.");
} catch (Exception e) {
assertThat(e, is(instanceOf(InvalidResponseException.class)));
}
assertThrows(
InvalidResponseException.class,
() -> res.get(KEY_LIST, Double.class),
"JSON parsing to incorrect type succeeded."
);
}
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
assertSecretData(new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class));
} catch (IOException e) {
fail("SecretResponse deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
SecretResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class),
"SecretResponse deserialization failed."
);
assertSecretData(res);
// KV v2 secret.
try {
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON_V2, SecretResponse.class);
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));
} catch (IOException e) {
fail("SecretResponse deserialization failed: " + e.getMessage());
}
res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON_V2, SecretResponse.class),
"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));
// Deleted KV v2 secret.
try {
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON_V2_2, SecretResponse.class);
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));
} catch (IOException e) {
fail("SecretResponse deserialization failed: " + e.getMessage());
}
res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(SECRET_JSON_V2_2, SecretResponse.class),
"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));
}
private void assertSecretData(SecretResponse res) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -19,12 +19,10 @@ package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.io.IOException;
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.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* JUnit Test for {@link SecretVersionResponse} model.
@ -32,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.8
*/
public class SecretVersionResponseTest {
class SecretVersionResponseTest {
private static final String CREATION_TIME = "2018-03-22T02:24:06.945319214Z";
private static final String DELETION_TIME = "2018-03-22T02:36:43.986212308Z";
private static final Integer VERSION = 42;
@ -50,17 +48,16 @@ public class SecretVersionResponseTest {
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
SecretVersionResponse res = new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class);
assertThat("Parsed response is NULL", res, is(notNullValue()));
assertThat("Parsed metadatra 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));
} catch (IOException e) {
fail("SecretVersionResponse deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
SecretVersionResponse res = assertDoesNotThrow(
() -> 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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.
@ -21,13 +21,14 @@ import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.HashMap;
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.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* JUnit Test for {@link TokenResponse} model.
@ -35,28 +36,46 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Stefan Kalscheuer
* @since 0.6.2
*/
public class TokenResponseTest {
class TokenResponseTest {
private static final Integer TOKEN_CREATION_TIME = 1457533232;
private static final Integer TOKEN_TTL = 2764800;
private static final Integer TOKEN_EXPLICIT_MAX_TTL = 0;
private static final String TOKEN_DISPLAY_NAME = "token";
private static final String TOKEN_META_KEY = "foo";
private static final String TOKEN_META_VALUE = "bar";
private static final Integer TOKEN_NUM_USES = 0;
private static final Boolean TOKEN_ORPHAN = false;
private static final Boolean TOKEN_RENEWABLE = true;
private static final String TOKEN_PATH = "auth/token/create";
private static final String TOKEN_POLICY_1 = "default";
private static final String TOKEN_POLICY_2 = "web";
private static final Boolean RES_RENEWABLE = false;
private static final Integer RES_TTL = 2591976;
private static final Integer RES_LEASE_DURATION = 0;
private static final String TOKEN_ACCESSOR = "VKvzT2fKHFsZFUus9LyoXCvu";
private static final String TOKEN_ENTITY_ID = "7d2e3179-f69b-450c-7179-ac8ee8bd8ca9";
private static final String TOKEN_EXPIRE_TIME = "2018-05-19T11:35:54.466476215-04:00";
private static final String TOKEN_ID = "my-token";
private static final String TOKEN_ISSUE_TIME = "2018-04-17T11:35:54.466476078-04:00";
private static final String TOKEN_TYPE = "service";
private static final String RES_JSON = "{\n" +
" \"lease_id\": \"\",\n" +
" \"renewable\": " + RES_RENEWABLE + ",\n" +
" \"lease_duration\": " + RES_LEASE_DURATION + ",\n" +
" \"data\": {\n" +
" \"accessor\": \"" + TOKEN_ACCESSOR + "\",\n" +
" \"creation_time\": " + TOKEN_CREATION_TIME + ",\n" +
" \"creation_ttl\": " + TOKEN_TTL + ",\n" +
" \"display_name\": \"" + TOKEN_DISPLAY_NAME + "\",\n" +
" \"meta\": null,\n" +
" \"entity_id\": \"" + TOKEN_ENTITY_ID + "\",\n" +
" \"expire_time\": \"" + TOKEN_EXPIRE_TIME + "\",\n" +
" \"explicit_max_ttl\": \"" + TOKEN_EXPLICIT_MAX_TTL + "\",\n" +
" \"id\": \"" + TOKEN_ID + "\",\n" +
" \"issue_time\": \"" + TOKEN_ISSUE_TIME + "\",\n" +
" \"meta\": {\n" +
" \"" + TOKEN_META_KEY + "\": \"" + TOKEN_META_VALUE + "\"\n" +
" },\n" +
" \"num_uses\": " + TOKEN_NUM_USES + ",\n" +
" \"orphan\": " + TOKEN_ORPHAN + ",\n" +
" \"path\": \"" + TOKEN_PATH + "\",\n" +
@ -64,7 +83,9 @@ public class TokenResponseTest {
" \"" + TOKEN_POLICY_1 + "\", \n" +
" \"" + TOKEN_POLICY_2 + "\"\n" +
" ],\n" +
" \"ttl\": " + RES_TTL + "\n" +
" \"renewable\": " + TOKEN_RENEWABLE + ",\n" +
" \"ttl\": " + RES_TTL + ",\n" +
" \"type\": \"" + TOKEN_TYPE + "\"\n" +
" },\n" +
" \"warnings\": null,\n" +
" \"auth\": null\n" +
@ -80,44 +101,55 @@ public class TokenResponseTest {
* Test getter, setter and get-methods for response data.
*/
@Test
public void getDataRoundtrip() {
void getDataRoundtrip() {
// Create empty Object.
TokenResponse res = new TokenResponse();
assertThat("Initial data should be empty", res.getData(), is(nullValue()));
// Parsing invalid data map should fail.
try {
res.setData(INVALID_TOKEN_DATA);
fail("Parsing invalid token data succeeded");
} catch (Exception e) {
assertThat(e, is(instanceOf(InvalidResponseException.class)));
}
assertThrows(
InvalidResponseException.class,
() -> res.setData(INVALID_TOKEN_DATA),
"Parsing invalid token data succeeded"
);
}
/**
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
*/
@Test
public void jsonRoundtrip() {
try {
TokenResponse res = new ObjectMapper().readValue(RES_JSON, TokenResponse.class);
assertThat("Parsed response is NULL", res, is(notNullValue()));
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION));
assertThat("Incorrect renewable status", res.isRenewable(), is(RES_RENEWABLE));
// Extract token data.
TokenData data = res.getData();
assertThat("Token data is NULL", data, is(notNullValue()));
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 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 response renewable flag", res.isRenewable(), is(RES_RENEWABLE));
assertThat("Incorrect response TTL", data.getTtl(), is(RES_TTL));
assertThat("Incorrect response lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION));
} catch (IOException e) {
fail("TokenResponse deserialization failed: " + e.getMessage());
}
void jsonRoundtrip() {
TokenResponse res = assertDoesNotThrow(
() -> new ObjectMapper().readValue(RES_JSON, TokenResponse.class),
"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));
// 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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 Stefan Kalscheuer
* 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.