Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
17145e53be | |||
e988833eb9 | |||
ea3b6d50cb | |||
3f7f88e14a | |||
3396693120 | |||
ca51fed145 | |||
9c216dd805 | |||
b98b7ab95c | |||
ecf398c9d0 | |||
a80805a044 |
@ -1,3 +1,8 @@
|
|||||||
|
## 0.4.1 [2016-12-24]
|
||||||
|
* [fix] Factory Null-tolerant for trusted certificate (#6)
|
||||||
|
* [test] StackTraces testet for secret leaks
|
||||||
|
* [test] Tested against Vault 0.6.4
|
||||||
|
|
||||||
## 0.4.0 [2016-11-06]
|
## 0.4.0 [2016-11-06]
|
||||||
* [feature] Option to provide a trusted CA certificate (#2)
|
* [feature] Option to provide a trusted CA certificate (#2)
|
||||||
* [feature] Deletion, revocation and renewal of secrets (#3)
|
* [feature] Deletion, revocation and renewal of secrets (#3)
|
||||||
|
13
README.md
13
README.md
@ -5,26 +5,31 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
|
|||||||
**Current available features:**
|
**Current available features:**
|
||||||
|
|
||||||
* HTTP(S) backend connector
|
* HTTP(S) backend connector
|
||||||
|
* Ability to provide or enforce custom CA certificate
|
||||||
* Authorization methods:
|
* Authorization methods:
|
||||||
* Token
|
* Token
|
||||||
* Username/Password
|
* Username/Password
|
||||||
* AppID (register and authenticate)
|
* AppID (register and authenticate) [_deprecated_]
|
||||||
* AppRole (register and authenticate)
|
* AppRole (register and authenticate)
|
||||||
|
* Tokens
|
||||||
|
* Creation and lookup of tokens
|
||||||
|
* TokenBuilder for speaking creation of complex configuraitons
|
||||||
* Secrets
|
* Secrets
|
||||||
* Read secrets
|
* Read secrets
|
||||||
* Write secrets
|
* Write secrets
|
||||||
* List secrets
|
* List secrets
|
||||||
* Delete secrets
|
* Delete secrets
|
||||||
* Renew/revoke leases
|
* Renew/revoke leases
|
||||||
|
* Raw secret content or JSON decoding
|
||||||
* Connector Factory with builder pattern
|
* Connector Factory with builder pattern
|
||||||
* Tested against Vault 0.6.2
|
* Tested against Vault 0.6.4
|
||||||
|
|
||||||
**Usage Example**
|
**Usage Example**
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Instanciate using builder pattern style factory
|
// Instanciate using builder pattern style factory
|
||||||
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
VaultConnector vault = VaultConnectorFactory.httpFactory()
|
||||||
.wiithHost("127.0.0.1")
|
.withHost("127.0.0.1")
|
||||||
.withPort(8200)
|
.withPort(8200)
|
||||||
.withTLS()
|
.withTLS()
|
||||||
.build();
|
.build();
|
||||||
@ -41,7 +46,7 @@ String secret = vault.readSecret("some/secret/key").getValue();
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.stklcode.jvault</groupId>
|
<groupId>de.stklcode.jvault</groupId>
|
||||||
<artifactId>connector</artifactId>
|
<artifactId>connector</artifactId>
|
||||||
<version>0.4.0</version>
|
<version>0.4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
8
pom.xml
8
pom.xml
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>de.stklcode.jvault</groupId>
|
<groupId>de.stklcode.jvault</groupId>
|
||||||
<artifactId>connector</artifactId>
|
<artifactId>connector</artifactId>
|
||||||
<version>0.4.0</version>
|
<version>0.4.1</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.6.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
@ -41,12 +41,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
<version>2.8.4</version>
|
<version>2.8.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>2.8.4</version>
|
<version>2.8.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -49,7 +49,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
private static final String PATH_SEAL_STATUS = "sys/seal-status";
|
private static final String PATH_SEAL_STATUS = "sys/seal-status";
|
||||||
private static final String PATH_SEAL = "sys/seal";
|
private static final String PATH_SEAL = "sys/seal";
|
||||||
private static final String PATH_UNSEAL = "sys/unseal";
|
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_RENEW = "sys/renew";
|
||||||
private static final String PATH_AUTH = "sys/auth";
|
private static final String PATH_AUTH = "sys/auth";
|
||||||
private static final String PATH_TOKEN = "auth/token";
|
private static final String PATH_TOKEN = "auth/token";
|
||||||
@ -136,7 +135,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
/**
|
/**
|
||||||
* Create connector using full URL and trusted certificate.
|
* Create connector using full URL and trusted certificate.
|
||||||
*
|
*
|
||||||
* @param baseURL The URL
|
* @param baseURL The URL
|
||||||
|
* @param sslContext Custom SSL Context
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnector(String baseURL, SSLContext sslContext) {
|
public HTTPVaultConnector(String baseURL, SSLContext sslContext) {
|
||||||
this.baseURL = baseURL;
|
this.baseURL = baseURL;
|
||||||
@ -196,12 +196,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean init() {
|
|
||||||
/* TODO: implement init() */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
public List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||||
try {
|
try {
|
||||||
@ -240,6 +234,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
public AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
||||||
final Map<String, String> payload = new HashMap<>();
|
final Map<String, String> payload = new HashMap<>();
|
||||||
payload.put("app_id", appID);
|
payload.put("app_id", appID);
|
||||||
@ -281,6 +276,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException {
|
public boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
throw new AuthorizationRequiredException();
|
throw new AuthorizationRequiredException();
|
||||||
@ -296,6 +292,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
public boolean registerUserId(final String appID, final String userID) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
throw new AuthorizationRequiredException();
|
throw new AuthorizationRequiredException();
|
||||||
@ -499,7 +496,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean writeSecret(final String key, final String value) throws VaultConnectorException {
|
public void writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
throw new AuthorizationRequiredException();
|
throw new AuthorizationRequiredException();
|
||||||
|
|
||||||
@ -508,11 +505,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
Map<String, String> param = new HashMap<>();
|
Map<String, String> param = new HashMap<>();
|
||||||
param.put("value", value);
|
param.put("value", value);
|
||||||
return requestPost(PATH_SECRET + "/" + key, param).equals("");
|
if (!requestPost(PATH_SECRET + "/" + key, param).equals(""))
|
||||||
|
throw new InvalidResponseException("Received response where none was expected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean deleteSecret(String key) throws VaultConnectorException {
|
public void deleteSecret(String key) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
throw new AuthorizationRequiredException();
|
throw new AuthorizationRequiredException();
|
||||||
|
|
||||||
@ -521,13 +519,11 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
/* Response should be code 204 without content */
|
/* Response should be code 204 without content */
|
||||||
if (!response.equals(""))
|
if (!response.equals(""))
|
||||||
throw new InvalidResponseException("Received response where non was expected.");
|
throw new InvalidResponseException("Received response where none was expected.");
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean revoke(String leaseID) throws VaultConnectorException {
|
public void revoke(String leaseID) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
throw new AuthorizationRequiredException();
|
throw new AuthorizationRequiredException();
|
||||||
|
|
||||||
@ -536,9 +532,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
/* Response should be code 204 without content */
|
/* Response should be code 204 without content */
|
||||||
if (!response.equals(""))
|
if (!response.equals(""))
|
||||||
throw new InvalidResponseException("Received response where non was expected.");
|
throw new InvalidResponseException("Received response where none was expected.");
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,13 +32,6 @@ import java.util.List;
|
|||||||
* @since 0.1
|
* @since 0.1
|
||||||
*/
|
*/
|
||||||
public interface VaultConnector {
|
public interface VaultConnector {
|
||||||
/**
|
|
||||||
* Verify that vault connection is initialized.
|
|
||||||
*
|
|
||||||
* @return TRUE if correctly initialized
|
|
||||||
*/
|
|
||||||
boolean init();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset authorization information.
|
* Reset authorization information.
|
||||||
*/
|
*/
|
||||||
@ -387,34 +380,32 @@ public interface VaultConnector {
|
|||||||
*
|
*
|
||||||
* @param key Secret path
|
* @param key Secret path
|
||||||
* @param value Secret value
|
* @param value Secret value
|
||||||
* @return TRUE on success
|
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
boolean writeSecret(final String key, final String value) throws VaultConnectorException;
|
void writeSecret(final String key, final String value) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete secret from Vault.
|
* Delete secret from Vault.
|
||||||
*
|
*
|
||||||
* @param key Secret path
|
* @param key Secret path
|
||||||
* @return TRUE on succevss
|
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
boolean deleteSecret(final String key) throws VaultConnectorException;
|
void deleteSecret(final String key) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke given lease immediately.
|
* Revoke given lease immediately.
|
||||||
*
|
*
|
||||||
* @param leaseID the lease ID
|
* @param leaseID the lease ID
|
||||||
* @return TRUE on success
|
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
boolean revoke(final String leaseID) throws VaultConnectorException;
|
void revoke(final String leaseID) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renew lease with given ID.
|
* Renew lease with given ID.
|
||||||
*
|
*
|
||||||
* @param leaseID the lase ID
|
* @param leaseID the lase ID
|
||||||
* @return Renewed lease
|
* @return Renewed lease
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
default SecretResponse renew(final String leaseID) throws VaultConnectorException {
|
default SecretResponse renew(final String leaseID) throws VaultConnectorException {
|
||||||
return renew(leaseID, null);
|
return renew(leaseID, null);
|
||||||
@ -426,6 +417,7 @@ public interface VaultConnector {
|
|||||||
* @param leaseID the lase ID
|
* @param leaseID the lase ID
|
||||||
* @param increment number of seconds to extend lease time
|
* @param increment number of seconds to extend lease time
|
||||||
* @return Renewed lease
|
* @return Renewed lease
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException;
|
SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException;
|
||||||
|
|
||||||
|
@ -128,10 +128,13 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
*
|
*
|
||||||
* @param cert path to certificate file
|
* @param cert path to certificate file
|
||||||
* @return self
|
* @return self
|
||||||
|
* @throws VaultConnectorException on error
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException {
|
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException {
|
||||||
return withSslContext(createSslContext(cert));
|
if (cert != null)
|
||||||
|
return withSslContext(createSslContext(cert));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,10 +30,7 @@ import org.junit.*;
|
|||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -46,7 +43,8 @@ import static org.junit.Assert.*;
|
|||||||
import static org.junit.Assume.*;
|
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
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
@ -143,10 +141,13 @@ public class HTTPVaultConnectorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void authTokenTest() {
|
public void authTokenTest() {
|
||||||
TokenResponse res;
|
TokenResponse res;
|
||||||
|
final String invalidToken = "52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6";
|
||||||
try {
|
try {
|
||||||
connector.authToken("52135869df23a5e64c5d33a9785af5edb456b8a4a235d1fe135e6fba1c35edf6");
|
connector.authToken(invalidToken);
|
||||||
fail("Logged in with invalid token");
|
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 {
|
try {
|
||||||
@ -164,10 +165,15 @@ public class HTTPVaultConnectorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void authUserPassTest() {
|
public void authUserPassTest() {
|
||||||
AuthResponse res = null;
|
AuthResponse res = null;
|
||||||
|
final String invalidUser = "foo";
|
||||||
|
final String invalidPass = "bar";
|
||||||
try {
|
try {
|
||||||
connector.authUserPass("foo", "bar");
|
connector.authUserPass(invalidUser, invalidPass);
|
||||||
fail("Logged in with invalid credentials");
|
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 {
|
try {
|
||||||
@ -183,6 +189,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
* App-ID authentication roundtrip.
|
* App-ID authentication roundtrip.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public void authAppIdTest() {
|
public void authAppIdTest() {
|
||||||
authRoot();
|
authRoot();
|
||||||
assumeTrue(connector.isAuthorized());
|
assumeTrue(connector.isAuthorized());
|
||||||
@ -231,19 +238,27 @@ public class HTTPVaultConnectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Authenticate with valid secret ID against unknown role */
|
/* Authenticate with valid secret ID against unknown role */
|
||||||
|
final String invalidRole = "foo";
|
||||||
try {
|
try {
|
||||||
AuthResponse res = connector.authAppRole("foo", APPROLE_SECRET);
|
connector.authAppRole(invalidRole, APPROLE_SECRET);
|
||||||
fail("Successfully logged in with unknown role");
|
fail("Successfully logged in with unknown role");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
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 */
|
/* Authenticate without wrong secret ID */
|
||||||
|
final String invalidSecret = "foo";
|
||||||
try {
|
try {
|
||||||
AuthResponse res = connector.authAppRole(APPROLE_ROLE, "foo");
|
AuthResponse res = connector.authAppRole(APPROLE_ROLE, "foo");
|
||||||
fail("Successfully logged in without secret ID");
|
fail("Successfully logged in without secret ID");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
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 */
|
/* Authenticate without secret ID */
|
||||||
@ -252,6 +267,8 @@ public class HTTPVaultConnectorTest {
|
|||||||
fail("Successfully logged in without secret ID");
|
fail("Successfully logged in without secret ID");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
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 */
|
/* Authenticate with secret ID on role with CIDR whitelist */
|
||||||
@ -437,11 +454,17 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Try to read path user has no permission to read */
|
/* Try to read path user has no permission to read */
|
||||||
SecretResponse res = null;
|
SecretResponse res = null;
|
||||||
|
final String invalidPath = "invalid/path";
|
||||||
try {
|
try {
|
||||||
res = connector.readSecret("invalid/path");
|
res = connector.readSecret(invalidPath);
|
||||||
fail("Invalid secret path successfully read.");
|
fail("Invalid secret path successfully read.");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, instanceOf(PermissionDeniedException.class));
|
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 to read accessible path with known value */
|
||||||
@ -523,29 +546,28 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Try to write to null path */
|
/* Try to write to null path */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret(null, "someValue");
|
connector.writeSecret(null, "someValue");
|
||||||
fail("Secret written to null path.");
|
fail("Secret written to null path.");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, instanceOf(InvalidRequestException.class));
|
assertThat(e, instanceOf(InvalidRequestException.class));
|
||||||
}
|
}
|
||||||
/* Try to write to invalid path */
|
/* Try to write to invalid path */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret("", "someValue");
|
connector.writeSecret("", "someValue");
|
||||||
fail("Secret written to invalid path.");
|
fail("Secret written to invalid path.");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, instanceOf(InvalidRequestException.class));
|
assertThat(e, instanceOf(InvalidRequestException.class));
|
||||||
}
|
}
|
||||||
/* Try to write to a path the user has no access for */
|
/* Try to write to a path the user has no access for */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret("invalid/path", "someValue");
|
connector.writeSecret("invalid/path", "someValue");
|
||||||
fail("Secret written to inaccessible path.");
|
fail("Secret written to inaccessible path.");
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
assertThat(e, instanceOf(PermissionDeniedException.class));
|
assertThat(e, instanceOf(PermissionDeniedException.class));
|
||||||
}
|
}
|
||||||
/* Perform a valid write/read roundtrip to valid path. Also check UTF8-encoding. */
|
/* Perform a valid write/read roundtrip to valid path. Also check UTF8-encoding. */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret(SECRET_PATH + "/temp", "Abc123äöü,!");
|
connector.writeSecret(SECRET_PATH + "/temp", "Abc123äöü,!");
|
||||||
assertThat("Secret could not be written to valid path.", res, is(true));
|
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Secret written to inaccessible path.");
|
fail("Secret written to inaccessible path.");
|
||||||
}
|
}
|
||||||
@ -567,8 +589,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Write a test secret to vault */
|
/* Write a test secret to vault */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret(SECRET_PATH + "/toDelete", "secret content");
|
connector.writeSecret(SECRET_PATH + "/toDelete", "secret content");
|
||||||
assumeThat("Secret could not be written path.", res, is(true));
|
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Secret written to inaccessible path.");
|
fail("Secret written to inaccessible path.");
|
||||||
}
|
}
|
||||||
@ -582,8 +603,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Delete secret */
|
/* Delete secret */
|
||||||
try {
|
try {
|
||||||
boolean deleted = connector.deleteSecret(SECRET_PATH + "/toDelete");
|
connector.deleteSecret(SECRET_PATH + "/toDelete");
|
||||||
assertThat("Revocation of secret faiked.", deleted, is(true));
|
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Revocation threw unexpected exception.");
|
fail("Revocation threw unexpected exception.");
|
||||||
}
|
}
|
||||||
@ -608,8 +628,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Write a test secret to vault */
|
/* Write a test secret to vault */
|
||||||
try {
|
try {
|
||||||
boolean res = connector.writeSecret(SECRET_PATH + "/toRevoke", "secret content");
|
connector.writeSecret(SECRET_PATH + "/toRevoke", "secret content");
|
||||||
assumeThat("Secret could not be written path.", res, is(true));
|
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Secret written to inaccessible path.");
|
fail("Secret written to inaccessible path.");
|
||||||
}
|
}
|
||||||
@ -623,8 +642,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Revoke secret */
|
/* Revoke secret */
|
||||||
try {
|
try {
|
||||||
boolean revoked = connector.revoke(SECRET_PATH + "/toRevoke");
|
connector.revoke(SECRET_PATH + "/toRevoke");
|
||||||
assertThat("Revocation of secret faiked.", revoked, is(true));
|
|
||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Revocation threw unexpected exception.");
|
fail("Revocation threw unexpected exception.");
|
||||||
}
|
}
|
||||||
@ -752,7 +770,7 @@ public class HTTPVaultConnectorTest {
|
|||||||
|
|
||||||
/* Write configuration file */
|
/* Write configuration file */
|
||||||
BufferedWriter bw = null;
|
BufferedWriter bw = null;
|
||||||
File configFile = null;
|
File configFile;
|
||||||
try {
|
try {
|
||||||
configFile = tmpDir.newFile("vault.conf");
|
configFile = tmpDir.newFile("vault.conf");
|
||||||
bw = new BufferedWriter(new FileWriter(configFile));
|
bw = new BufferedWriter(new FileWriter(configFile));
|
||||||
@ -831,4 +849,16 @@ public class HTTPVaultConnectorTest {
|
|||||||
}
|
}
|
||||||
throw new IllegalStateException("Unable to find a free TCP port.");
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user