Compare commits
114 Commits
Author | SHA1 | Date | |
---|---|---|---|
ed2b9d62a3 | |||
007b523295 | |||
061c1e9743 | |||
6904ed6817 | |||
1ed5d8d992 | |||
f70fc084be | |||
4b14ab3f4b | |||
29776f459e | |||
4ca8aa56d2 | |||
32ab9f4bb1 | |||
e002fc749a | |||
b9ad2d1551 | |||
35a8c2e0fa | |||
89f7581d17 | |||
43511dc20b | |||
05b44759c0 | |||
ba17286ab3 | |||
51e505313a | |||
a1784245a3 | |||
df7de5dd73 | |||
23419e94f1 | |||
5b34cfcc27 | |||
b1c78b50d2 | |||
238ac8bd10 | |||
c8a2e0784f | |||
23f98f190b | |||
745ab7a24c | |||
71f68f088f | |||
52a1abfb87 | |||
4bf9df5f73 | |||
8ae4dccdd6 | |||
7ac550230f | |||
c1d519826c | |||
a727ed960b | |||
c685ec82a0 | |||
934628f382 | |||
ce90f9fba2 | |||
6b25113b9f | |||
63dc329857 | |||
42094101a3 | |||
259747afae | |||
d7365dcaf1 | |||
c24d1cae0b | |||
af7b99587f | |||
13c2cce162 | |||
e9663ef794 | |||
3fd74a7fd2 | |||
21943896c7 | |||
3794f4aac6 | |||
f805a9c751 | |||
767c2cce91 | |||
ed703f6e53 | |||
e767c07a61 | |||
c1f6ee891b | |||
5d46e75068 | |||
7a67080aa0 | |||
81c28f10c1 | |||
b99edb86ac | |||
594b80f62b | |||
4bd614a633 | |||
0f6bccff02 | |||
fca6e496d8 | |||
0f5540913a | |||
8129017ad0 | |||
c0ad451134 | |||
5f3e285a8a | |||
107244cb81 | |||
e877d377c0 | |||
a565411b22 | |||
6f13af5c91 | |||
ce2de2df81 | |||
d7e4e7e5be | |||
2f312d3937 | |||
2f5b6d1523 | |||
69874bdceb | |||
8ab9c23605 | |||
324bff7e58 | |||
b036b73e11 | |||
17145e53be | |||
e988833eb9 | |||
ea3b6d50cb | |||
3f7f88e14a | |||
3396693120 | |||
ca51fed145 | |||
9c216dd805 | |||
b98b7ab95c | |||
ecf398c9d0 | |||
a80805a044 | |||
2b2b86023e | |||
3df2293741 | |||
c1a964b0d1 | |||
d2b31122b6 | |||
4adefc2cda | |||
3271e5e513 | |||
40742b00de | |||
c7b4c46ad2 | |||
9618a50646 | |||
53a459eda1 | |||
e99809cd46 | |||
fc493a2e73 | |||
048e4d12b4 | |||
c3ad6b6edd | |||
7069eabbff | |||
ffd97a696a | |||
ca529027f7 | |||
40f60cee03 | |||
aacbed836a | |||
351ea1fc62 | |||
847cce7bfb | |||
4c68e74a38 | |||
a8afae70cc | |||
ee5b112704 | |||
27eb1a1e8a | |||
96fc669b38 |
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/target/
|
||||
/*.iml
|
||||
/.idea/
|
||||
/*.project
|
||||
*~
|
28
.travis.yml
Normal file
28
.travis.yml
Normal file
@ -0,0 +1,28 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
dist: trusty
|
||||
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:.
|
||||
before_script:
|
||||
- wget https://releases.hashicorp.com/vault/0.8.3/vault_0.8.3_linux_amd64.zip
|
||||
- unzip vault_0.8.3_linux_amd64.zip
|
||||
- rm vault_0.8.3_linux_amd64.zip
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- '$HOME/.sonar/cache'
|
||||
script:
|
||||
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
|
||||
notifications:
|
||||
slack:
|
||||
secure: "YyE5GePOLkCVTtCy8j507BRmQrtrWhtvmUt4kY0Z2/ptf0LzfuDEJQ4ZbCxO5ri5IDJrrvyPAedjft818+bMzdFfxvi1oviIL+LZNhyev8gfeIBF/U2pvSLGKCRX4g4aZ6NKN3Untjdm8lmiVTltOyZ59JizQVwXzAl3LiOpnJugyBqbhOx4EIqBzwW3gaYAofMqY2LczW5W/M+99HJCst8Mb8H06GstCPEHCizAq7VRaUS68PstlxQMV0Q6bsSYMLFbLWmhuXs96WHqOrT+nNsl07ikr3N8c4HafhFutt2Jyc1+8gXO417+eSvVM0iBpHGwTmfGFfCqx/4Pf62DTJuvh8dR4fLgLDiqEeDrBEcRRDOs9cvXVOO22NN1HuBBJY8VRiFcwNAvuVMXCtnC+1RJRAZB2zubsANiFe+ygk/ywj37cVXY+NpqlBwcSph6jPHo2hD6cIl2rTWn1EnZH519Rh38xTSv6MRzAO9kWNVrAlX+UtvYS8Sk7Owrc0tET9Lc4zj6aI5tsA1wYbN3Jk6EbMhsF6K/XF2npt2qg09pxkj8wmxoUoR6/rGuSv55aSxTdLDmH+en4ahEm3uc4h1lYoVCk0yrZoTAas3zS4WpBCKnl+mweuKNxaejyy0Wv6NR9ZCTaS3yFgibNOjvDpxZxTAPdNBL7hn+k4LwgN4="
|
62
CHANGELOG.md
Normal file
62
CHANGELOG.md
Normal file
@ -0,0 +1,62 @@
|
||||
## 0.7.0 [2017-10-03]
|
||||
* [feature] Retrieval of health status via `getHealth()` (#15)
|
||||
* [improvement] `seal()`, `unseal()` are now `void` and throw Exception on error (#12)
|
||||
* [compatibility] Adaptation to Vault 0.8 endpoints for `renew` and `revoke`, **breaking** 0.7 compatibility (#11)
|
||||
* [deletion] Removed deprecated `listAppRoleSecretss()` (use `listAppRoleSecrets()`) (#14)
|
||||
* [test] Tested against Vault 0.8.3
|
||||
|
||||
## 0.6.2 [2017-08-19]
|
||||
* [fix] Prevent potential NPE on SecretResponse getter
|
||||
* [fix] Removed stack traces on PUT request and response deserialization (#13)
|
||||
* [improvement] Fields of InvalidResposneException made final
|
||||
* [deprecation] `listAppRoleSecretss()` in favor of `listAppRoleSecrets()` (#14)
|
||||
* [test] Tested against Vault 0.8.1, increased coverage
|
||||
|
||||
## 0.6.1 [2017-08-02]
|
||||
* [fix] `TokenModel.getPassword()` returned username instead of password
|
||||
* [fix] `TokenModel.getUsername()` and `getPassword()` could produce NPE in multithreaded environments
|
||||
* [fix] `TokenData.getCreatinTtl()` renamed to `getCreationTtl()` (typo fix)
|
||||
* [test] Tested against Vault 0.7.3
|
||||
|
||||
## 0.6.0 [2017-05-12]
|
||||
* [feature] Initialization from environment variables using `fromEnv()` in factory (#8)
|
||||
* [feature] Automatic authentication with `buildAndAuth()`
|
||||
* [feature] Custom timeout and number of retries (#9)
|
||||
* [feature] Connector implements `AutoCloseable`
|
||||
* [fix] `SecretResponse` does not throw NPE on `get(key)` and `getData()`
|
||||
* [test] Tested against Vault 0.7.2
|
||||
|
||||
## 0.5.0 [2017-03-18]
|
||||
* [feature] Convenience methods for DB credentials (#7)
|
||||
* [fix] Minor bugfix in TokenBuilder
|
||||
* [deprecation] `SecretResponse.getValue()` deprecated
|
||||
* [test] Tested against Vault 0.7.0
|
||||
|
||||
## 0.4.1 [2016-12-24]
|
||||
* [fix] Factory Null-tolerant for trusted certificate (#6)
|
||||
* [test] StackTraces tested for secret leaks
|
||||
* [test] Tested against Vault 0.6.4
|
||||
|
||||
## 0.4.0 [2016-11-06]
|
||||
* [feature] Option to provide a trusted CA certificate (#2)
|
||||
* [feature] Deletion, revocation and renewal of secrets (#3)
|
||||
* [feature] Token creation (#4)
|
||||
* [feature] AppRole auth backend supported (#5)
|
||||
* [improvement] Support for complex secrets
|
||||
* [deprecation] App-ID backend marked as deprecated
|
||||
|
||||
## 0.3.0 [2016-10-07]
|
||||
* [feature] Retrieval of JSON objects (#1)
|
||||
* [test] Tested against Vault 0.6.2
|
||||
|
||||
## 0.2.0 [2016-09-01]
|
||||
* Dependecies updated and CommonsIO removed
|
||||
* [fix] Fixed auth backend detection for Vault 0.6.1
|
||||
* [test] Tested against Vault 0.6.1
|
||||
|
||||
## 0.1.1 [2016-06-20]
|
||||
* [fix] Check for "permission denied" without status code 400 instead of 403
|
||||
* [test] Tested against Vault 0.6.0
|
||||
|
||||
## 0.1.0 [2016-03-29]
|
||||
* First release
|
116
README.md
116
README.md
@ -1,58 +1,132 @@
|
||||
Java Vault Connector
|
||||
=========
|
||||
# Java Vault Connector
|
||||
|
||||
[](https://travis-ci.org/stklcode/jvaultconnector)
|
||||
[](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Aconnector)
|
||||
[](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
|
||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22connector%22)
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
**Current available features:**
|
||||
## Features:
|
||||
|
||||
* HTTP(S) backend connector
|
||||
* Authorization methods:
|
||||
* Ability to provide or enforce custom CA certificate
|
||||
* Optional initialization from environment variables
|
||||
* Authorization methods
|
||||
* Token
|
||||
* Username/Password
|
||||
* AppID (register and authenticate)
|
||||
* AppID (register and authenticate) [_deprecated_]
|
||||
* AppRole (register and authenticate)
|
||||
* Tokens
|
||||
* Creation and lookup of tokens
|
||||
* TokenBuilder for speaking creation of complex configuraitons
|
||||
* Secrets
|
||||
* Read secrets
|
||||
* Write secrets
|
||||
* List secrets
|
||||
* Delete secrets
|
||||
* Renew/revoke leases
|
||||
* Raw secret content or JSON decoding
|
||||
* SQL secret handling
|
||||
* Connector Factory with builder pattern
|
||||
* Tested against Vault 0.6.0
|
||||
* Tested against Vault 0.8.3
|
||||
|
||||
**Usage Example**
|
||||
|
||||
## Maven Artifact
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.7.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Initialization
|
||||
|
||||
```java
|
||||
// Instanciate using builder pattern style factory
|
||||
// Instantiate using builder pattern style factory (TLS enabled by default)
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.wiithHost("127.0.0.1")
|
||||
.withHost("127.0.0.1")
|
||||
.withPort(8200)
|
||||
.withTLS()
|
||||
.build();
|
||||
|
||||
//authenticate with token
|
||||
// Instantiate with custom SSL context
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.withHost("example.com")
|
||||
.withPort(8200)
|
||||
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
||||
.build();
|
||||
|
||||
// Initialization from environment variables
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.fromEnv()
|
||||
.build();
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```java
|
||||
// Authenticate with token
|
||||
vault.authToken("01234567-89ab-cdef-0123-456789abcdef");
|
||||
|
||||
// retrieve secret
|
||||
// Authenticate with username and password
|
||||
vault.authUserPass("username", "p4ssw0rd");
|
||||
|
||||
// Authenticate with AppID (secret - 2nd argument - is optional)
|
||||
vault.authAppId("01234567-89ab-cdef-0123-456789abcdef", "fedcba98-7654-3210-fedc-ba9876543210");
|
||||
```
|
||||
|
||||
### Secret read & write
|
||||
|
||||
```java
|
||||
// Retrieve secret (prefix "secret/" assumed, use read() to read arbitrary paths)
|
||||
String secret = vault.readSecret("some/secret/key").getValue();
|
||||
|
||||
// Complex secret
|
||||
Map<String, Object> secretData = vault.readSecret("another/secret/key").getData();
|
||||
|
||||
// Write simple secret
|
||||
vault.writeSecret("new/secret/key", "secret value");
|
||||
|
||||
// Write complex data to arbitraty path
|
||||
Map<String, Object> map = [...]
|
||||
vault.write("any/path/to/write", map);
|
||||
|
||||
// Delete secret
|
||||
vault.delete("any/path/to/write");
|
||||
```
|
||||
|
||||
**Maven Artifact**
|
||||
```
|
||||
<dependency>
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.1.1</version>
|
||||
</dependency>
|
||||
### Token and role creation
|
||||
|
||||
```java
|
||||
// Create token using TokenBuilder
|
||||
Token token = new TokenBuilder().withId("token id")
|
||||
.withDisplayName("new test token")
|
||||
.withPolicies("pol1", "pol2")
|
||||
.build();
|
||||
vault.createToken(token);
|
||||
|
||||
// Create AppRole credentials
|
||||
vault.createAppRole("testrole", policyList);
|
||||
AppRoleSecretResponse secret = vault.createAppRoleSecret("testrole");
|
||||
```
|
||||
|
||||
**Links**
|
||||
## Links
|
||||
|
||||
[Project Page](http://jvault.stklcode.de)
|
||||
|
||||
[JavaDoc API](http://jvault.stklcode.de/apidocs/)
|
||||
|
||||
**Planned features:**
|
||||
## Planned features
|
||||
|
||||
* Creation and modification of policies
|
||||
* Implement more authentication methods
|
||||
|
||||
**License**
|
||||
## License
|
||||
|
||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
12
assets/logo.svg
Normal file
12
assets/logo.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128">
|
||||
<path d="M4,12 l60,104 l60,-104 z" stroke="none" fill="#000000" />
|
||||
<circle cx="78" cy="24" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="38" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="52" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="72" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="58" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="52" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
||||
</svg>
|
After Width: | Height: | Size: 759 B |
87
pom.xml
87
pom.xml
@ -2,58 +2,97 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>jVaultConnector</name>
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.1.1</version>
|
||||
<version>0.7.0</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jVaultConnector</name>
|
||||
<description>Connector artifact for Hashicorp's Vault secret management</description>
|
||||
<url>https://jvault.stklcode.de</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.20.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.4.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.0.2</version>
|
||||
<version>4.5.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<version>2.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<version>2.9.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -62,5 +101,23 @@
|
||||
<version>2.0.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-rules</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.7.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.7.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,43 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.response.SealResponse;
|
||||
import de.stklcode.jvault.connector.model.response.SecretResponse;
|
||||
import de.stklcode.jvault.connector.model.response.TokenResponse;
|
||||
import de.stklcode.jvault.connector.model.response.AuthResponse;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault Connector interface.
|
||||
* Provides methods to connect with Vault backend and handle secrets.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface VaultConnector {
|
||||
public interface VaultConnector extends AutoCloseable {
|
||||
/**
|
||||
* Verify that vault connection is initialized.
|
||||
* @return TRUE if correctly initialized
|
||||
* Default sub-path for Vault secrets.
|
||||
*/
|
||||
boolean init();
|
||||
String PATH_SECRET = "secret";
|
||||
|
||||
/**
|
||||
* Reset authorization information.
|
||||
@ -30,120 +46,589 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Retrieve status of vault seal.
|
||||
* @return Seal status
|
||||
*
|
||||
* @return Seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse sealStatus();
|
||||
SealResponse sealStatus() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Seal vault.
|
||||
* @return TRUE on success
|
||||
*
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean seal();
|
||||
void seal() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
* @param key A single master share key
|
||||
* @param reset Discard previously provided keys (optional)
|
||||
* @return TRUE on success
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @param reset Discard previously provided keys (optional)
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse unseal(final String key, final Boolean reset);
|
||||
SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
* @param key A single master share key
|
||||
* @return TRUE on success
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SealResponse unseal(final String key) {
|
||||
default SealResponse unseal(final String key) throws VaultConnectorException {
|
||||
return unseal(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query server health information.
|
||||
*
|
||||
* @return Health information.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.7.0
|
||||
*/
|
||||
HealthResponse getHealth() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Get all availale authentication backends.
|
||||
* @return List of backends
|
||||
*
|
||||
* @return List of backends
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<AuthBackend> getAuthBackends() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using token.
|
||||
* @param token The token
|
||||
* @return Token response
|
||||
*
|
||||
* @param token The token
|
||||
* @return Token response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
TokenResponse authToken(final String token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using username and password.
|
||||
* @param username The username
|
||||
* @param password The password
|
||||
* @return Authorization result
|
||||
* @throws VaultConnectorException
|
||||
*
|
||||
* @param username The username
|
||||
* @param password The password
|
||||
* @return Authorization result
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppID method.
|
||||
* @param appID The App ID
|
||||
* @param userID The User ID
|
||||
* @return TRUE on success
|
||||
*
|
||||
* @param appID The App ID
|
||||
* @param userID The User ID
|
||||
* @return The {@link AuthResponse}
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID with policy.
|
||||
* @param appID The unique App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException
|
||||
* Authorize to Vault using AppRole method without secret ID.
|
||||
*
|
||||
* @param roleID The role ID
|
||||
* @return The {@link AuthResponse}
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException;
|
||||
default AuthResponse authAppRole(final String roleID) throws VaultConnectorException {
|
||||
return authAppRole(roleID, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register User-ID with App-ID
|
||||
* @param appID The App-ID
|
||||
* @param userID The User-ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException
|
||||
* Authorize to Vault using AppRole method.
|
||||
*
|
||||
* @param roleID The role ID
|
||||
* @param secretID The secret ID
|
||||
* @return The {@link AuthResponse}
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID with policy.
|
||||
*
|
||||
* @param appID The unique App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
*
|
||||
* @param role The role
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean createAppRole(final AppRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies) throws VaultConnectorException {
|
||||
return createAppRole(roleName, policies, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>(), roleID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete AppRole role from Vault.
|
||||
*
|
||||
* @param roleName The role anme
|
||||
* @return {@code true} on succevss
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The role ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
String getAppRoleID(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Set custom ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID The role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new random generated AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName) throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID A custom secret ID
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secret The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret ID
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean destroyAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) AppRole roles.
|
||||
*
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) secret IDs for AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoleSecrets(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register User-ID with App-ID.
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param userID The User-ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
* Consider using {@link #createAppRoleSecret} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID and User-ID at once.
|
||||
* @param appID The App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @param userID The User-ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @param userID The User-ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
*/
|
||||
default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException {
|
||||
@Deprecated
|
||||
default boolean registerAppUserId(final String appID,
|
||||
final String policy,
|
||||
final String displayName,
|
||||
final String userID) throws VaultConnectorException {
|
||||
return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization status
|
||||
* @return TRUE, if successfully authorized
|
||||
* Get authorization status.
|
||||
*
|
||||
* @return TRUE, if successfully authorized
|
||||
*/
|
||||
boolean isAuthorized();
|
||||
|
||||
/**
|
||||
* Retrieve secret form Vault.
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* Retrieve any nodes content from Vault.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
SecretResponse readSecret(final String key) throws VaultConnectorException;
|
||||
SecretResponse read(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret from Vault.
|
||||
* Prefix "secret/" is automatically added to key.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||
return read(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* List available nodes from Vault.
|
||||
*
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
List<String> list(final String path) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available secrets from Vault.
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listSecrets(final String path) throws VaultConnectorException;
|
||||
default List<String> listSecrets(final String path) throws VaultConnectorException {
|
||||
return list(PATH_SECRET + "/" + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write simple value to Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param value Secret value
|
||||
* @throws VaultConnectorException on error
|
||||
* @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 value to Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
void write(final String key, final Map<String, Object> data) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param value Secret value
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean writeSecret(final String key, final String value) throws VaultConnectorException;
|
||||
default void writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("value", value);
|
||||
writeSecret(key, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
if (key == null || key.isEmpty()) {
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
}
|
||||
write(PATH_SECRET + "/" + key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete key from Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
void delete(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret from Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default void deleteSecret(final String key) throws VaultConnectorException {
|
||||
delete(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke given lease immediately.
|
||||
*
|
||||
* @param leaseID the lease ID
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
void revoke(final String leaseID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Renew lease with given ID.
|
||||
*
|
||||
* @param leaseID the lase ID
|
||||
* @return Renewed lease
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SecretResponse renew(final String leaseID) throws VaultConnectorException {
|
||||
return renew(leaseID, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew lease with given ID.
|
||||
*
|
||||
* @param leaseID the lase ID
|
||||
* @param increment number of seconds to extend lease time
|
||||
* @return Renewed lease
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @param orphan create orphan token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token, boolean orphan) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token for specific role.
|
||||
*
|
||||
* @param token the token
|
||||
* @param role the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token, final String role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
TokenResponse lookupToken(final String token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Read credentials for MySQL backend at default mount point.
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMySqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mysql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for PostgreSQL backend at default mount point.
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readPostgreSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "postgresql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MSSQL backend at default mount point.
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMsSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mssql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MSSQL backend at default mount point.
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMongoDbCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mongodb");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for SQL backends.
|
||||
*
|
||||
* @param role the role name
|
||||
* @param mount mount point of the SQL backend
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readDbCredentials(final String role, final String mount)
|
||||
throws VaultConnectorException {
|
||||
return (CredentialsResponse) read(mount + "/creds/" + role);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,24 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown on problems with connection to Vault backend.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class ConnectionException extends VaultConnectorException {
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public ConnectionException() {
|
||||
}
|
||||
|
||||
public ConnectionException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public ConnectionException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ConnectionException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public ConnectionException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public ConnectionException(String message, Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public ConnectionException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
@ -7,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class InvalidRequestException extends VaultConnectorException {
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public InvalidRequestException() {
|
||||
}
|
||||
|
||||
public InvalidRequestException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public InvalidRequestException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidRequestException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public InvalidRequestException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public InvalidRequestException(String message, Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public InvalidRequestException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,179 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when response from vault returned with erroneous status code or payload could not be parsed
|
||||
* to entity class.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class InvalidResponseException extends VaultConnectorException {
|
||||
private Integer statusCode;
|
||||
private String response;
|
||||
public final class InvalidResponseException extends VaultConnectorException {
|
||||
private final Integer statusCode;
|
||||
private final String response;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public InvalidResponseException() {
|
||||
this.statusCode = null;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public InvalidResponseException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message The detail message
|
||||
*/
|
||||
public InvalidResponseException(final String message) {
|
||||
super(message);
|
||||
this.statusCode = null;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public InvalidResponseException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause The cause
|
||||
*/
|
||||
public InvalidResponseException(final Throwable cause) {
|
||||
super(cause);
|
||||
this.statusCode = null;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public InvalidResponseException(String message, Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message The detail message
|
||||
* @param cause The cause
|
||||
*/
|
||||
public InvalidResponseException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
this.statusCode = null;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public InvalidResponseException withStatusCode(Integer statusCode) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and status code.
|
||||
* <p>
|
||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param message The detail message
|
||||
* @param statusCode Status code of the HTTP response
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public InvalidResponseException(final String message, final Integer statusCode) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
return this;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public InvalidResponseException withResponse(String response) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message, cause and status code.
|
||||
* <p>
|
||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param message The detail message
|
||||
* @param statusCode Status code of the HTTP response
|
||||
* @param cause The cause
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public InvalidResponseException(final String message, final Integer statusCode, final Throwable cause) {
|
||||
this(message, statusCode, null, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message, cause and status code.
|
||||
* <p>
|
||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param message The detail message
|
||||
* @param statusCode Status code of the HTTP response
|
||||
* @param response HTTP response string
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public InvalidResponseException(final String message,
|
||||
final Integer statusCode,
|
||||
final String response) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
this.response = response;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message, cause and status code.
|
||||
* <p>
|
||||
* The HTTP status code can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param message The detail message
|
||||
* @param statusCode Status code of the HTTP response
|
||||
* @param response HTTP response string
|
||||
* @param cause The cause
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public InvalidResponseException(final String message,
|
||||
final Integer statusCode,
|
||||
final String response,
|
||||
final Throwable cause) {
|
||||
super(message, cause);
|
||||
this.statusCode = statusCode;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the HTTP status code. Can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param statusCode The status code
|
||||
* @return self
|
||||
* @deprecated as of 0.6.2, use constructor with status code argument instead
|
||||
*/
|
||||
@Deprecated
|
||||
public InvalidResponseException withStatusCode(final Integer statusCode) {
|
||||
return new InvalidResponseException(getMessage(), statusCode, getResponse(), getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the response string. Can be retrieved by {@link #getResponse()} later.
|
||||
*
|
||||
* @param response Response text
|
||||
* @return self
|
||||
* @deprecated use constructor with response argument instead
|
||||
*/
|
||||
@Deprecated
|
||||
public InvalidResponseException withResponse(final String response) {
|
||||
return new InvalidResponseException(getMessage(), getStatusCode(), response, getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the HTTP status code.
|
||||
*
|
||||
* @return The status code or {@code null} if none specified.
|
||||
*/
|
||||
public Integer getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the response text.
|
||||
*
|
||||
* @return The response text or {@code null} if none specified.
|
||||
*/
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
@ -7,19 +23,38 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class PermissionDeniedException extends VaultConnectorException {
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public PermissionDeniedException() {
|
||||
super("Permission denied");
|
||||
}
|
||||
|
||||
public PermissionDeniedException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public PermissionDeniedException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PermissionDeniedException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public PermissionDeniedException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public PermissionDeniedException(String message, Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public PermissionDeniedException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown on errors with TLS connection.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TlsException extends VaultConnectorException {
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public TlsException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public TlsException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public TlsException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public TlsException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
/**
|
||||
@ -7,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultConnectorException extends Exception {
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public VaultConnectorException() {
|
||||
}
|
||||
|
||||
public VaultConnectorException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public VaultConnectorException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public VaultConnectorException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public VaultConnectorException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public VaultConnectorException(String message, Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public VaultConnectorException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,67 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.ConnectionException;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Vault Connector Factory implementation for HTTP Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
|
||||
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
|
||||
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
|
||||
private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES";
|
||||
|
||||
public static final String DEFAULT_HOST = "127.0.0.1";
|
||||
public static final Integer DEFAULT_PORT = 8200;
|
||||
public static final boolean DEFAULT_TLS = true;
|
||||
public static final String DEFAULT_PREFIX = "/v1/";
|
||||
public static final int DEFAULT_NUMBER_OF_RETRIES = 0;
|
||||
|
||||
private String host;
|
||||
private Integer port;
|
||||
private boolean tls;
|
||||
private String prefix;
|
||||
private SSLContext sslContext;
|
||||
private int numberOfRetries;
|
||||
private Integer timeout;
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* Default empty constructor.
|
||||
@ -28,49 +72,55 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
port = DEFAULT_PORT;
|
||||
tls = DEFAULT_TLS;
|
||||
prefix = DEFAULT_PREFIX;
|
||||
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hostname (default: 127.0.0.1)
|
||||
* @param host Hostname or IP address
|
||||
* @return self
|
||||
* Set hostname (default: 127.0.0.1).
|
||||
*
|
||||
* @param host Hostname or IP address
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withHost(String host) {
|
||||
public HTTPVaultConnectorFactory withHost(final String host) {
|
||||
this.host = host;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port (default: 8200)
|
||||
* @param port Vault TCP port
|
||||
* @return self
|
||||
* Set port (default: 8200).
|
||||
*
|
||||
* @param port Vault TCP port
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withPort(Integer port) {
|
||||
public HTTPVaultConnectorFactory withPort(final Integer port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TLS usage (default: TRUE)
|
||||
* @param useTLS use TLS or not
|
||||
* @return self
|
||||
* Set TLS usage (default: TRUE).
|
||||
*
|
||||
* @param useTLS use TLS or not
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTLS(boolean useTLS) {
|
||||
public HTTPVaultConnectorFactory withTLS(final boolean useTLS) {
|
||||
this.tls = useTLS;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience Method for TLS usage (enabled by default)
|
||||
* @return self
|
||||
* Convenience Method for TLS usage (enabled by default).
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTLS() {
|
||||
return withTLS(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience Method for NOT using TLS
|
||||
* @return self
|
||||
* Convenience Method for NOT using TLS.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withoutTLS() {
|
||||
return withTLS(false);
|
||||
@ -78,16 +128,185 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
|
||||
* @param prefix Vault API prefix (default: "/v1/"
|
||||
* @return self
|
||||
*
|
||||
* @param prefix Vault API prefix (default: "/v1/"
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withPrefix(String prefix) {
|
||||
public HTTPVaultConnectorFactory withPrefix(final String prefix) {
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trusted CA certifiate for HTTPS connections.
|
||||
*
|
||||
* @param cert path to certificate file
|
||||
* @return self
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||
if (cert != null)
|
||||
return withSslContext(createSslContext(cert));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom SSL context.
|
||||
* Overwrites certificates set by {@link #withTrustedCA}.
|
||||
*
|
||||
* @param sslContext the SSL context
|
||||
* @return self
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token for automatic authentication, using {@link #buildAndAuth()}.
|
||||
*
|
||||
* @param token Vault token
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withToken(final String token) {
|
||||
this.token = token;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
|
||||
*
|
||||
* @return self
|
||||
* @throws VaultConnectorException if Vault address from environment variables is malformed
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException {
|
||||
/* Parse URL from environment variable */
|
||||
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
|
||||
try {
|
||||
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
|
||||
this.host = url.getHost();
|
||||
this.port = url.getPort();
|
||||
this.tls = url.getProtocol().equals("https");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ConnectionException("URL provided in environment variable malformed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read number of retries */
|
||||
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
|
||||
try {
|
||||
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
|
||||
} catch (NumberFormatException ignored) {
|
||||
/* Ignore malformed values. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read token */
|
||||
token = System.getenv(ENV_VAULT_TOKEN);
|
||||
|
||||
/* Parse certificate, if set */
|
||||
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
|
||||
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the number of retries to attempt on 5xx errors.
|
||||
*
|
||||
* @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0)
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) {
|
||||
this.numberOfRetries = numberOfRetries;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a custom timeout for the HTTP connection.
|
||||
*
|
||||
* @param milliseconds Timeout value in milliseconds.
|
||||
* @return self
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTimeout(final int milliseconds) {
|
||||
this.timeout = milliseconds;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector build() {
|
||||
return new HTTPVaultConnector(host, tls, port, prefix);
|
||||
return new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||
if (token == null)
|
||||
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
||||
HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
||||
con.authToken(token);
|
||||
return con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create SSL Context trusting only provided certificate.
|
||||
*
|
||||
* @param trustedCert Path to trusted CA certificate
|
||||
* @return SSL context
|
||||
* @throws TlsException on errors
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private SSLContext createSslContext(final Path trustedCert) throws TlsException {
|
||||
try {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, createTrustManager(trustedCert), new SecureRandom());
|
||||
return context;
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new TlsException("Unable to intialize SSLContext", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom TrustManager for given CA certificate file.
|
||||
*
|
||||
* @param trustedCert Path to trusted CA certificate
|
||||
* @return TrustManger
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private TrustManager[] createTrustManager(final Path trustedCert) throws TlsException {
|
||||
try {
|
||||
/* Create Keystore with trusted certificate */
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null, null);
|
||||
keyStore.setCertificateEntry("trustedCert", certificateFromFile(trustedCert));
|
||||
/* Initialize TrustManager */
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(keyStore);
|
||||
return tmf.getTrustManagers();
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
|
||||
throw new TlsException("Unable to initialize TrustManager", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given certificate file to X.509 certificate.
|
||||
*
|
||||
* @param certFile Path to certificate file
|
||||
* @return X.509 Certificate object
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
|
||||
try (InputStream is = Files.newInputStream(certFile)) {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||
} catch (IOException | CertificateException e) {
|
||||
throw new TlsException("Unable to read certificate.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.VaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Abstract Vault Connector Factory interface.
|
||||
* Provides builder pattern style factory for Vault connectors.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultConnectorFactory {
|
||||
/**
|
||||
* Get Factory implementation for HTTP Vault Connector
|
||||
* @return HTTP Connector Factory
|
||||
* Get Factory implementation for HTTP Vault Connector.
|
||||
*
|
||||
* @return HTTP Connector Factory
|
||||
*/
|
||||
public static HTTPVaultConnectorFactory httpFactory() {
|
||||
return new HTTPVaultConnectorFactory();
|
||||
@ -20,7 +38,17 @@ public abstract class VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Build command, produces connector after initialization.
|
||||
* @return Vault Connector instance.
|
||||
*
|
||||
* @return Vault Connector instance.
|
||||
*/
|
||||
public abstract VaultConnector build();
|
||||
|
||||
/**
|
||||
* Build connector and authenticate with token set in factory or from environment.
|
||||
*
|
||||
* @return Authenticated Vault connector instance.
|
||||
* @throws VaultConnectorException if authentication failed
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public abstract VaultConnector buildAndAuth() throws VaultConnectorException;
|
||||
}
|
||||
|
209
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
209
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Vault AppRole role metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AppRole {
|
||||
@JsonProperty("role_name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("role_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty("bind_secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean bindSecretId;
|
||||
|
||||
private List<String> boundCidrList;
|
||||
|
||||
private List<String> policies;
|
||||
|
||||
@JsonProperty("secret_id_num_uses")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer secretIdNumUses;
|
||||
|
||||
@JsonProperty("secret_id_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer secretIdTtl;
|
||||
|
||||
@JsonProperty("token_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer tokenTtl;
|
||||
|
||||
@JsonProperty("token_max_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer tokenMaxTtl;
|
||||
|
||||
@JsonProperty("period")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer period;
|
||||
|
||||
/**
|
||||
* 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 boundCidrList 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> boundCidrList,
|
||||
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.boundCidrList = boundCidrList;
|
||||
this.policies = policies;
|
||||
this.secretIdNumUses = secretIdNumUses;
|
||||
this.secretIdTtl = secretIdTtl;
|
||||
this.tokenTtl = tokenTtl;
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the role name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the role ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bind secret ID
|
||||
*/
|
||||
public Boolean getBindSecretId() {
|
||||
return bindSecretId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of bound CIDR subnets
|
||||
*/
|
||||
public List<String> getBoundCidrList() {
|
||||
return boundCidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boundCidrList list of subnets in CIDR notation to bind role to
|
||||
*/
|
||||
@JsonSetter("bound_cidr_list")
|
||||
public void setBoundCidrList(final List<String> boundCidrList) {
|
||||
this.boundCidrList = boundCidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of subnets in CIDR notation as comma-separated {@link String}
|
||||
*/
|
||||
@JsonGetter("bound_cidr_list")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public String getBoundCidrListString() {
|
||||
if (boundCidrList == null || boundCidrList.isEmpty())
|
||||
return "";
|
||||
return String.join(",", boundCidrList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of policies
|
||||
*/
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policies list of policies
|
||||
*/
|
||||
@JsonSetter("policies")
|
||||
public void setPolicies(final List<String> policies) {
|
||||
this.policies = policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of policies as comma-separated {@link String}
|
||||
*/
|
||||
@JsonGetter("policies")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public String getPoliciesString() {
|
||||
if (policies == null || policies.isEmpty())
|
||||
return "";
|
||||
return String.join(",", policies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maximum number of uses per secret
|
||||
*/
|
||||
public Integer getSecretIdNumUses() {
|
||||
return secretIdNumUses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maximum TTL in seconds for secrets
|
||||
*/
|
||||
public Integer getSecretIdTtl() {
|
||||
return secretIdTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return token TTL in seconds
|
||||
*/
|
||||
public Integer getTokenTtl() {
|
||||
return tokenTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maximum token TTL in seconds, including renewals
|
||||
*/
|
||||
public Integer getTokenMaxTtl() {
|
||||
return tokenMaxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return duration in seconds, if specified
|
||||
*/
|
||||
public Integer getPeriod() {
|
||||
return period;
|
||||
}
|
||||
}
|
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A builder for vault AppRole roles..
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public final class AppRoleBuilder {
|
||||
private String name;
|
||||
private String id;
|
||||
private Boolean bindSecretId;
|
||||
private List<String> boundCidrList;
|
||||
private List<String> policies;
|
||||
private Integer secretIdNumUses;
|
||||
private Integer secretIdTtl;
|
||||
private Integer tokenTtl;
|
||||
private Integer tokenMaxTtl;
|
||||
private Integer period;
|
||||
|
||||
/**
|
||||
* Construct {@link AppRoleBuilder} with only the role name set.
|
||||
*
|
||||
* @param name Role name
|
||||
*/
|
||||
public AppRoleBuilder(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom role ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if role is bound to secret ID.
|
||||
*
|
||||
* @param bindSecretId the display name
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID(final Boolean bindSecretId) {
|
||||
this.bindSecretId = bindSecretId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID() {
|
||||
return withBindSecretID(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withoutBindSecretID() {
|
||||
return withBindSecretID(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bound CIDR blocks.
|
||||
*
|
||||
* @param boundCidrList List of CIDR blocks which can perform login
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBoundCidrList(final List<String> boundCidrList) {
|
||||
this.boundCidrList = boundCidrList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CIDR block to list of bound blocks.
|
||||
*
|
||||
* @param cidrBlock the CIDR block
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withCidrBlock(final String cidrBlock) {
|
||||
if (boundCidrList == null)
|
||||
boundCidrList = new ArrayList<>();
|
||||
boundCidrList.add(cidrBlock);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder 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 AppRoleBuilder withPolicy(final String policy) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
policies.add(policy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of uses for sectet IDs.
|
||||
*
|
||||
* @param secredIdNumUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdNumUses(final Integer secredIdNumUses) {
|
||||
this.secretIdNumUses = secredIdNumUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default sectet ID TTL in seconds.
|
||||
*
|
||||
* @param secredIdTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdTtl(final Integer secredIdTtl) {
|
||||
this.secretIdTtl = secredIdTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default token TTL in seconds.
|
||||
*
|
||||
* @param tokenTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenTtl(final Integer tokenTtl) {
|
||||
this.tokenTtl = tokenTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum token TTL in seconds.
|
||||
*
|
||||
* @param tokenMaxTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenMaxTtl(final Integer tokenMaxTtl) {
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param period period in seconds
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withPeriod(final Integer period) {
|
||||
this.period = period;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the AppRole role based on given parameters.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public AppRole build() {
|
||||
return new AppRole(name,
|
||||
id,
|
||||
bindSecretId,
|
||||
boundCidrList,
|
||||
policies,
|
||||
secretIdNumUses,
|
||||
secretIdTtl,
|
||||
tokenTtl,
|
||||
tokenMaxTtl,
|
||||
period);
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault AppRole role metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AppRoleSecret {
|
||||
@JsonProperty("secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty(value = "secret_id_accessor", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String accessor;
|
||||
|
||||
@JsonProperty("metadata")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
private List<String> cidrList;
|
||||
|
||||
@JsonProperty(value = "creation_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String creationTime;
|
||||
|
||||
@JsonProperty(value = "expiration_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String expirationTime;
|
||||
|
||||
@JsonProperty(value = "last_updated_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String lastUpdatedTime;
|
||||
|
||||
@JsonProperty(value = "secret_id_num_uses", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private Integer numUses;
|
||||
|
||||
@JsonProperty(value = "secret_id_ttl", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private Integer ttl;
|
||||
|
||||
/**
|
||||
* Construct empty {@link AppRoleSecret} object.
|
||||
*/
|
||||
public AppRoleSecret() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link AppRoleSecret} with secret ID.
|
||||
*
|
||||
* @param id Secret ID
|
||||
*/
|
||||
public AppRoleSecret(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link AppRoleSecret} with ID and metadata.
|
||||
*
|
||||
* @param id Secret ID
|
||||
* @param metadata Secret metadata
|
||||
* @param cidrList List of subnets in CIDR notation, the role is bound to
|
||||
*/
|
||||
public AppRoleSecret(final String id, final Map<String, Object> metadata, final List<String> cidrList) {
|
||||
this.id = id;
|
||||
this.metadata = metadata;
|
||||
this.cidrList = cidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Secret ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Secret accessor
|
||||
*/
|
||||
public String getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Secret metadata
|
||||
*/
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of bound subnets in CIDR notation
|
||||
*/
|
||||
public List<String> getCidrList() {
|
||||
return cidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cidrList List of subnets in CIDR notation
|
||||
*/
|
||||
@JsonSetter("cidr_list")
|
||||
public void setCidrList(final List<String> cidrList) {
|
||||
this.cidrList = cidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of bound subnets in CIDR notation as comma-separated {@link String}
|
||||
*/
|
||||
@JsonGetter("cidr_list")
|
||||
public String getCidrListString() {
|
||||
if (cidrList == null || cidrList.isEmpty())
|
||||
return "";
|
||||
return String.join(",", cidrList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Creation time
|
||||
*/
|
||||
public String getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expiration time
|
||||
*/
|
||||
public String getExpirationTime() {
|
||||
return expirationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time of last update
|
||||
*/
|
||||
public String getLastUpdatedTime() {
|
||||
return lastUpdatedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of uses
|
||||
*/
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time-to-live
|
||||
*/
|
||||
public Integer getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
}
|
@ -1,24 +1,53 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
|
||||
/**
|
||||
* Currently supported authentication backends.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public enum AuthBackend {
|
||||
TOKEN("token"),
|
||||
APPID("app-id"),
|
||||
APPROLE("approle"),
|
||||
USERPASS("userpass"),
|
||||
GITHUB("github"), // Not supported yet.
|
||||
UNKNOWN("");
|
||||
|
||||
private final String type;
|
||||
|
||||
AuthBackend(String type) {
|
||||
/**
|
||||
* Construct {@link AuthBackend} of given type.
|
||||
*
|
||||
* @param type Backend type
|
||||
*/
|
||||
AuthBackend(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static AuthBackend forType(String type) {
|
||||
/**
|
||||
* Retrieve {@link AuthBackend} value for given type string.
|
||||
*
|
||||
* @param type Type string
|
||||
* @return Auth backend value
|
||||
*/
|
||||
public static AuthBackend forType(final String type) {
|
||||
for (AuthBackend v : values())
|
||||
if (v.type.equalsIgnoreCase(type))
|
||||
return v;
|
||||
|
165
src/main/java/de/stklcode/jvault/connector/model/Token.java
Normal file
165
src/main/java/de/stklcode/jvault/connector/model/Token.java
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault Token metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class Token {
|
||||
@JsonProperty("id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty("display_name")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String displayName;
|
||||
|
||||
@JsonProperty("no_parent")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean noParent;
|
||||
|
||||
@JsonProperty("no_default_policy")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean noDefaultPolicy;
|
||||
|
||||
@JsonProperty("ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer ttl;
|
||||
|
||||
@JsonProperty("num_uses")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer numUses;
|
||||
|
||||
@JsonProperty("policies")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private List<String> policies;
|
||||
|
||||
@JsonProperty("meta")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Map<String, String> meta;
|
||||
|
||||
@JsonProperty("renewable")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean renewable;
|
||||
|
||||
/**
|
||||
* Construct complete {@link Token} object.
|
||||
*
|
||||
* @param id Token ID (optional)
|
||||
* @param displayName Token display name (optional)
|
||||
* @param noParent Token has no parent (optional)
|
||||
* @param noDefaultPolicy Do not add default policy (optional)
|
||||
* @param ttl Token TTL in seconds (optional)
|
||||
* @param numUses Number of uses (optional)
|
||||
* @param policies List of policies (optional)
|
||||
* @param meta Metadata (optional)
|
||||
* @param renewable Is the token renewable (optional)
|
||||
*/
|
||||
public Token(final String id,
|
||||
final String displayName,
|
||||
final Boolean noParent,
|
||||
final Boolean noDefaultPolicy,
|
||||
final Integer ttl,
|
||||
final Integer numUses,
|
||||
final List<String> policies,
|
||||
final Map<String, String> meta,
|
||||
final Boolean renewable) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.ttl = ttl;
|
||||
this.numUses = numUses;
|
||||
this.noParent = noParent;
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
this.policies = policies;
|
||||
this.meta = meta;
|
||||
this.renewable = renewable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token display name
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token has no parent
|
||||
*/
|
||||
public Boolean getNoParent() {
|
||||
return noParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token has no default policy
|
||||
*/
|
||||
public Boolean getNoDefaultPolicy() {
|
||||
return noDefaultPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Time-to-live in seconds
|
||||
*/
|
||||
public Integer getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of uses
|
||||
*/
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of policies
|
||||
*/
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Metadata
|
||||
*/
|
||||
public Map<String, String> getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token is renewable
|
||||
*/
|
||||
public Boolean isRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A builder for vault tokens.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public final class TokenBuilder {
|
||||
private String id;
|
||||
private String displayName;
|
||||
private Boolean noParent;
|
||||
private Boolean noDefaultPolicy;
|
||||
private Integer ttl;
|
||||
private Integer numUses;
|
||||
private List<String> policies;
|
||||
private Map<String, String> meta;
|
||||
private Boolean renewable;
|
||||
|
||||
/**
|
||||
* Add token ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add display name.
|
||||
*
|
||||
* @param displayName the display name
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDisplayName(final String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired time to live.
|
||||
*
|
||||
* @param ttl the ttl
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withTtl(final Integer ttl) {
|
||||
this.ttl = ttl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired number of uses.
|
||||
*
|
||||
* @param numUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNumUses(final Integer numUses) {
|
||||
this.numUses = numUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the token should be created without parent.
|
||||
*
|
||||
* @param noParent if TRUE, token is created as orphan
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoParent(final boolean noParent) {
|
||||
this.noParent = noParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token without parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder asOrphan() {
|
||||
return withNoParent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token with parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withParent() {
|
||||
return withNoParent(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the default policy should not be part of this token.
|
||||
*
|
||||
* @param noDefaultPolicy if TRUE, default policy is not attached
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoDefaultPolicy(final boolean noDefaultPolicy) {
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDefaultPolicy() {
|
||||
return withNoDefaultPolicy(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withoutDefaultPolicy() {
|
||||
return withNoDefaultPolicy(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
* @since 0.5.0
|
||||
*/
|
||||
public TokenBuilder withPolicies(final String... policies) {
|
||||
return withPolicies(Arrays.asList(policies));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicies(final List<String> policies) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
this.policies.addAll(policies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicy(final String policy) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
policies.add(policy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param meta the metadata
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final Map<String, String> meta) {
|
||||
if (this.meta == null)
|
||||
this.meta = new HashMap<>();
|
||||
this.meta.putAll(meta);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final String key, final String value) {
|
||||
if (this.meta == null)
|
||||
this.meta = new HashMap<>();
|
||||
this.meta.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if token is renewable.
|
||||
*
|
||||
* @param renewable TRUE, if renewable
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withRenewable(final Boolean renewable) {
|
||||
this.renewable = renewable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder renewable() {
|
||||
return withRenewable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be not renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder notRenewable() {
|
||||
return withRenewable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the token based on given parameters.
|
||||
*
|
||||
* @return the token
|
||||
*/
|
||||
public Token build() {
|
||||
return new Token(id,
|
||||
displayName,
|
||||
noParent,
|
||||
noDefaultPolicy,
|
||||
ttl,
|
||||
numUses,
|
||||
policies,
|
||||
meta,
|
||||
renewable);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.AppRole;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault response for AppRole lookup.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AppRoleResponse extends VaultDataResponse {
|
||||
private AppRole role;
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>();
|
||||
data.forEach((k, v) -> {
|
||||
if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k, v);
|
||||
});
|
||||
this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Failed deserializing response", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The role
|
||||
*/
|
||||
public AppRole getRole() {
|
||||
return role;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.AppRoleSecret;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault response for AppRole lookup.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AppRoleSecretResponse extends VaultDataResponse {
|
||||
private AppRoleSecret secret;
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>();
|
||||
data.forEach((k, v) -> {
|
||||
if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k, v);
|
||||
});
|
||||
this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Failed deserializing response", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The secret
|
||||
*/
|
||||
public AppRoleSecret getSecret() {
|
||||
return secret;
|
||||
}
|
||||
}
|
@ -1,11 +1,28 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.JsonAnySetter;
|
||||
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.response.embedded.AuthMethod;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -14,19 +31,34 @@ import java.util.Map;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class AuthMethodsResponse implements VaultResponse {
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethodsResponse extends VaultDataResponse {
|
||||
private Map<String, AuthMethod> supportedMethods;
|
||||
|
||||
private List<AuthMethod> supportedMethods;
|
||||
|
||||
@JsonAnySetter
|
||||
public void setMethod(String path, Map<String, String> data) throws InvalidResponseException {
|
||||
if (supportedMethods == null)
|
||||
supportedMethods = new ArrayList<>();
|
||||
|
||||
supportedMethods.add(new AuthMethod(path, data.get("description"), data.get("type")));
|
||||
/**
|
||||
* Construct empty {@link AuthMethodsResponse} object.
|
||||
*/
|
||||
public AuthMethodsResponse() {
|
||||
this.supportedMethods = new HashMap<>();
|
||||
}
|
||||
|
||||
public List<AuthMethod> getSupportedMethods() {
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
try {
|
||||
this.supportedMethods.put(entry.getKey(),
|
||||
mapper.readValue(mapper.writeValueAsString(entry.getValue()), AuthMethod.class));
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Supported authentication methods
|
||||
*/
|
||||
public Map<String, AuthMethod> getSupportedMethods() {
|
||||
return supportedMethods;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
@ -12,35 +28,46 @@ import java.util.Map;
|
||||
/**
|
||||
* Vault response for authentication providing auth info in {@link AuthData} field.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthResponse extends VaultDataResponse {
|
||||
public final class AuthResponse extends VaultDataResponse {
|
||||
private Map<String, Object> data;
|
||||
|
||||
private AuthData auth;
|
||||
|
||||
/**
|
||||
* Set authentication data. The input will be mapped to the {@link AuthData} model.
|
||||
*
|
||||
* @param auth Raw authentication data
|
||||
* @throws InvalidResponseException on mapping errors
|
||||
*/
|
||||
@JsonProperty("auth")
|
||||
public void setAuth(Map<String, Object> auth) throws InvalidResponseException {
|
||||
public void setAuth(final Map<String, Object> auth) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
this.auth = mapper.readValue(mapper.writeValueAsString(auth), AuthData.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new InvalidResponseException();
|
||||
throw new InvalidResponseException("Failed deserializing response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) {
|
||||
public void setData(final Map<String, Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw data
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Authentication data
|
||||
*/
|
||||
public AuthData getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
|
||||
/**
|
||||
* Vault response from credentials lookup. Simple wrapper for data objects containing username and password fields.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class CredentialsResponse extends SecretResponse {
|
||||
|
||||
/**
|
||||
* @return Username
|
||||
*/
|
||||
public String getUsername() {
|
||||
Object username = get("username");
|
||||
if (username != null)
|
||||
return username.toString();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Password
|
||||
*/
|
||||
public String getPassword() {
|
||||
Object password = get("password");
|
||||
if (password != null)
|
||||
return password.toString();
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
@ -12,11 +28,23 @@ import java.util.List;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ErrorResponse implements VaultResponse {
|
||||
public final class ErrorResponse implements VaultResponse {
|
||||
@JsonProperty("errors")
|
||||
private List<String> errors;
|
||||
|
||||
public List<String > getErrors() {
|
||||
/**
|
||||
* @return List of errors
|
||||
*/
|
||||
public List<String> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (errors == null || errors.isEmpty()) {
|
||||
return "error response";
|
||||
} else {
|
||||
return errors.get(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Vault response for health query.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class HealthResponse implements VaultResponse {
|
||||
@JsonProperty("cluster_id")
|
||||
private String clusterID;
|
||||
|
||||
@JsonProperty("cluster_name")
|
||||
private String clusterName;
|
||||
|
||||
@JsonProperty("version")
|
||||
private String version;
|
||||
|
||||
@JsonProperty("server_time_utc")
|
||||
private Long serverTimeUTC;
|
||||
|
||||
@JsonProperty("standby")
|
||||
private Boolean standby;
|
||||
|
||||
@JsonProperty("sealed")
|
||||
private Boolean sealed;
|
||||
|
||||
@JsonProperty("initialized")
|
||||
private Boolean initialized;
|
||||
|
||||
/**
|
||||
* @return The Cluster ID.
|
||||
*/
|
||||
public String getClusterID() {
|
||||
return clusterID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Cluster name.
|
||||
*/
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vault version.
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server time UTC (timestamp).
|
||||
*/
|
||||
public Long getServerTimeUTC() {
|
||||
return serverTimeUTC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server standby status.
|
||||
*/
|
||||
public Boolean isStandby() {
|
||||
return standby;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server seal status.
|
||||
*/
|
||||
public Boolean isSealed() {
|
||||
return sealed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server initialization status.
|
||||
*/
|
||||
public Boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
@ -10,10 +26,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class HelpResponse implements VaultResponse {
|
||||
public final class HelpResponse implements VaultResponse {
|
||||
@JsonProperty("help")
|
||||
private String help;
|
||||
|
||||
/**
|
||||
* @return Help text
|
||||
*/
|
||||
public String getHelp() {
|
||||
return help;
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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 java.util.Map;
|
||||
|
||||
/**
|
||||
* Simple Vault data response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class RawDataResponse extends VaultDataResponse {
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(final Map<String, Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw data {@link Map}
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
@ -10,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SealResponse implements VaultResponse {
|
||||
public final class SealResponse implements VaultResponse {
|
||||
@JsonProperty("sealed")
|
||||
private boolean sealed;
|
||||
|
||||
@ -23,18 +39,30 @@ public class SealResponse implements VaultResponse {
|
||||
@JsonProperty("progress")
|
||||
private Integer progress;
|
||||
|
||||
/**
|
||||
* @return Seal status
|
||||
*/
|
||||
public boolean isSealed() {
|
||||
return sealed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Required threshold of secret shares
|
||||
*/
|
||||
public Integer getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of secret shares
|
||||
*/
|
||||
public Integer getNumberOfShares() {
|
||||
return numberOfShares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current unseal progress (remaining required shares)
|
||||
*/
|
||||
public Integer getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
@ -10,23 +26,31 @@ import java.util.Map;
|
||||
/**
|
||||
* Vault response for secret list request.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SecretListResponse extends VaultDataResponse {
|
||||
public final class SecretListResponse extends VaultDataResponse {
|
||||
private List<String> keys;
|
||||
|
||||
/**
|
||||
* Set data. Extracts list of keys from raw response data.
|
||||
*
|
||||
* @param data Raw data
|
||||
* @throws InvalidResponseException on parsing errors
|
||||
*/
|
||||
@JsonProperty("data")
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
try {
|
||||
this.keys = (List<String>)data.get("keys");
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
this.keys = (List<String>) data.get("keys");
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidResponseException("Keys could not be parsed from data.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of secret keys
|
||||
*/
|
||||
public List<String> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
@ -1,30 +1,117 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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 java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault response for secret request.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SecretResponse extends VaultDataResponse {
|
||||
private String value;
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
try {
|
||||
this.value = (String) data.get("value");
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidResponseException("Value could not be parsed", e);
|
||||
}
|
||||
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
/**
|
||||
* Get complete data object.
|
||||
*
|
||||
* @return data map
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public final Map<String, Object> getData() {
|
||||
if (data == null)
|
||||
return new HashMap<>();
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single value for given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value or {@code null} if absent
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public final Object get(final String key) {
|
||||
if (data == null)
|
||||
return null;
|
||||
return getData().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data element for key "value".
|
||||
* Method for backwards compatibility in case of simple secrets.
|
||||
*
|
||||
* @return the value
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final String getValue() {
|
||||
Object value = get("value");
|
||||
if (value == null)
|
||||
return null;
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON.
|
||||
*
|
||||
* @param type Class to parse response
|
||||
* @param <T> Class to parse response
|
||||
* @return Parsed object
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.3
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final <T> T getValue(final Class<T> type) throws InvalidResponseException {
|
||||
return get("value", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON.
|
||||
*
|
||||
* @param key the key
|
||||
* @param type Class to parse response
|
||||
* @param <T> Class to parse response
|
||||
* @return Parsed object or {@code null} if absent
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public final <T> T get(final String key, final Class<T> type) throws InvalidResponseException {
|
||||
try {
|
||||
Object rawValue = get(key);
|
||||
if (rawValue == null)
|
||||
return null;
|
||||
return new ObjectMapper().readValue(rawValue.toString(), type);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,20 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@ -13,27 +28,35 @@ import java.util.Map;
|
||||
/**
|
||||
* Vault response from token lookup providing Token information in {@link TokenData} field.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class TokenResponse extends VaultDataResponse {
|
||||
public final class TokenResponse extends VaultDataResponse {
|
||||
private TokenData data;
|
||||
|
||||
@JsonProperty("auth")
|
||||
private Boolean auth;
|
||||
|
||||
/**
|
||||
* Set data. Parses response data map to {@link TokenData}.
|
||||
*
|
||||
* @param data Raw response data
|
||||
* @throws InvalidResponseException on parsing errors
|
||||
*/
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenData.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new InvalidResponseException();
|
||||
throw new InvalidResponseException("Failed deserializing response", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token data
|
||||
*/
|
||||
public TokenData getData() {
|
||||
return data;
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@ -9,8 +25,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Abstract Vault response with default payload fields.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class VaultDataResponse implements VaultResponse {
|
||||
@JsonProperty("lease_id")
|
||||
@ -25,22 +41,40 @@ public abstract class VaultDataResponse implements VaultResponse {
|
||||
@JsonProperty("warnings")
|
||||
private List<String> warnings;
|
||||
|
||||
/**
|
||||
* Set data. To be implemented in the specific subclasses, as data can be of arbitrary structure.
|
||||
*
|
||||
* @param data Raw response data
|
||||
* @throws InvalidResponseException on parsing errors
|
||||
*/
|
||||
@JsonProperty("data")
|
||||
public abstract void setData(Map<String, Object> data) throws InvalidResponseException;
|
||||
public abstract void setData(final Map<String, Object> data) throws InvalidResponseException;
|
||||
|
||||
public String getLeaseId() {
|
||||
/**
|
||||
* @return Lease ID
|
||||
*/
|
||||
public final String getLeaseId() {
|
||||
return leaseId;
|
||||
}
|
||||
|
||||
public boolean isRenewable() {
|
||||
/**
|
||||
* @return Lease is renewable
|
||||
*/
|
||||
public final boolean isRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
|
||||
public Integer getLeaseDuration() {
|
||||
/**
|
||||
* @return Lease duration
|
||||
*/
|
||||
public final Integer getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
public List<String> getWarnings() {
|
||||
/**
|
||||
* @return List of warnings
|
||||
*/
|
||||
public final List<String> getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@ -13,7 +29,7 @@ import java.util.Map;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthData {
|
||||
public final class AuthData {
|
||||
@JsonProperty("client_token")
|
||||
private String clientToken;
|
||||
|
||||
@ -32,26 +48,44 @@ public class AuthData {
|
||||
@JsonProperty("renewable")
|
||||
private boolean renewable;
|
||||
|
||||
/**
|
||||
* @return Client token
|
||||
*/
|
||||
public String getClientToken() {
|
||||
return clientToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token accessor
|
||||
*/
|
||||
public String getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of policies
|
||||
*/
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Metadata
|
||||
*/
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lease duration
|
||||
*/
|
||||
public Integer getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lease is renewable
|
||||
*/
|
||||
public boolean isRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
|
@ -1,40 +1,89 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Embedded authentication method response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class AuthMethod {
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethod {
|
||||
private AuthBackend type;
|
||||
private String rawType;
|
||||
private String path;
|
||||
|
||||
@JsonProperty("description")
|
||||
private String description;
|
||||
|
||||
public AuthMethod(String path, String description, String type) {
|
||||
this.path = path;
|
||||
this.description = description;
|
||||
@JsonProperty("config")
|
||||
private Map<String, String> config;
|
||||
|
||||
@JsonProperty("local")
|
||||
private boolean local;
|
||||
|
||||
/**
|
||||
* @param type Backend type, passed to {@link AuthBackend#forType(String)}
|
||||
*/
|
||||
@JsonSetter("type")
|
||||
public void setType(final String type) {
|
||||
this.rawType = type;
|
||||
this.type = AuthBackend.forType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Backend type
|
||||
*/
|
||||
public AuthBackend getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw backend type string
|
||||
*/
|
||||
public String getRawType() {
|
||||
return rawType;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Configuration data
|
||||
*/
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Is local backend
|
||||
*/
|
||||
public boolean isLocal() {
|
||||
return local;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@ -10,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class TokenData {
|
||||
public final class TokenData {
|
||||
@JsonProperty("accessor")
|
||||
private String accessor;
|
||||
|
||||
@ -18,7 +34,7 @@ public class TokenData {
|
||||
private Integer creationTime;
|
||||
|
||||
@JsonProperty("creation_ttl")
|
||||
private Integer creatinTtl;
|
||||
private Integer creationTtl;
|
||||
|
||||
@JsonProperty("display_name")
|
||||
private String name;
|
||||
@ -44,46 +60,79 @@ public class TokenData {
|
||||
@JsonProperty("ttl")
|
||||
private Integer ttl;
|
||||
|
||||
/**
|
||||
* @return Token accessor
|
||||
*/
|
||||
public String getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Creation time
|
||||
*/
|
||||
public Integer getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public Integer getCreatinTtl() {
|
||||
return creatinTtl;
|
||||
/**
|
||||
* @return Creation TTL (in seconds)
|
||||
*/
|
||||
public Integer getCreationTtl() {
|
||||
return creationTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of uses
|
||||
*/
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token is orphan
|
||||
*/
|
||||
public boolean isOrphan() {
|
||||
return orphan;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token path
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token role
|
||||
*/
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token TTL (in seconds)
|
||||
*/
|
||||
public Integer getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Metadata
|
||||
*/
|
||||
public String getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import 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 org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.powermock.api.mockito.PowerMockito.*;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector.
|
||||
* This test suite contains tests that do not require connection to an actual Vault instance.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({HttpClientBuilder.class})
|
||||
@PowerMockIgnore({"javax.net.ssl.*"})
|
||||
public class HTTPVaultConnectorOfflineTest {
|
||||
private static final String INVALID_URL = "foo:/\\1nv4l1d_UrL";
|
||||
|
||||
@Mock
|
||||
private HttpClientBuilder httpMockBuilder;
|
||||
|
||||
@Mock
|
||||
private CloseableHttpClient httpMock;
|
||||
|
||||
@Mock
|
||||
private CloseableHttpResponse responseMock;
|
||||
|
||||
/**
|
||||
* Test exceptions thrown during request.
|
||||
*/
|
||||
@Test
|
||||
public void requestExceptionTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("http://127.0.0.1", null, 0, 250);
|
||||
|
||||
// Test invalid response code.
|
||||
initHttpMock();
|
||||
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()));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// Now simulate a failing request that succeeds on second try.
|
||||
connector = new HTTPVaultConnector("https://127.0.0.1", null, 1, 250);
|
||||
doReturn(responseMock).doReturn(responseMock).when(httpMock).execute(any());
|
||||
doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, ""))
|
||||
.doReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, ""))
|
||||
.when(responseMock).getStatusLine();
|
||||
when(responseMock.getEntity()).thenReturn(new StringEntity("{}", ContentType.APPLICATION_JSON));
|
||||
|
||||
try {
|
||||
connector.getHealth();
|
||||
} catch (Exception e) {
|
||||
fail("Request failed unexpectedly: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constductors of the {@link HTTPVaultConnector} class.
|
||||
*/
|
||||
@Test
|
||||
public void constructorTest() throws NoSuchAlgorithmException {
|
||||
final String url = "https://vault.example.net/test/";
|
||||
final String hostname = "vault.example.com";
|
||||
final Integer port = 1337;
|
||||
final String prefix = "/custom/prefix/";
|
||||
final Integer retries = 42;
|
||||
final String expectedNoTls = "http://" + hostname + "/v1/";
|
||||
final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/";
|
||||
final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix;
|
||||
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
|
||||
// Most basic constructor expects complete URL.
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector(url);
|
||||
assertThat("Unexpected base URL", getPrivate(connector, "baseURL"), is(url));
|
||||
|
||||
// Now override TLS usage.
|
||||
connector = new HTTPVaultConnector(hostname, false);
|
||||
assertThat("Unexpected base URL with TLS disabled", getPrivate(connector, "baseURL"), is(expectedNoTls));
|
||||
|
||||
// Specify custom port.
|
||||
connector = new HTTPVaultConnector(hostname, true, port);
|
||||
assertThat("Unexpected base URL with custom port", getPrivate(connector, "baseURL"), is(expectedCustomPort));
|
||||
|
||||
// Specify custom prefix.
|
||||
connector = new HTTPVaultConnector(hostname, true, port, prefix);
|
||||
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||
assertThat("SSL context set, but not specified", getPrivate(connector, "sslContext"), is(nullValue()));
|
||||
|
||||
// Provide custom SSL context.
|
||||
connector = new HTTPVaultConnector(hostname, true, port, prefix, sslContext);
|
||||
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||
assertThat("SSL context not filled correctly", getPrivate(connector, "sslContext"), is(sslContext));
|
||||
|
||||
// Specify number of retries.
|
||||
connector = new HTTPVaultConnector(url, sslContext, retries);
|
||||
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(retries));
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||
*/
|
||||
@Test
|
||||
public void sealExceptionTest() throws IOException {
|
||||
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);
|
||||
|
||||
// Simulate NULL response (mock not supplied with data).
|
||||
initHttpMock();
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is designed to test exceptions caught and thrown by seal-methods if Vault is not reachable.
|
||||
*/
|
||||
@Test
|
||||
public void healthExceptionTest() throws IOException {
|
||||
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);
|
||||
|
||||
// Simulate NULL response (mock not supplied with data).
|
||||
initHttpMock();
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behavior on unparsable responses.
|
||||
*/
|
||||
@Test
|
||||
public void parseExceptionTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
initHttpMock();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertParseError(Exception e) {
|
||||
assertThat("Unexpected type of exception", e, instanceOf(InvalidResponseException.class));
|
||||
assertThat("Unexpected exception message", e.getMessage(), is("Unable to parse response"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test requests that expect an empty response with code 204, but receive a 200 body.
|
||||
*/
|
||||
@Test
|
||||
public void nonEmpty204ResponseTest() throws IOException {
|
||||
HTTPVaultConnector connector = new HTTPVaultConnector("https://127.0.0.1", null, 0, 250);
|
||||
// Mock authorization.
|
||||
setPrivate(connector, "authorized", true);
|
||||
// Mock response.
|
||||
initHttpMock();
|
||||
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));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.registerUserId("appID", "userID");
|
||||
fail("registerUserId() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.createAppRole("appID", Collections.singletonList("policy"));
|
||||
fail("createAppRole() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.deleteAppRole("roleName");
|
||||
fail("deleteAppRole() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.setAppRoleID("roleName", "roleID");
|
||||
fail("setAppRoleID() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.destroyAppRoleSecret("roleName", "secretID");
|
||||
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.destroyAppRoleSecret("roleName", "secretUD");
|
||||
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.delete("key");
|
||||
fail("delete() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
|
||||
try {
|
||||
connector.revoke("leaseID");
|
||||
fail("destroyAppRoleSecret() with 200 response succeeded");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat("Unexpected exception type", e, instanceOf(InvalidResponseException.class));
|
||||
}
|
||||
}
|
||||
|
||||
private Object getPrivate(Object target, String fieldName) {
|
||||
try {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.isAccessible())
|
||||
return field.get(target);
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
field.setAccessible(false);
|
||||
return value;
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setPrivate(Object target, String fieldName, Object value) {
|
||||
try {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible =field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
field.setAccessible(accessible);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
// Should not occur, to be taken care of in test code.
|
||||
}
|
||||
}
|
||||
|
||||
private void initHttpMock() {
|
||||
mockStatic(HttpClientBuilder.class);
|
||||
when(HttpClientBuilder.create()).thenReturn(httpMockBuilder);
|
||||
when(httpMockBuilder.setSSLContext(null)).thenReturn(httpMockBuilder);
|
||||
when(httpMockBuilder.build()).thenReturn(httpMock);
|
||||
}
|
||||
|
||||
private void mockResponse(int status, String body, ContentType type) throws IOException {
|
||||
when(httpMock.execute(any())).thenReturn(responseMock);
|
||||
when(responseMock.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), status, ""));
|
||||
when(responseMock.getEntity()).thenReturn(new StringEntity(body, type));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.exception;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Common JUnit test for Exceptions extending {@link VaultConnectorException}.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public 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() {
|
||||
assertEmptyConstructor(new AuthorizationRequiredException());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionExceptionTest() {
|
||||
assertEmptyConstructor(new ConnectionException());
|
||||
assertMsgConstructor(new ConnectionException(MSG));
|
||||
assertCauseConstructor(new ConnectionException(CAUSE));
|
||||
assertMsgCauseConstructor(new ConnectionException(MSG, CAUSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRequestExceptionTest() {
|
||||
assertEmptyConstructor(new InvalidRequestException());
|
||||
assertMsgConstructor(new InvalidRequestException(MSG));
|
||||
assertCauseConstructor(new InvalidRequestException(CAUSE));
|
||||
assertMsgCauseConstructor(new InvalidRequestException(MSG, CAUSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidResponseExceptionTest() {
|
||||
assertEmptyConstructor(new InvalidResponseException());
|
||||
assertMsgConstructor(new InvalidResponseException(MSG));
|
||||
assertCauseConstructor(new InvalidResponseException(CAUSE));
|
||||
assertMsgCauseConstructor(new InvalidResponseException(MSG, CAUSE));
|
||||
|
||||
// Constructor with message and status code.
|
||||
InvalidResponseException e = new InvalidResponseException(MSG, STATUS_CODE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(nullValue()));
|
||||
|
||||
// Constructor with message, status code and cause.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, CAUSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(nullValue()));
|
||||
|
||||
// Constructor with message, status code and response.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, RESPONSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(RESPONSE));
|
||||
|
||||
// Constructor with message, status code, response and cause.
|
||||
e = new InvalidResponseException(MSG, STATUS_CODE, RESPONSE, CAUSE);
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
assertThat(e.getStatusCode(), is(STATUS_CODE));
|
||||
assertThat(e.getResponse(), is(RESPONSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void permissionDeniedExceptionTest() {
|
||||
// Default message overwritten.
|
||||
PermissionDeniedException e = new PermissionDeniedException();
|
||||
assertThat(e, is(instanceOf(VaultConnectorException.class)));
|
||||
assertThat(e, is(instanceOf(Exception.class)));
|
||||
assertThat(e, is(instanceOf(Throwable.class)));
|
||||
assertThat(e.getMessage(), is("Permission denied"));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
|
||||
assertMsgConstructor(new PermissionDeniedException(MSG));
|
||||
assertCauseConstructor(new PermissionDeniedException(CAUSE));
|
||||
assertMsgCauseConstructor(new PermissionDeniedException(MSG, CAUSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tlsExceptionTest() {
|
||||
assertEmptyConstructor(new TlsException());
|
||||
assertMsgConstructor(new TlsException(MSG));
|
||||
assertCauseConstructor(new TlsException(CAUSE));
|
||||
assertMsgCauseConstructor(new TlsException(MSG, CAUSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertions for empty constructor.
|
||||
*
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertEmptyConstructor(VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(VaultConnectorException.class)));
|
||||
assertThat(e, is(instanceOf(Exception.class)));
|
||||
assertThat(e, is(instanceOf(Throwable.class)));
|
||||
assertThat(e.getMessage(), is(nullValue()));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertions for constructor with message.
|
||||
*
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertMsgConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertions for constructor with cause.
|
||||
*
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertCauseConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(CAUSE.toString()));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertions for constructor with message and cause.
|
||||
*
|
||||
* @param e the exception
|
||||
*/
|
||||
private void assertMsgCauseConstructor(VaultConnectorException e) {
|
||||
assertThat(e.getMessage(), is(MSG));
|
||||
assertThat(e.getCause(), is(CAUSE));
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* JUnit test for HTTP Vault connector factory
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public 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";
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public final EnvironmentVariables environment = new EnvironmentVariables();
|
||||
|
||||
/**
|
||||
* Test building from environment variables
|
||||
*/
|
||||
@Test
|
||||
public void testFromEnv() throws NoSuchFieldException, IllegalAccessException, IOException {
|
||||
/* Provide address only should be enough */
|
||||
setenv(VAULT_ADDR, null, null, null);
|
||||
|
||||
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", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
||||
assertThat("Non-default number of retries, when none set", getPrivate(connector, "retries"), is(0));
|
||||
|
||||
/* Provide address and number of retries */
|
||||
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null);
|
||||
|
||||
try {
|
||||
factory = VaultConnectorFactory.httpFactory().fromEnv();
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Factory creation from environment failed");
|
||||
}
|
||||
connector = factory.build();
|
||||
|
||||
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
||||
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||
|
||||
/* Provide CA certificate */
|
||||
String VAULT_CACERT = tmpDir.newFolder().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)));
|
||||
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
|
||||
assertThat(((NoSuchFileException)e.getCause()).getFile(), is(VAULT_CACERT));
|
||||
}
|
||||
|
||||
/* Automatic authentication */
|
||||
setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN);
|
||||
|
||||
try {
|
||||
factory = VaultConnectorFactory.httpFactory().fromEnv();
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Factory creation from minimal environment failed");
|
||||
}
|
||||
assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN)));
|
||||
}
|
||||
|
||||
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 Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = target.getClass().getDeclaredField(fieldName);
|
||||
if (field.isAccessible())
|
||||
return field.get(target);
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
field.setAccessible(false);
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for AppRole Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AppRoleBuilderTest {
|
||||
|
||||
|
||||
private static final String NAME = "TestRole";
|
||||
private static final String ID = "test-id";
|
||||
private static final Boolean BIND_SECRET_ID = true;
|
||||
private static final List<String> BOUND_CIDR_LIST = new ArrayList<>();
|
||||
private static final String CIDR_1 = "192.168.1.0/24";
|
||||
private static final String CIDR_2 = "172.16.0.0/16";
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final Integer SECRET_ID_NUM_USES = 10;
|
||||
private static final Integer SECRET_ID_TTL = 7200;
|
||||
private static final Integer TOKEN_TTL = 4800;
|
||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||
private static final Integer PERIOD = 1234;
|
||||
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\",\"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, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD);
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
BOUND_CIDR_LIST.add(CIDR_1);
|
||||
POLICIES.add(POLICY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build role with only a name.
|
||||
*/
|
||||
@Test
|
||||
public void buildDefaultTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getId(), is(nullValue()));
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
assertThat(role.getBoundCidrList(), is(nullValue()));
|
||||
assertThat(role.getPolicies(), is(nullValue()));
|
||||
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
||||
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getPeriod(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should only contain role_name */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
public void buildFullTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME)
|
||||
.withId(ID)
|
||||
.withBindSecretID(BIND_SECRET_ID)
|
||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
||||
.withPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withPeriod(PERIOD)
|
||||
.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.getPolicies(), is(POLICIES));
|
||||
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
||||
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
||||
assertThat(role.getTokenTtl(), is(TOKEN_TTL));
|
||||
assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL));
|
||||
assertThat(role.getPeriod(), is(PERIOD));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
public void convenienceMethodsTest() {
|
||||
/* bind_secret_id */
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
role = new AppRoleBuilder(NAME).withBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(true));
|
||||
role = new AppRoleBuilder(NAME).withoutBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(false));
|
||||
|
||||
/* Add single CIDR subnet */
|
||||
role = new AppRoleBuilder(NAME).withCidrBlock(CIDR_2).build();
|
||||
assertThat(role.getBoundCidrList(), hasSize(1));
|
||||
assertThat(role.getBoundCidrList(), contains(CIDR_2));
|
||||
role = new AppRoleBuilder(NAME)
|
||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
||||
.withCidrBlock(CIDR_2)
|
||||
.build();
|
||||
assertThat(role.getBoundCidrList(), hasSize(2));
|
||||
assertThat(role.getBoundCidrList(), 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)
|
||||
.withPolicies(POLICIES)
|
||||
.withPolicy(POLICY_2)
|
||||
.build();
|
||||
assertThat(role.getPolicies(), hasSize(2));
|
||||
assertThat(role.getPolicies(), contains(POLICY, POLICY_2));
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.emptyString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.junit.MatcherAssume.assumeThat;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for AppRoleSecret model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
*/
|
||||
public class AppRoleSecretTest {
|
||||
|
||||
private static final String TEST_ID = "abc123";
|
||||
private static final Map<String, Object> TEST_META = new HashMap<>();
|
||||
private static final List<String> TEST_CIDR = Arrays.asList("203.0.113.0/24", "198.51.100.0/24");
|
||||
|
||||
static {
|
||||
TEST_META.put("foo", "bar");
|
||||
TEST_META.put("number", 1337);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructors.
|
||||
*/
|
||||
@Test
|
||||
public void constructorTest() {
|
||||
/* Empty constructor */
|
||||
AppRoleSecret secret = new AppRoleSecret();
|
||||
assertThat(secret.getId(), is(nullValue()));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
|
||||
/* Constructor with ID */
|
||||
secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
|
||||
/* Constructor with Metadata and CIDR bindings */
|
||||
secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(TEST_META));
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setter.
|
||||
*/
|
||||
@Test
|
||||
public void setterTest() {
|
||||
AppRoleSecret secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
secret.setCidrList(TEST_CIDR);
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
secret.setCidrList(null);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test JSON (de)serialization.
|
||||
*/
|
||||
@Test
|
||||
public 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");
|
||||
}
|
||||
/* CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list */
|
||||
secretJson = 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");
|
||||
}
|
||||
|
||||
/* Test fields, that should not be written to JSON */
|
||||
setPrivateField(secret, "accessor", "TEST_ACCESSOR");
|
||||
assumeThat(secret.getAccessor(), is("TEST_ACCESSOR"));
|
||||
setPrivateField(secret, "creationTime", "TEST_CREATION");
|
||||
assumeThat(secret.getCreationTime(), is("TEST_CREATION"));
|
||||
setPrivateField(secret, "expirationTime", "TEST_EXPIRATION");
|
||||
assumeThat(secret.getExpirationTime(), is("TEST_EXPIRATION"));
|
||||
setPrivateField(secret, "lastUpdatedTime", "TEST_UPDATETIME");
|
||||
assumeThat(secret.getLastUpdatedTime(), is("TEST_UPDATETIME"));
|
||||
setPrivateField(secret, "numUses", 678);
|
||||
assumeThat(secret.getNumUses(), is(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");
|
||||
}
|
||||
|
||||
/* Those fields should be deserialized from JSON though */
|
||||
secretJson = "{\"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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void setPrivateField(Object object, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = object.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
|
||||
private static String commaSeparatedToList(String json) {
|
||||
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":\\[$1\\]")
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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 org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for AuthBackend model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AuthBackendTest {
|
||||
|
||||
/**
|
||||
* Test forType() method.
|
||||
*/
|
||||
@Test
|
||||
public void forTypeTest() {
|
||||
assertThat(AuthBackend.forType("token"), is(AuthBackend.TOKEN));
|
||||
assertThat(AuthBackend.forType("app-id"), is(AuthBackend.APPID));
|
||||
assertThat(AuthBackend.forType("userpass"), is(AuthBackend.USERPASS));
|
||||
assertThat(AuthBackend.forType("github"), is(AuthBackend.GITHUB));
|
||||
assertThat(AuthBackend.forType(""), is(AuthBackend.UNKNOWN));
|
||||
assertThat(AuthBackend.forType("foobar"), is(AuthBackend.UNKNOWN));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for Token Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public 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 NUM_USES = 4;
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final String POLICY_3 = "policy3";
|
||||
private static final Map<String, String> META = new HashMap<>();
|
||||
private static final String META_KEY = "key";
|
||||
private static final String META_VALUE = "value";
|
||||
private static final String META_KEY_2 = "key2";
|
||||
private static final String META_VALUE_2 = "value2";
|
||||
private static final Boolean RENEWABLE = true;
|
||||
private static final 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}";
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
POLICIES.add(POLICY);
|
||||
META.put(META_KEY, META_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without any parameters.
|
||||
*/
|
||||
@Test
|
||||
public void buildDefaultTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder().build();
|
||||
assertThat(token.getId(), is(nullValue()));
|
||||
assertThat(token.getDisplayName(), is(nullValue()));
|
||||
assertThat(token.getNoParent(), is(nullValue()));
|
||||
assertThat(token.getNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(token.getTtl(), is(nullValue()));
|
||||
assertThat(token.getNumUses(), is(nullValue()));
|
||||
assertThat(token.getPolicies(), is(nullValue()));
|
||||
assertThat(token.getMeta(), is(nullValue()));
|
||||
assertThat(token.isRenewable(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
public void buildFullTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder()
|
||||
.withId(ID)
|
||||
.withDisplayName(DISPLAY_NAME)
|
||||
.withNoParent(NO_PARENT)
|
||||
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
|
||||
.withTtl(TTL)
|
||||
.withNumUses(NUM_USES)
|
||||
.withPolicies(POLICIES)
|
||||
.withMeta(META)
|
||||
.withRenewable(RENEWABLE)
|
||||
.build();
|
||||
assertThat(token.getId(), is(ID));
|
||||
assertThat(token.getDisplayName(), is(DISPLAY_NAME));
|
||||
assertThat(token.getNoParent(), is(NO_PARENT));
|
||||
assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY));
|
||||
assertThat(token.getTtl(), is(TTL));
|
||||
assertThat(token.getNumUses(), is(NUM_USES));
|
||||
assertThat(token.getPolicies(), is(POLICIES));
|
||||
assertThat(token.getMeta(), is(META));
|
||||
assertThat(token.isRenewable(), is(RENEWABLE));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
public void convenienceMethodsTest() {
|
||||
/* Parent */
|
||||
Token token = new TokenBuilder().asOrphan().build();
|
||||
assertThat(token.getNoParent(), is(true));
|
||||
token = new TokenBuilder().withParent().build();
|
||||
assertThat(token.getNoParent(), is(false));
|
||||
|
||||
/* Default policy */
|
||||
token = new TokenBuilder().withDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(false));
|
||||
token = new TokenBuilder().withoutDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(true));
|
||||
|
||||
/* Renewability */
|
||||
token = new TokenBuilder().renewable().build();
|
||||
assertThat(token.isRenewable(), is(true));
|
||||
token = new TokenBuilder().notRenewable().build();
|
||||
assertThat(token.isRenewable(), is(false));
|
||||
|
||||
/* Add single policy */
|
||||
token = new TokenBuilder().withPolicy(POLICY_2).build();
|
||||
assertThat(token.getPolicies(), hasSize(1));
|
||||
assertThat(token.getPolicies(), contains(POLICY_2));
|
||||
token = new TokenBuilder()
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertThat(token.getPolicies(), hasSize(3));
|
||||
assertThat(token.getPolicies(), contains(POLICY, POLICY_2, POLICY_3));
|
||||
|
||||
/* Add single metadata */
|
||||
token = new TokenBuilder().withMeta(META_KEY_2, META_VALUE_2).build();
|
||||
assertThat(token.getMeta().size(), is(1));
|
||||
assertThat(token.getMeta().keySet(), contains(META_KEY_2));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
token = new TokenBuilder()
|
||||
.withMeta(META)
|
||||
.withMeta(META_KEY_2, META_VALUE_2)
|
||||
.build();
|
||||
assertThat(token.getMeta().size(), is(2));
|
||||
assertThat(token.getMeta().get(META_KEY), is(META_VALUE));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AppRole;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AppRoleResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public 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;
|
||||
private static final Integer ROLE_SECRET_NUM_USES = 40;
|
||||
private static final String ROLE_POLICY = "default";
|
||||
private static final Integer ROLE_PERIOD = 0;
|
||||
private static final Boolean ROLE_BIND_SECRET = true;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"auth\": null,\n" +
|
||||
" \"warnings\": null,\n" +
|
||||
" \"wrap_info\": null,\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"token_ttl\": " + ROLE_TOKEN_TTL + ",\n" +
|
||||
" \"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" +
|
||||
" \"" + ROLE_POLICY + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"period\": " + ROLE_PERIOD + ",\n" +
|
||||
" \"bind_secret_id\": " + ROLE_BIND_SECRET + ",\n" +
|
||||
" \"bound_cidr_list\": \"\"\n" +
|
||||
" },\n" +
|
||||
" \"lease_duration\": 0,\n" +
|
||||
" \"renewable\": false,\n" +
|
||||
" \"lease_id\": \"\"\n" +
|
||||
"}";
|
||||
|
||||
private static final Map<String, Object> INVALID_DATA = new HashMap<>();
|
||||
|
||||
static {
|
||||
INVALID_DATA.put("policies", "fancy-policy");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*/
|
||||
@Test
|
||||
public 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)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthMethodsResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public class AuthMethodsResponseTest {
|
||||
private static final String GH_PATH = "github/";
|
||||
private static final String GH_TYPE = "github";
|
||||
private static final String GH_DESCR = "GitHub auth";
|
||||
private static final String TK_PATH = "token/";
|
||||
private static final String TK_TYPE = "token";
|
||||
private static final String TK_DESCR = "token based credentials";
|
||||
private static final Integer TK_LEASE_TTL = 0;
|
||||
private static final Integer TK_MAX_LEASE_TTL = 0;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"data\": {" +
|
||||
" \"" + GH_PATH + "\": {\n" +
|
||||
" \"type\": \"" + GH_TYPE + "\",\n" +
|
||||
" \"description\": \"" + GH_DESCR + "\"\n" +
|
||||
" },\n" +
|
||||
" \"" + TK_PATH + "\": {\n" +
|
||||
" \"config\": {\n" +
|
||||
" \"default_lease_ttl\": " + TK_LEASE_TTL + ",\n" +
|
||||
" \"max_lease_ttl\": " + TK_MAX_LEASE_TTL + "\n" +
|
||||
" },\n" +
|
||||
" \"description\": \"" + TK_DESCR + "\",\n" +
|
||||
" \"type\": \"" + TK_TYPE + "\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
private static final Map<String, Object> INVALID_DATA = new HashMap<>();
|
||||
|
||||
static {
|
||||
INVALID_DATA.put("dummy/", new Dummy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*/
|
||||
@Test
|
||||
public 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)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
private static class Dummy {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthData;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public 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";
|
||||
private static final String AUTH_POLICY_2 = "stage";
|
||||
private static final String AUTH_META_KEY = "user";
|
||||
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 RES_JSON = "{\n" +
|
||||
" \"auth\": {\n" +
|
||||
" \"accessor\": \"" + AUTH_ACCESSOR + "\",\n" +
|
||||
" \"client_token\": \"" + AUTH_CLIENT_TOKEN + "\",\n" +
|
||||
" \"policies\": [\n" +
|
||||
" \"" + AUTH_POLICY_1 + "\", \n" +
|
||||
" \"" + AUTH_POLICY_2 + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"metadata\": {\n" +
|
||||
" \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" +
|
||||
" },\n" +
|
||||
" \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" +
|
||||
" \"renewable\": " + AUTH_RENEWABLE + "\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
private static final Map<String, Object> INVALID_AUTH_DATA = new HashMap<>();
|
||||
|
||||
static {
|
||||
INVALID_AUTH_DATA.put("policies", "fancy-policy");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*/
|
||||
@Test
|
||||
public 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)));
|
||||
}
|
||||
|
||||
// Data method should be agnostic.
|
||||
res.setData(INVALID_AUTH_DATA);
|
||||
assertThat("Data not passed through", res.getData(), is(INVALID_AUTH_DATA));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
// Extract auth data.
|
||||
AuthData data = res.getAuth();
|
||||
assertThat("Auth data is NULL", data, is(notNullValue()));
|
||||
assertThat("Incorrect auth accessor", data.getAccessor(), is(AUTH_ACCESSOR));
|
||||
assertThat("Incorrect auth client token", data.getClientToken(), is(AUTH_CLIENT_TOKEN));
|
||||
assertThat("Incorrect auth lease duration", data.getLeaseDuration(), is(AUTH_LEASE_DURATION));
|
||||
assertThat("Incorrect auth renewable flag", data.isRenewable(), is(AUTH_RENEWABLE));
|
||||
assertThat("Incorrect 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());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public 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.6.2";
|
||||
private static final Long SERVER_TIME_UTC = 1469555798L;
|
||||
private static final Boolean STANDBY = false;
|
||||
private static final Boolean SEALED = false;
|
||||
private static final Boolean INITIALIZED = true;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
|
||||
" \"version\": \"" + VERSION + "\",\n" +
|
||||
" \"server_time_utc\": " + SERVER_TIME_UTC + ",\n" +
|
||||
" \"standby\": " + STANDBY + ",\n" +
|
||||
" \"sealed\": " + SEALED + ",\n" +
|
||||
" \"initialized\": " + INITIALIZED + "\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));
|
||||
} catch (IOException e) {
|
||||
fail("Health deserialization failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link SecretResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public 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";
|
||||
private static final String VAL_STRING = "testvalue";
|
||||
private static final String KEY_INTEGER = "test2";
|
||||
private static final Integer VAL_INTEGER = 42;
|
||||
private static final String KEY_LIST = "list";
|
||||
private static final String VAL_LIST = "[\"first\",\"second\"]";
|
||||
|
||||
private static final String SECRET_REQUEST_ID = "68315073-6658-e3ff-2da7-67939fb91bbd";
|
||||
private static final String SECRET_LEASE_ID = "";
|
||||
private static final Integer SECRET_LEASE_DURATION = 2764800;
|
||||
private static final boolean SECRET_RENEWABLE = false;
|
||||
private static final String SECRET_DATA_K1 = "excited";
|
||||
private static final String SECRET_DATA_V1 = "yes";
|
||||
private static final String SECRET_DATA_K2 = "value";
|
||||
private static final String SECRET_DATA_V2 = "world";
|
||||
private static final List<String> SECRET_WARNINGS = null;
|
||||
private static final String SECRET_JSON = "{\n" +
|
||||
" \"request_id\": \"" + SECRET_REQUEST_ID + "\",\n" +
|
||||
" \"lease_id\": \"" + SECRET_LEASE_ID + "\",\n" +
|
||||
" \"lease_duration\": " + SECRET_LEASE_DURATION + ",\n" +
|
||||
" \"renewable\": " + SECRET_RENEWABLE + ",\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"" + SECRET_DATA_K1 + "\": \"" + SECRET_DATA_V1 + "\",\n" +
|
||||
" \"" + SECRET_DATA_K2 + "\": \"" + SECRET_DATA_V2 + "\"\n" +
|
||||
" },\n" +
|
||||
" \"warnings\": " + SECRET_WARNINGS + "\n" +
|
||||
"}";
|
||||
|
||||
|
||||
static {
|
||||
DATA.put(KEY_STRING, VAL_STRING);
|
||||
DATA.put(KEY_INTEGER, VAL_INTEGER);
|
||||
DATA.put(KEY_LIST, VAL_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*
|
||||
* @throws InvalidResponseException Should not occur
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getDataRoundtrip() throws InvalidResponseException {
|
||||
// Create empty Object.
|
||||
SecretResponse res = new SecretResponse();
|
||||
assertThat("Initial data should be Map", res.getData(), is(instanceOf(Map.class)));
|
||||
assertThat("Initial data should be empty", res.getData().entrySet(), empty());
|
||||
assertThat("Getter should return NULL on empty data map", res.get(KEY_STRING), is(nullValue()));
|
||||
|
||||
// Fill data map.
|
||||
res.setData(DATA);
|
||||
assertThat("Data setter/getter not transparent", res.getData(), is(DATA));
|
||||
assertThat("Data size modified", res.getData().keySet(), hasSize(DATA.size()));
|
||||
assertThat("Data keys not passed correctly", res.getData().keySet(), containsInAnyOrder(KEY_STRING, KEY_INTEGER, KEY_LIST));
|
||||
assertThat("Data values not passed correctly", res.get(KEY_STRING), is(VAL_STRING));
|
||||
assertThat("Data values not passed correctly", res.get(KEY_INTEGER), is(VAL_INTEGER));
|
||||
assertThat("Non-Null returned on unknown key", res.get(KEY_UNKNOWN), is(nullValue()));
|
||||
|
||||
// Try explicit JSON conversion.
|
||||
final List list = res.get(KEY_LIST, List.class);
|
||||
assertThat("JSON parsing of list failed", list, is(notNullValue()));
|
||||
assertThat("JSON parsing of list returned incorrect size", list.size(), is(2));
|
||||
assertThat("JSON parsing of list returned incorrect elements", (List<Object>)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)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||
*/
|
||||
@Test
|
||||
public void jsonRoundtrip() {
|
||||
try {
|
||||
SecretResponse res = new ObjectMapper().readValue(SECRET_JSON, SecretResponse.class);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect lease ID", res.getLeaseId(), is(SECRET_LEASE_ID));
|
||||
assertThat("Incorrect lease duration", res.getLeaseDuration(), is(SECRET_LEASE_DURATION));
|
||||
assertThat("Incorrect renewable status", res.isRenewable(), is(SECRET_RENEWABLE));
|
||||
assertThat("Incorrect warnings", res.getWarnings(), is(SECRET_WARNINGS));
|
||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K1), is(SECRET_DATA_V1));
|
||||
assertThat("Response does not contain correct data", res.get(SECRET_DATA_K2), is(SECRET_DATA_V2));
|
||||
} catch (IOException e) {
|
||||
fail("SecretResponse deserialization failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link TokenResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.6.2
|
||||
*/
|
||||
public class TokenResponseTest {
|
||||
private static final Integer TOKEN_CREATION_TIME = 1457533232;
|
||||
private static final Integer TOKEN_TTL = 2764800;
|
||||
private static final String TOKEN_DISPLAY_NAME = "token";
|
||||
private static final Integer TOKEN_NUM_USES = 0;
|
||||
private static final Boolean TOKEN_ORPHAN = false;
|
||||
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 RES_JSON = "{\n" +
|
||||
" \"lease_id\": \"\",\n" +
|
||||
" \"renewable\": " + RES_RENEWABLE + ",\n" +
|
||||
" \"lease_duration\": " + RES_LEASE_DURATION + ",\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"creation_time\": " + TOKEN_CREATION_TIME + ",\n" +
|
||||
" \"creation_ttl\": " + TOKEN_TTL + ",\n" +
|
||||
" \"display_name\": \"" + TOKEN_DISPLAY_NAME + "\",\n" +
|
||||
" \"meta\": null,\n" +
|
||||
" \"num_uses\": " + TOKEN_NUM_USES + ",\n" +
|
||||
" \"orphan\": " + TOKEN_ORPHAN + ",\n" +
|
||||
" \"path\": \"" + TOKEN_PATH + "\",\n" +
|
||||
" \"policies\": [\n" +
|
||||
" \"" + TOKEN_POLICY_1 + "\", \n" +
|
||||
" \"" + TOKEN_POLICY_2 + "\"\n" +
|
||||
" ],\n" +
|
||||
" \"ttl\": " + RES_TTL + "\n" +
|
||||
" },\n" +
|
||||
" \"warnings\": null,\n" +
|
||||
" \"auth\": null\n" +
|
||||
"}";
|
||||
|
||||
private static final Map<String, Object> INVALID_TOKEN_DATA = new HashMap<>();
|
||||
|
||||
static {
|
||||
INVALID_TOKEN_DATA.put("num_uses", "fourtytwo");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getter, setter and get-methods for response data.
|
||||
*/
|
||||
@Test
|
||||
public 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)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.test;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Simple credentials class for JSON testing.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class Credentials {
|
||||
@JsonProperty("username")
|
||||
private String username;
|
||||
|
||||
@JsonProperty("password")
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 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.test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@ -6,8 +22,8 @@ import java.nio.file.Paths;
|
||||
/**
|
||||
* Vault configuration String using builder pattern.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class VaultConfiguration {
|
||||
private String host;
|
||||
@ -15,6 +31,8 @@ public class VaultConfiguration {
|
||||
private boolean disableTLS;
|
||||
private boolean disableMlock;
|
||||
private Path dataLocation;
|
||||
private String certFile;
|
||||
private String keyFile;
|
||||
|
||||
public VaultConfiguration() {
|
||||
this.disableTLS = true;
|
||||
@ -36,6 +54,16 @@ public class VaultConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration withCert(String certFile) {
|
||||
this.certFile = certFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration withKey(String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration disableMlock() {
|
||||
this.disableMlock = true;
|
||||
return this;
|
||||
@ -64,12 +92,14 @@ public class VaultConfiguration {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "backend \"file\" {\n" +
|
||||
return "backend \"file\" {\n" +
|
||||
" path = \"" + dataLocation + "\"\n" +
|
||||
"}\n" +
|
||||
"listener \"tcp\" {\n" +
|
||||
" address = \"" + host + ":" + port + "\"\n" +
|
||||
((disableTLS) ? " tls_disable = 1\n" : "") +
|
||||
((certFile != null) ? " tls_cert_file = \"" + certFile + "\"\n" : "") +
|
||||
((keyFile != null) ? " tls_key_file = \"" + keyFile + "\"\n" : "") +
|
||||
"}\n" +
|
||||
((disableMlock) ? "disable_mlock = true" : "");
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/salt","Value":"AAAAAQKDLmmb/XlhfVJ45oKGyYwneS9s3tcQUenB8bTcxuDmAMUWnwG8oNNJFs0mSCF9Yv1KOq3Twxj4qPp05viFnP0z"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/da42ddc9a483efd8ddeae4ab38428f73d42ad7f6320705f333555fed8593cbe2","Value":"AAAAAQLCu78fbRRgGWG++5XDCfaO/8NTg7LMAJL7aCsrn6c1WHJ5yrAAmWmSs1euhNd7yKUd0lQ0aknCKdPAZFBlAsqgOdnN8JLFe/H9lISaWdU6lRIfgTH9whEXWT0VK25FcS4r5yVe3Qoxg0DfT8FhjuzOa70="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e83aed0dd0b867f09aa1dbc88b965eafba6030458d6555712e82c479cee3d2d7","Value":"AAAAAQL7t56z9Fr92ztubIfZPPkV3X1Aljnn95Y/tDXOxn8vjbjf21Fhyj3UnLwWyzK/9ip/6+x2DJBXikBOvXoCqKLXGegZ4JN9Z9UMiQ88aE9Z978r13E/rNbhIUa/PhT5NGwCbOl6vtK2hL06BHxKb+4+goM="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e96c348451147331101ad48e157e8056ca1b039ee63a6aafd2d66446c94bcad8","Value":"AAAAAQIcvMn5QMtwELRDXZD9nNf7y/8O6z7u0NUZqyJrBb2OYDRvGpSuPS3CIareSxl8y5F4xtadvhyhunCGBUd289H9foMjfGbVVsM1mbM5i6FDTW0sFOPmXX44mQV29PVNMO+fcLuSWb0+qU4erqylpcvdLW8="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role/testrole1","Value":"AAAAAQLyV03lH8m3IYxoZKLf+/suZ+2wwKAyIHqrR3QeJZK+68wslLXy0XZ35bPrdc3jzAFhTizqILlgTBHVccdM/pydtTtbsvGHQlWstLaC79GUTM32gS/jwSrbwfa9j0q/Yrdo2LSa9IM5lw2tmYy+xR9c3ZKcm+VADZMZy3+6UmbQ1t0lniZ4uuVmqu2gl3y0732UtdMSxJepPWMjfvVq5+tynhgvEZNGgZCPc9lsV1fcBVFswtBUeATNnSJPmTnxQflXyhitPOpEM+5L+gnEsSNsyinRjv5cSbIHCP5yDzvpiWtwZ5Q0psVRSh/WJppBHcovwbJsTLK/tZ1wtFl1OgU9NLONEpgDJYiDyU0ACeFJ7r+DhjIDrQkr+WITnfBBwI+65wpOPYboqGgd4qZy84PE2s/VhWS5hjpxgpM="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role/testrole2","Value":"AAAAAQIA7g8ifdb9dcRQtIagNGpu2Miv6Dy4jBif1J9OZd26AgFDL6eZTrDr3FfmUQQUs/izDlfI9FDB+UJZO6P2B6vkTchwSg0JdOD8lHjtuoCSDKrIPmzallXHFGwnMnzFY80JzNlzUEfbzciExXthpUjlvBoMlHydZPtAn3pL2NkJdwW1dDRARGB9RoWguqYVgCMkOVdpLFYMVSN1nyHvlt2sm3IdwsXxlE9kH1HGiIEKWYX1U0l8uM0NJTZPFo8Km09u9sz/yzS9B+cyIKXaom7h7S53yRyGP7rFZObl3INMloJyJn7+XxpqiZYAiK31tToZ9k4Y3Eez1ZyCj+oujM6MDwnnzlAkOm3nptIySOk9+iEehr6rG5fpt3WTVSEC3f+1Q+4S"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role_id/b2b271423a16ba322c3f87616230f8ced5e89bc8d1a32f0ce91c3d3b5f264a8a","Value":"AAAAAQJhm8OnoLuGdSqb3GhF36ALFfIdoRHQ0SMaC1CAuhlfgzuPcyZFMgHr7IL1UepjItfW"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role_id/fb5542bdc4127acea06e585384296c607d18d139be530ac52f850b703b22bcb4","Value":"AAAAAQJMBpriwrK36PPIVHKh4hNEU66EXyp5npyEF3JxUD0BTQW/vQC6hrnDnSF9F59Xh1Ut"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/secret_id/7ec357dbed8f1b49bb2302aff1f08c57c2f03e03b842b7714ed13a5f9fbe970d/941884199542458348fa08c650246e293eb2bf743350861d73b8fc2978ae5c3a","Value":"AAAAAQLESOciqLucvh8+6PvJKIAQV+P4dPm8q8lweJm5KKH5/Ffh7rtp3btSJhUj2ey5SZummV1mF2rABJ7VROSSjOTbb698VpdXPUeK/qDlyAiT3f2vP16dCbsr1K8Pd0XRdRyrw6osnUwuLgNa9L4pBAoprPn5UwflZVAmwNPWMH3B6Ieo5aZrStP3xuDfU+tjvljaEQALwQAqqo0LTBVU2idw96g/TO75VjbcnptiJOeTPqctJKmh/tdaf1F7x2vOyu5IkhBX3PO4Qn+5F4am66q7HQfB773ga8ZSUoSkph7nahF6JtmHKJ+A972iK9NFx/69jOe1ylwwzzlG4aP1bsrYjGgCIk3CNrvUmK7iO0X9AbzOEgz2d27/VbmGh/bb29z8Oc6Tiw2Qo/tiQtNUreamE5q0UN9XTVC/wdUd5ZdG7RftT6Zv3imPIuAwHJ+GTNSI4HCwc5as/HXMA2xrUdYeuj0rdJejYtyEBQ=="}
|
@ -1 +1 @@
|
||||
{"Key":"core/audit","Value":"AAAAAQJ+0lfxYOKIXzquksd3Il4zfW4ja6BdScu7mCAijGDph63S5yWH92olwI2SQA=="}
|
||||
{"Key":"core/audit","Value":"AAAAAQI4CkDWnI49wp9iDaEMhEgTyBBtXOuIcrn7m4qifUOwQ6reTf3BKc5IQXuhxN5h51KVeinMklz3Ld0Qgw=="}
|
||||
|
@ -1 +1 @@
|
||||
{"Key":"core/auth","Value":"AAAAAQJeg+aK83bfYUPm5KV/+Y1Cf8fVX8Oq7cFiYE3PN4Tcl2j9YD7c+fijkopFzPLxh/EBRVzGTjBBkWBDTLC4EKn2lU8A+NJK6frGOu5Vjc4+WipBUcsGGcfosvxrZk8ZrTt09PRo7CnAFzmH4CgIVuEFv3NZyjXX08EMakxmH6R4S8Ti3cmit5Kr1TKSGnHeMfO6lBnAobAfNlfgNDM90yAxaQUT9gR27TabSKsVvkIY/0oxIcVFQ1RuF7xcdAOJ82wlWkcfT+rMhSS6roGt9Njx9t0PQNjv2eomh/leuhTUzfu4oAbtJJO3IPuC/KkJZpKinjJaGlA5Kx5m7W09DHieyI0GXmjJXH9oCj0z9w6eKDNZmjC1xeFylBvkvnkAKA6QmUmZjoq+m81/UC/C/ShJYxDFxaHwCPgF92qSrT1VTrz5lYAyyjJmrnbyuUXfgG6d4dbDxT/DVddHtIzHbBBT0xxjNM/+WxOSdRYZXKsfm8ovGaFWJr9AyFfEnyS0E9FJvkEXp68eNdacgdM3Ow5Zchm2/I9F4wN577ZwK9oGO2kjkDv4pwKQJ6uDYXeJDZxeMO2rXk/9sY8rAV20loOnqryfO3IE876H97KyE1LEzrky7mVw3YL/CDlZCO5Sf2IHTmwKylTRlsnUO1I5bviFD3a3EdeIGeDuNbWIqiju2fpMQX4l2gUuY4pysBM28AwbTe3zp348PePFpTcGE0/YwsW/aJit3VOc6xNX9WU="}
|
||||
{"Key":"core/auth","Value":"AAAAAQKy/0yKRpmA5LiZxPlXV+5jBS7lsbsXcACqT/BmXs0nsEP0oHLb4423GWadgYKg1+Vow5qNcLgc6JufLVkEz4dnAcTU1plaCYhRxSGrO/rlAIsKTgwFkKYnV2YRmiSjxKT8hnWw1SHmxappAhZYDMvVVrE9BYGmrCXSmeopjIPLYWgO7UB9/jda7bzMQx9mDVDRUBhRRi4vXUYgo3Dwm1Dznh2yv20ts7O5BVBtpncXB/RovRRhvh2bn/H+RfE0NuZRhQnZ9S6ATF3kGmJX33OiTmBqHBaS8cvPPSZHWmEcXnM8bHEjYxUNZB6+RattgGYVfGtujKWHfwfwJ96VlfIXbQCoZ7bIa1czNa+xhuoOKvaV70crYT4drFnnu4RoV3+HqZl7qsmS8o4MJINoCO6All6GfK7lsRivVzPIZ9M4H6towxfBvEcDvTDHZlL5pOVp7yPP2PSTs0wHM/e9Gg2x9j7nNSDw2KWKTMrxvxHb53dZ3TaaTB388oylLoaNUTG3PlnKAwB4yMp7OpapWH1qX0oo1k3M+XzOX3krHD9UImCTN5DnNZ7jKf8MJ/0aoDi37lNLvQ+0dEXrhsnsRodb2mnCVbp0UhQpPp+Y3yLnB9zBYVAD8Dnt0hOgsxz3WcFOwNX2zeT7OgGnZlTP+NtKKVfXHYjh18JS7mypA7hkh1scBBLqwMyXpzWkKwnBrJYMM1Le1ht2erJvJ4hmLdISidQ8K7ULcS2Gjht+W83ITqC2fO4NIL8QwP9gk6QyIdC8BSHy0mOlZTkT0m5rnVnvl8CV2BbX0lUKTFSmEz6Z0L4nS0/obBRIrWgKgDw3jqnq6vcvmIH4xaOTfRWUeNMQiFnXEsj6tZvRSdpYmAv9jDbdWEBCA2gFkA8wxZ+MSgRIZE8ETUt//5gcvbLncBadS+d7DcqicXUje6jHCQbPg/j9zK38/cKGIszbqVavb89tf0PEQDJB4HOPiPs5kij3T8GtxgFW1DiT23TvtubQF0XsMnv9N3avwTeJoVtBwMTrO1mIam5EHqmvtftnTQycPg9MURmw54fpUevv/Og="}
|
||||
|
@ -1 +1 @@
|
||||
{"Key":"core/mounts","Value":"AAAAAQLyZ1sJsIcAqhtCBFotH08os+J6UEjDnte1gzUp8md8RNH2LFTBe+8iwqSjgpJCyQPYXxDb7l5S4YG8ypUAk5yZA/CaC5y2idWXBrvzihCdDgOv+xLB17mGRuIJdPSdG2TlPY/HJBkadAPOzzD+qFHJKOeH+YOVwBQQP8GA9uLm3DZNHOSej59Y8wN7R9hJX1aXBnkqFhpLdARXqrlSI8SiWz3TNA2vmm4cCzxGcmKEUF3m6peBr47TTnZtcciGI0vd7yIbMeblF93HcrNMcQnKB4ItR8a+yO4WZHg/Y1iWn0JQB0y0FSYg+OFFolsMQpQDDd+YTUpj8zJ2pmlRZ9n19WBHD2VbkzkCyR214+NzCpOfCUsguYdGR34trwU6/4W5ApxtY/+T35vQ+esztU2HgQqJES6s8708Nn589Kvzg/+etbvhfq/DmWOcwZOtb2X/EQHaDmHWzsWqQ26Ux32WiAjedVwoba6vT23MIgUBjdHIKuTlrV6JqNVeuevfmfpBW8y/EhcAm6e2s8jTkdoaSPvq2NaBT9HF6FWJNXhVxAXQlOp7ibx5nk7l312umi2hbZ0+2Ad2wTGCVsECa26ZqXzBbU3uNni4sNdqbTq0i7unpqEQnyfTGcHkxe1uIbT2sK/AydtaOV8IDN4Z0HUBX9tj2UpQr8LX+JW9wX3MIXxQVfogyi/AmQRiDYuPeJyvvTTininGOHLSQyl/jRO/A3SdrTmppcwyNmTS1tzpwDawCP9yLWcw0/QVYgd8wMgmVjKsGuxJqWtEibnEnP9oU8Epi1Zy0OPXLUAT/06R9xtIMRReS2+VhBrFGmkD6eVL6EX0OOZ3yA6CxIft7cHQNishwIGL"}
|
||||
{"Key":"core/mounts","Value":"AAAAAQKEEYCeXSTFocHW81rN1uI6MofozgPy2HnyOaonbuLKzaYM90H7UWfCymZ8sJ/3buSfv8/HNGkrjMHXnwyNbwTZrMt1+3LzSySfrNuq8naoLCbZK0Pn3vJElDnJAej44SBoKrmC04RAj7ROjxB5Eiqe4VJmj2KzjX8pnwKo2cFvetgNiW1a1W9zqqDZX4HRxTCfiS4RwLdkWrUjYvwjX4tQB+GYuixUEWWCsUXSAoIhHx/H7AkmJaJVyrHILjHAcSD8fgxCHwFwf7xaMgQhWqj+ofBYwilgtXkPc/vcmT1pZqw8RgHrfMKTl1gGmuXiiL9/tkWeMs4u9H9+nhLFYy6V2EDFDKPc+zvHg/c4lRUvN0AnX1A050ZJKucYDLq8IxRuBQL4ZZ0syyIVxoA2iJYgIy8dZXHg232LQg5Gicc+sqHKMAJxknkEwl2QBPhcAyGobent4UaAx9b+7LGXhg=="}
|
||||
|
1
src/test/resources/data_dir/core/cluster/local/_info
Normal file
1
src/test/resources/data_dir/core/cluster/local/_info
Normal file
@ -0,0 +1 @@
|
||||
{"Key":"core/cluster/local/info","Value":"AAAAAQLM3HpjYNukfnGPRBV4yhHkaDqTMag0rk3fDmRcUt5pzDH0yh/2ZRuF7czOYsfV6146nxmUfekMrH457GtCMPIppE4x0WkikQRxiA5fSw9lYT8yeErVL1o7ETNo3AHPib2ldxBdX8ik3jY="}
|
@ -0,0 +1 @@
|
||||
{"Key":"logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/complex","Value":"AAAAAQJGyPQ1TFtwJLO5tbYDvnXDxbK0GVxef0qXs4h2ddHTdWFvk+WJWsTw2l+Igr5v5KY5HOQz/apI6Vo2LmwY"}
|
@ -0,0 +1 @@
|
||||
{"Key":"logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/json","Value":"AAAAAQIow6Rc/bPZhf5PDQ3jK/diX99iQZM01NA62tkT0BaKE4UfmSYuYDVUCIrWUOKsVyvD48phL3hEHfgNrJzVsVIk296Br/y7/es9z5zOxe9VATSSJy3CI54AtA=="}
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/expire/id/auth/userpass/login/validUser/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLS9Dgic+3ywWAIR7I3J+9PmdEt81fce3eOTNpcT/TRNDkzD5NY3WEQjBLM7UzxGMg7M88IeGi6L7Rd+ZmoKjL0zogptwvKYggG4P0z+fCQW+/WgpIYEB1187wsF7wh7GQtXTXKE9F/dtKFvfi+3KsZ/0//tXcs9fUqPuJFJSUelcMaIeb2emle4p+kjs0pDuSNzovIGvRToLW4f5TbqVy0ve0zo8r/7IwKlrxo7E2uY0xzJX6IjygIACFm7GjRZgy2rkl0v9Be0T31k/zDWsEPINXu2a+vsYqjZTkRWevrK2ZE8IQBlJcFER5bcnsZiA89wm0VTcwBbYlWJ32IM9AJw/75DGMQ1wbdyJ8PUWvdhyl9i9HahtHWKCo9oH8qTiBjbmkrCECCaUeV1TgpqcqyglxBkgn6Qlb5kgNEHeXxCPy8GarT2gHlmPNaWunnxqE71WuVLZ4+PBlCjmksyXQtdqmDIRE1oSHeuohBQ2dA0B/rDmhLwXBssA+/eQDONLm639VrLJR4IRaNo04PEdxz8pec8W5fG5+Ea3Z171nl3FseZO78i3Wj7Y2KvYFA1XWNlrucxWg0jRI1hDlUHXqLh7nqctdudkI8NrkwbAE6W6a9imMUnTd3yIHN05ke9ihlJrVvAaBbgav4ssz3tnYC/s3TmozGic2TdXGxi9ewMKhdfntXi1VQEJ52i2QmWsnDAUoISHFaK+azNFt7sD5tCKmSIdpS4IL9g6RMH/sVAzuB0ZT+83jYY+jP9L4SajQs4ncWkrMQmJ0fxGs62x6lBxk1LtI2qzV1J57+1QZxFoQc6OQINec3VoQ1t7aFpqYYDk9GKEA/hk8vM5vhwc058RPpjYM8l+3PCPOilMh+FgqOs++8HBTarMTp"}
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/policy/response-wrapping","Value":"AAAAAQI0PU/pu6EEHcT4HwfZjzScyW8DLBzmGDanjLuWqGEtlLcKgRLZh7/c/CRWwbRXy2d3GUB1Bo3YVzpUuDDlNY3NaipcORS3zzCHep5uO/DFUJ3DPSlde8j1BrmSpQDHerAsJYXYEManr93puObYs1cEfP9Mt8WdC/IPhgecSw32tVGBz0SSP2qaXGwdJQva6xroMWqmwMVU/lsVi/qcV459xXiTYU/8Kp6Xbqx0p0SRR0yVdM+yNiMtYtnzoxWdptbSYLTG1mhumA=="}
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/token/accessor/f36b16467afa41b83f8d2f467ce86b0a848aebbf","Value":"AAAAAQKCq6Zqg/q7n6Oi/FfipknrqzI7vYVD9IB+FUuZR56CWUngRRLOs4kLU78vNboCenbYQ3kDYtnxOvUD4xOjNktUzvXoqV0sF0N1p50Mc+MBsR1kzRbbk3nhxocW6lvOmnwLwnE7TtQdEMiU4sHeCoitFgWXfITl2YVxNnY5SXbq4ZSHAVlF"}
|
@ -1 +1 @@
|
||||
{"Key":"sys/token/id/05b3023411dd89a9a27282d57d027f5312be4adc","Value":"AAAAAQIUAO6ILG2gwWjc+J2kp4n03Rp6ycNYAWBYEM0ygocB7DmIT531H5cLbqFVJF5Zw+OQie0HOVLX/zcAPWtxkTOIRXH9FIUT14T9k1IzoxEOYSrbI6ig8bFffe4cd9b0qj9UKgwakQ1GG8vfeSXZnJjVBCSsvWL46s/IGh+SEmirNTiGSE3iy8p3+zunl2s/mUP08i/We03LcLTsCBfSsHVa/CongLNKgSq4oF23LFxv3De+9j8+IQ9HKA0pAatTaCjHdU1TsAiBGsKUhujGW5oQuygkUYVIBFqFqwDOytpdcxiP/A2LAut6qvQjvfT7s7C/Cvke9ypOQAr7iSmUlAhKcXPPEN21NdBmFq4K4w=="}
|
||||
{"Key":"sys/token/id/05b3023411dd89a9a27282d57d027f5312be4adc","Value":"AAAAAQKiu1H1ntud1j4D5e/ZkrSbjuiQgzXK2/b+chRAVynYtfOSrY4pz4BYwZ31OU/VFdsL66Em2FLgGQDVWi6IdM9d3ao7i+EkRf842PAgKrX99coubFB4QBVHqyKhMwfDUmzflirVgSKy4IgKDVKkR08Z6ETHOGBs4Rc9c97pwYsXJP9OE8dSass3jXVLADKCe+MWJeqv1iKTAQSWlWxa75VNXNYiTYcVQ9LYS3egvDeMOqHWBICnoQGnjaHV9Yz/GmCT5YvqwZL+ZOYvy/DwlyFfr6XIWsrbpVOELWU+SPJCvVriE8E67mbDqthh0I1Du3FoE2AJl+5bIEXQIMlezWTLJN7DdnEnTCWssOdEE6LBz8Ue3o2yFe82HS8mucJECOLIjGuEm0aLAXrKzC7RlFOvkl7q0BNu+AQbg5tAe4PUBrFf+cdMdQ81FxNOOAmrjByhnnLCT8ASEd4Ugv3N1PafZtiZQ4ks8U0ppvqdFWgjnlw="}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/token/id/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLf0+mzTh9i2njHeuHQTkC0cDkZGbSHljPETXi4PtH7V1bwuJHi7LLiS3TQNDLl9M/jR6eVK/V374Q+qKdi6sZjVvRKErpbuZhX6YjYy/YNCKs9RJcU21wgXM0emBH6cvrVkzWz7y9UdrTR86e4PU8GrqkbtKUWZ08EcB+jt3mlzkOK+3lRBj9mmDC1McsZ4ALw8Y13Mq6a8xSeSxX4ZJLq4MYfI2GtR3JiEdYdx8gS5YlbbgxTjwxEOUC1mxwDHw+rsguh9eOD6RZaUTvL3MIvQsggoYU9kecvP9jvMnOfhRwd8pT93ilE+MWRylKI8ZOc7K1TMU+qw7Eho5KRKCuR7AXpWrc23SIkkMTDqmaLZiwyM5+fGR1R0c/KpsrzYo5X+TU3SMghlmrQyTHEEU6RGmAOC7RWfFrV1144T390hE9zhbY1zMRmtgBY9qsueXvK3pVaQT83/PswVGR8jliThzXjCsy12BwThBNlZVpEKZK8oI3HRqMk2jpkSpG2cAYiWNnZV9fbipNa92ovGeHHOTM9ZdPpX8apxS47CnMbuwdkNPmCvu+wtRBuGsbmmEwy+F8czMRJuAHu"}
|
21
src/test/resources/tls/ca.pem
Normal file
21
src/test/resources/tls/ca.pem
Normal file
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDfzCCAmegAwIBAgIJAIsdtmg40qeTMA0GCSqGSIb3DQEBDQUAMFYxCzAJBgNV
|
||||
BAYTAkRFMQowCAYDVQQIDAEgMREwDwYDVQQKDAhzdGtsY29kZTENMAsGA1UECwwE
|
||||
VGVzdDEZMBcGA1UEAwwQc3RrbGNvZGUgVGVzdCBDQTAeFw0xNjExMDYxMDM4MDda
|
||||
Fw00NjEwMzAxMDM4MDdaMFYxCzAJBgNVBAYTAkRFMQowCAYDVQQIDAEgMREwDwYD
|
||||
VQQKDAhzdGtsY29kZTENMAsGA1UECwwEVGVzdDEZMBcGA1UEAwwQc3RrbGNvZGUg
|
||||
VGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKIVAIDK++4v
|
||||
mH8/V9fELi3X3Ychgz2WP+dDbXrHsIdkQnmT9sdCfZuLH/0V98XwWQAFHlSfc9GB
|
||||
4NEID31y/f76AcKhuAx4aLebMBp6L4eJssahhxLoKzodFZm9WVIj6g6kXl6Auc9z
|
||||
v9d+DH70PHGtf/ORqnkiuraY5hTzUK7pMrRkL/BFuZyMOtsDsaBWuImZTuf8s2aF
|
||||
URLbD1cnFKn3LbeydlAipA12EXgZ1KhmY8X8BOrDRQlHTIjRjCs0kV3Jc8thi2xt
|
||||
N+Yo/Zm8HqP/fmuszeID0WWgRpmE8RTg8WuoDAJAb600xKEK11qpXkUT3vHiot5N
|
||||
np6HoQXm0HUCAwEAAaNQME4wHQYDVR0OBBYEFFiwMeDNFusyU90UELnglsankCkd
|
||||
MB8GA1UdIwQYMBaAFFiwMeDNFusyU90UELnglsankCkdMAwGA1UdEwQFMAMBAf8w
|
||||
DQYJKoZIhvcNAQENBQADggEBAEwk8fDIo1Wc3EpJKNKjsCZbaiyC8GiiYfuKQVmq
|
||||
82jAacf7MUw8EgpuboDwEbDSIhCeEyM/t8mgttcT/DP0vD3qMhpkNLQcuSK0NFza
|
||||
XvnoPqHMZhxerc7QBMeEKYFRjUd8iPiT3D8rYPdWq8klQnLIPyws2/uyijIXo9k3
|
||||
oiPMBUO+WAe3tLwO9EV6Ff9q5BmlVufngPT1R4wTNR6mZQ3yy8CWPOsk3CBCyleT
|
||||
8maCnFjhJ9fBz74WVgAO7QE72VTwsu9MZ+DawsHt8oKaNU1dfIXfqMHKh3KItn1N
|
||||
cIIlhpnIUtxoWEawH6NbtCoQpTRBSZ8EoBhP4z9jC2+A7i0=
|
||||
-----END CERTIFICATE-----
|
27
src/test/resources/tls/client.key
Normal file
27
src/test/resources/tls/client.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAs+l54Lm03sacNzjlj5V2gUJPJvDQsAKi/O313vbsv4FLxFX8
|
||||
QnGYFKouFAtVW4MTpEN6ciFP6ucwb6YxtoOKIxZ4nqmMDz4R3Q2Spep7Q9I9kISX
|
||||
LMvs92qE1phSqhi6dfH+ZTTPl9HlpWmSWhDReBqfSK1QPJVB1QUrmZA4yCxSfpD6
|
||||
sx0R28sPLuzR/lTiPB2aFst6aM9wG8ZMrl7KYO37W6QH/0p3CfvPdB42b8q5txTG
|
||||
l9Ia++eTcZE69ESyA9LLaPWLfjzGCCW/FbF/zd3WvV8oH7IXqrOfW532Sy6Ui2Id
|
||||
8DmtoNHTulFFKypDe5sF0aFWpkoJsqvaDj/I9wIDAQABAoIBAHXCDBQbeVeXiAhd
|
||||
JWSl37sbO9OxK+cI0sXau2QFG1D9wCnyXfrffzuHaEGWaXhMgz6xLCQnybdnOzzY
|
||||
+xELaA8vViQDtbkEV4zopWQT5jquEb3WC1023RPUlL4hVXogVWt9yZVUy8wDhtyO
|
||||
DU0GVRTX2Aop5qrAxyY3DCKnU4Mw5pZW6tVrALh2W+c/7tlB3mp89uzgRVLsOyP1
|
||||
KoCiIWkb83DT73rTTYg2NOL+69Pp0idtADEE8tuo/3pgcZhAVI9jtisnWg7MsSWu
|
||||
rKkNCS3vOcxAKG9kw3znJfVVH7ZF1LaDVx9LP4inEwVQfg9aImhkjquIgGT0iDgK
|
||||
e62Zx4ECgYEA2YWsXSjRFrscataSM+w71tH4GlE0FAJx5FW+F4YeTfnn+k7FaXuE
|
||||
562737GqsadOXkNiVVgfxsB6snR2WWjxJKuPHGJWncl7yR/MdRmradQGsQYe/xTa
|
||||
AMouZIHp7BWPV/TG6s3x2ezx2GvMhGUnJ43QvTipuJFSDFObgROvz+MCgYEA07yn
|
||||
4PnKXmnIZbhXz9wkvmDpbfPcCrapFmtRXBTK7fbwEA+YPl3xPjkvDX8cQDTsze7h
|
||||
R+o0jMG0VPwmjfECHva5GWemcN5AFMPfuGqik0jacXa81oti0H5L67Z/ffeFxYnD
|
||||
UXukXFInDLT0c8/k1Ex4shwfjiaat030olweBt0CgYEAu5+6ogx/9bxlcZ4tM84z
|
||||
e0NXXtPmONA3Dv4KXl4YK6hAuT5St36MkA3iPLwSAPTP+yziV70Qg64o517fapXD
|
||||
Up8MbS5Big5t0Hi2Mdd3bGwvbWhbOijxNbcvNxB8BmA+aV7AaW5Ei3X+0W+CVDyv
|
||||
/kUr5NtIQeRPQkSnoDmr74MCgYEAyrnqksEXPWZS9PGXQfEpTQ5E8X12xNs28bw2
|
||||
3c8arNSt7PLBdZVEkar2nhmB1wfVYybAk7ZuMgaUvnneADEtMrBPcT+IYLCq8jbI
|
||||
US3oEtTCMbjZ/SDfr3f9AOZvExCXCBdq5u1W5P3TXZs0Il5+XbYKKZ47qELWB4Og
|
||||
IoPITBECgYBvA3+4YL006l/Hkyf21aDiqh3kUAhuPVSXd5ef9EvE2fxMR225jTks
|
||||
URCwYxi/Njg5B2FtuXZjq/eqis/piNtqr3nwZcpiOiwr8J/jwwBXPbtIcE5Nxjzx
|
||||
ag6bkbXe6mpxvHDtroAw84sC0h77ztyJ4Lq/khiEjq+XTPn1iEJ+DQ==
|
||||
-----END RSA PRIVATE KEY-----
|
20
src/test/resources/tls/client.pem
Normal file
20
src/test/resources/tls/client.pem
Normal file
@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDVzCCAj8CCQDn4qCNgPQBezANBgkqhkiG9w0BAQ0FADBWMQswCQYDVQQGEwJE
|
||||
RTEKMAgGA1UECAwBIDERMA8GA1UECgwIc3RrbGNvZGUxDTALBgNVBAsMBFRlc3Qx
|
||||
GTAXBgNVBAMMEHN0a2xjb2RlIFRlc3QgQ0EwHhcNMTYxMTA2MTA0MTQ4WhcNNDEx
|
||||
MDMxMTA0MTQ4WjCBhDELMAkGA1UEBhMCREUxCjAIBgNVBAgMASAxETAPBgNVBAoM
|
||||
CHN0a2xjb2RlMQ0wCwYDVQQLDARUZXN0MSMwIQYDVQQDDBpzdGtsY29kZSBWYXVs
|
||||
dCBUZXN0IENsaWVudDEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBzdGtsY29kZS5k
|
||||
ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPpeeC5tN7GnDc45Y+V
|
||||
doFCTybw0LACovzt9d727L+BS8RV/EJxmBSqLhQLVVuDE6RDenIhT+rnMG+mMbaD
|
||||
iiMWeJ6pjA8+Ed0NkqXqe0PSPZCElyzL7PdqhNaYUqoYunXx/mU0z5fR5aVpkloQ
|
||||
0Xgan0itUDyVQdUFK5mQOMgsUn6Q+rMdEdvLDy7s0f5U4jwdmhbLemjPcBvGTK5e
|
||||
ymDt+1ukB/9Kdwn7z3QeNm/KubcUxpfSGvvnk3GROvREsgPSy2j1i348xgglvxWx
|
||||
f83d1r1fKB+yF6qzn1ud9ksulItiHfA5raDR07pRRSsqQ3ubBdGhVqZKCbKr2g4/
|
||||
yPcCAwEAATANBgkqhkiG9w0BAQ0FAAOCAQEAaW0XEGs8PpHV9dfDD3QERoDpuqsj
|
||||
IkTSO6+e1Ah/Uak6nDPSkAHwS53Avz2SElM3kGa9DVniXOVxC9OjM/E74vncv71w
|
||||
/MLiIS3aXbTgiUmDhuTutBrL9Q3HJGOfO6gqEyQakPfW1NFUFleJKvWKNX0S4eeZ
|
||||
2nXt7da7xaxR6r0L6nwRrWT85ys/jdDgfF0SnmQRmddQttsmRCJ3DXq0z2EeXbO3
|
||||
J8XFF+Y+SyV0CB7bjHx0BXZPaISUMAqnifRqDyw/4G/9iLqFN2Lc0Lxp74w6D/8z
|
||||
OSiHwFvjG1dwEkwnPL9V5vD4/BgeClre4FWqD6wqS3UwLdq6DzEaSNKHJw==
|
||||
-----END CERTIFICATE-----
|
51
src/test/resources/tls/server.key
Normal file
51
src/test/resources/tls/server.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKAIBAAKCAgEA3WItNwzszD4/ok3uydlOa7WCprOX4+4Lui8EscR4d7axWv31
|
||||
A8Vp8GyxASi1MyCIxMeldD/uCzh4EInvuxhfFHr0BjYqHMj4kSf8u5Qo4b7n6A2K
|
||||
rfiVH9qsoz1Cvl4ocLRGKH0JqcWORcKFVWhAhSDKjdu13ckgQxUWC4lNRzjIfMlI
|
||||
F8BLHTivZO/RTcVBlm/ukpVxG8aeaSyD0vGnoiqhkq6L9K8NRQ7H65lwALHtYeOB
|
||||
jEdIJxbMHi+G6Imm4eO88pneC7TIshPYSEMmIhpYYhXIMhyN2V31/ER7gOs4b+Sd
|
||||
ymInjRRH8zTYITIq1wcqbtTIWVqoYqLYAkiLzFVJgEDhOJaCToUv8SU2+bkjhS96
|
||||
e0h/01shcNKBNNO1z7g/gKG0ywwTgSijAENQxW5VmYV5n7ITyZF0mGR35dPszLG+
|
||||
uEpFTt959+WK/VgAUoeYk5gbr025hnD1MMByXkRUMnk2n8Y4ksZ083dtoyeEpgxz
|
||||
gT+kSAvDcjm1x/7GpAqUr5dKaJxmEUKflk+y7swhRJfp8KDgvrW8MhKsHsAEOynI
|
||||
3sehnqb49VZKfYwPgs9gGCDVLnS05CROPy3sPgYEh/N13PMdZq8UOcENnTye3NlA
|
||||
l3nXx0fm6wDwdVclVQq8P4mqGVpHmV0EJcNm9VtVohRZRgPYD7fjTVv5nVcCAwEA
|
||||
AQKCAgBo7xgvd9jmFrti2z3MP0yEkUyUZ5wfVb4JSjAXcuEHHXmDf8ybNP+6Dkr4
|
||||
GauJyGoLm/Y42/ShLOr8K+WN8UdgFceFCjd73Wa0pxeMcfXOywZxX7nULHfC2Yvq
|
||||
9CamxUq14T1AA8SIzDNbrZA1o2yxrZFVHEdgEO1R3rTMUxBmKewd+epKF8OC3lOE
|
||||
rIexLUahX/zdTiiG2eZMQ+VYH2Mt4rcjJ8j++dp4WUE500jbi3rRY10MeN0iahPm
|
||||
WvC/WD/Z4nC1LWmqcs6OWgmyduGkWIh8NYbm+dHirj7ijDNeMCBYKS0BuPS2Ul6o
|
||||
UOwBEB5uPd9HGWS9tdMKrdVlf62DE1IBQT1/Dl5gO6FpPZv+DPDirXjs90thEaUQ
|
||||
rgeGP/FiLwyYppr31rPKVSWZ3at7cxifHsiTBFQDGVOaId1BykBzqiEzi4SYgrSu
|
||||
Bd5hzH/nwjjfmx6MPo/mp/YEIIF1abwUghgwvFeo/NbLIof9/Tj77E3wHuOTdff7
|
||||
xPcM7a+9nqgquJ0OyiqB5qJLnBjqUF1X1jDOR2qS5+Y4E0nVE1bHI30yr/nl3TJT
|
||||
uVK3Ea+y5tMjydX7lzdRUmzuF+dRGrMiwAS9A85oI+oe+BS6LLjD1bLWAPK6kuIf
|
||||
jf9pxtAqOFnfOBF/bVPbS1xBVV224aErZwvNO+66+bkvsvdPgQKCAQEA8kudmJo3
|
||||
EDkK5rTLeeBfke2aLNxkIVSQtGAVh2F2Ra8+HQ5wpoWtm5Rc64G8kviuSZDgyG7Y
|
||||
x/tLPkXpb7kM1m1j6pxIw4163sSZNyKX2qtQZQP62tmxi2sGYwrB3aj7IXtQ7HjI
|
||||
NiEuZS1P9kP5djSBwtM7YDVu1nDc63vQPEOKwpfySxDf8ABSUscsrdl1lzKN+TOu
|
||||
+9uEO8V0RsQETiVkpirGXhrdz0wYViOGqwHNZNwQz99W2mjIrpO8bG94ctw6HJ5x
|
||||
x6P1U2L2GdHwIs9mDO4aUmWOKQ3+bGJ/J4G0Vwx13TR/DUDDPDTuUZhWSsstoB6F
|
||||
ekxKOyFtAtnFWQKCAQEA6efC/CYKEDrFe0MAfmXeDT5cKCrC9erpRukogMm9CvaH
|
||||
2GIdmhuMDbS7mkmOB3UW9SJ0HKQLtArZ2wFtk3CxPUxEGbPkk4HMsMKubwOpG751
|
||||
bSPo8PX7JUwEklPRqKhf0DoCEUjtessRqy/4ea/jiOhLiY+wPc/gLxjQzFMBR8fm
|
||||
mHArMahMa9fEuqwn+xRLcSDAWSb1CLJ4GV6ULupXhI/3l20gJiz6AobyZbHfTnBd
|
||||
nJJQQgvAa0QxAQy4HjQ+AmjedcyQnNfR27TuuCVwkQz4ffG9zHV9kuiYUqJ3nkBD
|
||||
3tYHoWCkRAiLorEuM4M67L3Fi0+durImmJxZ86syLwKCAQAL4PMoAR+D9xf2uZRk
|
||||
NEDbOafeXSu3iprRjQhhK8ENp4rHB+cz8sfRIdPwY9rn5bM9vhGXIgAUxdgphGnu
|
||||
ZUcg2BoW7XSPycblVwQf9N03BkEZwrkws42FxUh54JQilt9BA/eysDU4miXZJgCO
|
||||
lUSMrARUleCKVfRKJRxfmyFZYwJRifuB/KDN9mYS0tr45vlh4UOenQ8OH/P6rjKG
|
||||
KaQAZMrrbpttD6oiOJvU1UcL6Tm1oShd2Jg8evijvnB1bH2eO/fJYWc4n2wum2Jv
|
||||
X6CDRGG/bojx0zLGBn6bt7R+Lli2D9FTd/hmoO8xa3Lnoy1P22gwOm7W0Riuj3P1
|
||||
uNF5AoIBAAlt8Gxd1DYHSILJlrGBxcve4bQ01Rs41yKmr51RhK92dM+CVRMrXSAI
|
||||
Uy/LG1CtpblIJEorStV9Qn8Ttakl998yveQTXnmb1/agQovzJ9QYf39g3TkpkXBV
|
||||
ejGz81XLQ+GPFRpBSGGU4id2jZvKPW/9fV4UTtSPFsiPRYuXJQwRwPgQPY2I7VvD
|
||||
nQixfAMhNFFhMp/ldCdfmnvbVjn19IVBkIeoPI2Nbp6/dfInk4sD+KIhO98NvjoU
|
||||
y6zxKFL/ZCiQtbcmAgZwpOMojh8aU0llrnbVUgN2ERPlEI70QcI9cP8AvdoBnV2o
|
||||
wohSgDxPZAa7N8V/9inamLe6Rd4O3r0CggEBAJAWIm87f+tAI81UYG3ndDXFfy/m
|
||||
uODIRjnXyaPNj+B2+xJ0ygnmrSZo/7lZUCcU2ixCqx3HMwkWhOciOrpQ2i2yrY66
|
||||
db1/F/4RYanCpMp1b3OQxLk4VluketpCsZTR8ZJNKbBx5kCwFO6CYfvgeo7xO5b0
|
||||
2x3mt/QX+Ch9l+84TamClUdQsN0toMLQT821gLes7zgw2Rn3gWoN335dvKtVtyRC
|
||||
pZpLDm44vd+85piF2VOdr7r6RsmAylpKRvleyD3Q7kDI2PpIlb16zPt6BA5VjSjo
|
||||
U9UWQ4g4V0wum1KJiKYmumartgP9TGoql6zVAJxlcRdB3l2IaFPdizu7K1E=
|
||||
-----END RSA PRIVATE KEY-----
|
25
src/test/resources/tls/server.pem
Normal file
25
src/test/resources/tls/server.pem
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEMTCCAxkCCQDn4qCNgPQBejANBgkqhkiG9w0BAQ0FADBWMQswCQYDVQQGEwJE
|
||||
RTEKMAgGA1UECAwBIDERMA8GA1UECgwIc3RrbGNvZGUxDTALBgNVBAsMBFRlc3Qx
|
||||
GTAXBgNVBAMMEHN0a2xjb2RlIFRlc3QgQ0EwHhcNMTYxMTA2MTAzODQxWhcNNDEx
|
||||
MDMxMTAzODQxWjBfMQswCQYDVQQGEwJERTEKMAgGA1UECAwBIDERMA8GA1UECgwI
|
||||
c3RrbGNvZGUxHTAbBgNVBAsMFFZhdWx0IENvbm5lY3RvciBUZXN0MRIwEAYDVQQD
|
||||
DAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDdYi03
|
||||
DOzMPj+iTe7J2U5rtYKms5fj7gu6LwSxxHh3trFa/fUDxWnwbLEBKLUzIIjEx6V0
|
||||
P+4LOHgQie+7GF8UevQGNiocyPiRJ/y7lCjhvufoDYqt+JUf2qyjPUK+XihwtEYo
|
||||
fQmpxY5FwoVVaECFIMqN27XdySBDFRYLiU1HOMh8yUgXwEsdOK9k79FNxUGWb+6S
|
||||
lXEbxp5pLIPS8aeiKqGSrov0rw1FDsfrmXAAse1h44GMR0gnFsweL4boiabh47zy
|
||||
md4LtMiyE9hIQyYiGlhiFcgyHI3ZXfX8RHuA6zhv5J3KYieNFEfzNNghMirXBypu
|
||||
1MhZWqhiotgCSIvMVUmAQOE4loJOhS/xJTb5uSOFL3p7SH/TWyFw0oE007XPuD+A
|
||||
obTLDBOBKKMAQ1DFblWZhXmfshPJkXSYZHfl0+zMsb64SkVO33n35Yr9WABSh5iT
|
||||
mBuvTbmGcPUwwHJeRFQyeTafxjiSxnTzd22jJ4SmDHOBP6RIC8NyObXH/sakCpSv
|
||||
l0ponGYRQp+WT7LuzCFEl+nwoOC+tbwyEqwewAQ7Kcjex6Gepvj1Vkp9jA+Cz2AY
|
||||
INUudLTkJE4/Lew+BgSH83Xc8x1mrxQ5wQ2dPJ7c2UCXedfHR+brAPB1VyVVCrw/
|
||||
iaoZWkeZXQQlw2b1W1WiFFlGA9gPt+NNW/mdVwIDAQABMA0GCSqGSIb3DQEBDQUA
|
||||
A4IBAQA4nrZlyoN/iyRDWZqudXyedMRVUquekzvkcPndInAaW2ukOl+LMGdN7C5n
|
||||
wjglyg5DV0aDNy+Mpy/rInC4kZ5UDKfHjYg4Q9x6kdZOch9gJ6Qvq7hhP8hLUcta
|
||||
pi/m3+k+PP/X6V1oSLxTl/Ja6peDvK1eo5imAbyEPz0kQNHZ88BxEAWGaQgNbItM
|
||||
SC7xmrO78o832d07KF8fJL+o35KV0EuHKMnvr2TLv09kL61EKRRiEMxb6x/90Jw8
|
||||
Rys/FnZh+N0Xdk8sfpq6itGnaDqZSBw0EPhBDXcX9bNpztm8JIIZv101H208BfYG
|
||||
GyJ1DYEp2FfyLgVcY9hNi6P0tmzn
|
||||
-----END CERTIFICATE-----
|
Reference in New Issue
Block a user