From 3df2293741e3bc2e29f34f6165f6b799aa1615c8 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 6 Nov 2016 15:33:49 +0100 Subject: [PATCH] Support for complex secrets added --- .../model/response/SecretResponse.java | 66 +++++++++++++++---- .../connector/HTTPVaultConnectorTest.java | 32 ++++++++- .../userstore/_complex | 1 + .../_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae | 1 + .../_f36b16467afa41b83f8d2f467ce86b0a848aebbf | 1 + .../_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae | 1 + 6 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 src/test/resources/data_dir/logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/_complex create mode 100644 src/test/resources/data_dir/sys/expire/id/auth/userpass/login/validUser/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae create mode 100644 src/test/resources/data_dir/sys/token/accessor/_f36b16467afa41b83f8d2f467ce86b0a848aebbf create mode 100644 src/test/resources/data_dir/sys/token/id/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java index 07fdb2f..87e8934 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java @@ -26,37 +26,77 @@ import java.util.Map; /** * Vault response for secret request. * - * @author Stefan Kalscheuer - * @since 0.1 + * @author Stefan Kalscheuer + * @since 0.1 */ @JsonIgnoreProperties(ignoreUnknown = true) public class SecretResponse extends VaultDataResponse { - private String value; + private Map data; @Override public void setData(Map data) throws InvalidResponseException { - try { - this.value = (String) data.get("value"); - } catch (ClassCastException e) { - throw new InvalidResponseException("Value could not be parsed", e); - } + this.data = data; } + /** + * Get complete data object. + * + * @return data map + * @since 0.4.0 + */ + public Map getData() { + return data; + } + + /** + * Get a single value for given key. + * + * @param key the key + * @return the value or NULL if absent + * @since 0.4.0 + */ + public Object get(String key) { + return data.get(key); + } + + /** + * Get data element for key "value". + * Method for backwards compatibility in case of simple secrets. + * + * @return the value + */ public String getValue() { - return value; + if (data.get("value") == null) + return null; + return data.get("value").toString(); } /** * Get response parsed as JSON - * @param type Class to parse response - * @param Class to parse response - * @return Parsed object + * + * @param type Class to parse response + * @param Class to parse response + * @return Parsed object * @throws InvalidResponseException on parsing error * @since 0.3 */ public T getValue(Class type) throws InvalidResponseException { + return get("value", type); + } + + /** + * Get response parsed as JSON + * + * @param key the key + * @param type Class to parse response + * @param Class to parse response + * @return Parsed object + * @throws InvalidResponseException on parsing error + * @since 0.4.0 + */ + public T get(String key, Class type) throws InvalidResponseException { try { - return new ObjectMapper().readValue(getValue(), type); + return new ObjectMapper().readValue(get(key).toString(), type); } catch (IOException e) { throw new InvalidResponseException("Unable to parse response payload: " + e.getMessage()); } diff --git a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java index 667d6e0..0083400 100644 --- a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java +++ b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java @@ -64,8 +64,9 @@ public class HTTPVaultConnectorTest { private static String APPROLE_ROLE2 = "35b7bf43-9644-588a-e68f-2e8313bb23b7"; // role with CIDR subnet private static String SECRET_PATH = "userstore"; private static String SECRET_KEY = "foo"; - private static String SECRET_KEY_JSON = "json"; private static String SECRET_VALUE = "bar"; + private static String SECRET_KEY_JSON = "json"; + private static String SECRET_KEY_COMPLEX = "complex"; private Process vaultProcess; private VaultConnector connector; @@ -442,6 +443,7 @@ public class HTTPVaultConnectorTest { } catch (VaultConnectorException e) { assertThat(e, instanceOf(PermissionDeniedException.class)); } + /* Try to read accessible path with known value */ try { res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY); @@ -449,6 +451,7 @@ public class HTTPVaultConnectorTest { } catch (VaultConnectorException e) { fail("Valid secret path could not be read: " + e.getMessage()); } + /* Try to read accessible path with JSON value */ try { res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_JSON); @@ -464,6 +467,33 @@ public class HTTPVaultConnectorTest { } catch (InvalidResponseException e) { fail("JSON response could not be parsed: " + e.getMessage()); } + + /* Try to read accessible path with JSON value */ + try { + res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_JSON); + assertThat("Known secret returned null value.", res.getValue(), notNullValue()); + } catch (VaultConnectorException e) { + fail("Valid secret path could not be read: " + e.getMessage()); + } + try { + Credentials parsedRes = res.getValue(Credentials.class); + assertThat("JSON response was null", parsedRes, notNullValue()); + assertThat("JSON response incorrect", parsedRes.getUsername(), is("user")); + assertThat("JSON response incorrect", parsedRes.getPassword(), is("password")); + } catch (InvalidResponseException e) { + fail("JSON response could not be parsed: " + e.getMessage()); + } + + /* Try to read accessible complex secret */ + try { + res = connector.readSecret(SECRET_PATH + "/" + SECRET_KEY_COMPLEX); + assertThat("Known secret returned null value.", res.getData(), notNullValue()); + assertThat("Unexpected value size", res.getData().keySet(), hasSize(2)); + assertThat("Unexpected value", res.get("key1"), is("value1")); + assertThat("Unexpected value", res.get("key2"), is("value2")); + } catch (VaultConnectorException e) { + fail("Valid secret path could not be read: " + e.getMessage()); + } } /** diff --git a/src/test/resources/data_dir/logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/_complex b/src/test/resources/data_dir/logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/_complex new file mode 100644 index 0000000..03ed06b --- /dev/null +++ b/src/test/resources/data_dir/logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/_complex @@ -0,0 +1 @@ +{"Key":"logical/b85d867d-74d1-7d84-7a97-4597d813a5fb/userstore/complex","Value":"AAAAAQJGyPQ1TFtwJLO5tbYDvnXDxbK0GVxef0qXs4h2ddHTdWFvk+WJWsTw2l+Igr5v5KY5HOQz/apI6Vo2LmwY"} diff --git a/src/test/resources/data_dir/sys/expire/id/auth/userpass/login/validUser/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae b/src/test/resources/data_dir/sys/expire/id/auth/userpass/login/validUser/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae new file mode 100644 index 0000000..47adace --- /dev/null +++ b/src/test/resources/data_dir/sys/expire/id/auth/userpass/login/validUser/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae @@ -0,0 +1 @@ +{"Key":"sys/expire/id/auth/userpass/login/validUser/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLS9Dgic+3ywWAIR7I3J+9PmdEt81fce3eOTNpcT/TRNDkzD5NY3WEQjBLM7UzxGMg7M88IeGi6L7Rd+ZmoKjL0zogptwvKYggG4P0z+fCQW+/WgpIYEB1187wsF7wh7GQtXTXKE9F/dtKFvfi+3KsZ/0//tXcs9fUqPuJFJSUelcMaIeb2emle4p+kjs0pDuSNzovIGvRToLW4f5TbqVy0ve0zo8r/7IwKlrxo7E2uY0xzJX6IjygIACFm7GjRZgy2rkl0v9Be0T31k/zDWsEPINXu2a+vsYqjZTkRWevrK2ZE8IQBlJcFER5bcnsZiA89wm0VTcwBbYlWJ32IM9AJw/75DGMQ1wbdyJ8PUWvdhyl9i9HahtHWKCo9oH8qTiBjbmkrCECCaUeV1TgpqcqyglxBkgn6Qlb5kgNEHeXxCPy8GarT2gHlmPNaWunnxqE71WuVLZ4+PBlCjmksyXQtdqmDIRE1oSHeuohBQ2dA0B/rDmhLwXBssA+/eQDONLm639VrLJR4IRaNo04PEdxz8pec8W5fG5+Ea3Z171nl3FseZO78i3Wj7Y2KvYFA1XWNlrucxWg0jRI1hDlUHXqLh7nqctdudkI8NrkwbAE6W6a9imMUnTd3yIHN05ke9ihlJrVvAaBbgav4ssz3tnYC/s3TmozGic2TdXGxi9ewMKhdfntXi1VQEJ52i2QmWsnDAUoISHFaK+azNFt7sD5tCKmSIdpS4IL9g6RMH/sVAzuB0ZT+83jYY+jP9L4SajQs4ncWkrMQmJ0fxGs62x6lBxk1LtI2qzV1J57+1QZxFoQc6OQINec3VoQ1t7aFpqYYDk9GKEA/hk8vM5vhwc058RPpjYM8l+3PCPOilMh+FgqOs++8HBTarMTp"} diff --git a/src/test/resources/data_dir/sys/token/accessor/_f36b16467afa41b83f8d2f467ce86b0a848aebbf b/src/test/resources/data_dir/sys/token/accessor/_f36b16467afa41b83f8d2f467ce86b0a848aebbf new file mode 100644 index 0000000..94a526b --- /dev/null +++ b/src/test/resources/data_dir/sys/token/accessor/_f36b16467afa41b83f8d2f467ce86b0a848aebbf @@ -0,0 +1 @@ +{"Key":"sys/token/accessor/f36b16467afa41b83f8d2f467ce86b0a848aebbf","Value":"AAAAAQKCq6Zqg/q7n6Oi/FfipknrqzI7vYVD9IB+FUuZR56CWUngRRLOs4kLU78vNboCenbYQ3kDYtnxOvUD4xOjNktUzvXoqV0sF0N1p50Mc+MBsR1kzRbbk3nhxocW6lvOmnwLwnE7TtQdEMiU4sHeCoitFgWXfITl2YVxNnY5SXbq4ZSHAVlF"} diff --git a/src/test/resources/data_dir/sys/token/id/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae b/src/test/resources/data_dir/sys/token/id/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae new file mode 100644 index 0000000..7bf8735 --- /dev/null +++ b/src/test/resources/data_dir/sys/token/id/_dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae @@ -0,0 +1 @@ +{"Key":"sys/token/id/dadddf1d8c65ecfb20c4361929d1e7f6b72e39ae","Value":"AAAAAQLf0+mzTh9i2njHeuHQTkC0cDkZGbSHljPETXi4PtH7V1bwuJHi7LLiS3TQNDLl9M/jR6eVK/V374Q+qKdi6sZjVvRKErpbuZhX6YjYy/YNCKs9RJcU21wgXM0emBH6cvrVkzWz7y9UdrTR86e4PU8GrqkbtKUWZ08EcB+jt3mlzkOK+3lRBj9mmDC1McsZ4ALw8Y13Mq6a8xSeSxX4ZJLq4MYfI2GtR3JiEdYdx8gS5YlbbgxTjwxEOUC1mxwDHw+rsguh9eOD6RZaUTvL3MIvQsggoYU9kecvP9jvMnOfhRwd8pT93ilE+MWRylKI8ZOc7K1TMU+qw7Eho5KRKCuR7AXpWrc23SIkkMTDqmaLZiwyM5+fGR1R0c/KpsrzYo5X+TU3SMghlmrQyTHEEU6RGmAOC7RWfFrV1144T390hE9zhbY1zMRmtgBY9qsueXvK3pVaQT83/PswVGR8jliThzXjCsy12BwThBNlZVpEKZK8oI3HRqMk2jpkSpG2cAYiWNnZV9fbipNa92ovGeHHOTM9ZdPpX8apxS47CnMbuwdkNPmCvu+wtRBuGsbmmEwy+F8czMRJuAHu"}