11 Commits

Author SHA1 Message Date
6b25113b9f Bump version to 0.6.1 2017-08-02 17:50:20 +02:00
63dc329857 Revert Travis test to Vault 0.7,3
Partially reverts e9663ef (commented out), because fixes should be released before 0.8 compatibility is finally required.
2017-08-02 17:46:56 +02:00
42094101a3 Code style
A number of style corrections in main source files.
Trimmed lines to 120 characters, added some spaces and line breaks.
Removed unused imports
2017-08-02 17:46:56 +02:00
259747afae JavaDoc fixes
Added various JavaDoc blocks for public methods in model classes and some minor style corrections.
2017-08-02 17:46:56 +02:00
d7365dcaf1 Fix typo in TokenData.getCreationTtl()
The method getCreatinTtl() has been renamed to getCreatoinTtl(),
2017-08-02 17:46:56 +02:00
c24d1cae0b Fix CredentialsPassword model 2017-08-02 17:46:56 +02:00
af7b99587f Model classes and various method parameters declared final.
As the model classes are not designed for inheritance, they are now explicitly declared final.
Same for various input parameters, as thes should be immutable in most methods.
2017-08-02 17:46:55 +02:00
13c2cce162 Bump Jackson to 2.9.0 2017-07-31 20:46:15 +02:00
e9663ef794 Fix token creation test for compatibiltiy with Vault 0.8.0 (#10)
As of Vault 0.8.0 specifying the same token ID twice is prohibited. Adapted the unit test to match this behavior.
2017-07-31 20:38:54 +02:00
3fd74a7fd2 Jackson dependency Update
Updated Jackson libraries to 2.9.0.pr4 to evaluate compatibility with upcoming release
2017-07-18 11:12:56 +02:00
21943896c7 Test against 0.7.3 2017-06-08 21:18:50 +02:00
37 changed files with 774 additions and 271 deletions

View File

@ -8,6 +8,6 @@ dist: trusty
env: env:
- PATH=$PATH:. - PATH=$PATH:.
before_script: before_script:
- wget https://releases.hashicorp.com/vault/0.7.2/vault_0.7.2_linux_amd64.zip - wget https://releases.hashicorp.com/vault/0.7.3/vault_0.7.3_linux_amd64.zip
- unzip vault_0.7.2_linux_amd64.zip - unzip vault_0.7.3_linux_amd64.zip
- rm vault_0.7.2_linux_amd64.zip - rm vault_0.7.3_linux_amd64.zip

View File

@ -1,3 +1,9 @@
## 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] ## 0.6.0 [2017-05-12]
* [feature] Initialization from environment variables using `fromEnv()` in factory (#8) * [feature] Initialization from environment variables using `fromEnv()` in factory (#8)
* [feature] Automatic authentication with `buildAndAuth()` * [feature] Automatic authentication with `buildAndAuth()`
@ -39,4 +45,4 @@
* [test] Tested against Vault 0.6.0 * [test] Tested against Vault 0.6.0
## 0.1.0 [2016-03-29] ## 0.1.0 [2016-03-29]
* First release * First release

View File

@ -30,7 +30,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
* Raw secret content or JSON decoding * Raw secret content or JSON decoding
* SQL secret handling * SQL secret handling
* Connector Factory with builder pattern * Connector Factory with builder pattern
* Tested against Vault 0.7.2 * Tested against Vault 0.7.3
## Maven Artifact ## Maven Artifact

View File

@ -4,7 +4,7 @@
<groupId>de.stklcode.jvault</groupId> <groupId>de.stklcode.jvault</groupId>
<artifactId>connector</artifactId> <artifactId>connector</artifactId>
<version>0.6.0</version> <version>0.6.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -52,12 +52,12 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
<version>2.8.8</version> <version>2.9.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.8.8.1</version> <version>2.9.0</version>
</dependency> </dependency>
<dependency> <dependency>
@ -75,7 +75,7 @@
<dependency> <dependency>
<groupId>com.github.stefanbirkner</groupId> <groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId> <artifactId>system-rules</artifactId>
<version>1.16.0</version> <version>1.16.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -29,7 +29,6 @@ import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import javax.net.ssl.*; import javax.net.ssl.*;
@ -39,7 +38,6 @@ import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Vault Connector implementatin using Vault's HTTP API. * Vault Connector implementatin using Vault's HTTP API.
* *
@ -79,7 +77,7 @@ public class HTTPVaultConnector implements VaultConnector {
* @param hostname The hostname * @param hostname The hostname
* @param useTLS If TRUE, use HTTPS, otherwise HTTP * @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); this(hostname, useTLS, null);
} }
@ -90,7 +88,7 @@ public class HTTPVaultConnector implements VaultConnector {
* @param useTLS If TRUE, use HTTPS, otherwise HTTP * @param useTLS If TRUE, use HTTPS, otherwise HTTP
* @param port The port * @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); this(hostname, useTLS, port, PATH_PREFIX);
} }
@ -102,11 +100,11 @@ public class HTTPVaultConnector implements VaultConnector {
* @param port The port * @param port The port
* @param prefix HTTP API prefix (default: /v1/) * @param prefix HTTP API prefix (default: /v1/)
*/ */
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix) { public HTTPVaultConnector(final String hostname, final boolean useTLS, final Integer port, final String prefix) {
this(((useTLS) ? "https" : "http") + this(((useTLS) ? "https" : "http")
"://" + hostname + + "://" + hostname
((port != null) ? ":" + port : "") + + ((port != null) ? ":" + port : "")
prefix); + prefix);
} }
/** /**
@ -118,24 +116,36 @@ public class HTTPVaultConnector implements VaultConnector {
* @param prefix HTTP API prefix (default: /v1/) * @param prefix HTTP API prefix (default: /v1/)
* @param sslContext Custom SSL Context * @param sslContext Custom SSL Context
*/ */
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix, SSLContext 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); this(hostname, useTLS, port, prefix, sslContext, 0, null);
} }
/** /**
* Create connector using hostname, schema, port, path and trusted certificate. * Create connector using hostname, schema, port, path and trusted certificate.
* *
* @param hostname The hostname * @param hostname The hostname
* @param useTLS If TRUE, use HTTPS, otherwise HTTP * @param useTLS If TRUE, use HTTPS, otherwise HTTP
* @param port The port * @param port The port
* @param prefix HTTP API prefix (default: /v1/) * @param prefix HTTP API prefix (default: /v1/)
* @param sslContext Custom SSL Context * @param sslContext Custom SSL Context
* @param numberOfRetries Number of retries on 5xx errors
* @param timeout Timeout for HTTP requests (milliseconds)
*/ */
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix, SSLContext sslContext, int numberOfRetries, Integer timeout) { public HTTPVaultConnector(final String hostname,
this(((useTLS) ? "https" : "http") + final boolean useTLS,
"://" + hostname + final Integer port,
((port != null) ? ":" + port : "") + final String prefix,
prefix, final SSLContext sslContext,
final int numberOfRetries,
final Integer timeout) {
this(((useTLS) ? "https" : "http")
+ "://" + hostname
+ ((port != null) ? ":" + port : "")
+ prefix,
sslContext, sslContext,
numberOfRetries, numberOfRetries,
timeout); timeout);
@ -146,7 +156,7 @@ public class HTTPVaultConnector implements VaultConnector {
* *
* @param baseURL The URL * @param baseURL The URL
*/ */
public HTTPVaultConnector(String baseURL) { public HTTPVaultConnector(final String baseURL) {
this(baseURL, null); this(baseURL, null);
} }
@ -156,7 +166,7 @@ public class HTTPVaultConnector implements VaultConnector {
* @param baseURL The URL * @param baseURL The URL
* @param sslContext Custom SSL Context * @param sslContext Custom SSL Context
*/ */
public HTTPVaultConnector(String baseURL, SSLContext sslContext) { public HTTPVaultConnector(final String baseURL, final SSLContext sslContext) {
this(baseURL, sslContext, 0, null); this(baseURL, sslContext, 0, null);
} }
@ -165,9 +175,9 @@ public class HTTPVaultConnector implements VaultConnector {
* *
* @param baseURL The URL * @param baseURL The URL
* @param sslContext Custom SSL Context * @param sslContext Custom SSL Context
* @param numberOfRetries number of retries on 5xx errors * @param numberOfRetries Number of retries on 5xx errors
*/ */
public HTTPVaultConnector(String baseURL, SSLContext sslContext, int numberOfRetries) { public HTTPVaultConnector(final String baseURL, final SSLContext sslContext, final int numberOfRetries) {
this(baseURL, sslContext, numberOfRetries, null); this(baseURL, sslContext, numberOfRetries, null);
} }
@ -176,9 +186,13 @@ public class HTTPVaultConnector implements VaultConnector {
* *
* @param baseURL The URL * @param baseURL The URL
* @param sslContext Custom SSL Context * @param sslContext Custom SSL Context
* @param numberOfRetries number of retries on 5xx errors * @param numberOfRetries Number of retries on 5xx errors
* @param timeout Timeout for HTTP requests (milliseconds)
*/ */
public HTTPVaultConnector(String baseURL, SSLContext sslContext, int numberOfRetries, Integer timeout) { public HTTPVaultConnector(final String baseURL,
final SSLContext sslContext,
final int numberOfRetries,
final Integer timeout) {
this.baseURL = baseURL; this.baseURL = baseURL;
this.sslContext = sslContext; this.sslContext = sslContext;
this.retries = numberOfRetries; this.retries = numberOfRetries;
@ -187,14 +201,14 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public void resetAuth() { public final void resetAuth() {
token = null; token = null;
tokenTTL = 0; tokenTTL = 0;
authorized = false; authorized = false;
} }
@Override @Override
public SealResponse sealStatus() { public final SealResponse sealStatus() {
try { try {
String response = requestGet(PATH_SEAL_STATUS, new HashMap<>()); String response = requestGet(PATH_SEAL_STATUS, new HashMap<>());
return jsonMapper.readValue(response, SealResponse.class); return jsonMapper.readValue(response, SealResponse.class);
@ -208,7 +222,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public boolean seal() { public final boolean seal() {
try { try {
requestPut(PATH_SEAL, new HashMap<>()); requestPut(PATH_SEAL, new HashMap<>());
return true; return true;
@ -219,7 +233,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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<>(); Map<String, String> param = new HashMap<>();
param.put("key", key); param.put("key", key);
if (reset != null) if (reset != null)
@ -234,12 +248,12 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public boolean isAuthorized() { public final boolean isAuthorized() {
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis()); return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
} }
@Override @Override
public List<AuthBackend> getAuthBackends() throws VaultConnectorException { public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
try { try {
String response = requestGet(PATH_AUTH, new HashMap<>()); String response = requestGet(PATH_AUTH, new HashMap<>());
/* Parse response */ /* Parse response */
@ -254,7 +268,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public TokenResponse authToken(final String token) throws VaultConnectorException { public final TokenResponse authToken(final String token) throws VaultConnectorException {
/* set token */ /* set token */
this.token = token; this.token = token;
this.tokenTTL = 0; this.tokenTTL = 0;
@ -269,7 +283,8 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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<>(); final Map<String, String> payload = new HashMap<>();
payload.put("password", password); payload.put("password", password);
return queryAuth(PATH_AUTH_USERPASS + username, payload); return queryAuth(PATH_AUTH_USERPASS + username, payload);
@ -277,7 +292,7 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
@Deprecated @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<>(); final Map<String, String> payload = new HashMap<>();
payload.put("app_id", appID); payload.put("app_id", appID);
payload.put("user_id", userID); payload.put("user_id", userID);
@ -285,7 +300,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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<>(); final Map<String, String> payload = new HashMap<>();
payload.put("role_id", roleID); payload.put("role_id", roleID);
if (secretID != null) if (secretID != null)
@ -294,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 path The path to request
* @param payload Payload (credentials) * @param payload Payload (credentials)
* @return The AuthResponse * @return The AuthResponse
* @throws VaultConnectorException on errors * @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 { try {
/* Get response */ /* Get response */
String response = requestPost(path, payload); String response = requestPost(path, payload);
@ -319,7 +335,8 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
@Deprecated @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
Map<String, String> payload = new HashMap<>(); Map<String, String> payload = new HashMap<>();
@ -335,7 +352,7 @@ public class HTTPVaultConnector implements VaultConnector {
@Override @Override
@Deprecated @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
Map<String, String> payload = new HashMap<>(); Map<String, String> payload = new HashMap<>();
@ -349,7 +366,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public boolean createAppRole(final AppRole role) throws VaultConnectorException { public final boolean createAppRole(final AppRole role) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Get response */ /* Get response */
@ -363,7 +380,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException { public final AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
@ -379,7 +396,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public boolean deleteAppRole(String roleName) throws VaultConnectorException { public final boolean deleteAppRole(final String roleName) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -394,7 +411,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public String getAppRoleID(final String roleName) throws VaultConnectorException { public final String getAppRoleID(final String roleName) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
@ -410,7 +427,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
@ -424,7 +441,8 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Get response */ /* Get response */
@ -443,12 +461,15 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
try { 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); return jsonMapper.readValue(response, AppRoleSecretResponse.class);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidResponseException("Unable to parse response", e); throw new InvalidResponseException("Unable to parse response", e);
@ -456,12 +477,15 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and expect empty result */ /* 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 */ /* Response should be code 204 without content */
if (!response.equals("")) if (!response.equals(""))
@ -471,7 +495,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public List<String> listAppRoles() throws VaultConnectorException { public final List<String> listAppRoles() throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -488,12 +512,14 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException { public final List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
try { 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); SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
return secrets.getKeys(); return secrets.getKeys();
} catch (IOException e) { } catch (IOException e) {
@ -505,7 +531,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public SecretResponse read(final String key) throws VaultConnectorException { public final SecretResponse read(final String key) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
@ -521,7 +547,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public List<String> list(final String path) throws VaultConnectorException { public final List<String> list(final String path) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -537,7 +563,8 @@ public class HTTPVaultConnector implements VaultConnector {
} }
} }
public void write(final String key, final Map<String, Object> data) throws VaultConnectorException { @Override
public final void write(final String key, final Map<String, Object> data) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -549,7 +576,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public void delete(String key) throws VaultConnectorException { public final void delete(final String key) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -562,7 +589,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public void revoke(String leaseID) throws VaultConnectorException { public final void revoke(final String leaseID) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -575,7 +602,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public SecretResponse renew(String leaseID, Integer increment) throws VaultConnectorException { public final SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
@ -594,24 +621,24 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @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); return createTokenInternal(token, PATH_TOKEN + PATH_CREATE);
} }
@Override @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); return createTokenInternal(token, PATH_TOKEN + PATH_CREATE_ORPHAN);
} }
@Override @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()) if (role == null || role.isEmpty())
throw new InvalidRequestException("No role name specified."); throw new InvalidRequestException("No role name specified.");
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE + "/" + role); return createTokenInternal(token, PATH_TOKEN + PATH_CREATE + "/" + role);
} }
@Override @Override
public void close() { public final void close() {
authorized = false; authorized = false;
token = null; token = null;
tokenTTL = 0; tokenTTL = 0;
@ -642,7 +669,7 @@ public class HTTPVaultConnector implements VaultConnector {
} }
@Override @Override
public TokenResponse lookupToken(final String token) throws VaultConnectorException { public final TokenResponse lookupToken(final String token) throws VaultConnectorException {
if (!isAuthorized()) if (!isAuthorized())
throw new AuthorizationRequiredException(); throw new AuthorizationRequiredException();
/* Request HTTP response and parse Secret */ /* Request HTTP response and parse Secret */
@ -738,8 +765,10 @@ public class HTTPVaultConnector implements VaultConnector {
* @param payload Map of payload values (will be converted to JSON) * @param payload Map of payload values (will be converted to JSON)
* @return HTTP response * @return HTTP response
* @throws VaultConnectorException on connection error * @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 */ /* Add parameters to URI */
URIBuilder uriBuilder = new URIBuilder(baseURL + path); URIBuilder uriBuilder = new URIBuilder(baseURL + path);
payload.forEach(uriBuilder::addParameter); payload.forEach(uriBuilder::addParameter);
@ -762,7 +791,7 @@ public class HTTPVaultConnector implements VaultConnector {
* @return HTTP response * @return HTTP response
* @throws VaultConnectorException on connection error * @throws VaultConnectorException on connection error
*/ */
private String request(HttpRequestBase base, int retries) throws VaultConnectorException { private String request(final HttpRequestBase base, final int retries) throws VaultConnectorException {
/* Set JSON Header */ /* Set JSON Header */
base.addHeader("accept", "application/json"); base.addHeader("accept", "application/json");
@ -779,7 +808,8 @@ public class HTTPVaultConnector implements VaultConnector {
switch (response.getStatusLine().getStatusCode()) { switch (response.getStatusLine().getStatusCode()) {
case 200: 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")); return br.lines().collect(Collectors.joining("\n"));
} catch (IOException ignored) { } catch (IOException ignored) {
} }
@ -788,7 +818,8 @@ public class HTTPVaultConnector implements VaultConnector {
case 403: case 403:
throw new PermissionDeniedException(); throw new PermissionDeniedException();
default: default:
if (response.getStatusLine().getStatusCode() >= 500 && response.getStatusLine().getStatusCode() < 600 && retries > 0) { if (response.getStatusLine().getStatusCode() >= 500
&& response.getStatusLine().getStatusCode() < 600 && retries > 0) {
/* Retry on 5xx errors */ /* Retry on 5xx errors */
return request(base, retries - 1); return request(base, retries - 1);
} else { } else {
@ -796,7 +827,8 @@ public class HTTPVaultConnector implements VaultConnector {
InvalidResponseException ex = new InvalidResponseException("Invalid response code") InvalidResponseException ex = new InvalidResponseException("Invalid response code")
.withStatusCode(response.getStatusLine().getStatusCode()); .withStatusCode(response.getStatusLine().getStatusCode());
if (response.getEntity() != null) { 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")); String responseString = br.lines().collect(Collectors.joining("\n"));
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class); ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
/* Check for "permission denied" response */ /* Check for "permission denied" response */

View File

@ -144,7 +144,8 @@ public interface VaultConnector extends AutoCloseable {
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
*/ */
@Deprecated @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. * Register a new AppRole role from given metamodel.
@ -204,7 +205,8 @@ public interface VaultConnector extends AutoCloseable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.4.0 * @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()); return createAppRole(new AppRoleBuilder(roleName).withPolicies(policies).withId(roleID).build());
} }
@ -269,7 +271,8 @@ public interface VaultConnector extends AutoCloseable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.4.0 * @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)); return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
} }
@ -282,7 +285,8 @@ public interface VaultConnector extends AutoCloseable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.4.0 * @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. * Lookup an AppRole secret.
@ -293,7 +297,8 @@ public interface VaultConnector extends AutoCloseable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.4.0 * @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. * Destroy an AppRole secret.
@ -324,13 +329,14 @@ public interface VaultConnector extends AutoCloseable {
List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException; 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 appID The App-ID
* @param userID The User-ID * @param userID The User-ID
* @return TRUE on success * @return TRUE on success
* @throws VaultConnectorException on error * @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 @Deprecated
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException; boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
@ -347,12 +353,15 @@ public interface VaultConnector extends AutoCloseable {
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. * @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
*/ */
@Deprecated @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); return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
} }
/** /**
* Get authorization status * Get authorization status.
* *
* @return TRUE, if successfully authorized * @return TRUE, if successfully authorized
*/ */
@ -543,7 +552,7 @@ public interface VaultConnector extends AutoCloseable {
TokenResponse lookupToken(final String token) throws VaultConnectorException; TokenResponse lookupToken(final String token) throws VaultConnectorException;
/** /**
* Read credentials for MySQL backend at default mount point * Read credentials for MySQL backend at default mount point.
* *
* @param role the role name * @param role the role name
* @return the credentials response * @return the credentials response
@ -555,7 +564,7 @@ public interface VaultConnector extends AutoCloseable {
} }
/** /**
* Read credentials for PostgreSQL backend at default mount point * Read credentials for PostgreSQL backend at default mount point.
* *
* @param role the role name * @param role the role name
* @return the credentials response * @return the credentials response
@ -567,7 +576,7 @@ public interface VaultConnector extends AutoCloseable {
} }
/** /**
* Read credentials for MSSQL backend at default mount point * Read credentials for MSSQL backend at default mount point.
* *
* @param role the role name * @param role the role name
* @return the credentials response * @return the credentials response
@ -579,7 +588,7 @@ public interface VaultConnector extends AutoCloseable {
} }
/** /**
* Read credentials for MSSQL backend at default mount point * Read credentials for MSSQL backend at default mount point.
* *
* @param role the role name * @param role the role name
* @return the credentials response * @return the credentials response
@ -599,7 +608,8 @@ public interface VaultConnector extends AutoCloseable {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.5.0 * @since 0.5.0
*/ */
default CredentialsResponse readDbCredentials(final String role, final String mount) throws VaultConnectorException { default CredentialsResponse readDbCredentials(final String role, final String mount)
throws VaultConnectorException {
return (CredentialsResponse) read(mount + "/creds/" + role); return (CredentialsResponse) read(mount + "/creds/" + role);
} }
} }

View File

@ -19,22 +19,41 @@ package de.stklcode.jvault.connector.exception;
/** /**
* Exception thrown on problems with connection to Vault backend. * Exception thrown on problems with connection to Vault backend.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
public class ConnectionException extends VaultConnectorException { public class ConnectionException extends VaultConnectorException {
/**
* Constructs a new empty exception.
*/
public ConnectionException() { 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); 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); 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); super(message, cause);
} }
} }

View File

@ -23,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
* @since 0.1 * @since 0.1
*/ */
public class InvalidRequestException extends VaultConnectorException { public class InvalidRequestException extends VaultConnectorException {
/**
* Constructs a new empty exception.
*/
public InvalidRequestException() { 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); 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); 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); super(message, cause);
} }
} }

View File

@ -20,42 +20,83 @@ package de.stklcode.jvault.connector.exception;
* Exception thrown when response from vault returned with erroneous status code or payload could not be parsed * Exception thrown when response from vault returned with erroneous status code or payload could not be parsed
* to entity class. * to entity class.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
public class InvalidResponseException extends VaultConnectorException { public final class InvalidResponseException extends VaultConnectorException {
private Integer statusCode; private Integer statusCode;
private String response; private String response;
/**
* Constructs a new empty exception.
*/
public InvalidResponseException() { 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); 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); 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); 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; this.statusCode = statusCode;
return this; 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; this.response = response;
return this; return this;
} }
/**
* Retrieve the HTTP status code.
*
* @return the status code or {@code null} if none specified.
*/
public Integer getStatusCode() { public Integer getStatusCode() {
return statusCode; return statusCode;
} }
/**
* Retrieve the response text.
*
* @return the response text or {@code null} if none specified.
*/
public String getResponse() { public String getResponse() {
return response; return response;
} }

View File

@ -23,19 +23,38 @@ package de.stklcode.jvault.connector.exception;
* @since 0.1 * @since 0.1
*/ */
public class PermissionDeniedException extends VaultConnectorException { public class PermissionDeniedException extends VaultConnectorException {
/**
* Constructs a new empty exception.
*/
public PermissionDeniedException() { public PermissionDeniedException() {
super("Permission denied"); 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); 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); 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); super(message, cause);
} }
} }

View File

@ -23,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
* @since 0.4.0 * @since 0.4.0
*/ */
public class TlsException extends VaultConnectorException { public class TlsException extends VaultConnectorException {
/**
* Constructs a new empty exception.
*/
public TlsException() { 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); 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); 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); super(message, cause);
} }
} }

View File

@ -23,18 +23,37 @@ package de.stklcode.jvault.connector.exception;
* @since 0.1 * @since 0.1
*/ */
public abstract class VaultConnectorException extends Exception { public abstract class VaultConnectorException extends Exception {
/**
* Constructs a new empty exception.
*/
public VaultConnectorException() { 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); 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); 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); super(message, cause);
} }
} }

View File

@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.factory; package de.stklcode.jvault.connector.factory;
import de.stklcode.jvault.connector.HTTPVaultConnector; import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.VaultConnector;
import de.stklcode.jvault.connector.exception.ConnectionException; import de.stklcode.jvault.connector.exception.ConnectionException;
import de.stklcode.jvault.connector.exception.TlsException; import de.stklcode.jvault.connector.exception.TlsException;
import de.stklcode.jvault.connector.exception.VaultConnectorException; import de.stklcode.jvault.connector.exception.VaultConnectorException;
@ -43,7 +42,7 @@ import java.security.cert.X509Certificate;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @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_ADDR = "VAULT_ADDR";
private static final String ENV_VAULT_CACERT = "VAULT_CACERT"; private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
@ -77,40 +76,40 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
} }
/** /**
* Set hostname (default: 127.0.0.1) * Set hostname (default: 127.0.0.1).
* *
* @param host Hostname or IP address * @param host Hostname or IP address
* @return self * @return self
*/ */
public HTTPVaultConnectorFactory withHost(String host) { public HTTPVaultConnectorFactory withHost(final String host) {
this.host = host; this.host = host;
return this; return this;
} }
/** /**
* Set port (default: 8200) * Set port (default: 8200).
* *
* @param port Vault TCP port * @param port Vault TCP port
* @return self * @return self
*/ */
public HTTPVaultConnectorFactory withPort(Integer port) { public HTTPVaultConnectorFactory withPort(final Integer port) {
this.port = port; this.port = port;
return this; return this;
} }
/** /**
* Set TLS usage (default: TRUE) * Set TLS usage (default: TRUE).
* *
* @param useTLS use TLS or not * @param useTLS use TLS or not
* @return self * @return self
*/ */
public HTTPVaultConnectorFactory withTLS(boolean useTLS) { public HTTPVaultConnectorFactory withTLS(final boolean useTLS) {
this.tls = useTLS; this.tls = useTLS;
return this; return this;
} }
/** /**
* Convenience Method for TLS usage (enabled by default) * Convenience Method for TLS usage (enabled by default).
* *
* @return self * @return self
*/ */
@ -119,7 +118,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
} }
/** /**
* Convenience Method for NOT using TLS * Convenience Method for NOT using TLS.
* *
* @return self * @return self
*/ */
@ -133,7 +132,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @param prefix Vault API prefix (default: "/v1/" * @param prefix Vault API prefix (default: "/v1/"
* @return self * @return self
*/ */
public HTTPVaultConnectorFactory withPrefix(String prefix) { public HTTPVaultConnectorFactory withPrefix(final String prefix) {
this.prefix = prefix; this.prefix = prefix;
return this; return this;
} }
@ -146,7 +145,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @throws VaultConnectorException on error * @throws VaultConnectorException on error
* @since 0.4.0 * @since 0.4.0
*/ */
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException { public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
if (cert != null) if (cert != null)
return withSslContext(createSslContext(cert)); return withSslContext(createSslContext(cert));
return this; return this;
@ -160,7 +159,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @return self * @return self
* @since 0.4.0 * @since 0.4.0
*/ */
public HTTPVaultConnectorFactory withSslContext(SSLContext sslContext) { public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
this.sslContext = sslContext; this.sslContext = sslContext;
return this; return this;
} }
@ -172,7 +171,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @return self * @return self
* @since 0.6.0 * @since 0.6.0
*/ */
public HTTPVaultConnectorFactory withToken(String token) throws VaultConnectorException { public HTTPVaultConnectorFactory withToken(final String token) {
this.token = token; this.token = token;
return this; return this;
} }
@ -181,6 +180,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables. * Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
* *
* @return self * @return self
* @throws VaultConnectorException if Vault address from environment variables is malformed
* @since 0.6.0 * @since 0.6.0
*/ */
public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException { public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException {
@ -221,7 +221,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @return self * @return self
* @since 0.6.0 * @since 0.6.0
*/ */
public HTTPVaultConnectorFactory withNumberOfRetries(int numberOfRetries) { public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) {
this.numberOfRetries = numberOfRetries; this.numberOfRetries = numberOfRetries;
return this; return this;
} }
@ -233,7 +233,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @return self * @return self
* @since 0.6.0 * @since 0.6.0
*/ */
public HTTPVaultConnectorFactory withTimeout(int milliseconds) { public HTTPVaultConnectorFactory withTimeout(final int milliseconds) {
this.timeout = milliseconds; this.timeout = milliseconds;
return this; return this;
} }
@ -260,7 +260,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @throws TlsException on errors * @throws TlsException on errors
* @since 0.4.0 * @since 0.4.0
*/ */
private SSLContext createSslContext(Path trustedCert) throws TlsException { private SSLContext createSslContext(final Path trustedCert) throws TlsException {
try { try {
SSLContext context = SSLContext.getInstance("TLS"); SSLContext context = SSLContext.getInstance("TLS");
context.init(null, createTrustManager(trustedCert), new SecureRandom()); context.init(null, createTrustManager(trustedCert), new SecureRandom());
@ -278,7 +278,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @throws TlsException on error * @throws TlsException on error
* @since 0.4.0 * @since 0.4.0
*/ */
private TrustManager[] createTrustManager(Path trustedCert) throws TlsException { private TrustManager[] createTrustManager(final Path trustedCert) throws TlsException {
try { try {
/* Create Keystore with trusted certificate */ /* Create Keystore with trusted certificate */
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
@ -301,7 +301,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
* @throws TlsException on error * @throws TlsException on error
* @since 0.4.0 * @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)) { try (InputStream is = Files.newInputStream(certFile)) {
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is); return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
} catch (IOException | CertificateException e) { } catch (IOException | CertificateException e) {

View File

@ -28,7 +28,7 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException;
*/ */
public abstract class VaultConnectorFactory { public abstract class VaultConnectorFactory {
/** /**
* Get Factory implementation for HTTP Vault Connector * Get Factory implementation for HTTP Vault Connector.
* *
* @return HTTP Connector Factory * @return HTTP Connector Factory
*/ */
@ -47,6 +47,7 @@ public abstract class VaultConnectorFactory {
* Build connector and authenticate with token set in factory or from environment. * Build connector and authenticate with token set in factory or from environment.
* *
* @return Authenticated Vault connector instance. * @return Authenticated Vault connector instance.
* @throws VaultConnectorException if authentication failed
* @since 0.6.0 * @since 0.6.0
*/ */
public abstract VaultConnector buildAndAuth() throws VaultConnectorException; public abstract VaultConnector buildAndAuth() throws VaultConnectorException;

View File

@ -17,7 +17,6 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.List; import java.util.List;
@ -28,7 +27,7 @@ import java.util.List;
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AppRole { public final class AppRole {
@JsonProperty("role_name") @JsonProperty("role_name")
private String name; private String name;
@ -64,11 +63,30 @@ public class AppRole {
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Integer period; private Integer period;
/**
* Construct empty {@link AppRole} object.
*/
public AppRole() { 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.name = name;
this.id = id; this.id = id;
this.bindSecretId = bindSecretId; this.bindSecretId = bindSecretId;
@ -81,27 +99,45 @@ public class AppRole {
this.period = period; this.period = period;
} }
/**
* @return the role name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* @return the role ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* @return bind secret ID
*/
public Boolean getBindSecretId() { public Boolean getBindSecretId() {
return bindSecretId; return bindSecretId;
} }
/**
* @return list of bound CIDR subnets
*/
public List<String> getBoundCidrList() { public List<String> getBoundCidrList() {
return boundCidrList; return boundCidrList;
} }
/**
* @param boundCidrList list of subnets in CIDR notation to bind role to
*/
@JsonSetter("bound_cidr_list") @JsonSetter("bound_cidr_list")
public void setBoundCidrList(List<String> boundCidrList) { public void setBoundCidrList(final List<String> boundCidrList) {
this.boundCidrList = boundCidrList; this.boundCidrList = boundCidrList;
} }
/**
* @return list of subnets in CIDR notation as comma-separated {@link String}
*/
@JsonGetter("bound_cidr_list") @JsonGetter("bound_cidr_list")
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getBoundCidrListString() { public String getBoundCidrListString() {
@ -110,15 +146,24 @@ public class AppRole {
return String.join(",", boundCidrList); return String.join(",", boundCidrList);
} }
/**
* @return list of policies
*/
public List<String> getPolicies() { public List<String> getPolicies() {
return policies; return policies;
} }
/**
* @param policies list of policies
*/
@JsonSetter("policies") @JsonSetter("policies")
public void setPolicies(List<String> policies) { public void setPolicies(final List<String> policies) {
this.policies = policies; this.policies = policies;
} }
/**
* @return list of policies as comma-separated {@link String}
*/
@JsonGetter("policies") @JsonGetter("policies")
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getPoliciesString() { public String getPoliciesString() {
@ -127,22 +172,37 @@ public class AppRole {
return String.join(",", policies); return String.join(",", policies);
} }
/**
* @return maximum number of uses per secret
*/
public Integer getSecretIdNumUses() { public Integer getSecretIdNumUses() {
return secretIdNumUses; return secretIdNumUses;
} }
/**
* @return maximum TTL in seconds for secrets
*/
public Integer getSecretIdTtl() { public Integer getSecretIdTtl() {
return secretIdTtl; return secretIdTtl;
} }
/**
* @return token TTL in seconds
*/
public Integer getTokenTtl() { public Integer getTokenTtl() {
return tokenTtl; return tokenTtl;
} }
/**
* @return maximum token TTL in seconds, including renewals
*/
public Integer getTokenMaxTtl() { public Integer getTokenMaxTtl() {
return tokenMaxTtl; return tokenMaxTtl;
} }
/**
* @return duration in seconds, if specified
*/
public Integer getPeriod() { public Integer getPeriod() {
return period; return period;
} }

View File

@ -25,7 +25,7 @@ import java.util.List;
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
public class AppRoleBuilder { public final class AppRoleBuilder {
private String name; private String name;
private String id; private String id;
private Boolean bindSecretId; private Boolean bindSecretId;
@ -37,12 +37,17 @@ public class AppRoleBuilder {
private Integer tokenMaxTtl; private Integer tokenMaxTtl;
private Integer period; 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; this.name = name;
} }
/** /**
* Add custom role ID (optional) * Add custom role ID. (optional)
* *
* @param id the ID * @param id the ID
* @return self * @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 * @param bindSecretId the display name
* @return self * @return self
@ -108,7 +113,7 @@ public class AppRoleBuilder {
} }
/** /**
* Add given policies * Add given policies.
* *
* @param policies the policies * @param policies the policies
* @return self * @return self

View File

@ -18,7 +18,6 @@ package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.*;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -29,7 +28,7 @@ import java.util.Map;
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AppRoleSecret { public final class AppRoleSecret {
@JsonProperty("secret_id") @JsonProperty("secret_id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private String id; private String id;
@ -58,41 +57,73 @@ public class AppRoleSecret {
@JsonProperty(value = "secret_id_ttl", access = JsonProperty.Access.WRITE_ONLY) @JsonProperty(value = "secret_id_ttl", access = JsonProperty.Access.WRITE_ONLY)
private Integer ttl; private Integer ttl;
/**
* Construct empty {@link AppRoleSecret} object.
*/
public AppRoleSecret() { public AppRoleSecret() {
} }
public AppRoleSecret(String id) { /**
* Construct {@link AppRoleSecret} with secret ID.
*
* @param id Secret ID
*/
public AppRoleSecret(final String id) {
this.id = 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.id = id;
this.metadata = metadata; this.metadata = metadata;
this.cidrList = cidrList; this.cidrList = cidrList;
} }
/**
* @return Secret ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* @return Secret accessor
*/
public String getAccessor() { public String getAccessor() {
return accessor; return accessor;
} }
/**
* @return Secret metadata
*/
public Map<String, Object> getMetadata() { public Map<String, Object> getMetadata() {
return metadata; return metadata;
} }
/**
* @return List of bound subnets in CIDR notation
*/
public List<String> getCidrList() { public List<String> getCidrList() {
return cidrList; return cidrList;
} }
/**
* @param cidrList List of subnets in CIDR notation
*/
@JsonSetter("cidr_list") @JsonSetter("cidr_list")
public void setCidrList(List<String> cidrList) { public void setCidrList(final List<String> cidrList) {
this.cidrList = cidrList; this.cidrList = cidrList;
} }
/**
* @return List of bound subnets in CIDR notation as comma-separated {@link String}
*/
@JsonGetter("cidr_list") @JsonGetter("cidr_list")
public String getCidrListString() { public String getCidrListString() {
if (cidrList == null || cidrList.isEmpty()) if (cidrList == null || cidrList.isEmpty())
@ -100,22 +131,37 @@ public class AppRoleSecret {
return String.join(",", cidrList); return String.join(",", cidrList);
} }
/**
* @return Creation time
*/
public String getCreationTime() { public String getCreationTime() {
return creationTime; return creationTime;
} }
/**
* @return Expiration time
*/
public String getExpirationTime() { public String getExpirationTime() {
return expirationTime; return expirationTime;
} }
/**
* @return Time of last update
*/
public String getLastUpdatedTime() { public String getLastUpdatedTime() {
return lastUpdatedTime; return lastUpdatedTime;
} }
/**
* @return Number of uses
*/
public Integer getNumUses() { public Integer getNumUses() {
return numUses; return numUses;
} }
/**
* @return Time-to-live
*/
public Integer getTtl() { public Integer getTtl() {
return ttl; return ttl;
} }

View File

@ -19,8 +19,8 @@ package de.stklcode.jvault.connector.model;
/** /**
* Currently supported authentication backends. * Currently supported authentication backends.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
public enum AuthBackend { public enum AuthBackend {
TOKEN("token"), TOKEN("token"),
@ -31,11 +31,22 @@ public enum AuthBackend {
private final String type; private final String type;
AuthBackend(String type) { /**
* Construct {@link AuthBackend} of given type.
*
* @param type Backend type
*/
AuthBackend(final String type) {
this.type = 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()) for (AuthBackend v : values())
if (v.type.equalsIgnoreCase(type)) if (v.type.equalsIgnoreCase(type))
return v; return v;

View File

@ -30,7 +30,7 @@ import java.util.Map;
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class Token { public final class Token {
@JsonProperty("id") @JsonProperty("id")
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private String id; private String id;
@ -67,7 +67,28 @@ public class Token {
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean renewable; 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.id = id;
this.displayName = displayName; this.displayName = displayName;
this.ttl = ttl; this.ttl = ttl;
@ -79,38 +100,65 @@ public class Token {
this.renewable = renewable; this.renewable = renewable;
} }
/**
* @return Token ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* @return Token display name
*/
public String getDisplayName() { public String getDisplayName() {
return displayName; return displayName;
} }
/**
* @return Token has no parent
*/
public Boolean getNoParent() { public Boolean getNoParent() {
return noParent; return noParent;
} }
/**
* @return Token has no default policy
*/
public Boolean getNoDefaultPolicy() { public Boolean getNoDefaultPolicy() {
return noDefaultPolicy; return noDefaultPolicy;
} }
/**
* @return Time-to-live in seconds
*/
public Integer getTtl() { public Integer getTtl() {
return ttl; return ttl;
} }
/**
* @return Number of uses
*/
public Integer getNumUses() { public Integer getNumUses() {
return numUses; return numUses;
} }
/**
* @return List of policies
*/
public List<String> getPolicies() { public List<String> getPolicies() {
return policies; return policies;
} }
/**
* @return Metadata
*/
public Map<String, String> getMeta() { public Map<String, String> getMeta() {
return meta; return meta;
} }
/**
* @return Token is renewable
*/
public Boolean isRenewable() { public Boolean isRenewable() {
return renewable; return renewable;
} }

View File

@ -16,17 +16,15 @@
package de.stklcode.jvault.connector.model; package de.stklcode.jvault.connector.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*; import java.util.*;
/** /**
* A builder for vault tokens. * A builder for vault tokens.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
public class TokenBuilder { public final class TokenBuilder {
private String id; private String id;
private String displayName; private String displayName;
private Boolean noParent; private Boolean noParent;
@ -38,7 +36,7 @@ public class TokenBuilder {
private Boolean renewable; private Boolean renewable;
/** /**
* Add token ID (optional) * Add token ID. (optional)
* *
* @param id the ID * @param id the ID
* @return self * @return self
@ -49,7 +47,7 @@ public class TokenBuilder {
} }
/** /**
* Add display name * Add display name.
* *
* @param displayName the display name * @param displayName the display name
* @return self * @return self
@ -61,6 +59,7 @@ public class TokenBuilder {
/** /**
* Set desired time to live. * Set desired time to live.
*
* @param ttl the ttl * @param ttl the ttl
* @return self * @return self
*/ */
@ -71,6 +70,7 @@ public class TokenBuilder {
/** /**
* Set desired number of uses. * Set desired number of uses.
*
* @param numUses the number of uses * @param numUses the number of uses
* @return self * @return self
*/ */
@ -80,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 * @param noParent if TRUE, token is created as orphan
* @return self * @return self
@ -142,7 +142,7 @@ public class TokenBuilder {
} }
/** /**
* Add given policies * Add given policies.
* *
* @param policies the policies * @param policies the policies
* @return self * @return self
@ -153,7 +153,7 @@ public class TokenBuilder {
} }
/** /**
* Add given policies * Add given policies.
* *
* @param policies the policies * @param policies the policies
* @return self * @return self

View File

@ -24,25 +24,26 @@ import de.stklcode.jvault.connector.model.AppRole;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
* Vault response for AppRole lookup. * Vault response for AppRole lookup.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AppRoleResponse extends VaultDataResponse { public final class AppRoleResponse extends VaultDataResponse {
private AppRole role; private AppRole role;
@Override @Override
public void setData(Map<String, Object> data) throws InvalidResponseException { public void setData(final Map<String, Object> data) throws InvalidResponseException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
try { try {
/* null empty strings on list objects */ /* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>(); 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); this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -50,7 +51,10 @@ public class AppRoleResponse extends VaultDataResponse {
} }
} }
/**
* @return The role
*/
public AppRole getRole() { public AppRole getRole() {
return role; return role;
} }
} }

View File

@ -19,7 +19,6 @@ package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException; import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.AppRole;
import de.stklcode.jvault.connector.model.AppRoleSecret; import de.stklcode.jvault.connector.model.AppRoleSecret;
import java.io.IOException; import java.io.IOException;
@ -29,20 +28,22 @@ import java.util.Map;
/** /**
* Vault response for AppRole lookup. * Vault response for AppRole lookup.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AppRoleSecretResponse extends VaultDataResponse { public final class AppRoleSecretResponse extends VaultDataResponse {
private AppRoleSecret secret; private AppRoleSecret secret;
@Override @Override
public void setData(Map<String, Object> data) throws InvalidResponseException { public void setData(final Map<String, Object> data) throws InvalidResponseException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
try { try {
/* null empty strings on list objects */ /* null empty strings on list objects */
Map<String, Object> filteredData = new HashMap<>(); 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); this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -50,7 +51,10 @@ public class AppRoleSecretResponse extends VaultDataResponse {
} }
} }
/**
* @return The secret
*/
public AppRoleSecret getSecret() { public AppRoleSecret getSecret() {
return secret; return secret;
} }
} }

View File

@ -32,25 +32,33 @@ import java.util.Map;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AuthMethodsResponse extends VaultDataResponse { public final class AuthMethodsResponse extends VaultDataResponse {
private Map<String, AuthMethod> supportedMethods; private Map<String, AuthMethod> supportedMethods;
/**
* Construct empty {@link AuthMethodsResponse} object.
*/
public AuthMethodsResponse() { public AuthMethodsResponse() {
this.supportedMethods = new HashMap<>(); this.supportedMethods = new HashMap<>();
} }
@Override @Override
public void setData(Map<String, Object> data) throws InvalidResponseException { public void setData(final Map<String, Object> data) throws InvalidResponseException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
for (String path : data.keySet()) { for (String path : data.keySet()) {
try { 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) { } catch (IOException e) {
throw new InvalidResponseException(); throw new InvalidResponseException();
} }
} }
} }
/**
* @return Supported authentication methods
*/
public Map<String, AuthMethod> getSupportedMethods() { public Map<String, AuthMethod> getSupportedMethods() {
return supportedMethods; return supportedMethods;
} }

View File

@ -28,17 +28,23 @@ import java.util.Map;
/** /**
* Vault response for authentication providing auth info in {@link AuthData} field. * Vault response for authentication providing auth info in {@link AuthData} field.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AuthResponse extends VaultDataResponse { public final class AuthResponse extends VaultDataResponse {
private Map<String, Object> data; private Map<String, Object> data;
private AuthData auth; 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") @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(); ObjectMapper mapper = new ObjectMapper();
try { try {
this.auth = mapper.readValue(mapper.writeValueAsString(auth), AuthData.class); this.auth = mapper.readValue(mapper.writeValueAsString(auth), AuthData.class);
@ -49,14 +55,20 @@ public class AuthResponse extends VaultDataResponse {
} }
@Override @Override
public void setData(Map<String, Object> data) { public void setData(final Map<String, Object> data) {
this.data = data; this.data = data;
} }
/**
* @return Raw data
*/
public Map<String, Object> getData() { public Map<String, Object> getData() {
return data; return data;
} }
/**
* @return Authentication data
*/
public AuthData getAuth() { public AuthData getAuth() {
return auth; return auth;
} }

View File

@ -17,13 +17,6 @@
package de.stklcode.jvault.connector.model.response; package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.TokenData;
import java.io.IOException;
import java.util.Map;
/** /**
* Vault response from credentials lookup. Simple wrapper for data objects containing username and password fields. * Vault response from credentials lookup. Simple wrapper for data objects containing username and password fields.
@ -32,17 +25,25 @@ import java.util.Map;
* @since 0.5.0 * @since 0.5.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CredentialsResponse extends SecretResponse { public final class CredentialsResponse extends SecretResponse {
/**
* @return Username
*/
public String getUsername() { public String getUsername() {
if (get("username") != null) Object username = get("username");
return get("username").toString(); if (username != null)
return username.toString();
return null; return null;
} }
/**
* @return Password
*/
public String getPassword() { public String getPassword() {
if (get("username") != null) Object password = get("password");
return get("username").toString(); if (password != null)
return password.toString();
return null; return null;
} }
} }

View File

@ -28,11 +28,14 @@ import java.util.List;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorResponse implements VaultResponse { public final class ErrorResponse implements VaultResponse {
@JsonProperty("errors") @JsonProperty("errors")
private List<String> errors; private List<String> errors;
public List<String > getErrors() { /**
* @return List of errors
*/
public List<String> getErrors() {
return errors; return errors;
} }
} }

View File

@ -26,11 +26,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class HelpResponse implements VaultResponse { public final class HelpResponse implements VaultResponse {
@JsonProperty("help") @JsonProperty("help")
private String help; private String help;
/**
* @return Help text
*/
public String getHelp() { public String getHelp() {
return help; return help;
} }
} }

View File

@ -27,14 +27,17 @@ import java.util.Map;
* @since 0.4.0 * @since 0.4.0
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class RawDataResponse extends VaultDataResponse { public final class RawDataResponse extends VaultDataResponse {
private Map<String, Object> data; private Map<String, Object> data;
@Override @Override
public void setData(Map<String, Object> data) { public void setData(final Map<String, Object> data) {
this.data = data; this.data = data;
} }
/**
* @return Raw data {@link Map}
*/
public Map<String, Object> getData() { public Map<String, Object> getData() {
return data; return data;
} }

View File

@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SealResponse implements VaultResponse { public final class SealResponse implements VaultResponse {
@JsonProperty("sealed") @JsonProperty("sealed")
private boolean sealed; private boolean sealed;
@ -39,18 +39,30 @@ public class SealResponse implements VaultResponse {
@JsonProperty("progress") @JsonProperty("progress")
private Integer progress; private Integer progress;
/**
* @return Seal status
*/
public boolean isSealed() { public boolean isSealed() {
return sealed; return sealed;
} }
/**
* @return Required threshold of secret shares
*/
public Integer getThreshold() { public Integer getThreshold() {
return threshold; return threshold;
} }
/**
* @return Number of secret shares
*/
public Integer getNumberOfShares() { public Integer getNumberOfShares() {
return numberOfShares; return numberOfShares;
} }
/**
* @return Current unseal progress (remaining required shares)
*/
public Integer getProgress() { public Integer getProgress() {
return progress; return progress;
} }

View File

@ -26,23 +26,31 @@ import java.util.Map;
/** /**
* Vault response for secret list request. * Vault response for secret list request.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SecretListResponse extends VaultDataResponse { public final class SecretListResponse extends VaultDataResponse {
private List<String> keys; 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") @JsonProperty("data")
public void setData(Map<String, Object> data) throws InvalidResponseException { public void setData(final Map<String, Object> data) throws InvalidResponseException {
try { try {
this.keys = (List<String>)data.get("keys"); this.keys = (List<String>) data.get("keys");
} } catch (ClassCastException e) {
catch (ClassCastException e) {
throw new InvalidResponseException("Keys could not be parsed from data.", e); throw new InvalidResponseException("Keys could not be parsed from data.", e);
} }
} }
/**
* @return List of secret keys
*/
public List<String> getKeys() { public List<String> getKeys() {
return keys; return keys;
} }

View File

@ -35,7 +35,7 @@ public class SecretResponse extends VaultDataResponse {
private Map<String, Object> data; private Map<String, Object> data;
@Override @Override
public void setData(Map<String, Object> data) throws InvalidResponseException { public final void setData(final Map<String, Object> data) throws InvalidResponseException {
this.data = data; this.data = data;
} }
@ -45,7 +45,7 @@ public class SecretResponse extends VaultDataResponse {
* @return data map * @return data map
* @since 0.4.0 * @since 0.4.0
*/ */
public Map<String, Object> getData() { public final Map<String, Object> getData() {
if (data == null) if (data == null)
return new HashMap<>(); return new HashMap<>();
return data; return data;
@ -58,7 +58,7 @@ public class SecretResponse extends VaultDataResponse {
* @return the value or NULL if absent * @return the value or NULL if absent
* @since 0.4.0 * @since 0.4.0
*/ */
public Object get(String key) { public final Object get(final String key) {
if (data == null) if (data == null)
return null; return null;
return getData().get(key); return getData().get(key);
@ -72,14 +72,14 @@ public class SecretResponse extends VaultDataResponse {
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0 * @deprecated Deprecated artifact, will be removed at latest at v1.0.0
*/ */
@Deprecated @Deprecated
public String getValue() { public final String getValue() {
if (get("value") == null) if (get("value") == null)
return null; return null;
return get("value").toString(); return get("value").toString();
} }
/** /**
* Get response parsed as JSON * Get response parsed as JSON.
* *
* @param type Class to parse response * @param type Class to parse response
* @param <T> Class to parse response * @param <T> Class to parse response
@ -89,12 +89,12 @@ public class SecretResponse extends VaultDataResponse {
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0 * @deprecated Deprecated artifact, will be removed at latest at v1.0.0
*/ */
@Deprecated @Deprecated
public <T> T getValue(Class<T> type) throws InvalidResponseException { public final <T> T getValue(final Class<T> type) throws InvalidResponseException {
return get("value", type); return get("value", type);
} }
/** /**
* Get response parsed as JSON * Get response parsed as JSON.
* *
* @param key the key * @param key the key
* @param type Class to parse response * @param type Class to parse response
@ -103,11 +103,11 @@ public class SecretResponse extends VaultDataResponse {
* @throws InvalidResponseException on parsing error * @throws InvalidResponseException on parsing error
* @since 0.4.0 * @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 { try {
return new ObjectMapper().readValue(get(key).toString(), type); return new ObjectMapper().readValue(get(key).toString(), type);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage()); throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
} }
} }
} }

View File

@ -28,18 +28,24 @@ import java.util.Map;
/** /**
* Vault response from token lookup providing Token information in {@link TokenData} field. * Vault response from token lookup providing Token information in {@link TokenData} field.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class TokenResponse extends VaultDataResponse { public final class TokenResponse extends VaultDataResponse {
private TokenData data; private TokenData data;
@JsonProperty("auth") @JsonProperty("auth")
private Boolean auth; private Boolean auth;
/**
* Set data. Parses response data map to {@link TokenData}.
*
* @param data Raw response data
* @throws InvalidResponseException on parsing errors
*/
@Override @Override
public void setData(Map<String, Object> data) throws InvalidResponseException { public void setData(final Map<String, Object> data) throws InvalidResponseException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
try { try {
this.data = mapper.readValue(mapper.writeValueAsString(data), TokenData.class); this.data = mapper.readValue(mapper.writeValueAsString(data), TokenData.class);
@ -49,6 +55,9 @@ public class TokenResponse extends VaultDataResponse {
} }
} }
/**
* @return Token data
*/
public TokenData getData() { public TokenData getData() {
return data; return data;
} }

View File

@ -25,8 +25,8 @@ import java.util.Map;
/** /**
* Abstract Vault response with default payload fields. * Abstract Vault response with default payload fields.
* *
* @author Stefan Kalscheuer * @author Stefan Kalscheuer
* @since 0.1 * @since 0.1
*/ */
public abstract class VaultDataResponse implements VaultResponse { public abstract class VaultDataResponse implements VaultResponse {
@JsonProperty("lease_id") @JsonProperty("lease_id")
@ -41,22 +41,40 @@ public abstract class VaultDataResponse implements VaultResponse {
@JsonProperty("warnings") @JsonProperty("warnings")
private List<String> 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") @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; return leaseId;
} }
public boolean isRenewable() { /**
* @return Lease is renewable
*/
public final boolean isRenewable() {
return renewable; return renewable;
} }
public Integer getLeaseDuration() { /**
* @return Lease duration
*/
public final Integer getLeaseDuration() {
return leaseDuration; return leaseDuration;
} }
public List<String> getWarnings() { /**
* @return List of warnings
*/
public final List<String> getWarnings() {
return warnings; return warnings;
} }
} }

View File

@ -29,7 +29,7 @@ import java.util.Map;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AuthData { public final class AuthData {
@JsonProperty("client_token") @JsonProperty("client_token")
private String clientToken; private String clientToken;
@ -48,27 +48,45 @@ public class AuthData {
@JsonProperty("renewable") @JsonProperty("renewable")
private boolean renewable; private boolean renewable;
/**
* @return Client token
*/
public String getClientToken() { public String getClientToken() {
return clientToken; return clientToken;
} }
/**
* @return Token accessor
*/
public String getAccessor() { public String getAccessor() {
return accessor; return accessor;
} }
/**
* @return List of policies
*/
public List<String> getPolicies() { public List<String> getPolicies() {
return policies; return policies;
} }
/**
* @return Metadata
*/
public Map<String, Object> getMetadata() { public Map<String, Object> getMetadata() {
return metadata; return metadata;
} }
/**
* @return Lease duration
*/
public Integer getLeaseDuration() { public Integer getLeaseDuration() {
return leaseDuration; return leaseDuration;
} }
/**
* @return Lease is renewable
*/
public boolean isRenewable() { public boolean isRenewable() {
return renewable; return renewable;
} }
} }

View File

@ -30,7 +30,7 @@ import java.util.Map;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AuthMethod { public final class AuthMethod {
private AuthBackend type; private AuthBackend type;
private String rawType; private String rawType;
@ -43,28 +43,46 @@ public class AuthMethod {
@JsonProperty("local") @JsonProperty("local")
private boolean local; private boolean local;
/**
* @param type Backend type, passed to {@link AuthBackend#forType(String)}
*/
@JsonSetter("type") @JsonSetter("type")
public void setType(String type) { public void setType(final String type) {
this.rawType = type; this.rawType = type;
this.type = AuthBackend.forType(type); this.type = AuthBackend.forType(type);
} }
/**
* @return Backend type
*/
public AuthBackend getType() { public AuthBackend getType() {
return type; return type;
} }
/**
* @return Raw backend type string
*/
public String getRawType() { public String getRawType() {
return rawType; return rawType;
} }
/**
* @return Description
*/
public String getDescription() { public String getDescription() {
return description; return description;
} }
/**
* @return Configuration data
*/
public Map<String, String> getConfig() { public Map<String, String> getConfig() {
return config; return config;
} }
/**
* @return Is local backend
*/
public boolean isLocal() { public boolean isLocal() {
return local; return local;
} }

View File

@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @since 0.1 * @since 0.1
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class TokenData { public final class TokenData {
@JsonProperty("accessor") @JsonProperty("accessor")
private String accessor; private String accessor;
@ -34,7 +34,7 @@ public class TokenData {
private Integer creationTime; private Integer creationTime;
@JsonProperty("creation_ttl") @JsonProperty("creation_ttl")
private Integer creatinTtl; private Integer creationTtl;
@JsonProperty("display_name") @JsonProperty("display_name")
private String name; private String name;
@ -60,47 +60,80 @@ public class TokenData {
@JsonProperty("ttl") @JsonProperty("ttl")
private Integer ttl; private Integer ttl;
/**
* @return Token accessor
*/
public String getAccessor() { public String getAccessor() {
return accessor; return accessor;
} }
/**
* @return Creation time
*/
public Integer getCreationTime() { public Integer getCreationTime() {
return creationTime; return creationTime;
} }
public Integer getCreatinTtl() { /**
return creatinTtl; * @return Creation TTL (in seconds)
*/
public Integer getCreationTtl() {
return creationTtl;
} }
/**
* @return Token name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* @return Token ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* @return Number of uses
*/
public Integer getNumUses() { public Integer getNumUses() {
return numUses; return numUses;
} }
/**
* @return Token is orphan
*/
public boolean isOrphan() { public boolean isOrphan() {
return orphan; return orphan;
} }
/**
* @return Token path
*/
public String getPath() { public String getPath() {
return path; return path;
} }
/**
* @return Token role
*/
public String getRole() { public String getRole() {
return role; return role;
} }
/**
* @return Token TTL (in seconds)
*/
public Integer getTtl() { public Integer getTtl() {
return ttl; return ttl;
} }
/**
* @return Metadata
*/
public String getMeta() { public String getMeta() {
return meta; return meta;
} }
} }

View File

@ -696,31 +696,25 @@ public class HTTPVaultConnectorTest {
fail("Secret written to inaccessible path."); fail("Secret written to inaccessible path.");
} }
/* Overwrite token */ /* Overwrite token should fail as of Vault 0.8.0 */
token = new TokenBuilder() // token = new TokenBuilder()
.withId("test-id2") // .withId("test-id2")
.withDisplayName("test name 3") // .withDisplayName("test name 3")
.withPolicies(Arrays.asList("pol1", "pol2")) // .withPolicies(Arrays.asList("pol1", "pol2"))
.withDefaultPolicy() // .withDefaultPolicy()
.withMeta("test", "success") // .withMeta("test", "success")
.withMeta("key", "value") // .withMeta("key", "value")
.withTtl(1234) // .withTtl(1234)
.build(); // .build();
try { // try {
AuthResponse res = connector.createToken(token); // connector.createToken(token);
assertThat("Invalid token ID returned.", res.getAuth().getClientToken(), is("test-id2")); // fail("Overwriting token should fail as of Vault 0.8.0");
assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(3)); // } catch (VaultConnectorException e) {
assertThat("Policies not returned as expected.", res.getAuth().getPolicies(), contains("default", "pol1", "pol2")); // assertThat(e, is(instanceOf(InvalidResponseException.class)));
assertThat("Old policy not overwritten.", res.getAuth().getPolicies(), not(contains("testpolicy"))); // assertThat(((InvalidResponseException)e).getStatusCode(), is(400));
assertThat("Metadata not given.", res.getAuth().getMetadata(), is(notNullValue())); // /* Assert that the exception does not reveal token ID */
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("test"), is("success")); // assertThat(stackTrace(e), not(stringContainsInOrder(token.getId())));
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.");
}
} }
/** /**