Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
594b80f62b | |||
4bd614a633 | |||
0f6bccff02 | |||
fca6e496d8 | |||
0f5540913a | |||
8129017ad0 | |||
c0ad451134 | |||
5f3e285a8a | |||
107244cb81 | |||
e877d377c0 | |||
a565411b22 | |||
6f13af5c91 | |||
ce2de2df81 | |||
d7e4e7e5be | |||
2f312d3937 | |||
2f5b6d1523 | |||
69874bdceb | |||
8ab9c23605 | |||
324bff7e58 | |||
b036b73e11 | |||
17145e53be | |||
e988833eb9 | |||
ea3b6d50cb | |||
3f7f88e14a | |||
3396693120 | |||
ca51fed145 | |||
9c216dd805 | |||
b98b7ab95c | |||
ecf398c9d0 | |||
a80805a044 | |||
2b2b86023e | |||
3df2293741 | |||
c1a964b0d1 | |||
d2b31122b6 | |||
4adefc2cda | |||
3271e5e513 | |||
40742b00de | |||
c7b4c46ad2 | |||
9618a50646 | |||
53a459eda1 | |||
e99809cd46 | |||
fc493a2e73 | |||
048e4d12b4 | |||
c3ad6b6edd |
12
.travis.yml
Normal file
12
.travis.yml
Normal file
@ -0,0 +1,12 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
env:
|
||||
- PATH=$PATH:.
|
||||
before_script:
|
||||
- wget https://releases.hashicorp.com/vault/0.7.0/vault_0.7.0_linux_amd64.zip
|
||||
- unzip vault_0.7.0_linux_amd64.zip
|
||||
- rm vault_0.7.0_linux_amd64.zip
|
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,3 +1,22 @@
|
||||
## 0.5.0 [2017-03-18]
|
||||
* [feature] Convenience methods for DB credentials (#7)
|
||||
* [fix] Minor bugfix in TokenBuilder
|
||||
* [deprecation] `SecretResponse.getValue()` deprecated
|
||||
* [test] Tested against Vault 0.7.0
|
||||
|
||||
## 0.4.1 [2016-12-24]
|
||||
* [fix] Factory Null-tolerant for trusted certificate (#6)
|
||||
* [test] StackTraces tested for secret leaks
|
||||
* [test] Tested against Vault 0.6.4
|
||||
|
||||
## 0.4.0 [2016-11-06]
|
||||
* [feature] Option to provide a trusted CA certificate (#2)
|
||||
* [feature] Deletion, revocation and renewal of secrets (#3)
|
||||
* [feature] Token creation (#4)
|
||||
* [feature] AppRole auth backend supported (#5)
|
||||
* [improvement] Support for complex secrets
|
||||
* [deprecation] App-ID backend marked as deprecated
|
||||
|
||||
## 0.3.0 [2016-10-07]
|
||||
* [feature] Retrieval of JSON objects (#1)
|
||||
* [test] Tested against Vault 0.6.2
|
||||
|
120
README.md
120
README.md
@ -1,58 +1,124 @@
|
||||
Java Vault Connector
|
||||
=========
|
||||
# Java Vault Connector
|
||||
|
||||
[](https://travis-ci.org/stklcode/jvaultconnector)
|
||||
[](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
|
||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22connector%22)
|
||||
|
||||

|
||||
|
||||
Java Vault Connector is a connector library for [Vault](https://www.vaultproject.io) by [Hashicorp](https://www.hashicorp.com) written in Java. The connector allows simple usage of Vault's secret store in own applications.
|
||||
|
||||
**Current available features:**
|
||||
## Features:
|
||||
|
||||
* HTTP(S) backend connector
|
||||
* Authorization methods:
|
||||
* Ability to provide or enforce custom CA certificate
|
||||
* Authorization methods
|
||||
* Token
|
||||
* Username/Password
|
||||
* AppID (register and authenticate)
|
||||
* AppID (register and authenticate) [_deprecated_]
|
||||
* AppRole (register and authenticate)
|
||||
* Tokens
|
||||
* Creation and lookup of tokens
|
||||
* TokenBuilder for speaking creation of complex configuraitons
|
||||
* Secrets
|
||||
* Read secrets
|
||||
* Write secrets
|
||||
* List secrets
|
||||
* Delete secrets
|
||||
* Renew/revoke leases
|
||||
* Raw secret content or JSON decoding
|
||||
* Connector Factory with builder pattern
|
||||
* Tested against Vault 0.6.2
|
||||
* Tested against Vault 0.7.0
|
||||
|
||||
**Usage Example**
|
||||
|
||||
```java
|
||||
// Instanciate using builder pattern style factory
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.wiithHost("127.0.0.1")
|
||||
.withPort(8200)
|
||||
.withTLS()
|
||||
.build();
|
||||
|
||||
//authenticate with token
|
||||
vault.authToken("01234567-89ab-cdef-0123-456789abcdef");
|
||||
|
||||
// retrieve secret
|
||||
String secret = vault.readSecret("some/secret/key").getValue();
|
||||
```
|
||||
|
||||
**Maven Artifact**
|
||||
## Maven Artifact
|
||||
```
|
||||
<dependency>
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.3.0</version>
|
||||
<version>0.5.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Links**
|
||||
## Usage Examples
|
||||
|
||||
### Initialization
|
||||
|
||||
```java
|
||||
// Instantiate using builder pattern style factory (TLS enabled by default)
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.withHost("127.0.0.1")
|
||||
.withPort(8200)
|
||||
.withTLS()
|
||||
.build();
|
||||
|
||||
// Instantiate with custom SSL context
|
||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||
.withHost("example.com")
|
||||
.withPort(8200)
|
||||
.withTrustedCA(Paths.get("/path/to/CA.pem"))
|
||||
.build();
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```java
|
||||
// Authenticate with token
|
||||
vault.authToken("01234567-89ab-cdef-0123-456789abcdef");
|
||||
|
||||
// Authenticate with username and password
|
||||
vault.authUserPass("username", "p4ssw0rd");
|
||||
|
||||
// Authenticate with AppID (secret - 2nd argument - is optional)
|
||||
vault.authAppId("01234567-89ab-cdef-0123-456789abcdef", "fedcba98-7654-3210-fedc-ba9876543210");
|
||||
```
|
||||
|
||||
### Secret read & write
|
||||
|
||||
```java
|
||||
// Retrieve secret (prefix "secret/" assumed, use read() to read arbitrary paths)
|
||||
String secret = vault.readSecret("some/secret/key").getValue();
|
||||
|
||||
// Complex secret
|
||||
Map<String, Object> secretData = vault.readSecret("another/secret/key").getData();
|
||||
|
||||
// Write simple secret
|
||||
vault.writeSecret("new/secret/key", "secret value");
|
||||
|
||||
// Write complex data to arbitraty path
|
||||
Map<String, Object> map = [...]
|
||||
vault.write("any/path/to/write", map);
|
||||
|
||||
// Delete secret
|
||||
vault.delete("any/path/to/write");
|
||||
```
|
||||
|
||||
### Token and role creation
|
||||
|
||||
```java
|
||||
// Create token using TokenBuilder
|
||||
Token token = new TokenBuilder().withId("token id")
|
||||
.withDisplayName("new test token")
|
||||
.withPolicies("pol1", "pol2")
|
||||
.build();
|
||||
vault.createToken(token);
|
||||
|
||||
// Create AppRole credentials
|
||||
vault.createAppRole("testrole", policyList);
|
||||
AppRoleSecretResponse secret = vault.createAppRoleSecret("testrole");
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
[Project Page](http://jvault.stklcode.de)
|
||||
|
||||
[JavaDoc API](http://jvault.stklcode.de/apidocs/)
|
||||
|
||||
**Planned features:**
|
||||
## Planned features
|
||||
|
||||
* Creation and modification of policies
|
||||
* Implement more authentication methods
|
||||
|
||||
**License**
|
||||
## License
|
||||
|
||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
12
assets/logo.svg
Normal file
12
assets/logo.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128">
|
||||
<path d="M4,12 l60,104 l60,-104 z" stroke="none" fill="#000000" />
|
||||
<circle cx="78" cy="24" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="38" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="52" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="78" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="72" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="58" cy="78" r="6" stroke="none" fill="#00a9c7" />
|
||||
<circle cx="52" cy="66" r="6" stroke="none" fill="#00a9c7" />
|
||||
</svg>
|
After Width: | Height: | Size: 759 B |
29
pom.xml
29
pom.xml
@ -2,11 +2,23 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>jVaultConnector</name>
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.3.0</version>
|
||||
<version>0.5.0</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jVaultConnector</name>
|
||||
<description>Connector artifact for Hashicorp's Vault secret management</description>
|
||||
<url>https://jvault.stklcode.de</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@ -17,7 +29,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
@ -25,28 +37,27 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.4.5</version>
|
||||
<version>4.4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.2</version>
|
||||
<version>4.5.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.8.3</version>
|
||||
<version>2.8.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.3</version>
|
||||
<version>2.8.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -1,26 +1,37 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.*;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
@ -38,16 +49,21 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
private static final String PATH_SEAL_STATUS = "sys/seal-status";
|
||||
private static final String PATH_SEAL = "sys/seal";
|
||||
private static final String PATH_UNSEAL = "sys/unseal";
|
||||
private static final String PATH_INIT = "sys/init";
|
||||
private static final String PATH_RENEW = "sys/renew";
|
||||
private static final String PATH_AUTH = "sys/auth";
|
||||
private static final String PATH_TOKEN_LOOKUP = "auth/token/lookup";
|
||||
private static final String PATH_TOKEN = "auth/token";
|
||||
private static final String PATH_LOOKUP = "/lookup";
|
||||
private static final String PATH_CREATE = "/create";
|
||||
private static final String PATH_CREATE_ORPHAN = "/create-orphan";
|
||||
private static final String PATH_AUTH_USERPASS = "auth/userpass/login/";
|
||||
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
||||
private static final String PATH_SECRET = "secret";
|
||||
private static final String PATH_AUTH_APPROLE = "auth/approle/";
|
||||
private static final String PATH_REVOKE = "sys/revoke/";
|
||||
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
private final String baseURL; /* Base URL of Vault */
|
||||
private final SSLContext sslContext; /* Custom SSLSocketFactory */
|
||||
|
||||
private boolean authorized = false; /* authorization status */
|
||||
private String token; /* current token */
|
||||
@ -55,6 +71,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
/**
|
||||
* Create connector using hostname and schema.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
*/
|
||||
@ -64,6 +81,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schema and port.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
@ -73,11 +91,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using hostname, schame, port and path
|
||||
* Create connector using hostname, schema, port and path.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @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) {
|
||||
this(((useTLS) ? "https" : "http") +
|
||||
@ -87,11 +106,40 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL
|
||||
* Create connector using hostname, schema, port, path and trusted certificate.
|
||||
*
|
||||
* @param hostname The hostname
|
||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||
* @param port The port
|
||||
* @param prefix HTTP API prefix (default: /v1/)
|
||||
* @param sslContext Custom SSL Context
|
||||
*/
|
||||
public HTTPVaultConnector(String hostname, boolean useTLS, Integer port, String prefix, SSLContext sslContext) {
|
||||
this(((useTLS) ? "https" : "http") +
|
||||
"://" + hostname +
|
||||
((port != null) ? ":" + port : "") +
|
||||
prefix,
|
||||
sslContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
*/
|
||||
public HTTPVaultConnector(String baseURL) {
|
||||
this(baseURL, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connector using full URL and trusted certificate.
|
||||
*
|
||||
* @param baseURL The URL
|
||||
* @param sslContext Custom SSL Context
|
||||
*/
|
||||
public HTTPVaultConnector(String baseURL, SSLContext sslContext) {
|
||||
this.baseURL = baseURL;
|
||||
this.sslContext = sslContext;
|
||||
this.jsonMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@ -147,12 +195,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean init() {
|
||||
/* TODO: implement init() */
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
try {
|
||||
@ -174,7 +216,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
this.token = token;
|
||||
this.tokenTTL = 0;
|
||||
try {
|
||||
String response = requestPost(PATH_TOKEN_LOOKUP, new HashMap<>());
|
||||
String response = requestPost(PATH_TOKEN + PATH_LOOKUP, new HashMap<>());
|
||||
TokenResponse res = jsonMapper.readValue(response, TokenResponse.class);
|
||||
authorized = true;
|
||||
return res;
|
||||
@ -185,31 +227,41 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
@Override
|
||||
public AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException {
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("password", password);
|
||||
try {
|
||||
/* Get response */
|
||||
String response = requestPost(PATH_AUTH_USERPASS + username, payload);
|
||||
/* Parse response */
|
||||
AuthResponse upr = jsonMapper.readValue(response, AuthResponse.class);
|
||||
/* verify response */
|
||||
this.token = upr.getAuth().getClientToken();
|
||||
this.tokenTTL = System.currentTimeMillis() + upr.getAuth().getLeaseDuration() * 1000L;
|
||||
this.authorized = true;
|
||||
return upr;
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
}
|
||||
return queryAuth(PATH_AUTH_USERPASS + username, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("app_id", appID);
|
||||
payload.put("user_id", userID);
|
||||
return queryAuth(PATH_AUTH_APPID + "login", payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException {
|
||||
final Map<String, String> payload = new HashMap<>();
|
||||
payload.put("role_id", roleID);
|
||||
if (secretID != null)
|
||||
payload.put("secret_id", secretID);
|
||||
return queryAuth(PATH_AUTH_APPROLE + "login", payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query authorization request to given backend
|
||||
*
|
||||
* @param path The path to request
|
||||
* @param payload Payload (credentials)
|
||||
* @return The AuthResponse
|
||||
* @throws VaultConnectorException on errors
|
||||
*/
|
||||
private AuthResponse queryAuth(final String path, final Map<String, String> payload) throws VaultConnectorException {
|
||||
try {
|
||||
/* Get response */
|
||||
String response = requestPost(PATH_AUTH_APPID + "login", payload);
|
||||
String response = requestPost(path, payload);
|
||||
/* Parse response */
|
||||
AuthResponse auth = jsonMapper.readValue(response, AuthResponse.class);
|
||||
/* verify response */
|
||||
@ -223,6 +275,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
@ -238,6 +291,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
@ -252,13 +306,27 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||
public boolean createAppRole(final AppRole role) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Get response */
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + role.getName(), role);
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where non was expected.");
|
||||
|
||||
/* Set custom ID if provided */
|
||||
return !(role.getId() != null && !role.getId().isEmpty()) || setAppRoleID(role.getName(), role.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestGet(PATH_SECRET + "/" + key, new HashMap<>());
|
||||
return jsonMapper.readValue(response, SecretResponse.class);
|
||||
String response = requestGet(PATH_AUTH_APPROLE + "role/" + roleName, new HashMap<>());
|
||||
return jsonMapper.readValue(response, AppRoleResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
@ -268,12 +336,104 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listSecrets(final String path) throws VaultConnectorException {
|
||||
public boolean deleteAppRole(String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestDelete(PATH_AUTH_APPROLE + "role/" + roleName);
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where non was expected.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAppRoleID(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestGet(PATH_AUTH_APPROLE + "role/" + roleName + "/role-id", new HashMap<>());
|
||||
return jsonMapper.readValue(response, RawDataResponse.class).getData().get("role_id").toString();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
payload.put("role_id", roleID);
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/role-id", payload);
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where non was expected.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Get response */
|
||||
String response;
|
||||
if (secret.getId() != null && !secret.getId().isEmpty())
|
||||
response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/custom-secret-id", secret);
|
||||
else
|
||||
response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id", secret);
|
||||
|
||||
try {
|
||||
/* Extract the secret ID from response */
|
||||
return jsonMapper.readValue(response, AppRoleSecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/lookup", new AppRoleSecret(secretID));
|
||||
return jsonMapper.readValue(response, AppRoleSecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestPost(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id/destroy", new AppRoleSecret(secretID));
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where non was expected.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listAppRoles() throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
try {
|
||||
String response = requestGet(PATH_SECRET + "/" + path + "/?list=true", new HashMap<>());
|
||||
String response = requestGet(PATH_AUTH_APPROLE + "role?list=true", new HashMap<>());
|
||||
SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
|
||||
return secrets.getKeys();
|
||||
} catch (IOException e) {
|
||||
@ -285,25 +445,179 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||
public List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
try {
|
||||
String response = requestGet(PATH_AUTH_APPROLE + "role/" + roleName + "/secret-id?list=true", new HashMap<>());
|
||||
SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
|
||||
return secrets.getKeys();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretResponse read(final String key) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestGet(key, new HashMap<>());
|
||||
return jsonMapper.readValue(response, SecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> list(final String path) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
try {
|
||||
String response = requestGet(path + "/?list=true", new HashMap<>());
|
||||
SecretListResponse secrets = jsonMapper.readValue(response, SecretListResponse.class);
|
||||
return secrets.getKeys();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format.");
|
||||
}
|
||||
}
|
||||
|
||||
public void write(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
if (key == null || key.isEmpty())
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("value", value);
|
||||
return requestPost(PATH_SECRET + "/" + key, param).equals("");
|
||||
if (!requestPost(key, data).equals(""))
|
||||
throw new InvalidResponseException("Received response where none was expected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String key) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestDelete(key);
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where none was expected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revoke(String leaseID) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
String response = requestPut(PATH_REVOKE + leaseID, new HashMap<>());
|
||||
|
||||
/* Response should be code 204 without content */
|
||||
if (!response.equals(""))
|
||||
throw new InvalidResponseException("Received response where none was expected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretResponse renew(String leaseID, Integer increment) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
Map<String, String> payload = new HashMap<>();
|
||||
payload.put("lease_id", leaseID);
|
||||
if (increment != null)
|
||||
payload.put("increment", increment.toString());
|
||||
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestPut(PATH_RENEW, payload);
|
||||
return jsonMapper.readValue(response, SecretResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token) throws VaultConnectorException {
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token, boolean orphan) throws VaultConnectorException {
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE_ORPHAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse createToken(final Token token, final String role) throws VaultConnectorException {
|
||||
if (role == null || role.isEmpty())
|
||||
throw new InvalidRequestException("No role name specified.");
|
||||
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE + "/" + role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
* Centralized method to handle different token creation requests.
|
||||
*
|
||||
* @param token the token
|
||||
* @param path request path
|
||||
* @return the response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
private AuthResponse createTokenInternal(final Token token, final String path) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
|
||||
if (token == null)
|
||||
throw new InvalidRequestException("Token must be provided.");
|
||||
|
||||
String response = requestPost(path, token);
|
||||
try {
|
||||
return jsonMapper.readValue(response, AuthResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenResponse lookupToken(final String token) throws VaultConnectorException {
|
||||
if (!isAuthorized())
|
||||
throw new AuthorizationRequiredException();
|
||||
/* Request HTTP response and parse Secret */
|
||||
try {
|
||||
String response = requestGet(PATH_TOKEN + "/lookup/" + token, new HashMap<>());
|
||||
return jsonMapper.readValue(response, TokenResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException ignored) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute HTTP request using POST method.
|
||||
*
|
||||
* @param path URL path (relative to base)
|
||||
* @param payload Map of payload values (will be converted to JSON)
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
*/
|
||||
private String requestPost(final String path, final Map payload) throws VaultConnectorException {
|
||||
private String requestPost(final String path, final Object payload) throws VaultConnectorException {
|
||||
/* Initialize post */
|
||||
HttpPost post = new HttpPost(baseURL + path);
|
||||
/* generate JSON from payload */
|
||||
@ -325,13 +639,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
/**
|
||||
* Execute HTTP request using PUT method.
|
||||
*
|
||||
* @param path URL path (relative to base)
|
||||
* @param payload Map of payload values (will be converted to JSON)
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
*/
|
||||
private String requestPut(final String path, final Map<String, String> payload) throws VaultConnectorException {
|
||||
/* Initialize post */
|
||||
/* Initialize put */
|
||||
HttpPut put = new HttpPut(baseURL + path);
|
||||
/* generate JSON from payload */
|
||||
StringEntity entity = null;
|
||||
@ -349,8 +664,26 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
return request(put);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute HTTP request using DELETE method.
|
||||
*
|
||||
* @param path URL path (relative to base)
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
*/
|
||||
private String requestDelete(final String path) throws VaultConnectorException {
|
||||
/* Initialize delete */
|
||||
HttpDelete delete = new HttpDelete(baseURL + path);
|
||||
/* Set X-Vault-Token header */
|
||||
if (token != null)
|
||||
delete.addHeader("X-Vault-Token", token);
|
||||
|
||||
return request(delete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute HTTP request using GET method.
|
||||
*
|
||||
* @param path URL path (relative to base)
|
||||
* @param payload Map of payload values (will be converted to JSON)
|
||||
* @return HTTP response
|
||||
@ -372,7 +705,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute prepared HTTP request and return result
|
||||
* Execute prepared HTTP request and return result.
|
||||
*
|
||||
* @param base Prepares Request
|
||||
* @return HTTP response
|
||||
* @throws VaultConnectorException on connection error
|
||||
@ -382,7 +716,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
base.addHeader("accept", "application/json");
|
||||
|
||||
HttpResponse response = null;
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(sslContext).build()) {
|
||||
response = httpClient.execute(base);
|
||||
/* Check if response is valid */
|
||||
if (response == null)
|
||||
@ -390,9 +724,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
switch (response.getStatusLine().getStatusCode()) {
|
||||
case 200:
|
||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
||||
return br.lines().collect(Collectors.joining("\n"));
|
||||
} catch (IOException ignored) { }
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
case 204:
|
||||
return "";
|
||||
case 403:
|
||||
@ -415,8 +750,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to read response", e);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
if (response != null && response.getEntity() != null)
|
||||
try {
|
||||
EntityUtils.consume(response.getEntity());
|
||||
|
@ -1,10 +1,27 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Vault Connector interface.
|
||||
@ -14,11 +31,7 @@ import java.util.List;
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface VaultConnector {
|
||||
/**
|
||||
* Verify that vault connection is initialized.
|
||||
* @return TRUE if correctly initialized
|
||||
*/
|
||||
boolean init();
|
||||
String PATH_SECRET = "secret";
|
||||
|
||||
/**
|
||||
* Reset authorization information.
|
||||
@ -27,18 +40,21 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Retrieve status of vault seal.
|
||||
*
|
||||
* @return Seal status
|
||||
*/
|
||||
SealResponse sealStatus();
|
||||
|
||||
/**
|
||||
* Seal vault.
|
||||
*
|
||||
* @return TRUE on success
|
||||
*/
|
||||
boolean seal();
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @param reset Discard previously provided keys (optional)
|
||||
* @return TRUE on success
|
||||
@ -47,6 +63,7 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @return TRUE on success
|
||||
*/
|
||||
@ -56,6 +73,7 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Get all availale authentication backends.
|
||||
*
|
||||
* @return List of backends
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
@ -63,6 +81,7 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Authorize to Vault using token.
|
||||
*
|
||||
* @param token The token
|
||||
* @return Token response
|
||||
* @throws VaultConnectorException on error
|
||||
@ -71,6 +90,7 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Authorize to Vault using username and password.
|
||||
*
|
||||
* @param username The username
|
||||
* @param password The password
|
||||
* @return Authorization result
|
||||
@ -80,73 +100,506 @@ public interface VaultConnector {
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppID method.
|
||||
*
|
||||
* @param appID The App ID
|
||||
* @param userID The User ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppRole method without secret ID.
|
||||
*
|
||||
* @param roleID The role ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AuthResponse authAppRole(final String roleID) throws VaultConnectorException {
|
||||
return authAppRole(roleID, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize to Vault using AppRole method.
|
||||
*
|
||||
* @param roleID The role ID
|
||||
* @param secretID The secret ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID with policy.
|
||||
*
|
||||
* @param appID The unique App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
*
|
||||
* @param role The role
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean createAppRole(final AppRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies) throws VaultConnectorException {
|
||||
return createAppRole(roleName, policies, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID A custom role ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>(), roleID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @param roleID A custom role ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies, final String roleID) throws VaultConnectorException {
|
||||
return createAppRole(new AppRoleBuilder(roleName).withPolicies(policies).withId(roleID).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete AppRole role from Vault.
|
||||
*
|
||||
* @param roleName The role anme
|
||||
* @return TRUE on succevss
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The role ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
String getAppRoleID(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Set custom ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID The role ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new random generated AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName) throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID A custom secret ID
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secret The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret ID
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean destroyAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) AppRole roles.
|
||||
*
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) secret IDs for AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoleSecretss(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register User-ID with App-ID
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param userID The User-ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRoleSecret} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new App-ID and User-ID at once.
|
||||
*
|
||||
* @param appID The App-ID
|
||||
* @param policy The policy to associate with
|
||||
* @param displayName Arbitrary name to display
|
||||
* @param userID The User-ID
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException {
|
||||
return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization status
|
||||
*
|
||||
* @return TRUE, if successfully authorized
|
||||
*/
|
||||
boolean isAuthorized();
|
||||
|
||||
/**
|
||||
* Retrieve secret form Vault.
|
||||
* Retrieve any nodes content from Vault.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
SecretResponse read(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret from Vault.
|
||||
* Prefix "secret/" is automatically added to key.
|
||||
*
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SecretResponse readSecret(final String key) throws VaultConnectorException;
|
||||
default SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||
return read(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* List available nodes from Vault.
|
||||
*
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
List<String> list(final String path) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available secrets from Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param path Root path to search
|
||||
* @return List of secret keys
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listSecrets(final String path) throws VaultConnectorException;
|
||||
default List<String> listSecrets(final String path) throws VaultConnectorException {
|
||||
return list(PATH_SECRET + "/" + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write simple value to Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param value Secret value
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default void write(final String key, final String value) throws VaultConnectorException {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("value", value);
|
||||
write(key, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write value to Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
void write(final String key, final Map<String, Object> data) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param value Secret value
|
||||
* @return TRUE on success
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean writeSecret(final String key, final String value) throws VaultConnectorException;
|
||||
default void writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("value", value);
|
||||
writeSecret(key, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
|
||||
if (key == null || key.isEmpty())
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
write(PATH_SECRET + "/" + key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete key from Vault.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
void delete(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret from Vault.
|
||||
* Prefix "secret/" is automatically added to path.
|
||||
*
|
||||
* @param key Secret path
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default void deleteSecret(final String key) throws VaultConnectorException {
|
||||
delete(PATH_SECRET + "/" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke given lease immediately.
|
||||
*
|
||||
* @param leaseID the lease ID
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
void revoke(final String leaseID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Renew lease with given ID.
|
||||
*
|
||||
* @param leaseID the lase ID
|
||||
* @return Renewed lease
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SecretResponse renew(final String leaseID) throws VaultConnectorException {
|
||||
return renew(leaseID, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew lease with given ID.
|
||||
*
|
||||
* @param leaseID the lase ID
|
||||
* @param increment number of seconds to extend lease time
|
||||
* @return Renewed lease
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @param orphan create orphan token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token, boolean orphan) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token for specific role.
|
||||
*
|
||||
* @param token the token
|
||||
* @param role the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse createToken(final Token token, final String role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
TokenResponse lookupToken(final String token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Read credentials for MySQL backend at default mount point
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMySqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mysql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for PostgreSQL backend at default mount point
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readPostgreSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "postgresql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MSSQL backend at default mount point
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMsSqlCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mssql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for MSSQL backend at default mount point
|
||||
*
|
||||
* @param role the role name
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readMongoDbCredentials(final String role) throws VaultConnectorException {
|
||||
return readDbCredentials(role, "mongodb");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read credentials for SQL backends.
|
||||
*
|
||||
* @param role the role name
|
||||
* @param mount mount point of the SQL backend
|
||||
* @return the credentials response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.5.0
|
||||
*/
|
||||
default CredentialsResponse readDbCredentials(final String role, final String mount) throws VaultConnectorException {
|
||||
return (CredentialsResponse) read(mount + "/creds/" + role);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown on errors with TLS connection.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TlsException extends VaultConnectorException {
|
||||
private Integer statusCode;
|
||||
private String response;
|
||||
|
||||
public TlsException() {
|
||||
}
|
||||
|
||||
public TlsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TlsException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public TlsException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public Integer getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.HTTPVaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.TlsException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Vault Connector Factory implementation for HTTP Vault connectors.
|
||||
@ -18,6 +48,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
private Integer port;
|
||||
private boolean tls;
|
||||
private String prefix;
|
||||
private SSLContext sslContext;
|
||||
|
||||
/**
|
||||
* Default empty constructor.
|
||||
@ -32,6 +63,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Set hostname (default: 127.0.0.1)
|
||||
*
|
||||
* @param host Hostname or IP address
|
||||
* @return self
|
||||
*/
|
||||
@ -42,6 +74,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Set port (default: 8200)
|
||||
*
|
||||
* @param port Vault TCP port
|
||||
* @return self
|
||||
*/
|
||||
@ -52,6 +85,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Set TLS usage (default: TRUE)
|
||||
*
|
||||
* @param useTLS use TLS or not
|
||||
* @return self
|
||||
*/
|
||||
@ -62,6 +96,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Convenience Method for TLS usage (enabled by default)
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTLS() {
|
||||
@ -70,6 +105,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Convenience Method for NOT using TLS
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withoutTLS() {
|
||||
@ -78,6 +114,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
|
||||
/**
|
||||
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
|
||||
*
|
||||
* @param prefix Vault API prefix (default: "/v1/"
|
||||
* @return self
|
||||
*/
|
||||
@ -86,8 +123,92 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trusted CA certifiate for HTTPS connections.
|
||||
*
|
||||
* @param cert path to certificate file
|
||||
* @return self
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException {
|
||||
if (cert != null)
|
||||
return withSslContext(createSslContext(cert));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom SSL context.
|
||||
* Overwrites certificates set by {@link #withTrustedCA}.
|
||||
*
|
||||
* @param sslContext the SSL context
|
||||
* @return self
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public HTTPVaultConnectorFactory withSslContext(SSLContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPVaultConnector build() {
|
||||
return new HTTPVaultConnector(host, tls, port, prefix);
|
||||
return new HTTPVaultConnector(host, tls, port, prefix, sslContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create SSL Context trusting only provided certificate.
|
||||
*
|
||||
* @param trustedCert Path to trusted CA certificate
|
||||
* @return SSL context
|
||||
* @throws TlsException on errors
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private SSLContext createSslContext(Path trustedCert) throws TlsException {
|
||||
try {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, createTrustManager(trustedCert), new SecureRandom());
|
||||
return context;
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new TlsException("Unable to intialize SSLContext", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom TrustManager for given CA certificate file.
|
||||
*
|
||||
* @param trustedCert Path to trusted CA certificate
|
||||
* @return TrustManger
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private TrustManager[] createTrustManager(Path trustedCert) throws TlsException {
|
||||
try {
|
||||
/* Create Keystore with trusted certificate */
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null, null);
|
||||
keyStore.setCertificateEntry("trustedCert", certificateFromFile(trustedCert));
|
||||
/* Initialize TrustManager */
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(keyStore);
|
||||
return tmf.getTrustManagers();
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
|
||||
throw new TlsException("Unable to initialize TrustManager", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given certificate file to X.509 certificate.
|
||||
*
|
||||
* @param certFile Path to certificate file
|
||||
* @return X.509 Certificate object
|
||||
* @throws TlsException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
private X509Certificate certificateFromFile(Path certFile) throws TlsException {
|
||||
try (InputStream is = Files.newInputStream(certFile)) {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||
} catch (IOException | CertificateException e) {
|
||||
throw new TlsException("Unable to read certificate.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,23 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.factory;
|
||||
|
||||
import de.stklcode.jvault.connector.VaultConnector;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Abstract Vault Connector Factory interface.
|
||||
|
149
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
149
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Vault AppRole role metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRole {
|
||||
@JsonProperty("role_name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("role_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty("bind_secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean bindSecretId;
|
||||
|
||||
private List<String> boundCidrList;
|
||||
|
||||
private List<String> policies;
|
||||
|
||||
@JsonProperty("secret_id_num_uses")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer secretIdNumUses;
|
||||
|
||||
@JsonProperty("secret_id_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer secretIdTtl;
|
||||
|
||||
@JsonProperty("token_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer tokenTtl;
|
||||
|
||||
@JsonProperty("token_max_ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer tokenMaxTtl;
|
||||
|
||||
@JsonProperty("period")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer period;
|
||||
|
||||
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) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.bindSecretId = bindSecretId;
|
||||
this.boundCidrList = boundCidrList;
|
||||
this.policies = policies;
|
||||
this.secretIdNumUses = secretIdNumUses;
|
||||
this.secretIdTtl = secretIdTtl;
|
||||
this.tokenTtl = tokenTtl;
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Boolean getBindSecretId() {
|
||||
return bindSecretId;
|
||||
}
|
||||
|
||||
public List<String> getBoundCidrList() {
|
||||
return boundCidrList;
|
||||
}
|
||||
|
||||
@JsonSetter("bound_cidr_list")
|
||||
public void setBoundCidrList(List<String> boundCidrList) {
|
||||
this.boundCidrList = boundCidrList;
|
||||
}
|
||||
|
||||
@JsonGetter("bound_cidr_list")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public String getBoundCidrListString() {
|
||||
if (boundCidrList == null || boundCidrList.isEmpty())
|
||||
return "";
|
||||
return String.join(",", boundCidrList);
|
||||
}
|
||||
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
@JsonSetter("policies")
|
||||
public void setPolicies(List<String> policies) {
|
||||
this.policies = policies;
|
||||
}
|
||||
|
||||
@JsonGetter("policies")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public String getPoliciesString() {
|
||||
if (policies == null || policies.isEmpty())
|
||||
return "";
|
||||
return String.join(",", policies);
|
||||
}
|
||||
|
||||
public Integer getSecretIdNumUses() {
|
||||
return secretIdNumUses;
|
||||
}
|
||||
|
||||
public Integer getSecretIdTtl() {
|
||||
return secretIdTtl;
|
||||
}
|
||||
|
||||
public Integer getTokenTtl() {
|
||||
return tokenTtl;
|
||||
}
|
||||
|
||||
public Integer getTokenMaxTtl() {
|
||||
return tokenMaxTtl;
|
||||
}
|
||||
|
||||
public Integer getPeriod() {
|
||||
return period;
|
||||
}
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A builder for vault AppRole roles..
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AppRoleBuilder {
|
||||
private String name;
|
||||
private String id;
|
||||
private Boolean bindSecretId;
|
||||
private List<String> boundCidrList;
|
||||
private List<String> policies;
|
||||
private Integer secretIdNumUses;
|
||||
private Integer secretIdTtl;
|
||||
private Integer tokenTtl;
|
||||
private Integer tokenMaxTtl;
|
||||
private Integer period;
|
||||
|
||||
public AppRoleBuilder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom role ID (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if role is bound to secret ID
|
||||
*
|
||||
* @param bindSecretId the display name
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID(final Boolean bindSecretId) {
|
||||
this.bindSecretId = bindSecretId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBindSecretID() {
|
||||
return withBindSecretID(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not bind role to secret ID.
|
||||
* Convenience method for {@link #withBindSecretID(Boolean)}
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withoutBindSecretID() {
|
||||
return withBindSecretID(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bound CIDR blocks.
|
||||
*
|
||||
* @param boundCidrList List of CIDR blocks which can perform login
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withBoundCidrList(final List<String> boundCidrList) {
|
||||
this.boundCidrList = boundCidrList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CIDR block to list of bound blocks.
|
||||
*
|
||||
* @param cidrBlock the CIDR block
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withCidrBlock(final String cidrBlock) {
|
||||
if (boundCidrList == null)
|
||||
boundCidrList = new ArrayList<>();
|
||||
boundCidrList.add(cidrBlock);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withPolicies(final List<String> policies) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
this.policies.addAll(policies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withPolicy(final String policy) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
policies.add(policy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of uses for sectet IDs.
|
||||
*
|
||||
* @param secredIdNumUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdNumUses(final Integer secredIdNumUses) {
|
||||
this.secretIdNumUses = secredIdNumUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default sectet ID TTL in seconds.
|
||||
*
|
||||
* @param secredIdTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withSecretIdTtl(final Integer secredIdTtl) {
|
||||
this.secretIdTtl = secredIdTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default token TTL in seconds.
|
||||
*
|
||||
* @param tokenTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenTtl(final Integer tokenTtl) {
|
||||
this.tokenTtl = tokenTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum token TTL in seconds.
|
||||
*
|
||||
* @param tokenMaxTtl the TTL
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withTokenMaxTtl(final Integer tokenMaxTtl) {
|
||||
this.tokenMaxTtl = tokenMaxTtl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renewal period for generated token in seconds.
|
||||
*
|
||||
* @param period period in seconds
|
||||
* @return self
|
||||
*/
|
||||
public AppRoleBuilder withPeriod(final Integer period) {
|
||||
this.period = period;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the AppRole role based on given parameters.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public AppRole build() {
|
||||
return new AppRole(name,
|
||||
id,
|
||||
bindSecretId,
|
||||
boundCidrList,
|
||||
policies,
|
||||
secretIdNumUses,
|
||||
secretIdTtl,
|
||||
tokenTtl,
|
||||
tokenMaxTtl,
|
||||
period);
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault AppRole role metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleSecret {
|
||||
@JsonProperty("secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty(value = "secret_id_accessor", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String accessor;
|
||||
|
||||
@JsonProperty("metadata")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
private List<String> cidrList;
|
||||
|
||||
@JsonProperty(value = "creation_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String creationTime;
|
||||
|
||||
@JsonProperty(value = "expiration_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String expirationTime;
|
||||
|
||||
@JsonProperty(value = "last_updated_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String lastUpdatedTime;
|
||||
|
||||
@JsonProperty(value = "secret_id_num_uses", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private Integer numUses;
|
||||
|
||||
@JsonProperty(value = "secret_id_ttl", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private Integer ttl;
|
||||
|
||||
public AppRoleSecret() {
|
||||
|
||||
}
|
||||
|
||||
public AppRoleSecret(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public AppRoleSecret(String id, Map<String, Object> metadata, List<String> cidrList) {
|
||||
this.id = id;
|
||||
this.metadata = metadata;
|
||||
this.cidrList = cidrList;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public List<String> getCidrList() {
|
||||
return cidrList;
|
||||
}
|
||||
|
||||
@JsonSetter("cidr_list")
|
||||
public void setCidrList(List<String> cidrList) {
|
||||
this.cidrList = cidrList;
|
||||
}
|
||||
|
||||
@JsonGetter("cidr_list")
|
||||
public String getCidrListString() {
|
||||
if (cidrList == null || cidrList.isEmpty())
|
||||
return "";
|
||||
return String.join(",", cidrList);
|
||||
}
|
||||
|
||||
public String getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public String getExpirationTime() {
|
||||
return expirationTime;
|
||||
}
|
||||
|
||||
public String getLastUpdatedTime() {
|
||||
return lastUpdatedTime;
|
||||
}
|
||||
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
public Integer getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
/**
|
||||
@ -9,6 +25,7 @@ package de.stklcode.jvault.connector.model;
|
||||
public enum AuthBackend {
|
||||
TOKEN("token"),
|
||||
APPID("app-id"),
|
||||
APPROLE("approle"),
|
||||
USERPASS("userpass"),
|
||||
UNKNOWN("");
|
||||
|
||||
|
117
src/main/java/de/stklcode/jvault/connector/model/Token.java
Normal file
117
src/main/java/de/stklcode/jvault/connector/model/Token.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault Token metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Token {
|
||||
@JsonProperty("id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String id;
|
||||
|
||||
@JsonProperty("display_name")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String displayName;
|
||||
|
||||
@JsonProperty("no_parent")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean noParent;
|
||||
|
||||
@JsonProperty("no_default_policy")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean noDefaultPolicy;
|
||||
|
||||
@JsonProperty("ttl")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer ttl;
|
||||
|
||||
@JsonProperty("num_uses")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Integer numUses;
|
||||
|
||||
@JsonProperty("policies")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private List<String> policies;
|
||||
|
||||
@JsonProperty("meta")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Map<String, String> meta;
|
||||
|
||||
@JsonProperty("renewable")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Boolean renewable;
|
||||
|
||||
public Token(String id, String displayName, Boolean noParent, Boolean noDefaultPolicy, Integer ttl, Integer numUses, List<String> policies, Map<String, String> meta, Boolean renewable) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.ttl = ttl;
|
||||
this.numUses = numUses;
|
||||
this.noParent = noParent;
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
this.policies = policies;
|
||||
this.meta = meta;
|
||||
this.renewable = renewable;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public Boolean getNoParent() {
|
||||
return noParent;
|
||||
}
|
||||
|
||||
public Boolean getNoDefaultPolicy() {
|
||||
return noDefaultPolicy;
|
||||
}
|
||||
|
||||
public Integer getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public Integer getNumUses() {
|
||||
return numUses;
|
||||
}
|
||||
|
||||
public List<String> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
public Map<String, String> getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
public Boolean isRenewable() {
|
||||
return renewable;
|
||||
}
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A builder for vault tokens.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TokenBuilder {
|
||||
private String id;
|
||||
private String displayName;
|
||||
private Boolean noParent;
|
||||
private Boolean noDefaultPolicy;
|
||||
private Integer ttl;
|
||||
private Integer numUses;
|
||||
private List<String> policies;
|
||||
private Map<String, String> meta;
|
||||
private Boolean renewable;
|
||||
|
||||
/**
|
||||
* Add token ID (optional)
|
||||
*
|
||||
* @param id the ID
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withId(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add display name
|
||||
*
|
||||
* @param displayName the display name
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDisplayName(final String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired time to live.
|
||||
* @param ttl the ttl
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withTtl(final Integer ttl) {
|
||||
this.ttl = ttl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desired number of uses.
|
||||
* @param numUses the number of uses
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNumUses(final Integer numUses) {
|
||||
this.numUses = numUses;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the token should be created without parent
|
||||
*
|
||||
* @param noParent if TRUE, token is created as orphan
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoParent(final boolean noParent) {
|
||||
this.noParent = noParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token without parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder asOrphan() {
|
||||
return withNoParent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token with parent.
|
||||
* Convenience method for withNoParent()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withParent() {
|
||||
return withNoParent(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TRUE if the default policy should not be part of this token.
|
||||
*
|
||||
* @param noDefaultPolicy if TRUE, default policy is not attached
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withNoDefaultPolicy(final boolean noDefaultPolicy) {
|
||||
this.noDefaultPolicy = noDefaultPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withDefaultPolicy() {
|
||||
return withNoDefaultPolicy(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not attach default policy to token.
|
||||
* Convenience method for withNoDefaultPolicy()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withoutDefaultPolicy() {
|
||||
return withNoDefaultPolicy(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
* @since 0.5.0
|
||||
*/
|
||||
public TokenBuilder withPolicies(final String... policies) {
|
||||
return withPolicies(Arrays.asList(policies));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given policies
|
||||
*
|
||||
* @param policies the policies
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicies(final List<String> policies) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
this.policies.addAll(policies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single policy.
|
||||
*
|
||||
* @param policy the policy
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withPolicy(final String policy) {
|
||||
if (this.policies == null)
|
||||
this.policies = new ArrayList<>();
|
||||
policies.add(policy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param meta the metadata
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final Map<String, String> meta) {
|
||||
if (this.meta == null)
|
||||
this.meta = new HashMap<>();
|
||||
this.meta.putAll(meta);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta data.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withMeta(final String key, final String value) {
|
||||
if (this.meta == null)
|
||||
this.meta = new HashMap<>();
|
||||
this.meta.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if token is renewable.
|
||||
*
|
||||
* @param renewable TRUE, if renewable
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder withRenewable(final Boolean renewable) {
|
||||
this.renewable = renewable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder renewable() {
|
||||
return withRenewable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token to be not renewable.
|
||||
* Convenience method for withRenewable()
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public TokenBuilder notRenewable() {
|
||||
return withRenewable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the token based on given parameters.
|
||||
*
|
||||
* @return the token
|
||||
*/
|
||||
public Token build() {
|
||||
return new Token(id,
|
||||
displayName,
|
||||
noParent,
|
||||
noDefaultPolicy,
|
||||
ttl,
|
||||
numUses,
|
||||
policies,
|
||||
meta,
|
||||
renewable);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AppRole;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Vault response for AppRole lookup.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleResponse extends VaultDataResponse {
|
||||
private AppRole role;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>();
|
||||
data.forEach((k,v) -> { if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k,v); });
|
||||
this.role = mapper.readValue(mapper.writeValueAsString(filteredData), AppRole.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new InvalidResponseException();
|
||||
}
|
||||
}
|
||||
|
||||
public AppRole getRole() {
|
||||
return role;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.AppRole;
|
||||
import de.stklcode.jvault.connector.model.AppRoleSecret;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Vault response for AppRole lookup.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AppRoleSecretResponse extends VaultDataResponse {
|
||||
private AppRoleSecret secret;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
/* null empty strings on list objects */
|
||||
Map<String, Object> filteredData = new HashMap<>();
|
||||
data.forEach((k,v) -> { if (!(v instanceof String && ((String) v).isEmpty())) filteredData.put(k,v); });
|
||||
this.secret = mapper.readValue(mapper.writeValueAsString(filteredData), AppRoleSecret.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new InvalidResponseException();
|
||||
}
|
||||
}
|
||||
|
||||
public AppRoleSecret getSecret() {
|
||||
return secret;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
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.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class CredentialsResponse extends SecretResponse {
|
||||
|
||||
public String getUsername() {
|
||||
if (get("username") != null)
|
||||
return get("username").toString();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
if (get("username") != null)
|
||||
return get("username").toString();
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Simple Vault data response.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class RawDataResponse extends VaultDataResponse {
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@ -15,32 +31,76 @@ import java.util.Map;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SecretResponse extends VaultDataResponse {
|
||||
private String value;
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public void setData(Map<String, Object> data) throws InvalidResponseException {
|
||||
try {
|
||||
this.value = (String) data.get("value");
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidResponseException("Value could not be parsed", e);
|
||||
}
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get complete data object.
|
||||
*
|
||||
* @return data map
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single value for given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value or NULL if absent
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data element for key "value".
|
||||
* Method for backwards compatibility in case of simple secrets.
|
||||
*
|
||||
* @return the value
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public String getValue() {
|
||||
return value;
|
||||
if (data.get("value") == null)
|
||||
return null;
|
||||
return data.get("value").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON
|
||||
*
|
||||
* @param type Class to parse response
|
||||
* @param <T> Class to parse response
|
||||
* @return Parsed object
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.3
|
||||
* @deprecated Deprecated artifact, will be removed at latest at v1.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T getValue(Class<T> type) throws InvalidResponseException {
|
||||
return get("value", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response parsed as JSON
|
||||
*
|
||||
* @param key the key
|
||||
* @param type Class to parse response
|
||||
* @param <T> Class to parse response
|
||||
* @return Parsed object
|
||||
* @throws InvalidResponseException on parsing error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public <T> T get(String key, Class<T> type) throws InvalidResponseException {
|
||||
try {
|
||||
return new ObjectMapper().readValue(getValue(), type);
|
||||
return new ObjectMapper().readValue(get(key).toString(), type);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage());
|
||||
}
|
||||
|
@ -1,5 +1,20 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,5 +1,22 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
@ -12,6 +29,7 @@ import java.util.Map;
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthMethod {
|
||||
private AuthBackend type;
|
||||
private String rawType;
|
||||
@ -22,6 +40,9 @@ public class AuthMethod {
|
||||
@JsonProperty("config")
|
||||
private Map<String, String> config;
|
||||
|
||||
@JsonProperty("local")
|
||||
private boolean local;
|
||||
|
||||
@JsonSetter("type")
|
||||
public void setType(String type) {
|
||||
this.rawType = type;
|
||||
@ -43,4 +64,8 @@ public class AuthMethod {
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return local;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model.response.embedded;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
@ -1,34 +1,50 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector;
|
||||
|
||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||
import de.stklcode.jvault.connector.model.*;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
import de.stklcode.jvault.connector.factory.HTTPVaultConnectorFactory;
|
||||
import de.stklcode.jvault.connector.test.Credentials;
|
||||
import de.stklcode.jvault.connector.test.VaultConfiguration;
|
||||
import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
||||
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
|
||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.factory.VaultConnectorFactory;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
/**
|
||||
* JUnit Test for HTTP Vault connector.
|
||||
* JUnit test for HTTP Vault connector.
|
||||
* This test requires Vault binary in executable Path as it instantiates a real Vault server on given test data.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.1
|
||||
@ -40,10 +56,15 @@ public class HTTPVaultConnectorTest {
|
||||
private static String PASS_VALID = "validPass";
|
||||
private static String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA";
|
||||
private static String USER_ID = "5ADF8218-D7FB-4089-9E38-287465DBF37E";
|
||||
private static String APPROLE_ROLE_NAME = "testrole1"; // role with secret ID
|
||||
private static String APPROLE_ROLE = "627b6400-90c3-a239-49a9-af65a448ca10";
|
||||
private static String APPROLE_SECRET = "5e8b0e99-d906-27f5-f043-ccb9bb53b5e8";
|
||||
private static String APPROLE_ROLE2 = "35b7bf43-9644-588a-e68f-2e8313bb23b7"; // role with CIDR subnet
|
||||
private static String SECRET_PATH = "userstore";
|
||||
private static String SECRET_KEY = "foo";
|
||||
private static String SECRET_KEY_JSON = "json";
|
||||
private static String SECRET_VALUE = "bar";
|
||||
private static String SECRET_KEY_JSON = "json";
|
||||
private static String SECRET_KEY_COMPLEX = "complex";
|
||||
|
||||
private Process vaultProcess;
|
||||
private VaultConnector connector;
|
||||
@ -51,25 +72,35 @@ public class HTTPVaultConnectorTest {
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
/**
|
||||
* Initialize Vault instance with generated configuration and provided file backend.
|
||||
* Requires "vault" binary to be in current user's executable path. Not using MLock, so no extended rights required.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setUp() throws VaultConnectorException {
|
||||
/* Determine, if TLS is required */
|
||||
boolean isTls = testName.getMethodName().equals("tlsConnectionTest");
|
||||
|
||||
/* Initialize Vault */
|
||||
VaultConfiguration config = initializeVault();
|
||||
VaultConfiguration config = initializeVault(isTls);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/* Initialize connector */
|
||||
connector = VaultConnectorFactory.httpFactory()
|
||||
HTTPVaultConnectorFactory factory = VaultConnectorFactory.httpFactory()
|
||||
.withHost(config.getHost())
|
||||
.withPort(config.getPort())
|
||||
.withoutTLS()
|
||||
.build();
|
||||
.withTLS(isTls);
|
||||
if (isTls)
|
||||
factory.withTrustedCA(Paths.get(getClass().getResource("/tls/ca.pem").getPath()));
|
||||
connector = factory.build();
|
||||
|
||||
/* Unseal Vault and check result */
|
||||
SealResponse sealStatus = connector.unseal(KEY);
|
||||
assumeNotNull(sealStatus);
|
||||
@ -90,8 +121,7 @@ public class HTTPVaultConnectorTest {
|
||||
/* Authenticate as valid user */
|
||||
try {
|
||||
connector.authToken(TOKEN_ROOT);
|
||||
}
|
||||
catch(VaultConnectorException ignored) {
|
||||
} catch (VaultConnectorException ignored) {
|
||||
}
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
@ -101,8 +131,8 @@ public class HTTPVaultConnectorTest {
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Could not list supported auth backends: " + e.getMessage());
|
||||
}
|
||||
assertThat(supportedBackends.size(), is(3));
|
||||
assertThat(supportedBackends, hasItems(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID));
|
||||
assertThat(supportedBackends, hasSize(4));
|
||||
assertThat(supportedBackends, hasItems(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID, AuthBackend.APPROLE));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,10 +141,13 @@ public class HTTPVaultConnectorTest {
|
||||
@Test
|
||||
public void authTokenTest() {
|
||||
TokenResponse res;
|
||||
final String invalidToken = "52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6";
|
||||
try {
|
||||
connector.authToken("52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6");
|
||||
connector.authToken(invalidToken);
|
||||
fail("Logged in with invalid token");
|
||||
} catch (VaultConnectorException ignored) {
|
||||
} catch (VaultConnectorException e) {
|
||||
/* Assert that the exception does not reveal the token */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidToken)));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -132,11 +165,15 @@ public class HTTPVaultConnectorTest {
|
||||
@Test
|
||||
public void authUserPassTest() {
|
||||
AuthResponse res = null;
|
||||
final String invalidUser = "foo";
|
||||
final String invalidPass = "bar";
|
||||
try {
|
||||
connector.authUserPass("foo", "bar");
|
||||
connector.authUserPass(invalidUser, invalidPass);
|
||||
fail("Logged in with invalid credentials");
|
||||
}
|
||||
catch(VaultConnectorException ignored) {
|
||||
} catch (VaultConnectorException e) {
|
||||
/* Assert that the exception does not reveal credentials */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidUser)));
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidPass)));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -152,6 +189,7 @@ public class HTTPVaultConnectorTest {
|
||||
* App-ID authentication roundtrip.
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void authAppIdTest() {
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
@ -160,8 +198,7 @@ public class HTTPVaultConnectorTest {
|
||||
try {
|
||||
boolean res = connector.registerAppId(APP_ID, "user", "App Name");
|
||||
assertThat("Failed to register App-ID", res, is(true));
|
||||
}
|
||||
catch (VaultConnectorException e) {
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Failed to register App-ID: " + e.getMessage());
|
||||
}
|
||||
|
||||
@ -169,8 +206,7 @@ public class HTTPVaultConnectorTest {
|
||||
try {
|
||||
boolean res = connector.registerUserId(APP_ID, USER_ID);
|
||||
assertThat("Failed to register App-ID", res, is(true));
|
||||
}
|
||||
catch (VaultConnectorException e) {
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Failed to register App-ID: " + e.getMessage());
|
||||
}
|
||||
|
||||
@ -186,6 +222,228 @@ public class HTTPVaultConnectorTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* App-ID authentication roundtrip.
|
||||
*/
|
||||
@Test
|
||||
public void authAppRole() {
|
||||
assumeFalse(connector.isAuthorized());
|
||||
|
||||
/* Authenticate with correct credentials */
|
||||
try {
|
||||
AuthResponse res = connector.authAppRole(APPROLE_ROLE, APPROLE_SECRET);
|
||||
assertThat("Authorization flag not set after AppRole login.", connector.isAuthorized(), is(true));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Failed to authenticate using AppRole: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Authenticate with valid secret ID against unknown role */
|
||||
final String invalidRole = "foo";
|
||||
try {
|
||||
connector.authAppRole(invalidRole, APPROLE_SECRET);
|
||||
fail("Successfully logged in with unknown role");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
/* Assert that the exception does not reveal role ID or secret */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidRole)));
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(APPROLE_SECRET)));
|
||||
}
|
||||
|
||||
/* Authenticate without wrong secret ID */
|
||||
final String invalidSecret = "foo";
|
||||
try {
|
||||
AuthResponse res = connector.authAppRole(APPROLE_ROLE, "foo");
|
||||
fail("Successfully logged in without secret ID");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
/* Assert that the exception does not reveal role ID or secret */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(APPROLE_ROLE)));
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidSecret)));
|
||||
}
|
||||
|
||||
/* Authenticate without secret ID */
|
||||
try {
|
||||
AuthResponse res = connector.authAppRole(APPROLE_ROLE);
|
||||
fail("Successfully logged in without secret ID");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
/* Assert that the exception does not reveal role ID */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(APPROLE_ROLE)));
|
||||
}
|
||||
|
||||
/* Authenticate with secret ID on role with CIDR whitelist */
|
||||
try {
|
||||
AuthResponse res = connector.authAppRole(APPROLE_ROLE2, APPROLE_SECRET);
|
||||
assertThat("Authorization flag not set after AppRole login.", connector.isAuthorized(), is(true));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Failed to log in without secret ID");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation of a new AppRole.
|
||||
*/
|
||||
@Test
|
||||
public void createAppRoleTest() {
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
String roleName = "TestRole";
|
||||
|
||||
/* Create role model */
|
||||
AppRole role = new AppRoleBuilder(roleName).build();
|
||||
|
||||
/* Create role */
|
||||
try {
|
||||
boolean res = connector.createAppRole(role);
|
||||
assertThat("No result given.", res, is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Role creation failed.");
|
||||
}
|
||||
|
||||
/* Lookup role */
|
||||
try {
|
||||
AppRoleResponse res = connector.lookupAppRole(roleName);
|
||||
assertThat("Role lookup returned no role.", res.getRole(), is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Role lookup failed.");
|
||||
}
|
||||
|
||||
/* Lookup role ID */
|
||||
try {
|
||||
String res = connector.getAppRoleID(roleName);
|
||||
assertThat("Role ID lookup returned empty ID.", res, is(not(emptyString())));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Role ID lookup failed.");
|
||||
}
|
||||
|
||||
/* Set custom role ID */
|
||||
String roleID = "custom-role-id";
|
||||
try {
|
||||
connector.setAppRoleID(roleName, roleID);
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Setting custom role ID failed.");
|
||||
}
|
||||
|
||||
/* Verify role ID */
|
||||
try {
|
||||
String res = connector.getAppRoleID(roleName);
|
||||
assertThat("Role ID lookup returned wrong ID.", res, is(roleID));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Role ID lookup failed.");
|
||||
}
|
||||
|
||||
/* Create role by name */
|
||||
roleName = "RoleByName";
|
||||
try {
|
||||
connector.createAppRole(roleName);
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
try {
|
||||
AppRoleResponse res = connector.lookupAppRole(roleName);
|
||||
assertThat("Role lookuo returned not value", res.getRole(), is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
|
||||
/* Create role by name with custom ID */
|
||||
roleName = "RoleByName";
|
||||
roleID = "RolyByNameID";
|
||||
try {
|
||||
connector.createAppRole(roleName, roleID);
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
try {
|
||||
AppRoleResponse res = connector.lookupAppRole(roleName);
|
||||
assertThat("Role lookuo returned not value", res.getRole(), is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
|
||||
try {
|
||||
String res = connector.getAppRoleID(roleName);
|
||||
assertThat("Role lookuo returned wrong ID", res, is(roleID));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
|
||||
/* Create role by name with policies */
|
||||
try {
|
||||
connector.createAppRole(roleName, Collections.singletonList("testpolicy"));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
try {
|
||||
AppRoleResponse res = connector.lookupAppRole(roleName);
|
||||
assertThat("Role lookuo returned wrong policy count", res.getRole().getPolicies(), hasSize(2));
|
||||
assertThat("Role lookuo returned wrong policies", res.getRole().getPolicies(), hasItem("testpolicy"));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Creation of role by name failed.");
|
||||
}
|
||||
|
||||
/* Delete role */
|
||||
try {
|
||||
connector.deleteAppRole(roleName);
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Deletion of role failed.");
|
||||
}
|
||||
try {
|
||||
connector.lookupAppRole(roleName);
|
||||
fail("Deleted role could be looked up.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation of AppRole secrets.
|
||||
*/
|
||||
@Test
|
||||
public void createAppRoleSecretTest() {
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
/* Create default (random) secret for existing role */
|
||||
try {
|
||||
AppRoleSecretResponse res = connector.createAppRoleSecret(APPROLE_ROLE_NAME);
|
||||
assertThat("No secret returned", res.getSecret(), is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("AppRole secret creation failed.");
|
||||
}
|
||||
|
||||
/* Create secret with custom ID */
|
||||
String secretID = "customSecretId";
|
||||
try {
|
||||
AppRoleSecretResponse res = connector.createAppRoleSecret(APPROLE_ROLE_NAME, secretID);
|
||||
assertThat("Unexpected secret ID returned", res.getSecret().getId(), is(secretID));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("AppRole secret creation failed.");
|
||||
}
|
||||
|
||||
/* Lookup secret */
|
||||
try {
|
||||
AppRoleSecretResponse res = connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID);
|
||||
assertThat("No secret information returned", res.getSecret(), is(notNullValue()));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("AppRole secret lookup failed.");
|
||||
}
|
||||
|
||||
/* Destroy secret */
|
||||
try {
|
||||
connector.destroyAppRoleSecret(APPROLE_ROLE_NAME, secretID);
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("AppRole secret destruction failed.");
|
||||
}
|
||||
try {
|
||||
AppRoleSecretResponse res = connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID);
|
||||
fail("Destroyed AppRole secret successfully read.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test reading of secrets.
|
||||
*/
|
||||
@ -196,12 +454,19 @@ public class HTTPVaultConnectorTest {
|
||||
|
||||
/* Try to read path user has no permission to read */
|
||||
SecretResponse res = null;
|
||||
final String invalidPath = "invalid/path";
|
||||
try {
|
||||
res = connector.readSecret("invalid/path");
|
||||
res = connector.readSecret(invalidPath);
|
||||
fail("Invalid secret path successfully read.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, instanceOf(PermissionDeniedException.class));
|
||||
/* Assert that the exception does not reveal secret or credentials */
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(invalidPath)));
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(USER_VALID)));
|
||||
assertThat(stackTrace(e), not(stringContainsInOrder(PASS_VALID)));
|
||||
assertThat(stackTrace(e), not(matchesPattern("[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}")));
|
||||
}
|
||||
|
||||
/* Try to read accessible path with known value */
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY);
|
||||
@ -209,6 +474,7 @@ public class HTTPVaultConnectorTest {
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Valid secret path could not be read: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Try to read accessible path with JSON value */
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_JSON);
|
||||
@ -224,6 +490,33 @@ public class HTTPVaultConnectorTest {
|
||||
} catch (InvalidResponseException e) {
|
||||
fail("JSON response could not be parsed: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Try to read accessible path with JSON value */
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_JSON);
|
||||
assertThat("Known secret returned null value.", res.getValue(), notNullValue());
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Valid secret path could not be read: " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
Credentials parsedRes = res.getValue(Credentials.class);
|
||||
assertThat("JSON response was null", parsedRes, notNullValue());
|
||||
assertThat("JSON response incorrect", parsedRes.getUsername(), is("user"));
|
||||
assertThat("JSON response incorrect", parsedRes.getPassword(), is("password"));
|
||||
} catch (InvalidResponseException e) {
|
||||
fail("JSON response could not be parsed: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Try to read accessible complex secret */
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_COMPLEX);
|
||||
assertThat("Known secret returned null value.", res.getData(), notNullValue());
|
||||
assertThat("Unexpected value size", res.getData().keySet(), hasSize(2));
|
||||
assertThat("Unexpected value", res.get("key1"), is("value1"));
|
||||
assertThat("Unexpected value", res.get("key2"), is("value2"));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Valid secret path could not be read: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,29 +546,28 @@ public class HTTPVaultConnectorTest {
|
||||
|
||||
/* Try to write to null path */
|
||||
try {
|
||||
boolean res = connector.writeSecret(null, "someValue");
|
||||
connector.writeSecret(null, "someValue");
|
||||
fail("Secret written to null path.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, instanceOf(InvalidRequestException.class));
|
||||
}
|
||||
/* Try to write to invalid path */
|
||||
try {
|
||||
boolean res = connector.writeSecret("", "someValue");
|
||||
connector.writeSecret("", "someValue");
|
||||
fail("Secret written to invalid path.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, instanceOf(InvalidRequestException.class));
|
||||
}
|
||||
/* Try to write to a path the user has no access for */
|
||||
try {
|
||||
boolean res = connector.writeSecret("invalid/path", "someValue");
|
||||
connector.writeSecret("invalid/path", "someValue");
|
||||
fail("Secret written to inaccessible path.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, instanceOf(PermissionDeniedException.class));
|
||||
}
|
||||
/* Perform a valid write/read roundtrip to valid path. Also check UTF8-encoding. */
|
||||
try {
|
||||
boolean res = connector.writeSecret(SECRET_PATH + "/temp", "Abc123äöü,!");
|
||||
assertThat("Secret could not be written to valid path.", res, is(true));
|
||||
connector.writeSecret(SECRET_PATH + "/temp", "Abc123äöü,!");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
@ -287,39 +579,210 @@ public class HTTPVaultConnectorTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deletion of secrets.
|
||||
*/
|
||||
@Test
|
||||
public void deleteSecretTest() {
|
||||
authUser();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
/* Write a test secret to vault */
|
||||
try {
|
||||
connector.writeSecret(SECRET_PATH + "/toDelete", "secret content");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
SecretResponse res = null;
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/toDelete");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Written secret could not be read.");
|
||||
}
|
||||
assumeThat(res, is(notNullValue()));
|
||||
|
||||
/* Delete secret */
|
||||
try {
|
||||
connector.deleteSecret(SECRET_PATH + "/toDelete");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Revocation threw unexpected exception.");
|
||||
}
|
||||
|
||||
/* Try to read again */
|
||||
try {
|
||||
connector.readSecret(SECRET_PATH + "/toDelete");
|
||||
fail("Successfully read deleted secret.");
|
||||
} catch (VaultConnectorException e) {
|
||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||
assertThat(((InvalidResponseException) e).getStatusCode(), is(404));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test revocation of secrets.
|
||||
*/
|
||||
@Test
|
||||
public void revokeTest() {
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
/* Write a test secret to vault */
|
||||
try {
|
||||
connector.writeSecret(SECRET_PATH + "/toRevoke", "secret content");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
SecretResponse res = null;
|
||||
try {
|
||||
res = connector.readSecret(SECRET_PATH + "/toRevoke");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Written secret could not be read.");
|
||||
}
|
||||
assumeThat(res, is(notNullValue()));
|
||||
|
||||
/* Revoke secret */
|
||||
try {
|
||||
connector.revoke(SECRET_PATH + "/toRevoke");
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Revocation threw unexpected exception.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test revocation of secrets.
|
||||
*/
|
||||
@Test
|
||||
public void createTokenTest() {
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
/* Create token */
|
||||
Token token = new TokenBuilder()
|
||||
.withId("test-id")
|
||||
.withDisplayName("test name")
|
||||
.build();
|
||||
|
||||
/* Create token */
|
||||
try {
|
||||
AuthResponse res = connector.createToken(token);
|
||||
assertThat("No result given.", res, is(notNullValue()));
|
||||
assertThat("Token creation returned warnings.", res.getWarnings(), is(nullValue()));
|
||||
assertThat("Invalid token ID returned.", res.getAuth().getClientToken(), is("test-id"));
|
||||
assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(1));
|
||||
assertThat("Root policy not inherited.", res.getAuth().getPolicies(), contains("root"));
|
||||
assertThat("Metadata unexpected.", res.getAuth().getMetadata(), is(nullValue()));
|
||||
assertThat("Root token should not be renewable", res.getAuth().isRenewable(), is(false));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
|
||||
/* Create token with attributes */
|
||||
token = new TokenBuilder()
|
||||
.withId("test-id2")
|
||||
.withDisplayName("test name 2")
|
||||
.withPolicies(Collections.singletonList("testpolicy"))
|
||||
.withoutDefaultPolicy()
|
||||
.withMeta("foo", "bar")
|
||||
.build();
|
||||
try {
|
||||
AuthResponse res = connector.createToken(token);
|
||||
assertThat("Invalid token ID returned.", res.getAuth().getClientToken(), is("test-id2"));
|
||||
assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(1));
|
||||
assertThat("Root policy not inherited.", res.getAuth().getPolicies(), contains("testpolicy"));
|
||||
assertThat("Metadata not given.", res.getAuth().getMetadata(), is(notNullValue()));
|
||||
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("foo"), is("bar"));
|
||||
assertThat("Token should be renewable", res.getAuth().isRenewable(), is(true));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
|
||||
/* Overwrite token */
|
||||
token = new TokenBuilder()
|
||||
.withId("test-id2")
|
||||
.withDisplayName("test name 3")
|
||||
.withPolicies(Arrays.asList("pol1", "pol2"))
|
||||
.withDefaultPolicy()
|
||||
.withMeta("test", "success")
|
||||
.withMeta("key", "value")
|
||||
.withTtl(1234)
|
||||
.build();
|
||||
try {
|
||||
AuthResponse res = connector.createToken(token);
|
||||
assertThat("Invalid token ID returned.", res.getAuth().getClientToken(), is("test-id2"));
|
||||
assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(3));
|
||||
assertThat("Policies not returned as expected.", res.getAuth().getPolicies(), contains("default", "pol1", "pol2"));
|
||||
assertThat("Old policy not overwritten.", res.getAuth().getPolicies(), not(contains("testpolicy")));
|
||||
assertThat("Metadata not given.", res.getAuth().getMetadata(), is(notNullValue()));
|
||||
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("test"), is("success"));
|
||||
assertThat("Metadata not correct.", res.getAuth().getMetadata().get("key"), is("value"));
|
||||
assertThat("Old metadata not overwritten.", res.getAuth().getMetadata().get("foo"), is(nullValue()));
|
||||
assertThat("TTL not set correctly", res.getAuth().getLeaseDuration(), is(1234));
|
||||
assertThat("Token should be renewable", res.getAuth().isRenewable(), is(true));
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Secret written to inaccessible path.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test TLS connection with custom certificate chain.
|
||||
*/
|
||||
@Test
|
||||
public void tlsConnectionTest() {
|
||||
TokenResponse res;
|
||||
try {
|
||||
connector.authToken("52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6");
|
||||
fail("Logged in with invalid token");
|
||||
} catch (VaultConnectorException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
res = connector.authToken(TOKEN_ROOT);
|
||||
assertNotNull("Login failed with valid token", res);
|
||||
assertThat("Login failed with valid token", connector.isAuthorized(), is(true));
|
||||
} catch (VaultConnectorException ignored) {
|
||||
fail("Login failed with valid token");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Vault with resource datastore and generated configuration.
|
||||
*
|
||||
* @param tls use TLS
|
||||
* @return Vault Configuration
|
||||
* @throws IllegalStateException on error
|
||||
*/
|
||||
private VaultConfiguration initializeVault() throws IllegalStateException {
|
||||
private VaultConfiguration initializeVault(boolean tls) throws IllegalStateException {
|
||||
String dataResource = getClass().getResource("/data_dir").getPath();
|
||||
|
||||
/* Generate vault local unencrypted configuration */
|
||||
VaultConfiguration config = new VaultConfiguration()
|
||||
.withHost("127.0.0.1")
|
||||
.withHost("localhost")
|
||||
.withPort(getFreePort())
|
||||
.withDataLocation(dataResource)
|
||||
.disableMlock();
|
||||
|
||||
/* Enable TLS with custom certificate and key, if required */
|
||||
if (tls) {
|
||||
config.enableTLS()
|
||||
.withCert(getClass().getResource("/tls/server.pem").getPath())
|
||||
.withKey(getClass().getResource("/tls/server.key").getPath());
|
||||
}
|
||||
|
||||
/* Write configuration file */
|
||||
BufferedWriter bw = null;
|
||||
File configFile = null;
|
||||
File configFile;
|
||||
try {
|
||||
configFile = tmpDir.newFile("vault.conf");
|
||||
bw = new BufferedWriter(new FileWriter(configFile));
|
||||
bw.write(config.toString());
|
||||
}
|
||||
catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException("Unable to generate config file.");
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
try {
|
||||
if (bw != null)
|
||||
bw.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -342,8 +805,7 @@ public class HTTPVaultConnectorTest {
|
||||
/* Authenticate as valid user */
|
||||
try {
|
||||
connector.authToken(TOKEN_ROOT);
|
||||
}
|
||||
catch(VaultConnectorException ignored) {
|
||||
} catch (VaultConnectorException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,13 +815,13 @@ public class HTTPVaultConnectorTest {
|
||||
private void authUser() {
|
||||
try {
|
||||
connector.authUserPass(USER_VALID, PASS_VALID);
|
||||
}
|
||||
catch(VaultConnectorException ignored) {
|
||||
} catch (VaultConnectorException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return a free TCP port.
|
||||
*
|
||||
* @return port number
|
||||
*/
|
||||
private static Integer getFreePort() {
|
||||
@ -387,4 +849,16 @@ public class HTTPVaultConnectorTest {
|
||||
}
|
||||
throw new IllegalStateException("Unable to find a free TCP port.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve StackTrace from throwable as string
|
||||
*
|
||||
* @param th the throwable
|
||||
* @return the stack trace
|
||||
*/
|
||||
private static String stackTrace(final Throwable th) {
|
||||
StringWriter sw = new StringWriter();
|
||||
th.printStackTrace(new PrintWriter(sw, true));
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for AppRole Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AppRoleBuilderTest {
|
||||
|
||||
|
||||
private static final String NAME = "TestRole";
|
||||
private static final String ID = "test-id";
|
||||
private static final Boolean BIND_SECRET_ID = true;
|
||||
private static final List<String> BOUND_CIDR_LIST = new ArrayList<>();
|
||||
private static final String CIDR_1 = "192.168.1.0/24";
|
||||
private static final String CIDR_2 = "172.16.0.0/16";
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final Integer SECRET_ID_NUM_USES = 10;
|
||||
private static final Integer SECRET_ID_TTL = 7200;
|
||||
private static final Integer TOKEN_TTL = 4800;
|
||||
private static final Integer TOKEN_MAX_TTL = 9600;
|
||||
private static final Integer PERIOD = 1234;
|
||||
private static final String JSON_MIN = "{\"role_name\":\"" + NAME + "\"}";
|
||||
private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"bound_cidr_list\":\"%s\",\"policies\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"token_ttl\":%d,\"token_max_ttl\":%d,\"period\":%d}",
|
||||
NAME, ID, BIND_SECRET_ID, CIDR_1, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD);
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
BOUND_CIDR_LIST.add(CIDR_1);
|
||||
POLICIES.add(POLICY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build role with only a name.
|
||||
*/
|
||||
@Test
|
||||
public void buildDefaultTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getId(), is(nullValue()));
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
assertThat(role.getBoundCidrList(), is(nullValue()));
|
||||
assertThat(role.getPolicies(), is(nullValue()));
|
||||
assertThat(role.getSecretIdNumUses(), is(nullValue()));
|
||||
assertThat(role.getSecretIdTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenTtl(), is(nullValue()));
|
||||
assertThat(role.getTokenMaxTtl(), is(nullValue()));
|
||||
assertThat(role.getPeriod(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should only contain role_name */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
public void buildFullTest() throws JsonProcessingException {
|
||||
AppRole role = new AppRoleBuilder(NAME)
|
||||
.withId(ID)
|
||||
.withBindSecretID(BIND_SECRET_ID)
|
||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
||||
.withPolicies(POLICIES)
|
||||
.withSecretIdNumUses(SECRET_ID_NUM_USES)
|
||||
.withSecretIdTtl(SECRET_ID_TTL)
|
||||
.withTokenTtl(TOKEN_TTL)
|
||||
.withTokenMaxTtl(TOKEN_MAX_TTL)
|
||||
.withPeriod(PERIOD)
|
||||
.build();
|
||||
assertThat(role.getName(), is(NAME));
|
||||
assertThat(role.getId(), is(ID));
|
||||
assertThat(role.getBindSecretId(), is(BIND_SECRET_ID));
|
||||
assertThat(role.getBoundCidrList(), is(BOUND_CIDR_LIST));
|
||||
assertThat(role.getPolicies(), is(POLICIES));
|
||||
assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES));
|
||||
assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL));
|
||||
assertThat(role.getTokenTtl(), is(TOKEN_TTL));
|
||||
assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL));
|
||||
assertThat(role.getPeriod(), is(PERIOD));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
public void convenienceMethodsTest() {
|
||||
/* bind_secret_id */
|
||||
AppRole role = new AppRoleBuilder(NAME).build();
|
||||
assertThat(role.getBindSecretId(), is(nullValue()));
|
||||
role = new AppRoleBuilder(NAME).withBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(true));
|
||||
role = new AppRoleBuilder(NAME).withoutBindSecretID().build();
|
||||
assertThat(role.getBindSecretId(), is(false));
|
||||
|
||||
/* Add single CIDR subnet */
|
||||
role = new AppRoleBuilder(NAME).withCidrBlock(CIDR_2).build();
|
||||
assertThat(role.getBoundCidrList(), hasSize(1));
|
||||
assertThat(role.getBoundCidrList(), contains(CIDR_2));
|
||||
role = new AppRoleBuilder(NAME)
|
||||
.withBoundCidrList(BOUND_CIDR_LIST)
|
||||
.withCidrBlock(CIDR_2)
|
||||
.build();
|
||||
assertThat(role.getBoundCidrList(), hasSize(2));
|
||||
assertThat(role.getBoundCidrList(), contains(CIDR_1, CIDR_2));
|
||||
|
||||
/* Add single policy */
|
||||
role = new AppRoleBuilder(NAME).withPolicy(POLICY_2).build();
|
||||
assertThat(role.getPolicies(), hasSize(1));
|
||||
assertThat(role.getPolicies(), contains(POLICY_2));
|
||||
role = new AppRoleBuilder(NAME)
|
||||
.withPolicies(POLICIES)
|
||||
.withPolicy(POLICY_2)
|
||||
.build();
|
||||
assertThat(role.getPolicies(), hasSize(2));
|
||||
assertThat(role.getPolicies(), contains(POLICY, POLICY_2));
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.emptyString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.junit.MatcherAssume.assumeThat;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for AppRoleSecret model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.5.0
|
||||
*/
|
||||
public class AppRoleSecretTest {
|
||||
|
||||
private static final String TEST_ID = "abc123";
|
||||
private static final Map<String, Object> TEST_META = new HashMap<>();
|
||||
private static final List<String> TEST_CIDR = Arrays.asList("203.0.113.0/24", "198.51.100.0/24");
|
||||
|
||||
static {
|
||||
TEST_META.put("foo", "bar");
|
||||
TEST_META.put("number", 1337);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructors.
|
||||
*/
|
||||
@Test
|
||||
public void constructorTest() {
|
||||
/* Empty constructor */
|
||||
AppRoleSecret secret = new AppRoleSecret();
|
||||
assertThat(secret.getId(), is(nullValue()));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
|
||||
/* Constructor with ID */
|
||||
secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(nullValue()));
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
|
||||
/* Constructor with Metadata and CIDR bindings */
|
||||
secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
|
||||
assertThat(secret.getId(), is(TEST_ID));
|
||||
assertThat(secret.getAccessor(), is(nullValue()));
|
||||
assertThat(secret.getMetadata(), is(TEST_META));
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
assertThat(secret.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret.getNumUses(), is(nullValue()));
|
||||
assertThat(secret.getTtl(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setter.
|
||||
*/
|
||||
@Test
|
||||
public void setterTest() {
|
||||
AppRoleSecret secret = new AppRoleSecret(TEST_ID);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
secret.setCidrList(TEST_CIDR);
|
||||
assertThat(secret.getCidrList(), is(TEST_CIDR));
|
||||
assertThat(secret.getCidrListString(), is(String.join(",", TEST_CIDR)));
|
||||
secret.setCidrList(null);
|
||||
assertThat(secret.getCidrList(), is(nullValue()));
|
||||
assertThat(secret.getCidrListString(), is(emptyString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test JSON (de)serialization.
|
||||
*/
|
||||
@Test
|
||||
public void jsonTest() throws NoSuchFieldException, IllegalAccessException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
/* A simple roundtrip first. All set fields should be present afterwards. */
|
||||
AppRoleSecret secret = new AppRoleSecret(TEST_ID, TEST_META, TEST_CIDR);
|
||||
String secretJson = "";
|
||||
try {
|
||||
secretJson = mapper.writeValueAsString(secret);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
fail("Serialization failed");
|
||||
}
|
||||
/* CIDR list is comma-separated when used as input, but List otherwise, hence convert string to list */
|
||||
secretJson = commaSeparatedToList(secretJson);
|
||||
|
||||
AppRoleSecret secret2;
|
||||
try {
|
||||
secret2 = mapper.readValue(secretJson, AppRoleSecret.class);
|
||||
assertThat(secret.getId(), is(secret2.getId()));
|
||||
assertThat(secret.getMetadata(), is(secret2.getMetadata()));
|
||||
assertThat(secret.getCidrList(), is(secret2.getCidrList()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail("Deserialization failed");
|
||||
}
|
||||
|
||||
/* Test fields, that should not be written to JSON */
|
||||
setPrivateField(secret, "accessor", "TEST_ACCESSOR");
|
||||
assumeThat(secret.getAccessor(), is("TEST_ACCESSOR"));
|
||||
setPrivateField(secret, "creationTime", "TEST_CREATION");
|
||||
assumeThat(secret.getCreationTime(), is("TEST_CREATION"));
|
||||
setPrivateField(secret, "expirationTime", "TEST_EXPIRATION");
|
||||
assumeThat(secret.getExpirationTime(), is("TEST_EXPIRATION"));
|
||||
setPrivateField(secret, "lastUpdatedTime", "TEST_UPDATETIME");
|
||||
assumeThat(secret.getLastUpdatedTime(), is("TEST_UPDATETIME"));
|
||||
setPrivateField(secret, "numUses", 678);
|
||||
assumeThat(secret.getNumUses(), is(678));
|
||||
setPrivateField(secret, "ttl", 12345);
|
||||
assumeThat(secret.getTtl(), is(12345));
|
||||
try {
|
||||
secretJson = mapper.writeValueAsString(secret);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
fail("Serialization failed");
|
||||
}
|
||||
try {
|
||||
secret2 = mapper.readValue(commaSeparatedToList(secretJson), AppRoleSecret.class);
|
||||
assertThat(secret.getId(), is(secret2.getId()));
|
||||
assertThat(secret.getMetadata(), is(secret2.getMetadata()));
|
||||
assertThat(secret.getCidrList(), is(secret2.getCidrList()));
|
||||
assertThat(secret2.getAccessor(), is(nullValue()));
|
||||
assertThat(secret2.getCreationTime(), is(nullValue()));
|
||||
assertThat(secret2.getExpirationTime(), is(nullValue()));
|
||||
assertThat(secret2.getLastUpdatedTime(), is(nullValue()));
|
||||
assertThat(secret2.getNumUses(), is(nullValue()));
|
||||
assertThat(secret2.getTtl(), is(nullValue()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail("Deserialization failed");
|
||||
}
|
||||
|
||||
/* Those fields should be deserialized from JSON though */
|
||||
secretJson = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
|
||||
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
|
||||
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
|
||||
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}";
|
||||
try {
|
||||
secret2 = mapper.readValue(secretJson, AppRoleSecret.class);
|
||||
assertThat(secret2.getAccessor(), is("TEST_ACCESSOR"));
|
||||
assertThat(secret2.getCreationTime(), is("TEST_CREATION"));
|
||||
assertThat(secret2.getExpirationTime(), is("TEST_EXPIRATION"));
|
||||
assertThat(secret2.getLastUpdatedTime(), is("TEST_LASTUPDATE"));
|
||||
assertThat(secret2.getNumUses(), is(678));
|
||||
assertThat(secret2.getTtl(), is(12345));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail("Deserialization failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void setPrivateField(Object object, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = object.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
|
||||
private static String commaSeparatedToList(String json) {
|
||||
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":\\[$1\\]")
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for AuthBackend model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class AuthBackendTest {
|
||||
|
||||
/**
|
||||
* Test forType() method.
|
||||
*/
|
||||
@Test
|
||||
public void forTypeTest() {
|
||||
assertThat(AuthBackend.forType("token"), is(AuthBackend.TOKEN));
|
||||
assertThat(AuthBackend.forType("app-id"), is(AuthBackend.APPID));
|
||||
assertThat(AuthBackend.forType("userpass"), is(AuthBackend.USERPASS));
|
||||
assertThat(AuthBackend.forType(""), is(AuthBackend.UNKNOWN));
|
||||
assertThat(AuthBackend.forType("foobar"), is(AuthBackend.UNKNOWN));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.model;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit Test for Token Builder.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public class TokenBuilderTest {
|
||||
|
||||
private static final String ID = "test-id";
|
||||
private static final String DISPLAY_NAME = "display-name";
|
||||
private static final Boolean NO_PARENT = false;
|
||||
private static final Boolean NO_DEFAULT_POLICY = false;
|
||||
private static final Integer TTL = 123;
|
||||
private static final Integer NUM_USES = 4;
|
||||
private static final List<String> POLICIES = new ArrayList<>();
|
||||
private static final String POLICY = "policy";
|
||||
private static final String POLICY_2 = "policy2";
|
||||
private static final String POLICY_3 = "policy3";
|
||||
private static final Map<String, String> META = new HashMap<>();
|
||||
private static final String META_KEY = "key";
|
||||
private static final String META_VALUE = "value";
|
||||
private static final String META_KEY_2 = "key2";
|
||||
private static final String META_VALUE_2 = "value2";
|
||||
private static final Boolean RENEWABLE = true;
|
||||
private static final String JSON_FULL = "{\"id\":\"test-id\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}";
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
POLICIES.add(POLICY);
|
||||
META.put(META_KEY, META_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without any parameters.
|
||||
*/
|
||||
@Test
|
||||
public void buildDefaultTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder().build();
|
||||
assertThat(token.getId(), is(nullValue()));
|
||||
assertThat(token.getDisplayName(), is(nullValue()));
|
||||
assertThat(token.getNoParent(), is(nullValue()));
|
||||
assertThat(token.getNoDefaultPolicy(), is(nullValue()));
|
||||
assertThat(token.getTtl(), is(nullValue()));
|
||||
assertThat(token.getNumUses(), is(nullValue()));
|
||||
assertThat(token.getPolicies(), is(nullValue()));
|
||||
assertThat(token.getMeta(), is(nullValue()));
|
||||
assertThat(token.isRenewable(), is(nullValue()));
|
||||
|
||||
/* optional fields should be ignored, so JSON string should be empty */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token without all parameters set.
|
||||
*/
|
||||
@Test
|
||||
public void buildFullTest() throws JsonProcessingException {
|
||||
Token token = new TokenBuilder()
|
||||
.withId(ID)
|
||||
.withDisplayName(DISPLAY_NAME)
|
||||
.withNoParent(NO_PARENT)
|
||||
.withNoDefaultPolicy(NO_DEFAULT_POLICY)
|
||||
.withTtl(TTL)
|
||||
.withNumUses(NUM_USES)
|
||||
.withPolicies(POLICIES)
|
||||
.withMeta(META)
|
||||
.withRenewable(RENEWABLE)
|
||||
.build();
|
||||
assertThat(token.getId(), is(ID));
|
||||
assertThat(token.getDisplayName(), is(DISPLAY_NAME));
|
||||
assertThat(token.getNoParent(), is(NO_PARENT));
|
||||
assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY));
|
||||
assertThat(token.getTtl(), is(TTL));
|
||||
assertThat(token.getNumUses(), is(NUM_USES));
|
||||
assertThat(token.getPolicies(), is(POLICIES));
|
||||
assertThat(token.getMeta(), is(META));
|
||||
assertThat(token.isRenewable(), is(RENEWABLE));
|
||||
|
||||
/* Verify that all parameters are included in JSON string */
|
||||
assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test convenience methods
|
||||
*/
|
||||
@Test
|
||||
public void convenienceMethodsTest() {
|
||||
/* Parent */
|
||||
Token token = new TokenBuilder().asOrphan().build();
|
||||
assertThat(token.getNoParent(), is(true));
|
||||
token = new TokenBuilder().withParent().build();
|
||||
assertThat(token.getNoParent(), is(false));
|
||||
|
||||
/* Default policy */
|
||||
token = new TokenBuilder().withDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(false));
|
||||
token = new TokenBuilder().withoutDefaultPolicy().build();
|
||||
assertThat(token.getNoDefaultPolicy(), is(true));
|
||||
|
||||
/* Renewability */
|
||||
token = new TokenBuilder().renewable().build();
|
||||
assertThat(token.isRenewable(), is(true));
|
||||
token = new TokenBuilder().notRenewable().build();
|
||||
assertThat(token.isRenewable(), is(false));
|
||||
|
||||
/* Add single policy */
|
||||
token = new TokenBuilder().withPolicy(POLICY_2).build();
|
||||
assertThat(token.getPolicies(), hasSize(1));
|
||||
assertThat(token.getPolicies(), contains(POLICY_2));
|
||||
token = new TokenBuilder()
|
||||
.withPolicies(POLICY, POLICY_2)
|
||||
.withPolicy(POLICY_3)
|
||||
.build();
|
||||
assertThat(token.getPolicies(), hasSize(3));
|
||||
assertThat(token.getPolicies(), contains(POLICY, POLICY_2, POLICY_3));
|
||||
|
||||
/* Add single metadata */
|
||||
token = new TokenBuilder().withMeta(META_KEY_2, META_VALUE_2).build();
|
||||
assertThat(token.getMeta().size(), is(1));
|
||||
assertThat(token.getMeta().keySet(), contains(META_KEY_2));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
token = new TokenBuilder()
|
||||
.withMeta(META)
|
||||
.withMeta(META_KEY_2, META_VALUE_2)
|
||||
.build();
|
||||
assertThat(token.getMeta().size(), is(2));
|
||||
assertThat(token.getMeta().get(META_KEY), is(META_VALUE));
|
||||
assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2));
|
||||
}
|
||||
}
|
@ -1,5 +1,20 @@
|
||||
package de.stklcode.jvault.connector.test;
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.test;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.jvault.connector.test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@ -15,6 +31,8 @@ public class VaultConfiguration {
|
||||
private boolean disableTLS;
|
||||
private boolean disableMlock;
|
||||
private Path dataLocation;
|
||||
private String certFile;
|
||||
private String keyFile;
|
||||
|
||||
public VaultConfiguration() {
|
||||
this.disableTLS = true;
|
||||
@ -36,6 +54,16 @@ public class VaultConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration withCert(String certFile) {
|
||||
this.certFile = certFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration withKey(String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VaultConfiguration disableMlock() {
|
||||
this.disableMlock = true;
|
||||
return this;
|
||||
@ -70,6 +98,8 @@ public class VaultConfiguration {
|
||||
"listener \"tcp\" {\n" +
|
||||
" address = \"" + host + ":" + port + "\"\n" +
|
||||
((disableTLS) ? " tls_disable = 1\n" : "") +
|
||||
((certFile != null) ? " tls_cert_file = \"" + certFile + "\"\n" : "") +
|
||||
((keyFile != null) ? " tls_key_file = \"" + keyFile + "\"\n" : "") +
|
||||
"}\n" +
|
||||
((disableMlock) ? "disable_mlock = true" : "");
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/salt","Value":"AAAAAQKDLmmb/XlhfVJ45oKGyYwneS9s3tcQUenB8bTcxuDmAMUWnwG8oNNJFs0mSCF9Yv1KOq3Twxj4qPp05viFnP0z"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/da42ddc9a483efd8ddeae4ab38428f73d42ad7f6320705f333555fed8593cbe2","Value":"AAAAAQLCu78fbRRgGWG++5XDCfaO/8NTg7LMAJL7aCsrn6c1WHJ5yrAAmWmSs1euhNd7yKUd0lQ0aknCKdPAZFBlAsqgOdnN8JLFe/H9lISaWdU6lRIfgTH9whEXWT0VK25FcS4r5yVe3Qoxg0DfT8FhjuzOa70="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e83aed0dd0b867f09aa1dbc88b965eafba6030458d6555712e82c479cee3d2d7","Value":"AAAAAQL7t56z9Fr92ztubIfZPPkV3X1Aljnn95Y/tDXOxn8vjbjf21Fhyj3UnLwWyzK/9ip/6+x2DJBXikBOvXoCqKLXGegZ4JN9Z9UMiQ88aE9Z978r13E/rNbhIUa/PhT5NGwCbOl6vtK2hL06BHxKb+4+goM="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/accessor/e96c348451147331101ad48e157e8056ca1b039ee63a6aafd2d66446c94bcad8","Value":"AAAAAQIcvMn5QMtwELRDXZD9nNf7y/8O6z7u0NUZqyJrBb2OYDRvGpSuPS3CIareSxl8y5F4xtadvhyhunCGBUd289H9foMjfGbVVsM1mbM5i6FDTW0sFOPmXX44mQV29PVNMO+fcLuSWb0+qU4erqylpcvdLW8="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role/testrole1","Value":"AAAAAQLyV03lH8m3IYxoZKLf+/suZ+2wwKAyIHqrR3QeJZK+68wslLXy0XZ35bPrdc3jzAFhTizqILlgTBHVccdM/pydtTtbsvGHQlWstLaC79GUTM32gS/jwSrbwfa9j0q/Yrdo2LSa9IM5lw2tmYy+xR9c3ZKcm+VADZMZy3+6UmbQ1t0lniZ4uuVmqu2gl3y0732UtdMSxJepPWMjfvVq5+tynhgvEZNGgZCPc9lsV1fcBVFswtBUeATNnSJPmTnxQflXyhitPOpEM+5L+gnEsSNsyinRjv5cSbIHCP5yDzvpiWtwZ5Q0psVRSh/WJppBHcovwbJsTLK/tZ1wtFl1OgU9NLONEpgDJYiDyU0ACeFJ7r+DhjIDrQkr+WITnfBBwI+65wpOPYboqGgd4qZy84PE2s/VhWS5hjpxgpM="}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role/testrole2","Value":"AAAAAQIA7g8ifdb9dcRQtIagNGpu2Miv6Dy4jBif1J9OZd26AgFDL6eZTrDr3FfmUQQUs/izDlfI9FDB+UJZO6P2B6vkTchwSg0JdOD8lHjtuoCSDKrIPmzallXHFGwnMnzFY80JzNlzUEfbzciExXthpUjlvBoMlHydZPtAn3pL2NkJdwW1dDRARGB9RoWguqYVgCMkOVdpLFYMVSN1nyHvlt2sm3IdwsXxlE9kH1HGiIEKWYX1U0l8uM0NJTZPFo8Km09u9sz/yzS9B+cyIKXaom7h7S53yRyGP7rFZObl3INMloJyJn7+XxpqiZYAiK31tToZ9k4Y3Eez1ZyCj+oujM6MDwnnzlAkOm3nptIySOk9+iEehr6rG5fpt3WTVSEC3f+1Q+4S"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role_id/b2b271423a16ba322c3f87616230f8ced5e89bc8d1a32f0ce91c3d3b5f264a8a","Value":"AAAAAQJhm8OnoLuGdSqb3GhF36ALFfIdoRHQ0SMaC1CAuhlfgzuPcyZFMgHr7IL1UepjItfW"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/role_id/fb5542bdc4127acea06e585384296c607d18d139be530ac52f850b703b22bcb4","Value":"AAAAAQJMBpriwrK36PPIVHKh4hNEU66EXyp5npyEF3JxUD0BTQW/vQC6hrnDnSF9F59Xh1Ut"}
|
@ -0,0 +1 @@
|
||||
{"Key":"auth/ac4e0527-a7b2-1b40-1148-dc0dfaf01990/secret_id/7ec357dbed8f1b49bb2302aff1f08c57c2f03e03b842b7714ed13a5f9fbe970d/941884199542458348fa08c650246e293eb2bf743350861d73b8fc2978ae5c3a","Value":"AAAAAQLESOciqLucvh8+6PvJKIAQV+P4dPm8q8lweJm5KKH5/Ffh7rtp3btSJhUj2ey5SZummV1mF2rABJ7VROSSjOTbb698VpdXPUeK/qDlyAiT3f2vP16dCbsr1K8Pd0XRdRyrw6osnUwuLgNa9L4pBAoprPn5UwflZVAmwNPWMH3B6Ieo5aZrStP3xuDfU+tjvljaEQALwQAqqo0LTBVU2idw96g/TO75VjbcnptiJOeTPqctJKmh/tdaf1F7x2vOyu5IkhBX3PO4Qn+5F4am66q7HQfB773ga8ZSUoSkph7nahF6JtmHKJ+A972iK9NFx/69jOe1ylwwzzlG4aP1bsrYjGgCIk3CNrvUmK7iO0X9AbzOEgz2d27/VbmGh/bb29z8Oc6Tiw2Qo/tiQtNUreamE5q0UN9XTVC/wdUd5ZdG7RftT6Zv3imPIuAwHJ+GTNSI4HCwc5as/HXMA2xrUdYeuj0rdJejYtyEBQ=="}
|
@ -1 +1 @@
|
||||
{"Key":"core/auth","Value":"AAAAAQKA3+V0TsgRYXO8NxjN1y6nBjUL9B2eOJe4Cfi56B3qmzGx1mhyn1SRkyWBbRIjIOp/a8d52P5ukK3AU3FpOC8w8W/aYLZVZONhMn4tnzvN9+FDYp5Kx8FqNBunDgOwygkMsgd0fnrAgxefUU1z4iY5hlXl/45qwWE6HXbrCJ5uBciHZajmKbCZPe9oc/i0Lw0hZXW598kJV6OmzGesWqYmkbyohv5d1vTB1nuDNG5MvxtWoNIcF5u5+x487zg0FQ6womZOyR7xQKxXyIYescIjAmSjJ6Xlr0rj41NSCzMIhP6fkDHI+YiPAcXDHynjMRV4rky9PG5PSJQgp1jYUUjo/3crc1ssBMSPTEecdc9xOyS903o2/fvc9aFm0CBOtlrlbLzzEztIrHPwJAkCoyqgpk/LcJgV6DRM8xmy+MDTNBFnLhzTeKyK2z7c932JYHTNO8YiIzmc8xAOY46YMEofGu0dVi6QTtfxIs3934NoO5p+EM0RcBnLme8FVWr+QsyL64SFJ3sF7t9WuwRccLTpJaQm5r7YsUFSOZSczrMkWAPIyJFprCA678HVgpVUUOeA1vC96am7+IybvOD8n7Hwu8PCKoXUStsJya+WR1gZ3zjd6zN9byibve6MXxMvYpFp4zv4l2whavvPzO5sCM6xookFvhUVZPvcTrQIhxSoTLabJClss4VJKZoV6HK4m4JZcgKXAVuHBf4WHDV+vFPnc5IITneMR1I2GYJPaOlhDlB2MO0WbCBWDc+EhuelmuiUdZFT3u4zshaODpPzvVzWwbWwIQyFfL7dM3ZCiIGS9Bo6pAj6b8zsjg=="}
|
||||
{"Key":"core/auth","Value":"AAAAAQKy/0yKRpmA5LiZxPlXV+5jBS7lsbsXcACqT/BmXs0nsEP0oHLb4423GWadgYKg1+Vow5qNcLgc6JufLVkEz4dnAcTU1plaCYhRxSGrO/rlAIsKTgwFkKYnV2YRmiSjxKT8hnWw1SHmxappAhZYDMvVVrE9BYGmrCXSmeopjIPLYWgO7UB9/jda7bzMQx9mDVDRUBhRRi4vXUYgo3Dwm1Dznh2yv20ts7O5BVBtpncXB/RovRRhvh2bn/H+RfE0NuZRhQnZ9S6ATF3kGmJX33OiTmBqHBaS8cvPPSZHWmEcXnM8bHEjYxUNZB6+RattgGYVfGtujKWHfwfwJ96VlfIXbQCoZ7bIa1czNa+xhuoOKvaV70crYT4drFnnu4RoV3+HqZl7qsmS8o4MJINoCO6All6GfK7lsRivVzPIZ9M4H6towxfBvEcDvTDHZlL5pOVp7yPP2PSTs0wHM/e9Gg2x9j7nNSDw2KWKTMrxvxHb53dZ3TaaTB388oylLoaNUTG3PlnKAwB4yMp7OpapWH1qX0oo1k3M+XzOX3krHD9UImCTN5DnNZ7jKf8MJ/0aoDi37lNLvQ+0dEXrhsnsRodb2mnCVbp0UhQpPp+Y3yLnB9zBYVAD8Dnt0hOgsxz3WcFOwNX2zeT7OgGnZlTP+NtKKVfXHYjh18JS7mypA7hkh1scBBLqwMyXpzWkKwnBrJYMM1Le1ht2erJvJ4hmLdISidQ8K7ULcS2Gjht+W83ITqC2fO4NIL8QwP9gk6QyIdC8BSHy0mOlZTkT0m5rnVnvl8CV2BbX0lUKTFSmEz6Z0L4nS0/obBRIrWgKgDw3jqnq6vcvmIH4xaOTfRWUeNMQiFnXEsj6tZvRSdpYmAv9jDbdWEBCA2gFkA8wxZ+MSgRIZE8ETUt//5gcvbLncBadS+d7DcqicXUje6jHCQbPg/j9zK38/cKGIszbqVavb89tf0PEQDJB4HOPiPs5kij3T8GtxgFW1DiT23TvtubQF0XsMnv9N3avwTeJoVtBwMTrO1mIam5EHqmvtftnTQycPg9MURmw54fpUevv/Og="}
|
||||
|
1
src/test/resources/data_dir/core/cluster/local/_info
Normal file
1
src/test/resources/data_dir/core/cluster/local/_info
Normal file
@ -0,0 +1 @@
|
||||
{"Key":"core/cluster/local/info","Value":"AAAAAQLM3HpjYNukfnGPRBV4yhHkaDqTMag0rk3fDmRcUt5pzDH0yh/2ZRuF7czOYsfV6146nxmUfekMrH457GtCMPIppE4x0WkikQRxiA5fSw9lYT8yeErVL1o7ETNo3AHPib2ldxBdX8ik3jY="}
|
@ -0,0 +1 @@
|
||||
{"Key":"logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/complex","Value":"AAAAAQJGyPQ1TFtwJLO5tbYDvnXDxbK0GVxef0qXs4h2ddHTdWFvk+WJWsTw2l+Igr5v5KY5HOQz/apI6Vo2LmwY"}
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/expire/id/auth/userpass/login/validUser/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLS9Dgic+3ywWAIR7I3J+9PmdEt81fce3eOTNpcT/TRNDkzD5NY3WEQjBLM7UzxGMg7M88IeGi6L7Rd+ZmoKjL0zogptwvKYggG4P0z+fCQW+/WgpIYEB1187wsF7wh7GQtXTXKE9F/dtKFvfi+3KsZ/0//tXcs9fUqPuJFJSUelcMaIeb2emle4p+kjs0pDuSNzovIGvRToLW4f5TbqVy0ve0zo8r/7IwKlrxo7E2uY0xzJX6IjygIACFm7GjRZgy2rkl0v9Be0T31k/zDWsEPINXu2a+vsYqjZTkRWevrK2ZE8IQBlJcFER5bcnsZiA89wm0VTcwBbYlWJ32IM9AJw/75DGMQ1wbdyJ8PUWvdhyl9i9HahtHWKCo9oH8qTiBjbmkrCECCaUeV1TgpqcqyglxBkgn6Qlb5kgNEHeXxCPy8GarT2gHlmPNaWunnxqE71WuVLZ4+PBlCjmksyXQtdqmDIRE1oSHeuohBQ2dA0B/rDmhLwXBssA+/eQDONLm639VrLJR4IRaNo04PEdxz8pec8W5fG5+Ea3Z171nl3FseZO78i3Wj7Y2KvYFA1XWNlrucxWg0jRI1hDlUHXqLh7nqctdudkI8NrkwbAE6W6a9imMUnTd3yIHN05ke9ihlJrVvAaBbgav4ssz3tnYC/s3TmozGic2TdXGxi9ewMKhdfntXi1VQEJ52i2QmWsnDAUoISHFaK+azNFt7sD5tCKmSIdpS4IL9g6RMH/sVAzuB0ZT+83jYY+jP9L4SajQs4ncWkrMQmJ0fxGs62x6lBxk1LtI2qzV1J57+1QZxFoQc6OQINec3VoQ1t7aFpqYYDk9GKEA/hk8vM5vhwc058RPpjYM8l+3PCPOilMh+FgqOs++8HBTarMTp"}
|
@ -1 +1 @@
|
||||
{"Key":"sys/policy/response-wrapping","Value":"AAAAAQLDl3zy1uKv9o2NhIyl43YAtoxGChOUc4aMa7beod+3e8FkdOsZt9BIirHsqjJ+VoxQyz+HroBaNfKPsyos3WLWvz5IUZ1UHr/jLG2SjrJfCKvco85RsFytkzp3T+Z5JB2vVfm22PpBIbjq2+XpHLKIqARqTWYl7Wnql572JZOvPY0w"}
|
||||
{"Key":"sys/policy/response-wrapping","Value":"AAAAAQI0PU/pu6EEHcT4HwfZjzScyW8DLBzmGDanjLuWqGEtlLcKgRLZh7/c/CRWwbRXy2d3GUB1Bo3YVzpUuDDlNY3NaipcORS3zzCHep5uO/DFUJ3DPSlde8j1BrmSpQDHerAsJYXYEManr93puObYs1cEfP9Mt8WdC/IPhgecSw32tVGBz0SSP2qaXGwdJQva6xroMWqmwMVU/lsVi/qcV459xXiTYU/8Kp6Xbqx0p0SRR0yVdM+yNiMtYtnzoxWdptbSYLTG1mhumA=="}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/token/accessor/f36b16467afa41b83f8d2f467ce86b0a848aebbf","Value":"AAAAAQKCq6Zqg/q7n6Oi/FfipknrqzI7vYVD9IB+FUuZR56CWUngRRLOs4kLU78vNboCenbYQ3kDYtnxOvUD4xOjNktUzvXoqV0sF0N1p50Mc+MBsR1kzRbbk3nhxocW6lvOmnwLwnE7TtQdEMiU4sHeCoitFgWXfITl2YVxNnY5SXbq4ZSHAVlF"}
|
@ -1 +1 @@
|
||||
{"Key":"sys/token/id/05b3023411dd89a9a27282d57d027f5312be4adc","Value":"AAAAAQIUAO6ILG2gwWjc+J2kp4n03Rp6ycNYAWBYEM0ygocB7DmIT531H5cLbqFVJF5Zw+OQie0HOVLX/zcAPWtxkTOIRXH9FIUT14T9k1IzoxEOYSrbI6ig8bFffe4cd9b0qj9UKgwakQ1GG8vfeSXZnJjVBCSsvWL46s/IGh+SEmirNTiGSE3iy8p3+zunl2s/mUP08i/We03LcLTsCBfSsHVa/CongLNKgSq4oF23LFxv3De+9j8+IQ9HKA0pAatTaCjHdU1TsAiBGsKUhujGW5oQuygkUYVIBFqFqwDOytpdcxiP/A2LAut6qvQjvfT7s7C/Cvke9ypOQAr7iSmUlAhKcXPPEN21NdBmFq4K4w=="}
|
||||
{"Key":"sys/token/id/05b3023411dd89a9a27282d57d027f5312be4adc","Value":"AAAAAQKiu1H1ntud1j4D5e/ZkrSbjuiQgzXK2/b+chRAVynYtfOSrY4pz4BYwZ31OU/VFdsL66Em2FLgGQDVWi6IdM9d3ao7i+EkRf842PAgKrX99coubFB4QBVHqyKhMwfDUmzflirVgSKy4IgKDVKkR08Z6ETHOGBs4Rc9c97pwYsXJP9OE8dSass3jXVLADKCe+MWJeqv1iKTAQSWlWxa75VNXNYiTYcVQ9LYS3egvDeMOqHWBICnoQGnjaHV9Yz/GmCT5YvqwZL+ZOYvy/DwlyFfr6XIWsrbpVOELWU+SPJCvVriE8E67mbDqthh0I1Du3FoE2AJl+5bIEXQIMlezWTLJN7DdnEnTCWssOdEE6LBz8Ue3o2yFe82HS8mucJECOLIjGuEm0aLAXrKzC7RlFOvkl7q0BNu+AQbg5tAe4PUBrFf+cdMdQ81FxNOOAmrjByhnnLCT8ASEd4Ugv3N1PafZtiZQ4ks8U0ppvqdFWgjnlw="}
|
||||
|
@ -0,0 +1 @@
|
||||
{"Key":"sys/token/id/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLf0+mzTh9i2njHeuHQTkC0cDkZGbSHljPETXi4PtH7V1bwuJHi7LLiS3TQNDLl9M/jR6eVK/V374Q+qKdi6sZjVvRKErpbuZhX6YjYy/YNCKs9RJcU21wgXM0emBH6cvrVkzWz7y9UdrTR86e4PU8GrqkbtKUWZ08EcB+jt3mlzkOK+3lRBj9mmDC1McsZ4ALw8Y13Mq6a8xSeSxX4ZJLq4MYfI2GtR3JiEdYdx8gS5YlbbgxTjwxEOUC1mxwDHw+rsguh9eOD6RZaUTvL3MIvQsggoYU9kecvP9jvMnOfhRwd8pT93ilE+MWRylKI8ZOc7K1TMU+qw7Eho5KRKCuR7AXpWrc23SIkkMTDqmaLZiwyM5+fGR1R0c/KpsrzYo5X+TU3SMghlmrQyTHEEU6RGmAOC7RWfFrV1144T390hE9zhbY1zMRmtgBY9qsueXvK3pVaQT83/PswVGR8jliThzXjCsy12BwThBNlZVpEKZK8oI3HRqMk2jpkSpG2cAYiWNnZV9fbipNa92ovGeHHOTM9ZdPpX8apxS47CnMbuwdkNPmCvu+wtRBuGsbmmEwy+F8czMRJuAHu"}
|
21
src/test/resources/tls/ca.pem
Normal file
21
src/test/resources/tls/ca.pem
Normal file
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDfzCCAmegAwIBAgIJAIsdtmg40qeTMA0GCSqGSIb3DQEBDQUAMFYxCzAJBgNV
|
||||
BAYTAkRFMQowCAYDVQQIDAEgMREwDwYDVQQKDAhzdGtsY29kZTENMAsGA1UECwwE
|
||||
VGVzdDEZMBcGA1UEAwwQc3RrbGNvZGUgVGVzdCBDQTAeFw0xNjExMDYxMDM4MDda
|
||||
Fw00NjEwMzAxMDM4MDdaMFYxCzAJBgNVBAYTAkRFMQowCAYDVQQIDAEgMREwDwYD
|
||||
VQQKDAhzdGtsY29kZTENMAsGA1UECwwEVGVzdDEZMBcGA1UEAwwQc3RrbGNvZGUg
|
||||
VGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKIVAIDK++4v
|
||||
mH8/V9fELi3X3Ychgz2WP+dDbXrHsIdkQnmT9sdCfZuLH/0V98XwWQAFHlSfc9GB
|
||||
4NEID31y/f76AcKhuAx4aLebMBp6L4eJssahhxLoKzodFZm9WVIj6g6kXl6Auc9z
|
||||
v9d+DH70PHGtf/ORqnkiuraY5hTzUK7pMrRkL/BFuZyMOtsDsaBWuImZTuf8s2aF
|
||||
URLbD1cnFKn3LbeydlAipA12EXgZ1KhmY8X8BOrDRQlHTIjRjCs0kV3Jc8thi2xt
|
||||
N+Yo/Zm8HqP/fmuszeID0WWgRpmE8RTg8WuoDAJAb600xKEK11qpXkUT3vHiot5N
|
||||
np6HoQXm0HUCAwEAAaNQME4wHQYDVR0OBBYEFFiwMeDNFusyU90UELnglsankCkd
|
||||
MB8GA1UdIwQYMBaAFFiwMeDNFusyU90UELnglsankCkdMAwGA1UdEwQFMAMBAf8w
|
||||
DQYJKoZIhvcNAQENBQADggEBAEwk8fDIo1Wc3EpJKNKjsCZbaiyC8GiiYfuKQVmq
|
||||
82jAacf7MUw8EgpuboDwEbDSIhCeEyM/t8mgttcT/DP0vD3qMhpkNLQcuSK0NFza
|
||||
XvnoPqHMZhxerc7QBMeEKYFRjUd8iPiT3D8rYPdWq8klQnLIPyws2/uyijIXo9k3
|
||||
oiPMBUO+WAe3tLwO9EV6Ff9q5BmlVufngPT1R4wTNR6mZQ3yy8CWPOsk3CBCyleT
|
||||
8maCnFjhJ9fBz74WVgAO7QE72VTwsu9MZ+DawsHt8oKaNU1dfIXfqMHKh3KItn1N
|
||||
cIIlhpnIUtxoWEawH6NbtCoQpTRBSZ8EoBhP4z9jC2+A7i0=
|
||||
-----END CERTIFICATE-----
|
27
src/test/resources/tls/client.key
Normal file
27
src/test/resources/tls/client.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAs+l54Lm03sacNzjlj5V2gUJPJvDQsAKi/O313vbsv4FLxFX8
|
||||
QnGYFKouFAtVW4MTpEN6ciFP6ucwb6YxtoOKIxZ4nqmMDz4R3Q2Spep7Q9I9kISX
|
||||
LMvs92qE1phSqhi6dfH+ZTTPl9HlpWmSWhDReBqfSK1QPJVB1QUrmZA4yCxSfpD6
|
||||
sx0R28sPLuzR/lTiPB2aFst6aM9wG8ZMrl7KYO37W6QH/0p3CfvPdB42b8q5txTG
|
||||
l9Ia++eTcZE69ESyA9LLaPWLfjzGCCW/FbF/zd3WvV8oH7IXqrOfW532Sy6Ui2Id
|
||||
8DmtoNHTulFFKypDe5sF0aFWpkoJsqvaDj/I9wIDAQABAoIBAHXCDBQbeVeXiAhd
|
||||
JWSl37sbO9OxK+cI0sXau2QFG1D9wCnyXfrffzuHaEGWaXhMgz6xLCQnybdnOzzY
|
||||
+xELaA8vViQDtbkEV4zopWQT5jquEb3WC1023RPUlL4hVXogVWt9yZVUy8wDhtyO
|
||||
DU0GVRTX2Aop5qrAxyY3DCKnU4Mw5pZW6tVrALh2W+c/7tlB3mp89uzgRVLsOyP1
|
||||
KoCiIWkb83DT73rTTYg2NOL+69Pp0idtADEE8tuo/3pgcZhAVI9jtisnWg7MsSWu
|
||||
rKkNCS3vOcxAKG9kw3znJfVVH7ZF1LaDVx9LP4inEwVQfg9aImhkjquIgGT0iDgK
|
||||
e62Zx4ECgYEA2YWsXSjRFrscataSM+w71tH4GlE0FAJx5FW+F4YeTfnn+k7FaXuE
|
||||
562737GqsadOXkNiVVgfxsB6snR2WWjxJKuPHGJWncl7yR/MdRmradQGsQYe/xTa
|
||||
AMouZIHp7BWPV/TG6s3x2ezx2GvMhGUnJ43QvTipuJFSDFObgROvz+MCgYEA07yn
|
||||
4PnKXmnIZbhXz9wkvmDpbfPcCrapFmtRXBTK7fbwEA+YPl3xPjkvDX8cQDTsze7h
|
||||
R+o0jMG0VPwmjfECHva5GWemcN5AFMPfuGqik0jacXa81oti0H5L67Z/ffeFxYnD
|
||||
UXukXFInDLT0c8/k1Ex4shwfjiaat030olweBt0CgYEAu5+6ogx/9bxlcZ4tM84z
|
||||
e0NXXtPmONA3Dv4KXl4YK6hAuT5St36MkA3iPLwSAPTP+yziV70Qg64o517fapXD
|
||||
Up8MbS5Big5t0Hi2Mdd3bGwvbWhbOijxNbcvNxB8BmA+aV7AaW5Ei3X+0W+CVDyv
|
||||
/kUr5NtIQeRPQkSnoDmr74MCgYEAyrnqksEXPWZS9PGXQfEpTQ5E8X12xNs28bw2
|
||||
3c8arNSt7PLBdZVEkar2nhmB1wfVYybAk7ZuMgaUvnneADEtMrBPcT+IYLCq8jbI
|
||||
US3oEtTCMbjZ/SDfr3f9AOZvExCXCBdq5u1W5P3TXZs0Il5+XbYKKZ47qELWB4Og
|
||||
IoPITBECgYBvA3+4YL006l/Hkyf21aDiqh3kUAhuPVSXd5ef9EvE2fxMR225jTks
|
||||
URCwYxi/Njg5B2FtuXZjq/eqis/piNtqr3nwZcpiOiwr8J/jwwBXPbtIcE5Nxjzx
|
||||
ag6bkbXe6mpxvHDtroAw84sC0h77ztyJ4Lq/khiEjq+XTPn1iEJ+DQ==
|
||||
-----END RSA PRIVATE KEY-----
|
20
src/test/resources/tls/client.pem
Normal file
20
src/test/resources/tls/client.pem
Normal file
@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDVzCCAj8CCQDn4qCNgPQBezANBgkqhkiG9w0BAQ0FADBWMQswCQYDVQQGEwJE
|
||||
RTEKMAgGA1UECAwBIDERMA8GA1UECgwIc3RrbGNvZGUxDTALBgNVBAsMBFRlc3Qx
|
||||
GTAXBgNVBAMMEHN0a2xjb2RlIFRlc3QgQ0EwHhcNMTYxMTA2MTA0MTQ4WhcNNDEx
|
||||
MDMxMTA0MTQ4WjCBhDELMAkGA1UEBhMCREUxCjAIBgNVBAgMASAxETAPBgNVBAoM
|
||||
CHN0a2xjb2RlMQ0wCwYDVQQLDARUZXN0MSMwIQYDVQQDDBpzdGtsY29kZSBWYXVs
|
||||
dCBUZXN0IENsaWVudDEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBzdGtsY29kZS5k
|
||||
ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPpeeC5tN7GnDc45Y+V
|
||||
doFCTybw0LACovzt9d727L+BS8RV/EJxmBSqLhQLVVuDE6RDenIhT+rnMG+mMbaD
|
||||
iiMWeJ6pjA8+Ed0NkqXqe0PSPZCElyzL7PdqhNaYUqoYunXx/mU0z5fR5aVpkloQ
|
||||
0Xgan0itUDyVQdUFK5mQOMgsUn6Q+rMdEdvLDy7s0f5U4jwdmhbLemjPcBvGTK5e
|
||||
ymDt+1ukB/9Kdwn7z3QeNm/KubcUxpfSGvvnk3GROvREsgPSy2j1i348xgglvxWx
|
||||
f83d1r1fKB+yF6qzn1ud9ksulItiHfA5raDR07pRRSsqQ3ubBdGhVqZKCbKr2g4/
|
||||
yPcCAwEAATANBgkqhkiG9w0BAQ0FAAOCAQEAaW0XEGs8PpHV9dfDD3QERoDpuqsj
|
||||
IkTSO6+e1Ah/Uak6nDPSkAHwS53Avz2SElM3kGa9DVniXOVxC9OjM/E74vncv71w
|
||||
/MLiIS3aXbTgiUmDhuTutBrL9Q3HJGOfO6gqEyQakPfW1NFUFleJKvWKNX0S4eeZ
|
||||
2nXt7da7xaxR6r0L6nwRrWT85ys/jdDgfF0SnmQRmddQttsmRCJ3DXq0z2EeXbO3
|
||||
J8XFF+Y+SyV0CB7bjHx0BXZPaISUMAqnifRqDyw/4G/9iLqFN2Lc0Lxp74w6D/8z
|
||||
OSiHwFvjG1dwEkwnPL9V5vD4/BgeClre4FWqD6wqS3UwLdq6DzEaSNKHJw==
|
||||
-----END CERTIFICATE-----
|
51
src/test/resources/tls/server.key
Normal file
51
src/test/resources/tls/server.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKAIBAAKCAgEA3WItNwzszD4/ok3uydlOa7WCprOX4+4Lui8EscR4d7axWv31
|
||||
A8Vp8GyxASi1MyCIxMeldD/uCzh4EInvuxhfFHr0BjYqHMj4kSf8u5Qo4b7n6A2K
|
||||
rfiVH9qsoz1Cvl4ocLRGKH0JqcWORcKFVWhAhSDKjdu13ckgQxUWC4lNRzjIfMlI
|
||||
F8BLHTivZO/RTcVBlm/ukpVxG8aeaSyD0vGnoiqhkq6L9K8NRQ7H65lwALHtYeOB
|
||||
jEdIJxbMHi+G6Imm4eO88pneC7TIshPYSEMmIhpYYhXIMhyN2V31/ER7gOs4b+Sd
|
||||
ymInjRRH8zTYITIq1wcqbtTIWVqoYqLYAkiLzFVJgEDhOJaCToUv8SU2+bkjhS96
|
||||
e0h/01shcNKBNNO1z7g/gKG0ywwTgSijAENQxW5VmYV5n7ITyZF0mGR35dPszLG+
|
||||
uEpFTt959+WK/VgAUoeYk5gbr025hnD1MMByXkRUMnk2n8Y4ksZ083dtoyeEpgxz
|
||||
gT+kSAvDcjm1x/7GpAqUr5dKaJxmEUKflk+y7swhRJfp8KDgvrW8MhKsHsAEOynI
|
||||
3sehnqb49VZKfYwPgs9gGCDVLnS05CROPy3sPgYEh/N13PMdZq8UOcENnTye3NlA
|
||||
l3nXx0fm6wDwdVclVQq8P4mqGVpHmV0EJcNm9VtVohRZRgPYD7fjTVv5nVcCAwEA
|
||||
AQKCAgBo7xgvd9jmFrti2z3MP0yEkUyUZ5wfVb4JSjAXcuEHHXmDf8ybNP+6Dkr4
|
||||
GauJyGoLm/Y42/ShLOr8K+WN8UdgFceFCjd73Wa0pxeMcfXOywZxX7nULHfC2Yvq
|
||||
9CamxUq14T1AA8SIzDNbrZA1o2yxrZFVHEdgEO1R3rTMUxBmKewd+epKF8OC3lOE
|
||||
rIexLUahX/zdTiiG2eZMQ+VYH2Mt4rcjJ8j++dp4WUE500jbi3rRY10MeN0iahPm
|
||||
WvC/WD/Z4nC1LWmqcs6OWgmyduGkWIh8NYbm+dHirj7ijDNeMCBYKS0BuPS2Ul6o
|
||||
UOwBEB5uPd9HGWS9tdMKrdVlf62DE1IBQT1/Dl5gO6FpPZv+DPDirXjs90thEaUQ
|
||||
rgeGP/FiLwyYppr31rPKVSWZ3at7cxifHsiTBFQDGVOaId1BykBzqiEzi4SYgrSu
|
||||
Bd5hzH/nwjjfmx6MPo/mp/YEIIF1abwUghgwvFeo/NbLIof9/Tj77E3wHuOTdff7
|
||||
xPcM7a+9nqgquJ0OyiqB5qJLnBjqUF1X1jDOR2qS5+Y4E0nVE1bHI30yr/nl3TJT
|
||||
uVK3Ea+y5tMjydX7lzdRUmzuF+dRGrMiwAS9A85oI+oe+BS6LLjD1bLWAPK6kuIf
|
||||
jf9pxtAqOFnfOBF/bVPbS1xBVV224aErZwvNO+66+bkvsvdPgQKCAQEA8kudmJo3
|
||||
EDkK5rTLeeBfke2aLNxkIVSQtGAVh2F2Ra8+HQ5wpoWtm5Rc64G8kviuSZDgyG7Y
|
||||
x/tLPkXpb7kM1m1j6pxIw4163sSZNyKX2qtQZQP62tmxi2sGYwrB3aj7IXtQ7HjI
|
||||
NiEuZS1P9kP5djSBwtM7YDVu1nDc63vQPEOKwpfySxDf8ABSUscsrdl1lzKN+TOu
|
||||
+9uEO8V0RsQETiVkpirGXhrdz0wYViOGqwHNZNwQz99W2mjIrpO8bG94ctw6HJ5x
|
||||
x6P1U2L2GdHwIs9mDO4aUmWOKQ3+bGJ/J4G0Vwx13TR/DUDDPDTuUZhWSsstoB6F
|
||||
ekxKOyFtAtnFWQKCAQEA6efC/CYKEDrFe0MAfmXeDT5cKCrC9erpRukogMm9CvaH
|
||||
2GIdmhuMDbS7mkmOB3UW9SJ0HKQLtArZ2wFtk3CxPUxEGbPkk4HMsMKubwOpG751
|
||||
bSPo8PX7JUwEklPRqKhf0DoCEUjtessRqy/4ea/jiOhLiY+wPc/gLxjQzFMBR8fm
|
||||
mHArMahMa9fEuqwn+xRLcSDAWSb1CLJ4GV6ULupXhI/3l20gJiz6AobyZbHfTnBd
|
||||
nJJQQgvAa0QxAQy4HjQ+AmjedcyQnNfR27TuuCVwkQz4ffG9zHV9kuiYUqJ3nkBD
|
||||
3tYHoWCkRAiLorEuM4M67L3Fi0+durImmJxZ86syLwKCAQAL4PMoAR+D9xf2uZRk
|
||||
NEDbOafeXSu3iprRjQhhK8ENp4rHB+cz8sfRIdPwY9rn5bM9vhGXIgAUxdgphGnu
|
||||
ZUcg2BoW7XSPycblVwQf9N03BkEZwrkws42FxUh54JQilt9BA/eysDU4miXZJgCO
|
||||
lUSMrARUleCKVfRKJRxfmyFZYwJRifuB/KDN9mYS0tr45vlh4UOenQ8OH/P6rjKG
|
||||
KaQAZMrrbpttD6oiOJvU1UcL6Tm1oShd2Jg8evijvnB1bH2eO/fJYWc4n2wum2Jv
|
||||
X6CDRGG/bojx0zLGBn6bt7R+Lli2D9FTd/hmoO8xa3Lnoy1P22gwOm7W0Riuj3P1
|
||||
uNF5AoIBAAlt8Gxd1DYHSILJlrGBxcve4bQ01Rs41yKmr51RhK92dM+CVRMrXSAI
|
||||
Uy/LG1CtpblIJEorStV9Qn8Ttakl998yveQTXnmb1/agQovzJ9QYf39g3TkpkXBV
|
||||
ejGz81XLQ+GPFRpBSGGU4id2jZvKPW/9fV4UTtSPFsiPRYuXJQwRwPgQPY2I7VvD
|
||||
nQixfAMhNFFhMp/ldCdfmnvbVjn19IVBkIeoPI2Nbp6/dfInk4sD+KIhO98NvjoU
|
||||
y6zxKFL/ZCiQtbcmAgZwpOMojh8aU0llrnbVUgN2ERPlEI70QcI9cP8AvdoBnV2o
|
||||
wohSgDxPZAa7N8V/9inamLe6Rd4O3r0CggEBAJAWIm87f+tAI81UYG3ndDXFfy/m
|
||||
uODIRjnXyaPNj+B2+xJ0ygnmrSZo/7lZUCcU2ixCqx3HMwkWhOciOrpQ2i2yrY66
|
||||
db1/F/4RYanCpMp1b3OQxLk4VluketpCsZTR8ZJNKbBx5kCwFO6CYfvgeo7xO5b0
|
||||
2x3mt/QX+Ch9l+84TamClUdQsN0toMLQT821gLes7zgw2Rn3gWoN335dvKtVtyRC
|
||||
pZpLDm44vd+85piF2VOdr7r6RsmAylpKRvleyD3Q7kDI2PpIlb16zPt6BA5VjSjo
|
||||
U9UWQ4g4V0wum1KJiKYmumartgP9TGoql6zVAJxlcRdB3l2IaFPdizu7K1E=
|
||||
-----END RSA PRIVATE KEY-----
|
25
src/test/resources/tls/server.pem
Normal file
25
src/test/resources/tls/server.pem
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEMTCCAxkCCQDn4qCNgPQBejANBgkqhkiG9w0BAQ0FADBWMQswCQYDVQQGEwJE
|
||||
RTEKMAgGA1UECAwBIDERMA8GA1UECgwIc3RrbGNvZGUxDTALBgNVBAsMBFRlc3Qx
|
||||
GTAXBgNVBAMMEHN0a2xjb2RlIFRlc3QgQ0EwHhcNMTYxMTA2MTAzODQxWhcNNDEx
|
||||
MDMxMTAzODQxWjBfMQswCQYDVQQGEwJERTEKMAgGA1UECAwBIDERMA8GA1UECgwI
|
||||
c3RrbGNvZGUxHTAbBgNVBAsMFFZhdWx0IENvbm5lY3RvciBUZXN0MRIwEAYDVQQD
|
||||
DAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDdYi03
|
||||
DOzMPj+iTe7J2U5rtYKms5fj7gu6LwSxxHh3trFa/fUDxWnwbLEBKLUzIIjEx6V0
|
||||
P+4LOHgQie+7GF8UevQGNiocyPiRJ/y7lCjhvufoDYqt+JUf2qyjPUK+XihwtEYo
|
||||
fQmpxY5FwoVVaECFIMqN27XdySBDFRYLiU1HOMh8yUgXwEsdOK9k79FNxUGWb+6S
|
||||
lXEbxp5pLIPS8aeiKqGSrov0rw1FDsfrmXAAse1h44GMR0gnFsweL4boiabh47zy
|
||||
md4LtMiyE9hIQyYiGlhiFcgyHI3ZXfX8RHuA6zhv5J3KYieNFEfzNNghMirXBypu
|
||||
1MhZWqhiotgCSIvMVUmAQOE4loJOhS/xJTb5uSOFL3p7SH/TWyFw0oE007XPuD+A
|
||||
obTLDBOBKKMAQ1DFblWZhXmfshPJkXSYZHfl0+zMsb64SkVO33n35Yr9WABSh5iT
|
||||
mBuvTbmGcPUwwHJeRFQyeTafxjiSxnTzd22jJ4SmDHOBP6RIC8NyObXH/sakCpSv
|
||||
l0ponGYRQp+WT7LuzCFEl+nwoOC+tbwyEqwewAQ7Kcjex6Gepvj1Vkp9jA+Cz2AY
|
||||
INUudLTkJE4/Lew+BgSH83Xc8x1mrxQ5wQ2dPJ7c2UCXedfHR+brAPB1VyVVCrw/
|
||||
iaoZWkeZXQQlw2b1W1WiFFlGA9gPt+NNW/mdVwIDAQABMA0GCSqGSIb3DQEBDQUA
|
||||
A4IBAQA4nrZlyoN/iyRDWZqudXyedMRVUquekzvkcPndInAaW2ukOl+LMGdN7C5n
|
||||
wjglyg5DV0aDNy+Mpy/rInC4kZ5UDKfHjYg4Q9x6kdZOch9gJ6Qvq7hhP8hLUcta
|
||||
pi/m3+k+PP/X6V1oSLxTl/Ja6peDvK1eo5imAbyEPz0kQNHZ88BxEAWGaQgNbItM
|
||||
SC7xmrO78o832d07KF8fJL+o35KV0EuHKMnvr2TLv09kL61EKRRiEMxb6x/90Jw8
|
||||
Rys/FnZh+N0Xdk8sfpq6itGnaDqZSBw0EPhBDXcX9bNpztm8JIIZv101H208BfYG
|
||||
GyJ1DYEp2FfyLgVcY9hNi6P0tmzn
|
||||
-----END CERTIFICATE-----
|
Reference in New Issue
Block a user