Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/target/
|
||||
/*.iml
|
||||
/.idea/
|
||||
/*.project
|
||||
*~
|
13
.travis.yml
Normal file
13
.travis.yml
Normal file
@ -0,0 +1,13 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
dist: trusty
|
||||
env:
|
||||
- PATH=$PATH:.
|
||||
before_script:
|
||||
- wget https://releases.hashicorp.com/vault/0.7.3/vault_0.7.3_linux_amd64.zip
|
||||
- unzip vault_0.7.3_linux_amd64.zip
|
||||
- rm vault_0.7.3_linux_amd64.zip
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,6 +1,26 @@
|
||||
## 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 testet for secret leaks
|
||||
* [test] StackTraces tested for secret leaks
|
||||
* [test] Tested against Vault 0.6.4
|
||||
|
||||
## 0.4.0 [2016-11-06]
|
||||
|
103
README.md
103
README.md
@ -1,12 +1,19 @@
|
||||
Java Vault Connector
|
||||
=========
|
||||
# Java Vault Connector
|
||||
|
||||
[](https://travis-ci.org/stklcode/jvaultconnector)
|
||||
[](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
|
||||
* Ability to provide or enforce custom CA certificate
|
||||
* Authorization methods:
|
||||
* Optional initialization from environment variables
|
||||
* Authorization methods
|
||||
* Token
|
||||
* Username/Password
|
||||
* AppID (register and authenticate) [_deprecated_]
|
||||
@ -21,46 +28,104 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
||||
* Delete secrets
|
||||
* Renew/revoke leases
|
||||
* Raw secret content or JSON decoding
|
||||
* SQL secret handling
|
||||
* Connector Factory with builder pattern
|
||||
* Tested against Vault 0.6.4
|
||||
* Tested against Vault 0.7.3
|
||||
|
||||
**Usage Example**
|
||||
|
||||
## Maven Artifact
|
||||
```
|
||||
<dependency>
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.6.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()
|
||||
.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.4.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 |
35
pom.xml
35
pom.xml
@ -2,11 +2,23 @@
|
||||
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.4.1</version>
|
||||
<version>0.6.1</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>
|
||||
@ -17,7 +29,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
@ -25,28 +37,27 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.4.5</version>
|
||||
<version>4.4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.2</version>
|
||||
<version>4.5.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -61,5 +72,11 @@
|
||||
<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>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,6 +23,7 @@ import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
@ -37,7 +38,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Vault Connector implementatin using Vault's HTTP API.
|
||||
*
|
||||
@ -58,13 +58,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
private static final String PATH_AUTH_USERPASS = "auth/userpass/login/";
|
||||
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
||||
private static final String PATH_AUTH_APPROLE = "auth/approle/";
|
||||
private static final String PATH_SECRET = "secret";
|
||||
private static final String PATH_REVOKE = "sys/revoke/";
|
||||
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
private final String baseURL; /* Base URL of Vault */
|
||||
private final SSLContext sslContext; /* Custom SSLSocketFactory */
|
||||
private final int retries; /* Number of retries on 5xx errors */
|
||||
private final Integer timeout; /* Timeout in milliseconds */
|
||||
|
||||
private boolean authorized = false; /* authorization status */
|
||||
private String token; /* current token */
|
||||
@ -76,7 +77,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
*/
|
||||
public HTTPVaultConnector(String hostname, boolean useTLS) {
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS) {
|
||||
this(hostname, useTLS, null);
|
||||
}
|
||||
|
||||
@ -87,7 +88,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
*/
|
||||
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port) {
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS, final Integer port) {
|
||||
this(hostname, useTLS, port, PATH_PREFIX);
|
||||
}
|
||||
|
||||
@ -99,11 +100,11 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
*/
|
||||
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix) {
|
||||
this(((useTLS) ? "https" : "http") +
|
||||
"://" + hostname +
|
||||
((port != null) ? ":" + port : "") +
|
||||
prefix);
|
||||
public HTTPVaultConnector(final String hostname, final boolean useTLS, final Integer port, final String prefix) {
|
||||
this(((useTLS) ? "https" : "http")
|
||||
+ "://" + hostname
|
||||
+ ((port != null) ? ":" + port : "")
|
||||
+ prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,12 +116,39 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param sslContext Custom SSL Context
|
||||
*/
|
||||
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix, SSLContext sslContext) {
|
||||
this(((useTLS) ? "https" : "http") +
|
||||
"://" + hostname +
|
||||
((port != null) ? ":" + port : "") +
|
||||
prefix,
|
||||
sslContext);
|
||||
public HTTPVaultConnector(final String hostname,
|
||||
final boolean useTLS,
|
||||
final Integer port,
|
||||
final String prefix,
|
||||
final SSLContext sslContext) {
|
||||
this(hostname, useTLS, port, prefix, sslContext, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema, port, path and trusted certificate.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param sslContext Custom SSL Context
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||
*/
|
||||
public HTTPVaultConnector(final String hostname,
|
||||
final boolean useTLS,
|
||||
final Integer port,
|
||||
final String prefix,
|
||||
final SSLContext sslContext,
|
||||
final int numberOfRetries,
|
||||
final Integer timeout) {
|
||||
this(((useTLS) ? "https" : "http")
|
||||
+ "://" + hostname
|
||||
+ ((port != null) ? ":" + port : "")
|
||||
+ prefix,
|
||||
sslContext,
|
||||
numberOfRetries,
|
||||
timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +156,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
*
|
||||
* @param baseURL The URL
|
||||
*/
|
||||
public HTTPVaultConnector(String baseURL) {
|
||||
public HTTPVaultConnector(final String baseURL) {
|
||||
this(baseURL, null);
|
||||
}
|
||||
|
||||
@ -138,21 +166,49 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param baseURL The URL
|
||||
* @param sslContext Custom SSL Context
|
||||
*/
|
||||
public HTTPVaultConnector(String baseURL, SSLContext sslContext) {
|
||||
public HTTPVaultConnector(final String baseURL, final SSLContext sslContext) {
|
||||
this(baseURL, sslContext, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param sslContext Custom SSL Context
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL, final SSLContext sslContext, final int numberOfRetries) {
|
||||
this(baseURL, sslContext, numberOfRetries, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param sslContext Custom SSL Context
|
||||
* @param numberOfRetries Number of retries on 5xx errors
|
||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||
*/
|
||||
public HTTPVaultConnector(final String baseURL,
|
||||
final SSLContext sslContext,
|
||||
final int numberOfRetries,
|
||||
final Integer timeout) {
|
||||
this.baseURL = baseURL;
|
||||
this.sslContext = sslContext;
|
||||
this.retries = numberOfRetries;
|
||||
this.timeout = timeout;
|
||||
this.jsonMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAuth() {
|
||||
public final void resetAuth() {
|
||||
token = null;
|
||||
tokenTTL = 0;
|
||||
authorized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SealResponse sealStatus() {
|
||||
public final SealResponse sealStatus() {
|
||||
try {
|
||||
String response = requestGet(PATH_SEAL_STATUS, new HashMap<>());
|
||||
return jsonMapper.readValue(response, SealResponse.class);
|
||||
@ -166,7 +222,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean seal() {
|
||||
public final boolean seal() {
|
||||
try {
|
||||
requestPut(PATH_SEAL, new HashMap<>());
|
||||
return true;
|
||||
@ -177,7 +233,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SealResponse unseal(final String key, final Boolean reset) {
|
||||
public final SealResponse unseal(final String key, final Boolean reset) {
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("key", key);
|
||||
if (reset != null)
|
||||
@ -192,12 +248,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized() {
|
||||
public final boolean isAuthorized() {
|
||||
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
try {
|
||||
String response = requestGet(PATH_AUTH, new HashMap<>());
|
||||
/* Parse response */
|
||||
@ -212,7 +268,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenResponse authToken(final String token) throws VaultConnectorException {
|
||||
public final TokenResponse authToken(final String token) throws VaultConnectorException {
|
||||
/* set token */
|
||||
this.token = token;
|
||||
this.tokenTTL = 0;
|
||||
@ -227,7 +283,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException {
|
||||
public final AuthResponse authUserPass(final String username, final String password)
|
||||
throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("password", password);
|
||||
return queryAuth(PATH_AUTH_USERPASS + username, payload);
|
||||
@ -235,7 +292,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||
public final AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("app_id", appID);
|
||||
payload.put("user_id", userID);
|
||||
@ -243,7 +300,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
|
||||
public final AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("role_id", roleID);
|
||||
if (secretID != null)
|
||||
@ -252,14 +309,15 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query authorization request to given backend
|
||||
* Query authorization request to given backend.
|
||||
*
|
||||
* @param path The path to request
|
||||
* @param payload Payload (credentials)
|
||||
* @return The AuthResponse
|
||||
* @throws VaultConnectorException on errors
|
||||
*/
|
||||
private AuthResponse queryAuth(final String path, final Map<String, String> payload) throws VaultConnectorException {
|
||||
private AuthResponse queryAuth(final String path, final Map<String, String> payload)
|
||||
throws VaultConnectorException {
|
||||
try {
|
||||
/* Get response */
|
||||
String response = requestPost(path, payload);
|
||||
@ -277,7 +335,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException {
|
||||
public final boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
@ -293,7 +352,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||
public final boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
@ -307,7 +366,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAppRole(final AppRole role) throws VaultConnectorException {
|
||||
public final boolean createAppRole(final AppRole role) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Get response */
|
||||
@ -321,7 +380,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
|
||||
public final AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
@ -337,7 +396,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteAppRole(String roleName) throws VaultConnectorException {
|
||||
public final boolean deleteAppRole(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
@ -352,7 +411,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAppRoleID(final String roleName) throws VaultConnectorException {
|
||||
public final String getAppRoleID(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
@ -368,7 +427,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
public final boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
@ -382,7 +441,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret) throws VaultConnectorException {
|
||||
public final AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Get response */
|
||||
@ -401,12 +461,15 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
public final AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/lookup", new AppRoleSecret(secretID));
|
||||
String response = requestPost(
|
||||
PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/lookup",
|
||||
new AppRoleSecret(secretID));
|
||||
return jsonMapper.readValue(response, AppRoleSecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
@ -414,12 +477,15 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
public final boolean destroyAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/destroy", new AppRoleSecret(secretID));
|
||||
String response = requestPost(
|
||||
PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/destroy",
|
||||
new AppRoleSecret(secretID));
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
@ -429,7 +495,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listAppRoles() throws VaultConnectorException {
|
||||
public final List<String> listAppRoles() throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
@ -446,12 +512,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException {
|
||||
public final List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
try {
|
||||
String response = requestGet(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id?list=true", new HashMap<>());
|
||||
String response = requestGet(
|
||||
PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id?list=true",
|
||||
new HashMap<>());
|
||||
SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
|
||||
return secrets.getKeys();
|
||||
} catch (IOException e) {
|
||||
@ -463,12 +531,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||
public final SecretResponse read(final String key) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestGet(PATH_SECRET + "/" + key, new HashMap<>());
|
||||
String response = requestGet(key, new HashMap<>());
|
||||
return jsonMapper.readValue(response, SecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
@ -479,12 +547,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listSecrets(final String path) throws VaultConnectorException {
|
||||
public final List<String> list(final String path) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
try {
|
||||
String response = requestGet(PATH_SECRET + "/" + path + "/?list=true", new HashMap<>());
|
||||
String response = requestGet(path + "/?list=true", new HashMap<>());
|
||||
SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
|
||||
return secrets.getKeys();
|
||||
} catch (IOException e) {
|
||||
@ -496,26 +564,24 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||
public final void write(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
if (key == null || key.isEmpty())
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("value", value);
|
||||
if (!requestPost(PATH_SECRET + "/" + key, param).equals(""))
|
||||
if (!requestPost(key, data).equals(""))
|
||||
throw new InvalidResponseException("Received response where none was expected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSecret(String key) throws VaultConnectorException {
|
||||
public final void delete(final String key) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestDelete(PATH_SECRET + "/" + key);
|
||||
String response = requestDelete(key);
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
@ -523,7 +589,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revoke(String leaseID) throws VaultConnectorException {
|
||||
public final void revoke(final String leaseID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
@ -536,7 +602,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretResponse renew(String leaseID, Integer increment) throws VaultConnectorException {
|
||||
public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
@ -555,22 +621,29 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token) throws VaultConnectorException {
|
||||
public final AuthResponse createToken(final Token token) throws VaultConnectorException {
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token, boolean orphan) throws VaultConnectorException {
|
||||
public final AuthResponse createToken(final Token token, final boolean orphan) throws VaultConnectorException {
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE_ORPHAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token, final String role) throws VaultConnectorException {
|
||||
public final AuthResponse createToken(final Token token, final String role) throws VaultConnectorException {
|
||||
if (role == null || role.isEmpty())
|
||||
throw new InvalidRequestException("No role name specified.");
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE + "/" + role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void close() {
|
||||
authorized = false;
|
||||
token = null;
|
||||
tokenTTL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
* Centralized method to handle different token creation requests.
|
||||
@ -596,7 +669,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenResponse lookupToken(final String token) throws VaultConnectorException {
|
||||
public final TokenResponse lookupToken(final String token) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
@ -638,7 +711,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
if (token != null)
|
||||
post.addHeader("X-Vault-Token", token);
|
||||
|
||||
return request(post);
|
||||
return request(post, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -665,7 +738,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
if (token != null)
|
||||
put.addHeader("X-Vault-Token", token);
|
||||
|
||||
return request(put);
|
||||
return request(put, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -682,7 +755,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
if (token != null)
|
||||
delete.addHeader("X-Vault-Token", token);
|
||||
|
||||
return request(delete);
|
||||
return request(delete, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,8 +765,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
* @param payload Map of payload values (will be converted to JSON)
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
* @throws URISyntaxException on invalid URI syntax
|
||||
*/
|
||||
private String requestGet(final String path, final Map<String, String> payload) throws VaultConnectorException, URISyntaxException {
|
||||
private String requestGet(final String path, final Map<String, String> payload)
|
||||
throws VaultConnectorException, URISyntaxException {
|
||||
/* Add parameters to URI */
|
||||
URIBuilder uriBuilder = new URIBuilder(baseURL + path);
|
||||
payload.forEach(uriBuilder::addParameter);
|
||||
@ -705,22 +780,27 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
if (token != null)
|
||||
get.addHeader("X-Vault-Token", token);
|
||||
|
||||
return request(get);
|
||||
return request(get, retries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute prepared HTTP request and return result.
|
||||
*
|
||||
* @param base Prepares Request
|
||||
* @param retries number of retries
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
*/
|
||||
private String request(HttpRequestBase base) throws VaultConnectorException {
|
||||
private String request(final HttpRequestBase base, final int retries) throws VaultConnectorException {
|
||||
/* Set JSON Header */
|
||||
base.addHeader("accept", "application/json");
|
||||
|
||||
HttpResponse response = null;
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(sslContext).build()) {
|
||||
/* Set custom timeout, if defined */
|
||||
if (this.timeout != null)
|
||||
base.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(timeout).build());
|
||||
/* Execute request */
|
||||
response = httpClient.execute(base);
|
||||
/* Check if response is valid */
|
||||
if (response == null)
|
||||
@ -728,7 +808,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
switch (response.getStatusLine().getStatusCode()) {
|
||||
case 200:
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(response.getEntity().getContent()))) {
|
||||
return br.lines().collect(Collectors.joining("\n"));
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
@ -737,10 +818,17 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
case 403:
|
||||
throw new PermissionDeniedException();
|
||||
default:
|
||||
if (response.getStatusLine().getStatusCode() >= 500
|
||||
&& response.getStatusLine().getStatusCode() < 600 && retries > 0) {
|
||||
/* Retry on 5xx errors */
|
||||
return request(base, retries - 1);
|
||||
} else {
|
||||
/* Fail on different error code and/or no retries left */
|
||||
InvalidResponseException ex = new InvalidResponseException("Invalid response code")
|
||||
.withStatusCode(response.getStatusLine().getStatusCode());
|
||||
if (response.getEntity() != null) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(response.getEntity().getContent()))) {
|
||||
String responseString = br.lines().collect(Collectors.joining("\n"));
|
||||
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
|
||||
/* Check for "permission denied" response */
|
||||
@ -752,6 +840,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to read response", e);
|
||||
} finally {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -16,13 +16,12 @@
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.AuthorizationRequiredException;
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Vault Connector interface.
|
||||
@ -31,7 +30,9 @@ import java.util.List;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface VaultConnector {
|
||||
public interface VaultConnector extends AutoCloseable {
|
||||
String PATH_SECRET = "secret";
|
||||
|
||||
/**
|
||||
* Reset authorization information.
|
||||
*/
|
||||
@ -143,7 +144,8 @@ public interface VaultConnector {
|
||||
* @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;
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
@ -203,7 +205,8 @@ public interface VaultConnector {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies, final String roleID) throws VaultConnectorException {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -268,7 +271,8 @@ public interface VaultConnector {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
@ -281,7 +285,8 @@ public interface VaultConnector {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret) throws VaultConnectorException;
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
@ -292,7 +297,8 @@ public interface VaultConnector {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
@ -323,13 +329,14 @@ public interface VaultConnector {
|
||||
List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register User-ID with App-ID
|
||||
* Register User-ID with App-ID.
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param userID The User-ID
|
||||
* @return 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 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;
|
||||
@ -346,51 +353,136 @@ public interface VaultConnector {
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException {
|
||||
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
|
||||
* Get authorization status.
|
||||
*
|
||||
* @return TRUE, if successfully authorized
|
||||
*/
|
||||
boolean isAuthorized();
|
||||
|
||||
/**
|
||||
* Retrieve secret form Vault.
|
||||
* Retrieve any nodes content from Vault.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
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
|
||||
*/
|
||||
SecretResponse readSecret(final String key) throws VaultConnectorException;
|
||||
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.
|
||||
* 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
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
void 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
|
||||
*/
|
||||
void deleteSecret(final String key) throws VaultConnectorException;
|
||||
default void deleteSecret(final String key) throws VaultConnectorException {
|
||||
delete(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke given lease immediately.
|
||||
@ -458,4 +550,66 @@ public interface VaultConnector {
|
||||
* @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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,39 +23,80 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class InvalidResponseException extends VaultConnectorException {
|
||||
public final class InvalidResponseException extends VaultConnectorException {
|
||||
private Integer statusCode;
|
||||
private String response;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public InvalidResponseException() {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public InvalidResponseException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public InvalidResponseException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public InvalidResponseException withStatusCode(Integer statusCode) {
|
||||
/**
|
||||
* Specify the HTTP status code. Can be retrieved by {@link #getStatusCode()} later.
|
||||
*
|
||||
* @param statusCode the status code
|
||||
* @return self
|
||||
*/
|
||||
public InvalidResponseException withStatusCode(final Integer statusCode) {
|
||||
this.statusCode = statusCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InvalidResponseException withResponse(String response) {
|
||||
/**
|
||||
* Specify the response string. Can be retrieved by {@link #getResponse()} later.
|
||||
*
|
||||
* @param response response text
|
||||
* @return self
|
||||
*/
|
||||
public InvalidResponseException withResponse(final String response) {
|
||||
this.response = response;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,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);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,29 +23,37 @@ package de.stklcode.jvault.connector.exception;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TlsException extends VaultConnectorException {
|
||||
private Integer statusCode;
|
||||
private String response;
|
||||
|
||||
/**
|
||||
* Constructs a new empty exception.
|
||||
*/
|
||||
public TlsException() {
|
||||
}
|
||||
|
||||
public TlsException(String message) {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public TlsException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TlsException(Throwable cause) {
|
||||
/**
|
||||
* Constructs a new exception with the specified cause.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public TlsException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public TlsException(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 TlsException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public Integer getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -23,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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -17,6 +17,7 @@
|
||||
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;
|
||||
|
||||
@ -25,8 +26,11 @@ 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;
|
||||
@ -38,17 +42,26 @@ import java.security.cert.X509Certificate;
|
||||
* @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.
|
||||
@ -59,43 +72,44 @@ 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)
|
||||
* 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)
|
||||
* 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)
|
||||
* 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)
|
||||
* Convenience Method for TLS usage (enabled by default).
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
@ -104,7 +118,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience Method for NOT using TLS
|
||||
* Convenience Method for NOT using TLS.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
@ -118,7 +132,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @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;
|
||||
}
|
||||
@ -131,7 +145,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException {
|
||||
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||
if (cert != null)
|
||||
return withSslContext(createSslContext(cert));
|
||||
return this;
|
||||
@ -145,14 +159,97 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @return self
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withSslContext(SSLContext sslContext) {
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, sslContext);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,7 +260,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @throws TlsException on errors
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private SSLContext createSslContext(Path trustedCert) throws TlsException {
|
||||
private SSLContext createSslContext(final Path trustedCert) throws TlsException {
|
||||
try {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, createTrustManager(trustedCert), new SecureRandom());
|
||||
@ -181,7 +278,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private TrustManager[] createTrustManager(Path trustedCert) throws TlsException {
|
||||
private TrustManager[] createTrustManager(final Path trustedCert) throws TlsException {
|
||||
try {
|
||||
/* Create Keystore with trusted certificate */
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
@ -204,7 +301,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private X509Certificate certificateFromFile(Path certFile) throws TlsException {
|
||||
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) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -28,7 +28,8 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
*/
|
||||
public abstract class VaultConnectorFactory {
|
||||
/**
|
||||
* Get Factory implementation for HTTP Vault Connector
|
||||
* Get Factory implementation for HTTP Vault Connector.
|
||||
*
|
||||
* @return HTTP Connector Factory
|
||||
*/
|
||||
public static HTTPVaultConnectorFactory httpFactory() {
|
||||
@ -37,7 +38,17 @@ public abstract class VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Build command, produces connector after initialization.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -17,7 +17,6 @@
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -28,7 +27,7 @@ import java.util.List;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRole {
|
||||
public final class AppRole {
|
||||
@JsonProperty("role_name")
|
||||
private String name;
|
||||
|
||||
@ -64,11 +63,30 @@ public class AppRole {
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer period;
|
||||
|
||||
/**
|
||||
* Construct empty {@link AppRole} object.
|
||||
*/
|
||||
public AppRole() {
|
||||
|
||||
}
|
||||
|
||||
public AppRole(String name, String id, Boolean bindSecretId, List<String> boundCidrList, List<String> policies, Integer secretIdNumUses, Integer secretIdTtl, Integer tokenTtl, Integer tokenMaxTtl, Integer period) {
|
||||
/**
|
||||
* 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;
|
||||
@ -81,27 +99,45 @@ public class AppRole {
|
||||
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(List<String> boundCidrList) {
|
||||
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() {
|
||||
@ -110,15 +146,24 @@ public class AppRole {
|
||||
return String.join(",", boundCidrList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of policies
|
||||
*/
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policies list of policies
|
||||
*/
|
||||
@JsonSetter("policies")
|
||||
public void setPolicies(List<String> 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() {
|
||||
@ -127,22 +172,37 @@ public class AppRole {
|
||||
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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -25,7 +25,7 @@ import java.util.List;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AppRoleBuilder {
|
||||
public final class AppRoleBuilder {
|
||||
private String name;
|
||||
private String id;
|
||||
private Boolean bindSecretId;
|
||||
@ -37,12 +37,17 @@ public class AppRoleBuilder {
|
||||
private Integer tokenMaxTtl;
|
||||
private Integer period;
|
||||
|
||||
public AppRoleBuilder(String name) {
|
||||
/**
|
||||
* 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)
|
||||
* Add custom role ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
@ -53,7 +58,7 @@ public class AppRoleBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if role is bound to secret ID
|
||||
* Set if role is bound to secret ID.
|
||||
*
|
||||
* @param bindSecretId the display name
|
||||
* @return self
|
||||
@ -108,7 +113,7 @@ public class AppRoleBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies
|
||||
* Add given policies.
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -28,7 +28,7 @@ import java.util.Map;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleSecret {
|
||||
public final class AppRoleSecret {
|
||||
@JsonProperty("secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
@ -57,41 +57,73 @@ public class AppRoleSecret {
|
||||
@JsonProperty(value = "secret_id_ttl", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private Integer ttl;
|
||||
|
||||
/**
|
||||
* Construct empty {@link AppRoleSecret} object.
|
||||
*/
|
||||
public AppRoleSecret() {
|
||||
|
||||
}
|
||||
|
||||
public AppRoleSecret(String id) {
|
||||
/**
|
||||
* Construct {@link AppRoleSecret} with secret ID.
|
||||
*
|
||||
* @param id Secret ID
|
||||
*/
|
||||
public AppRoleSecret(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public AppRoleSecret(String id, Map<String, Object> metadata, List<String> cidrList) {
|
||||
/**
|
||||
* 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(List<String> cidrList) {
|
||||
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())
|
||||
@ -99,22 +131,37 @@ public class AppRoleSecret {
|
||||
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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -31,11 +31,22 @@ public enum AuthBackend {
|
||||
|
||||
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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -30,7 +30,7 @@ import java.util.Map;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Token {
|
||||
public final class Token {
|
||||
@JsonProperty("id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
@ -67,7 +67,28 @@ public class Token {
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean renewable;
|
||||
|
||||
public Token(String id, String displayName, Boolean noParent, Boolean noDefaultPolicy, Integer ttl, Integer numUses, List<String> policies, Map<String, String> meta, 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;
|
||||
@ -79,38 +100,65 @@ public class Token {
|
||||
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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -16,12 +16,7 @@
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A builder for vault tokens.
|
||||
@ -29,7 +24,7 @@ import java.util.Map;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TokenBuilder {
|
||||
public final class TokenBuilder {
|
||||
private String id;
|
||||
private String displayName;
|
||||
private Boolean noParent;
|
||||
@ -41,7 +36,7 @@ public class TokenBuilder {
|
||||
private Boolean renewable;
|
||||
|
||||
/**
|
||||
* Add token ID (optional)
|
||||
* Add token ID. (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
@ -52,7 +47,7 @@ public class TokenBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add display name
|
||||
* Add display name.
|
||||
*
|
||||
* @param displayName the display name
|
||||
* @return self
|
||||
@ -64,6 +59,7 @@ public class TokenBuilder {
|
||||
|
||||
/**
|
||||
* Set desired time to live.
|
||||
*
|
||||
* @param ttl the ttl
|
||||
* @return self
|
||||
*/
|
||||
@ -74,6 +70,7 @@ public class TokenBuilder {
|
||||
|
||||
/**
|
||||
* Set desired number of uses.
|
||||
*
|
||||
* @param numUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
@ -83,7 +80,7 @@ public class TokenBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the token should be created without parent
|
||||
* Set TRUE if the token should be created without parent.
|
||||
*
|
||||
* @param noParent if TRUE, token is created as orphan
|
||||
* @return self
|
||||
@ -145,7 +142,18 @@ public class TokenBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -24,7 +24,6 @@ import de.stklcode.jvault.connector.model.AppRole;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Vault response for AppRole lookup.
|
||||
@ -33,16 +32,18 @@ import java.util.stream.Collectors;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleResponse extends VaultDataResponse {
|
||||
public final class AppRoleResponse extends VaultDataResponse {
|
||||
private AppRole role;
|
||||
|
||||
@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 {
|
||||
/* 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); });
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
@ -50,6 +51,9 @@ public class AppRoleResponse extends VaultDataResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The role
|
||||
*/
|
||||
public AppRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -19,7 +19,6 @@ 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 de.stklcode.jvault.connector.model.AppRoleSecret;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -33,16 +32,18 @@ import java.util.Map;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleSecretResponse extends VaultDataResponse {
|
||||
public final class AppRoleSecretResponse extends VaultDataResponse {
|
||||
private AppRoleSecret secret;
|
||||
|
||||
@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 {
|
||||
/* 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); });
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
@ -50,6 +51,9 @@ public class AppRoleSecretResponse extends VaultDataResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The secret
|
||||
*/
|
||||
public AppRoleSecret getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -32,25 +32,33 @@ import java.util.Map;
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthMethodsResponse extends VaultDataResponse {
|
||||
public final class AuthMethodsResponse extends VaultDataResponse {
|
||||
private Map<String, AuthMethod> supportedMethods;
|
||||
|
||||
/**
|
||||
* Construct empty {@link AuthMethodsResponse} object.
|
||||
*/
|
||||
public AuthMethodsResponse() {
|
||||
this.supportedMethods = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
public void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
for (String path : data.keySet()) {
|
||||
try {
|
||||
this.supportedMethods.put(path, mapper.readValue(mapper.writeValueAsString(data.get(path)), AuthMethod.class));
|
||||
this.supportedMethods.put(
|
||||
path, mapper.readValue(mapper.writeValueAsString(data.get(path)),
|
||||
AuthMethod.class));
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Supported authentication methods
|
||||
*/
|
||||
public Map<String, AuthMethod> getSupportedMethods() {
|
||||
return supportedMethods;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -32,13 +32,19 @@ import java.util.Map;
|
||||
* @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);
|
||||
@ -49,14 +55,20 @@ public class AuthResponse extends VaultDataResponse {
|
||||
}
|
||||
|
||||
@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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -28,10 +28,13 @@ 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;
|
||||
|
||||
/**
|
||||
* @return List of errors
|
||||
*/
|
||||
public List<String> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -26,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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -27,14 +27,17 @@ import java.util.Map;
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class RawDataResponse extends VaultDataResponse {
|
||||
public final class RawDataResponse extends VaultDataResponse {
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) {
|
||||
public void setData(final Map<String, Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw data {@link Map}
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -26,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;
|
||||
|
||||
@ -39,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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -30,19 +30,27 @@ import java.util.Map;
|
||||
* @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) {
|
||||
} 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -21,6 +21,7 @@ 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;
|
||||
|
||||
/**
|
||||
@ -34,7 +35,7 @@ public class SecretResponse extends VaultDataResponse {
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
public final void setData(final Map<String, Object> data) throws InvalidResponseException {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@ -44,7 +45,9 @@ public class SecretResponse extends VaultDataResponse {
|
||||
* @return data map
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
public final Map<String, Object> getData() {
|
||||
if (data == null)
|
||||
return new HashMap<>();
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -55,8 +58,10 @@ public class SecretResponse extends VaultDataResponse {
|
||||
* @return the value or NULL if absent
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return data.get(key);
|
||||
public final Object get(final String key) {
|
||||
if (data == null)
|
||||
return null;
|
||||
return getData().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,28 +69,32 @@ public class SecretResponse extends VaultDataResponse {
|
||||
* Method for backwards compatibility in case of simple secrets.
|
||||
*
|
||||
* @return the value
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
public String getValue() {
|
||||
if (data.get("value") == null)
|
||||
@Deprecated
|
||||
public final String getValue() {
|
||||
if (get("value") == null)
|
||||
return null;
|
||||
return data.get("value").toString();
|
||||
return get("value").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON
|
||||
* 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
|
||||
*/
|
||||
public <T> T getValue(Class<T> type) throws InvalidResponseException {
|
||||
@Deprecated
|
||||
public final <T> T getValue(final Class<T> type) throws InvalidResponseException {
|
||||
return get("value", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON
|
||||
* Get response parsed as JSON.
|
||||
*
|
||||
* @param key the key
|
||||
* @param type Class to parse response
|
||||
@ -94,7 +103,7 @@ public class SecretResponse extends VaultDataResponse {
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public <T> T get(String key, Class<T> type) throws InvalidResponseException {
|
||||
public final <T> T get(final String key, final Class<T> type) throws InvalidResponseException {
|
||||
try {
|
||||
return new ObjectMapper().readValue(get(key).toString(), type);
|
||||
} catch (IOException e) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -32,14 +32,20 @@ import java.util.Map;
|
||||
* @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);
|
||||
@ -49,6 +55,9 @@ public class TokenResponse extends VaultDataResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Token data
|
||||
*/
|
||||
public TokenData getData() {
|
||||
return data;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -41,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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -29,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;
|
||||
|
||||
@ -48,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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
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;
|
||||
@ -28,7 +29,8 @@ import java.util.Map;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
public class AuthMethod {
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AuthMethod {
|
||||
private AuthBackend type;
|
||||
private String rawType;
|
||||
|
||||
@ -38,25 +40,50 @@ public class AuthMethod {
|
||||
@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(String 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -26,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;
|
||||
|
||||
@ -34,7 +34,7 @@ public class TokenData {
|
||||
private Integer creationTime;
|
||||
|
||||
@JsonProperty("creation_ttl")
|
||||
private Integer creatinTtl;
|
||||
private Integer creationTtl;
|
||||
|
||||
@JsonProperty("display_name")
|
||||
private String name;
|
||||
@ -60,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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -696,31 +696,25 @@ public class HTTPVaultConnectorTest {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
|
||||
/* Overwrite token */
|
||||
token = new TokenBuilder()
|
||||
.withId("test-id2")
|
||||
.withDisplayName("test name 3")
|
||||
.withPolicies(Arrays.asList("pol1", "pol2"))
|
||||
.withDefaultPolicy()
|
||||
.withMeta("test", "success")
|
||||
.withMeta("key", "value")
|
||||
.withTtl(1234)
|
||||
.build();
|
||||
try {
|
||||
AuthResponse res = connector.createToken(token);
|
||||
assertThat("Invalid token ID returned.", res.getAuth().getClientToken(), is("test-id2"));
|
||||
assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(3));
|
||||
assertThat("Policies not returned as expected.", res.getAuth().getPolicies(), contains("default", "pol1", "pol2"));
|
||||
assertThat("Old policy not overwritten.", res.getAuth().getPolicies(), not(contains("testpolicy")));
|
||||
assertThat("Metadata not given.", res.getAuth().getMetadata(), is(notNullValue()));
|
||||
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("test"), is("success"));
|
||||
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("key"), is("value"));
|
||||
assertThat("Old metadata not overwritten.", res.getAuth().getMetadata().get("foo"), is(nullValue()));
|
||||
assertThat("TTL not set correctly", res.getAuth().getLeaseDuration(), is(1234));
|
||||
assertThat("Token should be renewable", res.getAuth().isRenewable(), is(true));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
/* Overwrite token should fail as of Vault 0.8.0 */
|
||||
// token = new TokenBuilder()
|
||||
// .withId("test-id2")
|
||||
// .withDisplayName("test name 3")
|
||||
// .withPolicies(Arrays.asList("pol1", "pol2"))
|
||||
// .withDefaultPolicy()
|
||||
// .withMeta("test", "success")
|
||||
// .withMeta("key", "value")
|
||||
// .withTtl(1234)
|
||||
// .build();
|
||||
// try {
|
||||
// connector.createToken(token);
|
||||
// fail("Overwriting token should fail as of Vault 0.8.0");
|
||||
// } catch (VaultConnectorException e) {
|
||||
// assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
// assertThat(((InvalidResponseException)e).getStatusCode(), is(400));
|
||||
// /* Assert that the exception does not reveal token ID */
|
||||
// assertThat(stackTrace(e), not(stringContainsInOrder(token.getId())));
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
@ -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\"");
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
@ -45,7 +45,8 @@ public class TokenBuilderTest {
|
||||
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 = "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";
|
||||
@ -138,11 +139,11 @@ public class TokenBuilderTest {
|
||||
assertThat(token.getPolicies(), hasSize(1));
|
||||
assertThat(token.getPolicies(), contains(POLICY_2));
|
||||
token = new TokenBuilder()
|
||||
.withPolicies(POLICIES)
|
||||
.withPolicy(POLICY_2)
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertThat(token.getPolicies(), hasSize(2));
|
||||
assertThat(token.getPolicies(), contains(POLICY, POLICY_2));
|
||||
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();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* 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.
|
||||
|
Reference in New Issue
Block a user