#4 token creation implemented
This commit is contained in:
parent
53a459eda1
commit
9618a50646
@ -54,7 +54,10 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
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_INIT = "sys/init";
|
||||||
private static final String PATH_AUTH = "sys/auth";
|
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_USERPASS = "auth/userpass/login/";
|
||||||
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
||||||
private static final String PATH_SECRET = "secret";
|
private static final String PATH_SECRET = "secret";
|
||||||
@ -193,7 +196,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
this.tokenTTL = 0;
|
this.tokenTTL = 0;
|
||||||
try {
|
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);
|
TokenResponse res = jsonMapper.readValue(response, TokenResponse.class);
|
||||||
authorized = true;
|
authorized = true;
|
||||||
return res;
|
return res;
|
||||||
@ -305,6 +308,9 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean writeSecret(final String key, final String value) throws VaultConnectorException {
|
public boolean writeSecret(final String key, final String value) throws VaultConnectorException {
|
||||||
|
if (!isAuthorized())
|
||||||
|
throw new AuthorizationRequiredException();
|
||||||
|
|
||||||
if (key == null || key.isEmpty())
|
if (key == null || key.isEmpty())
|
||||||
throw new InvalidRequestException("Secret path must not be empty.");
|
throw new InvalidRequestException("Secret path must not be empty.");
|
||||||
|
|
||||||
@ -320,7 +326,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
/* Request HTTP response and expect empty result */
|
/* Request HTTP response and expect empty result */
|
||||||
String response = requestDelete(PATH_SECRET + "/" + key);
|
String response = requestDelete(PATH_SECRET + "/" + key);
|
||||||
return response.equals("");
|
|
||||||
|
/* Response should be code 204 without content */
|
||||||
|
if (!response.equals(""))
|
||||||
|
throw new InvalidResponseException("Received response where non was expected.");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -330,7 +341,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
/* Request HTTP response and expect empty result */
|
/* Request HTTP response and expect empty result */
|
||||||
String response = requestPut(PATH_REVOKE + leaseID, new HashMap<>());
|
String response = requestPut(PATH_REVOKE + leaseID, new HashMap<>());
|
||||||
return response.equals("");
|
|
||||||
|
/* Response should be code 204 without content */
|
||||||
|
if (!response.equals(""))
|
||||||
|
throw new InvalidResponseException("Received response where non was expected.");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -340,9 +356,44 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenResponse createToken(final Token token) throws VaultConnectorException {
|
public AuthResponse createToken(final Token token) throws VaultConnectorException {
|
||||||
/* TODO */
|
return createTokenInternal(token, PATH_TOKEN + PATH_CREATE);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,7 +405,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
* @return HTTP response
|
* @return HTTP response
|
||||||
* @throws VaultConnectorException on connection error
|
* @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 */
|
/* Initialize post */
|
||||||
HttpPost post = new HttpPost(baseURL + path);
|
HttpPost post = new HttpPost(baseURL + path);
|
||||||
/* generate JSON from payload */
|
/* generate JSON from payload */
|
||||||
|
@ -217,5 +217,25 @@ public interface VaultConnector {
|
|||||||
* @return the result response
|
* @return the result response
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
*/
|
*/
|
||||||
TokenResponse createToken(final Token token) throws VaultConnectorException;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package de.stklcode.jvault.connector;
|
package de.stklcode.jvault.connector;
|
||||||
|
|
||||||
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
import de.stklcode.jvault.connector.exception.InvalidResponseException;
|
||||||
|
import de.stklcode.jvault.connector.model.Token;
|
||||||
|
import de.stklcode.jvault.connector.model.TokenBuilder;
|
||||||
import de.stklcode.jvault.connector.model.response.*;
|
import de.stklcode.jvault.connector.model.response.*;
|
||||||
import de.stklcode.jvault.connector.test.Credentials;
|
import de.stklcode.jvault.connector.test.Credentials;
|
||||||
import de.stklcode.jvault.connector.test.VaultConfiguration;
|
import de.stklcode.jvault.connector.test.VaultConfiguration;
|
||||||
@ -33,6 +35,8 @@ import java.io.File;
|
|||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
@ -373,6 +377,81 @@ public class HTTPVaultConnectorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Vault with resource datastore and generated configuration.
|
* Initialize Vault with resource datastore and generated configuration.
|
||||||
* @return Vault Configuration
|
* @return Vault Configuration
|
||||||
|
Loading…
x
Reference in New Issue
Block a user