#5 Role and Secret creation implemented and tested
This commit is contained in:
parent
c7b4c46ad2
commit
40742b00de
@ -19,8 +19,7 @@ package de.stklcode.jvault.connector;
|
|||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import de.stklcode.jvault.connector.exception.*;
|
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.Token;
|
|
||||||
import de.stklcode.jvault.connector.model.response.*;
|
import de.stklcode.jvault.connector.model.response.*;
|
||||||
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
import de.stklcode.jvault.connector.model.response.embedded.AuthMethod;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
@ -60,6 +59,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
private static final String PATH_CREATE_ORPHAN = "/create-orphan";
|
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_AUTH_APPROLE = "auth/approle/";
|
||||||
private static final String PATH_SECRET = "secret";
|
private static final String PATH_SECRET = "secret";
|
||||||
private static final String PATH_REVOKE = "sys/revoke/";
|
private static final String PATH_REVOKE = "sys/revoke/";
|
||||||
|
|
||||||
@ -207,31 +207,40 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException {
|
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);
|
payload.put("password", password);
|
||||||
try {
|
return queryAuth(PATH_AUTH_USERPASS + username, payload);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException {
|
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("app_id", appID);
|
||||||
payload.put("user_id", userID);
|
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 {
|
try {
|
||||||
/* Get response */
|
/* Get response */
|
||||||
String response = requestPost(PATH_AUTH_APPID + "login", payload);
|
String response = requestPost(path, payload);
|
||||||
/* Parse response */
|
/* Parse response */
|
||||||
AuthResponse auth = jsonMapper.readValue(response, AuthResponse.class);
|
AuthResponse auth = jsonMapper.readValue(response, AuthResponse.class);
|
||||||
/* verify response */
|
/* verify response */
|
||||||
@ -273,6 +282,162 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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_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) {
|
||||||
|
/* this should never occur and may leak sensible information */
|
||||||
|
throw new InvalidRequestException("Invalid URI format.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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_AUTH_APPROLE + "role?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 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
|
@Override
|
||||||
public SecretResponse readSecret(final String key) throws VaultConnectorException {
|
public SecretResponse readSecret(final String key) throws VaultConnectorException {
|
||||||
if (!isAuthorized())
|
if (!isAuthorized())
|
||||||
@ -514,7 +679,8 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
case 200:
|
case 200:
|
||||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
|
||||||
return br.lines().collect(Collectors.joining("\n"));
|
return br.lines().collect(Collectors.joining("\n"));
|
||||||
} catch (IOException ignored) { }
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
case 204:
|
case 204:
|
||||||
return "";
|
return "";
|
||||||
case 403:
|
case 403:
|
||||||
@ -537,8 +703,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new InvalidResponseException("Unable to read response", e);
|
throw new InvalidResponseException("Unable to read response", e);
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
if (response != null && response.getEntity() != null)
|
if (response != null && response.getEntity() != null)
|
||||||
try {
|
try {
|
||||||
EntityUtils.consume(response.getEntity());
|
EntityUtils.consume(response.getEntity());
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
package de.stklcode.jvault.connector;
|
package de.stklcode.jvault.connector;
|
||||||
|
|
||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
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.Token;
|
|
||||||
import de.stklcode.jvault.connector.model.response.*;
|
import de.stklcode.jvault.connector.model.response.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,9 +110,34 @@ public interface VaultConnector {
|
|||||||
* @param userID The User ID
|
* @param userID The User ID
|
||||||
* @return TRUE on success
|
* @return TRUE on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #authAppRole} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException;
|
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.
|
* Register new App-ID with policy.
|
||||||
*
|
*
|
||||||
@ -121,9 +146,188 @@ public interface VaultConnector {
|
|||||||
* @param displayName Arbitrary name to display
|
* @param displayName Arbitrary name to display
|
||||||
* @return TRUE on success
|
* @return TRUE on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRole} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException;
|
boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new AppRole role from given metamodel.
|
||||||
|
*
|
||||||
|
* @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
|
* Register User-ID with App-ID
|
||||||
*
|
*
|
||||||
@ -131,7 +335,9 @@ public interface VaultConnector {
|
|||||||
* @param userID The User-ID
|
* @param userID The User-ID
|
||||||
* @return TRUE on success
|
* @return TRUE on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole. Consider using {@link #createAppRoleSecret} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
boolean registerUserId(final String appID, final String userID) throws VaultConnectorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,7 +349,9 @@ public interface VaultConnector {
|
|||||||
* @param userID The User-ID
|
* @param userID The User-ID
|
||||||
* @return TRUE on success
|
* @return TRUE on success
|
||||||
* @throws VaultConnectorException on error
|
* @throws VaultConnectorException on error
|
||||||
|
* @deprecated As of Vault 0.6.1 App-ID is superseded by AppRole.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException {
|
default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException {
|
||||||
return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
|
return registerAppId(appID, policy, userID) && registerUserId(appID, userID);
|
||||||
}
|
}
|
||||||
|
147
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
147
src/main/java/de/stklcode/jvault/connector/model/AppRole.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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")
|
||||||
|
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")
|
||||||
|
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 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,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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.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;
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ package de.stklcode.jvault.connector.model;
|
|||||||
public enum AuthBackend {
|
public enum AuthBackend {
|
||||||
TOKEN("token"),
|
TOKEN("token"),
|
||||||
APPID("app-id"),
|
APPID("app-id"),
|
||||||
|
APPROLE("approle"),
|
||||||
USERPASS("userpass"),
|
USERPASS("userpass"),
|
||||||
UNKNOWN("");
|
UNKNOWN("");
|
||||||
|
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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;
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,7 @@
|
|||||||
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.*;
|
||||||
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;
|
||||||
@ -26,7 +25,6 @@ import de.stklcode.jvault.connector.exception.InvalidRequestException;
|
|||||||
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
|
import de.stklcode.jvault.connector.exception.PermissionDeniedException;
|
||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
import de.stklcode.jvault.connector.factory.VaultConnectorFactory;
|
import de.stklcode.jvault.connector.factory.VaultConnectorFactory;
|
||||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
@ -35,9 +33,7 @@ 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.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.core.Is.is;
|
import static org.hamcrest.core.Is.is;
|
||||||
@ -57,6 +53,10 @@ public class HTTPVaultConnectorTest {
|
|||||||
private static String PASS_VALID = "validPass";
|
private static String PASS_VALID = "validPass";
|
||||||
private static String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA";
|
private static String APP_ID = "152AEA38-85FB-47A8-9CBD-612D645BFACA";
|
||||||
private static String USER_ID = "5ADF8218-D7FB-4089-9E38-287465DBF37E";
|
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 = "154fe52a-6df2-b4e9-2dbd-d3c5e6539f9b";
|
||||||
|
private static String APPROLE_ROLE2 = "35b7bf43-9644-588a-e68f-2e8313bb23b7"; // role with CIDR subnet
|
||||||
private static String SECRET_PATH = "userstore";
|
private static String SECRET_PATH = "userstore";
|
||||||
private static String SECRET_KEY = "foo";
|
private static String SECRET_KEY = "foo";
|
||||||
private static String SECRET_KEY_JSON = "json";
|
private static String SECRET_KEY_JSON = "json";
|
||||||
@ -118,8 +118,8 @@ public class HTTPVaultConnectorTest {
|
|||||||
} catch (VaultConnectorException e) {
|
} catch (VaultConnectorException e) {
|
||||||
fail("Could not list supported auth backends: " + e.getMessage());
|
fail("Could not list supported auth backends: " + e.getMessage());
|
||||||
}
|
}
|
||||||
assertThat(supportedBackends.size(), is(3));
|
assertThat(supportedBackends, hasSize(4));
|
||||||
assertThat(supportedBackends, hasItems(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID));
|
assertThat(supportedBackends, hasItems(AuthBackend.TOKEN, AuthBackend.USERPASS, AuthBackend.APPID, AuthBackend.APPROLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,6 +203,218 @@ 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 */
|
||||||
|
try {
|
||||||
|
AuthResponse res = connector.authAppRole("foo", APPROLE_SECRET);
|
||||||
|
fail("Successfully logged in with unknown role");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Authenticate without wrong secret ID */
|
||||||
|
try {
|
||||||
|
AuthResponse res = connector.authAppRole(APPROLE_ROLE, "foo");
|
||||||
|
fail("Successfully logged in without secret ID");
|
||||||
|
} catch (VaultConnectorException e) {
|
||||||
|
assertThat(e, is(instanceOf(InvalidResponseException.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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.
|
* Test reading of secrets.
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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\",\"secret_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)
|
||||||
|
.withPolicies(BOUND_CIDR_LIST)
|
||||||
|
.withPolicy(CIDR_1)
|
||||||
|
.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 @@
|
|||||||
|
{"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/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"}
|
@ -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="}
|
@ -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=="}
|
||||||
|
@ -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="}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user