diff --git a/.drone.yml b/.drone.yml index 8e3a979..0195d77 100644 --- a/.drone.yml +++ b/.drone.yml @@ -2,25 +2,38 @@ kind: pipeline name: default steps: - - name: test-online + - name: compile image: maven:3-jdk-11 - environment: - VAULT_VERSION: 1.3.0 commands: - - curl -o vault_1.3.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.3.0/vault_1.3.0_linux_amd64.zip - - curl -s https://releases.hashicorp.com/vault/1.3.0/vault_1.3.0_SHA256SUMS | grep linux_amd64 | sha256sum -c - - unzip vault_1.3.0_linux_amd64.zip - - rm vault_1.3.0_linux_amd64.zip - - mv vault /bin/ - - mvn clean test + - mvn clean compile when: branch: - master - - name: test-offline + - develop + - feature/* + - fix/* + - release/* + - name: unit-tests image: maven:3-jdk-11 commands: - - mvn clean test -P offline-tests + - mvn test -P offline-tests when: branch: - develop - feature/* + - fix/* + - name: unit-integration-tests + image: maven:3-jdk-11 + environment: + VAULT_VERSION: 1.4.0 + commands: + - curl -s -o vault_1.4.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.4.0/vault_1.4.0_linux_amd64.zip + - curl -s https://releases.hashicorp.com/vault/1.4.0/vault_1.4.0_SHA256SUMS | grep linux_amd64 | sha256sum -c + - unzip vault_1.4.0_linux_amd64.zip + - rm vault_1.4.0_linux_amd64.zip + - mv vault /bin/ + - mvn test + when: + branch: + - master + - release/* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 5f46483..30922b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,16 @@ addons: organization: "stklcode-github" token: secure: "sM9OfX5jW764pn9cb2LSXArnXucKMws+eGeg5NnZxHRcGYt4hpBKLSregBSsBNzUoWVj0zNzPCpnh+UQvgxQzUerOqwEdjTBpy3SNPaxSn7UpoSg+Wz3aUmL9ugmx01b51/wMG4UCHEwTZt2tpgTPVtw8K6uSO78e0dSICCBHDnRcdQwOjMEQHIJJ/qHVRwuy/MzLCAP3W1JPZlsphZg9QsFyhB4hW97dE90joZezfocQIv2xI/r6k+BLz0pY6MxYCul0RiDumaiaej0CPvEJI/uSu//BAQjUdHw+mQgnKUYIbrn2ONOviwNfwdr94JyoZEN2B6zASUmNLjPf4AbIojDeyS+CrpQpm17EVm/Qk/Ds+Xra4PPPIcsZhiWzV0KoDUz9xLfXuRJ526VT5tDPiaeI7oETf0+8l+JIS1b399FyqHi7smzjpvC6GuKflQrbuHK4MuKzDh7WTHiqokGG4SS0wOQIaaHB3dfdwwQzPh6IM24e8CETxh3DjMeqUTU4DWmv5po55jZ934TtxVQvVN78bTG9O0zS9u+JmRY04OZ+OaXuFam6MfMUFQi0EPZzdGul/oWSibGUu3bNfVEBp60CnJwYNM/dKG6U7pJthLHvSwiQFOdKzHZ+l1jZJ4gPaXaIGqpwqVGr28ntqA/El1rytPixr2driE6bYMt5jw=" +stages: + - Compile + - Test + - Analysis env: - - PATH=$PATH:. VAULT_VERSION=1.3.0 + - PATH=$PATH:. VAULT_VERSION=1.4.0 before_script: - | - if [ "$TRAVIS_BRANCH" = "master" ]; then - wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip + if [[ "$TRAVIS_BRANCH" =~ ^master|(release\/.+)$ ]]; then + wget -q https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip wget -q -O - https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c unzip vault_${VAULT_VERSION}_linux_amd64.zip rm vault_${VAULT_VERSION}_linux_amd64.zip @@ -21,13 +25,26 @@ cache: directories: - '$HOME/.m2/repository' - '$HOME/.sonar/cache' -script: - - | - if [ "$TRAVIS_BRANCH" = "master" ]; then - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar - else - mvn clean test -P offline-tests - fi +jobs: + include: + - stage: Compile + name: Compile + script: + - mvn clean compile + - stage: Test + name: Unit Tests + if: NOT branch =~ ^master|(release/.+)$ + script: + - mvn test -P offline-tests + - name: Unit and Integration Tests + if: branch =~ ^master|(release/.+)$ + script: + - mvn -P coverage clean package + - stage: Analysis + if: branch = master + script: + - mvn sonar:sonar + notifications: slack: secure: "YyE5GePOLkCVTtCy8j507BRmQrtrWhtvmUt4kY0Z2/ptf0LzfuDEJQ4ZbCxO5ri5IDJrrvyPAedjft818+bMzdFfxvi1oviIL+LZNhyev8gfeIBF/U2pvSLGKCRX4g4aZ6NKN3Untjdm8lmiVTltOyZ59JizQVwXzAl3LiOpnJugyBqbhOx4EIqBzwW3gaYAofMqY2LczW5W/M+99HJCst8Mb8H06GstCPEHCizAq7VRaUS68PstlxQMV0Q6bsSYMLFbLWmhuXs96WHqOrT+nNsl07ikr3N8c4HafhFutt2Jyc1+8gXO417+eSvVM0iBpHGwTmfGFfCqx/4Pf62DTJuvh8dR4fLgLDiqEeDrBEcRRDOs9cvXVOO22NN1HuBBJY8VRiFcwNAvuVMXCtnC+1RJRAZB2zubsANiFe+ygk/ywj37cVXY+NpqlBwcSph6jPHo2hD6cIl2rTWn1EnZH519Rh38xTSv6MRzAO9kWNVrAlX+UtvYS8Sk7Owrc0tET9Lc4zj6aI5tsA1wYbN3Jk6EbMhsF6K/XF2npt2qg09pxkj8wmxoUoR6/rGuSv55aSxTdLDmH+en4ahEm3uc4h1lYoVCk0yrZoTAas3zS4WpBCKnl+mweuKNxaejyy0Wv6NR9ZCTaS3yFgibNOjvDpxZxTAPdNBL7hn+k4LwgN4=" diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a451d..27e36d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +## 0.9.0 (2020-04-29) + +### Fixes +* Correctly parse Map field for token metadata (#34) +* Correctly map token policies on token lookup (#35) + +### Features +* Support for token types (#26) +* Support for token role handling (#27) (#37) + +### Improvements +* Added `entity_id`, `token_policies`, `token_type` and `orphan` flags to auth response +* Added `entity_id`, `expire_time`, `explicit_max_ttl`, `issue_time`, `renewable` and `type` flags to token data +* Added `explicit_max_ttl`, `period` and `entity_alias` flags to _Token_ model (#41) +* Added `enable_local_secret_ids`, `token_bound_cidrs`, `token_explicit_max_ttl`, `token_no_default_policy`, + `token_num_uses`, `token_period` and `token_type` flags to _AppRole_ model +* Minor dependency updates + +### Deprecations +* `AppRole#getPolicies()` and `#setPolicies()` are deprecated in favor of `#getTokenPolicies()` and `#setTokenPolicies()` +* `AppRole#getPeriod()` is deprecated in favor of `#getTokenPeriod()` +* `AppRoleBuilder` and `TokenBuilder` in favor of `AppRole.Builder` and `Token.Builder` +* All-arg constructors of `AppRole` and `Token` in favor of `.builder()....build()` introduced in 0.8 + +### Removals +* Deprecated methods `AppRole#getBoundCidrList()`, `#setBoundCidrList()` and `getBoundCidrListString()` have been removed. + +### Test +* Tested against Vault 1.4.0 + + ## 0.8.2 (2019-10-20) ### Fixes diff --git a/README.md b/README.md index d5f157f..99b17e5 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject * AppRole (register and authenticate) * AppID (register and authenticate) [_deprecated_] * Tokens - * Creation and lookup of tokens - * TokenBuilder for speaking creation of complex configuraitons + * Creation and lookup of tokens and token roles + * TokenBuilder for speaking creation of complex configurations * Secrets * Read secrets * Write secrets @@ -32,7 +32,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject * SQL secret handling * KV v1 and v2 support * Connector Factory with builder pattern -* Tested against Vault 1.3.0 +* Tested against Vault 1.4.0 ## Maven Artifact @@ -40,7 +40,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject de.stklcode.jvault jvault-connector - 0.8.2 + 0.9.0 ``` diff --git a/pom.xml b/pom.xml index 43474f6..f9ac031 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ de.stklcode.jvault jvault-connector - 0.8.2 + 0.9.0 jar @@ -71,7 +71,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.1.2 + 3.2.0 @@ -101,18 +101,18 @@ org.apache.httpcomponents httpclient - 4.5.10 + 4.5.12 com.fasterxml.jackson.core jackson-databind - 2.10.0 + 2.10.3 org.junit.jupiter junit-jupiter - 5.5.2 + 5.6.2 test @@ -124,7 +124,7 @@ org.mockito mockito-core - 3.1.0 + 3.3.3 test @@ -140,20 +140,20 @@ org.mockito mockito-inline - 3.1.0 + 3.3.3 test net.bytebuddy byte-buddy - 1.9.16 + 1.10.9 test net.bytebuddy byte-buddy-agent - 1.9.16 + 1.10.9 test @@ -164,6 +164,16 @@ + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.7.0.1746 + + + + @@ -176,7 +186,7 @@ org.apache.maven.plugins maven-source-plugin - 3.1.0 + 3.2.1 attach-sources @@ -200,7 +210,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.2.0 1.8 @@ -242,6 +252,34 @@ + + coverage + + + + org.jacoco + jacoco-maven-plugin + 0.8.5 + + + prepare-agent + + prepare-agent + + + + report + prepare-package + + report + + + + + + + + offline-tests diff --git a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java index 2494b12..dbe21b9 100644 --- a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,7 @@ import de.stklcode.jvault.connector.exception.AuthorizationRequiredException; import de.stklcode.jvault.connector.exception.InvalidRequestException; import de.stklcode.jvault.connector.exception.VaultConnectorException; import de.stklcode.jvault.connector.internal.RequestHelper; -import de.stklcode.jvault.connector.model.AppRole; -import de.stklcode.jvault.connector.model.AppRoleSecret; -import de.stklcode.jvault.connector.model.AuthBackend; -import de.stklcode.jvault.connector.model.Token; +import de.stklcode.jvault.connector.model.*; import de.stklcode.jvault.connector.model.response.*; import de.stklcode.jvault.connector.model.response.embedded.AuthMethod; @@ -34,7 +31,7 @@ import java.util.Map; import java.util.stream.Collectors; /** - * Vault Connector implementatin using Vault's HTTP API. + * Vault Connector implementation using Vault's HTTP API. * * @author Stefan Kalscheuer * @since 0.1 @@ -49,6 +46,7 @@ public class HTTPVaultConnector implements VaultConnector { 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_ROLES = "/roles"; private static final String PATH_CREATE_ORPHAN = "/create-orphan"; private static final String PATH_AUTH_USERPASS = "auth/userpass/login/"; private static final String PATH_AUTH_APPID = "auth/app-id/"; @@ -530,7 +528,7 @@ public class HTTPVaultConnector implements VaultConnector { if (cas != null) { options.put("cas", cas); } - + Map payload = new HashMap<>(); payload.put("data", data); payload.put("options", options); @@ -607,7 +605,7 @@ public class HTTPVaultConnector implements VaultConnector { /** * Common method to bundle secret version operations. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param pathPart Path part to query. * @param key Secret key. * @param versions Versions to handle. @@ -701,6 +699,51 @@ public class HTTPVaultConnector implements VaultConnector { return request.get(PATH_TOKEN + PATH_LOOKUP, param, token, TokenResponse.class); } + @Override + public boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException { + requireAuth(); + + if (name == null) { + throw new InvalidRequestException("Role name must be provided."); + } else if (role == null) { + throw new InvalidRequestException("Role must be provided."); + } + + // Issue request and expect code 204 with empty response. + request.postWithoutResponse(PATH_TOKEN + PATH_ROLES + "/" + name, role, token); + + return true; + } + + @Override + public TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException { + requireAuth(); + + // Request HTTP response and parse response. + return request.get(PATH_TOKEN + PATH_ROLES + "/" + name, new HashMap<>(), token, TokenRoleResponse.class); + } + + @Override + public List listTokenRoles() throws VaultConnectorException { + requireAuth(); + + return list(PATH_TOKEN + PATH_ROLES); + } + + @Override + public boolean deleteTokenRole(final String name) throws VaultConnectorException { + requireAuth(); + + if (name == null) { + throw new InvalidRequestException("Role name must be provided."); + } + + // Issue request and expect code 204 with empty response. + request.deleteWithoutResponse(PATH_TOKEN + PATH_ROLES + "/" + name, token); + + return true; + } + /** * Check for required authorization. * diff --git a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java index 83b9187..ce5a1f6 100644 --- a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,7 +91,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { HealthResponse getHealth() throws VaultConnectorException; /** - * Get all availale authentication backends. + * Get all available authentication backends. * * @return List of backends * @throws VaultConnectorException on error @@ -226,14 +226,14 @@ public interface VaultConnector extends AutoCloseable, Serializable { */ default boolean createAppRole(final String roleName, final List policies, final String roleID) throws VaultConnectorException { - return createAppRole(new AppRoleBuilder(roleName).withPolicies(policies).withId(roleID).build()); + return createAppRole(AppRole.builder(roleName).withTokenPolicies(policies).withId(roleID).build()); } /** * Delete AppRole role from Vault. * - * @param roleName The role anme - * @return {@code true} on succevss + * @param roleName The role name + * @return {@code true} on success * @throws VaultConnectorException on error */ boolean deleteAppRole(final String roleName) throws VaultConnectorException; @@ -430,7 +430,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /data/} is read here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret identifier * @return Secret response * @throws VaultConnectorException on error @@ -446,7 +446,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Prefix {@code secret/} is automatically added to path. * Only available for KV v2 secrets. * - * @param key Secret identifier. + * @param key Secret identifier. * @param data Secret content. Value must be be JSON serializable. * @return Metadata for the created/updated secret. * @throws VaultConnectorException on error @@ -462,9 +462,9 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /data/} is written here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). - * @param key Secret identifier - * @param data Secret content. Value must be be JSON serializable. + * @param mount Secret store mount point (without leading or trailing slash). + * @param key Secret identifier + * @param data Secret content. Value must be be JSON serializable. * @return Metadata for the created/updated secret. * @throws VaultConnectorException on error * @since 0.8 @@ -479,10 +479,10 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /data/} is written here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). - * @param key Secret identifier - * @param data Secret content. Value must be be JSON serializable. - * @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value. + * @param mount Secret store mount point (without leading or trailing slash). + * @param key Secret identifier + * @param data Secret content. Value must be be JSON serializable. + * @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value. * @return Metadata for the created/updated secret. * @throws VaultConnectorException on error * @since 0.8 @@ -511,10 +511,10 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /data/} is read here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret identifier * @param version Version to read. If {@code null} or zero, the latest version will be returned. - * @return Secret responsef + * @return Secret response. * @throws VaultConnectorException on error * @since 0.8 */ @@ -540,7 +540,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code secret/metadata/} is read here. * Only available for KV v2 secrets. * - * @param key Secret identifier + * @param key Secret identifier * @param maxVersions Maximum number of versions (fallback to backend default if {@code null}) * @param casRequired Specify if Check-And-Set is required for this secret. * @throws VaultConnectorException on error @@ -556,7 +556,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /metadata/} is read here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret identifier * @return Metadata response * @throws VaultConnectorException on error @@ -570,7 +570,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Path {@code /metadata/} is written here. * Only available for KV v2 secrets. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret identifier * @param maxVersions Maximum number of versions (fallback to backend default if {@code null}) * @param casRequired Specify if Check-And-Set is required for this secret. @@ -710,7 +710,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { *
* Only available for KV v2 stores. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret path. * @throws VaultConnectorException on error * @since 0.8 @@ -737,8 +737,8 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Prefix {@code secret/} is automatically added to path. * Only available for KV v2 stores. * - * @param mount Secret store mountpoint (without leading or trailing slash). - * @param key Secret path. + * @param mount Secret store mount point (without leading or trailing slash). + * @param key Secret path. * @throws VaultConnectorException on error * @since 0.8 */ @@ -763,7 +763,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { *
* Only available for KV v2 stores. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret path. * @param versions Versions of the secret to delete. * @throws VaultConnectorException on error @@ -788,7 +788,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Undelete (restore) secret versions from Vault. * Only available for KV v2 stores. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret path. * @param versions Versions of the secret to undelete. * @throws VaultConnectorException on error @@ -813,7 +813,7 @@ public interface VaultConnector extends AutoCloseable, Serializable { * Destroy secret versions from Vault. * Only available for KV v2 stores. * - * @param mount Secret store mountpoint (without leading or trailing slash). + * @param mount Secret store mount point (without leading or trailing slash). * @param key Secret path. * @param versions Versions of the secret to destroy. * @throws VaultConnectorException on error @@ -888,7 +888,57 @@ public interface VaultConnector extends AutoCloseable, Serializable { */ TokenResponse lookupToken(final String token) throws VaultConnectorException; + /** + * Create a new or update an existing token role. + * + * @param role the role entity (name must be set) + * @return {@code true} on success + * @throws VaultConnectorException on error + * @since 0.9 + */ + default boolean createOrUpdateTokenRole(final TokenRole role) throws VaultConnectorException { + return createOrUpdateTokenRole(role.getName(), role); + } + /** + * Create a new or update an existing token role. + * + * @param name the role name (overrides name possibly set in role entity) + * @param role the role entity + * @return {@code true} on success + * @throws VaultConnectorException on error + * @since 0.9 + */ + boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException; + + /** + * Lookup token information. + * + * @param name the role name + * @return the result response + * @throws VaultConnectorException on error + * @since 0.9 + */ + TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException; + + /** + * List available token roles from Vault. + * + * @return List of token roles + * @throws VaultConnectorException on error + * @since 0.9 + */ + List listTokenRoles() throws VaultConnectorException; + + /** + * Delete a token role. + * + * @param name the role name to delete + * @return {@code true} on success + * @throws VaultConnectorException on error + * @since 0.9 + */ + boolean deleteTokenRole(final String name) throws VaultConnectorException; /** * Read credentials for MySQL backend at default mount point. diff --git a/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java index 101972f..97e8597 100644 --- a/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java +++ b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; /** - * Vault Connector Factory implementation for HTTP Vault connectors. + * Vault Connector Builder implementation for HTTP Vault connectors. * * @author Stefan Kalscheuer * @since 0.8.0 @@ -162,7 +162,7 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { } /** - * Add a trusted CA certifiate for HTTPS connections. + * Add a trusted CA certificate for HTTPS connections. * * @param cert path to certificate file * @return self @@ -179,7 +179,7 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { } /** - * Add a trusted CA certifiate for HTTPS connections. + * Add a trusted CA certificate for HTTPS connections. * * @param cert path to certificate file * @return self diff --git a/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java b/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java index 1a3fcd3..b6e344d 100644 --- a/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java +++ b/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/builder/package-info.java b/src/main/java/de/stklcode/jvault/connector/builder/package-info.java index f2f4c1b..fd7ebac 100644 --- a/src/main/java/de/stklcode/jvault/connector/builder/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/builder/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/AuthorizationRequiredException.java b/src/main/java/de/stklcode/jvault/connector/exception/AuthorizationRequiredException.java index 2e9a957..c56063d 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/AuthorizationRequiredException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/AuthorizationRequiredException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/ConnectionException.java b/src/main/java/de/stklcode/jvault/connector/exception/ConnectionException.java index cd2cd98..cb240e6 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/ConnectionException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/ConnectionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/InvalidRequestException.java b/src/main/java/de/stklcode/jvault/connector/exception/InvalidRequestException.java index bc5759a..958bbe6 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/InvalidRequestException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/InvalidRequestException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/InvalidResponseException.java b/src/main/java/de/stklcode/jvault/connector/exception/InvalidResponseException.java index 42f4184..3931f69 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/InvalidResponseException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/InvalidResponseException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/PermissionDeniedException.java b/src/main/java/de/stklcode/jvault/connector/exception/PermissionDeniedException.java index 9f01658..a953271 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/PermissionDeniedException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/PermissionDeniedException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/TlsException.java b/src/main/java/de/stklcode/jvault/connector/exception/TlsException.java index 20f465a..e2c3517 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/TlsException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/TlsException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/VaultConnectorException.java b/src/main/java/de/stklcode/jvault/connector/exception/VaultConnectorException.java index 8e9644c..418abda 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/VaultConnectorException.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/VaultConnectorException.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/exception/package-info.java b/src/main/java/de/stklcode/jvault/connector/exception/package-info.java index 1cdbeeb..3131472 100644 --- a/src/main/java/de/stklcode/jvault/connector/exception/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/exception/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java b/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java index 678b35d..4389916 100644 --- a/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java +++ b/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,7 +107,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { } /** - * Add a trusted CA certifiate for HTTPS connections. + * Add a trusted CA certificate for HTTPS connections. * * @param cert path to certificate file * @return self @@ -120,7 +120,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { } /** - * Add a trusted CA certifiate for HTTPS connections. + * Add a trusted CA certificate for HTTPS connections. * * @param cert path to certificate file * @return self diff --git a/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java b/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java index 1147bac..1f3c2be 100644 --- a/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java +++ b/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/factory/package-info.java b/src/main/java/de/stklcode/jvault/connector/factory/package-info.java index f6323de..1774531 100644 --- a/src/main/java/de/stklcode/jvault/connector/factory/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/factory/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/internal/Error.java b/src/main/java/de/stklcode/jvault/connector/internal/Error.java index 55331d7..f72ab65 100644 --- a/src/main/java/de/stklcode/jvault/connector/internal/Error.java +++ b/src/main/java/de/stklcode/jvault/connector/internal/Error.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ final class Error { static final String UNEXPECTED_RESPONSE = "Received response where none was expected"; static final String URI_FORMAT = "Invalid URI format"; static final String RESPONSE_CODE = "Invalid response code"; - static final String INIT_SSL_CONTEXT = "Unable to intialize SSLContext"; + static final String INIT_SSL_CONTEXT = "Unable to initialize SSLContext"; /** * Constructor hidden, this class should not be instantiated. diff --git a/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java b/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java index 560355f..00b5f1b 100644 --- a/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java +++ b/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java @@ -340,7 +340,7 @@ public final class RequestHelper implements Serializable { /* Fail on different error code and/or no retries left */ handleError(response); - /* Throw exception withoud details, if response entity is empty. */ + /* Throw exception without details, if response entity is empty. */ throw new InvalidResponseException(Error.RESPONSE_CODE, response.getStatusLine().getStatusCode()); } @@ -362,7 +362,7 @@ public final class RequestHelper implements Serializable { * Create a custom socket factory from trusted CA certificate. * * @return The factory. - * @throws TlsException An error occured during initialization of the SSL context. + * @throws TlsException An error occurred during initialization of the SSL context. * @since 0.8.0 */ private SSLConnectionSocketFactory createSSLSocketFactory() throws TlsException { @@ -376,7 +376,7 @@ public final class RequestHelper implements Serializable { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); - // Create context usint this TrustManager. + // Create context using this TrustManager. SSLContext context = SSLContext.getInstance(tlsVersion); context.init(null, tmf.getTrustManagers(), new SecureRandom()); diff --git a/src/main/java/de/stklcode/jvault/connector/model/AppRole.java b/src/main/java/de/stklcode/jvault/connector/model/AppRole.java index ce700d3..db1b249 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/AppRole.java +++ b/src/main/java/de/stklcode/jvault/connector/model/AppRole.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package de.stklcode.jvault.connector.model; import com.fasterxml.jackson.annotation.*; +import java.util.ArrayList; import java.util.List; /** @@ -29,14 +30,14 @@ import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public final class AppRole { /** - * Get {@link AppRoleBuilder} instance. + * Get {@link Builder} instance. * * @param name Role name. * @return AppRole Builder. * @since 0.8 */ - public static AppRoleBuilder builder(final String name) { - return new AppRoleBuilder(name); + public static Builder builder(final String name) { + return new Builder(name); } @JsonProperty("role_name") @@ -50,12 +51,8 @@ public final class AppRole { @JsonInclude(JsonInclude.Include.NON_NULL) private Boolean bindSecretId; - private List boundCidrList; - private List secretIdBoundCidrs; - private List policies; - @JsonProperty("secret_id_num_uses") @JsonInclude(JsonInclude.Include.NON_NULL) private Integer secretIdNumUses; @@ -64,6 +61,10 @@ public final class AppRole { @JsonInclude(JsonInclude.Include.NON_NULL) private Integer secretIdTtl; + @JsonProperty("enable_local_secret_ids") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean enableLocalSecretIds; + @JsonProperty("token_ttl") @JsonInclude(JsonInclude.Include.NON_NULL) private Integer tokenTtl; @@ -72,44 +73,36 @@ public final class AppRole { @JsonInclude(JsonInclude.Include.NON_NULL) private Integer tokenMaxTtl; - @JsonProperty("period") + private List tokenPolicies; + + @JsonProperty("token_bound_cidrs") @JsonInclude(JsonInclude.Include.NON_NULL) - private Integer period; + private List tokenBoundCidrs; + + @JsonProperty("token_explicit_max_ttl") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenExplicitMaxTtl; + + @JsonProperty("token_no_default_policy") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean tokenNoDefaultPolicy; + + @JsonProperty("token_num_uses") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenNumUses; + + @JsonProperty("token_period") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenPeriod; + + @JsonProperty("token_type") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String tokenType; /** * Construct empty {@link AppRole} object. */ public AppRole() { - - } - - /** - * Construct complete {@link AppRole} object. - * - * @param name Role name (required) - * @param id Role ID (optional) - * @param bindSecretId Bind secret ID (optional) - * @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional) - * @param policies List of policies (optional) - * @param secretIdNumUses Maximum number of uses per secret (optional) - * @param secretIdTtl Maximum TTL in seconds for secrets (optional) - * @param tokenTtl Token TTL in seconds (optional) - * @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional) - * @param period Duration in seconds, if set the token is a periodic token (optional) - */ - public AppRole(final String name, final String id, final Boolean bindSecretId, final List secretIdBoundCidrs, - final List policies, final Integer secretIdNumUses, final Integer secretIdTtl, - final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) { - this.name = name; - this.id = id; - this.bindSecretId = bindSecretId; - this.secretIdBoundCidrs = secretIdBoundCidrs; - this.policies = policies; - this.secretIdNumUses = secretIdNumUses; - this.secretIdTtl = secretIdTtl; - this.tokenTtl = tokenTtl; - this.tokenMaxTtl = tokenMaxTtl; - this.period = period; } /** @@ -117,32 +110,70 @@ public final class AppRole { *

* This constructor is used for transition from {@code bound_cidr_list} to {@code secret_id_bound_cidrs} only. * - * @param name Role name (required) - * @param id Role ID (optional) - * @param bindSecretId Bind secret ID (optional) - * @param boundCidrList Whitelist of subnets in CIDR notation (optional) - * @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional) - * @param policies List of policies (optional) - * @param secretIdNumUses Maximum number of uses per secret (optional) - * @param secretIdTtl Maximum TTL in seconds for secrets (optional) - * @param tokenTtl Token TTL in seconds (optional) - * @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional) - * @param period Duration in seconds, if set the token is a periodic token (optional) + * @param name Role name (required) + * @param id Role ID (optional) + * @param bindSecretId Bind secret ID (optional) + * @param secretIdBoundCidrs Whitelist of subnets in CIDR notation (optional) + * @param secretIdNumUses Maximum number of uses per secret (optional) + * @param secretIdTtl Maximum TTL in seconds for secrets (optional) + * @param enableLocalSecretIds Enable local secret IDs (optional) + * @param tokenTtl Token TTL in seconds (optional) + * @param tokenMaxTtl Maximum token TTL in seconds, including renewals (optional) + * @param tokenPolicies List of token policies (optional) + * @param tokenBoundCidrs Whitelist of subnets in CIDR notation for associated tokens (optional) + * @param tokenExplicitMaxTtl Explicit maximum TTL for associated tokens (optional) + * @param tokenNoDefaultPolicy Enable or disable default policy for associated tokens (optional) + * @param tokenNumUses Number of uses for tokens (optional) + * @param tokenPeriod Duration in seconds, if set the token is a periodic token (optional) + * @param tokenType Token type (optional) + * @deprecated As of 0.9 in favor of {@link #builder(String)}. Will be removed with next major release. */ - AppRole(final String name, final String id, final Boolean bindSecretId, final List boundCidrList, - final List secretIdBoundCidrs, final List policies, final Integer secretIdNumUses, - final Integer secretIdTtl, final Integer tokenTtl, final Integer tokenMaxTtl, final Integer period) { + @Deprecated + AppRole(final String name, final String id, final Boolean bindSecretId, final List secretIdBoundCidrs, + final Integer secretIdNumUses, final Integer secretIdTtl, final Boolean enableLocalSecretIds, + final Integer tokenTtl, final Integer tokenMaxTtl, final List tokenPolicies, + final List tokenBoundCidrs, final Integer tokenExplicitMaxTtl, final Boolean tokenNoDefaultPolicy, + final Integer tokenNumUses, final Integer tokenPeriod, final String tokenType) { this.name = name; this.id = id; this.bindSecretId = bindSecretId; - this.boundCidrList = boundCidrList; this.secretIdBoundCidrs = secretIdBoundCidrs; - this.policies = policies; + this.tokenPolicies = tokenPolicies; this.secretIdNumUses = secretIdNumUses; this.secretIdTtl = secretIdTtl; + this.enableLocalSecretIds = enableLocalSecretIds; this.tokenTtl = tokenTtl; this.tokenMaxTtl = tokenMaxTtl; - this.period = period; + this.tokenBoundCidrs = tokenBoundCidrs; + this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; + this.tokenNoDefaultPolicy = tokenNoDefaultPolicy; + this.tokenNumUses = tokenNumUses; + this.tokenPeriod = tokenPeriod; + this.tokenType = tokenType; + } + + /** + * Construct {@link AppRole} object from {@link AppRole.Builder}. + * + * @param builder AppRole builder. + */ + public AppRole(final Builder builder) { + this.name = builder.name; + this.id = builder.id; + this.bindSecretId = builder.bindSecretId; + this.secretIdBoundCidrs = builder.secretIdBoundCidrs; + this.secretIdNumUses = builder.secretIdNumUses; + this.secretIdTtl = builder.secretIdTtl; + this.enableLocalSecretIds = builder.enableLocalSecretIds; + this.tokenTtl = builder.tokenTtl; + this.tokenMaxTtl = builder.tokenMaxTtl; + this.tokenPolicies = builder.tokenPolicies; + this.tokenBoundCidrs = builder.tokenBoundCidrs; + this.tokenExplicitMaxTtl = builder.tokenExplicitMaxTtl; + this.tokenNoDefaultPolicy = builder.tokenNoDefaultPolicy; + this.tokenNumUses = builder.tokenNumUses; + this.tokenPeriod = builder.tokenPeriod; + this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null; } /** @@ -167,41 +198,38 @@ public final class AppRole { } /** - * @return list of bound CIDR subnets - * @deprecated Use {@link #getSecretIdBoundCidrs()} instead, as this parameter is deprecated in Vault. + * @return list of bound CIDR subnets of associated tokens + * @since 0.9 */ - @Deprecated - public List getBoundCidrList() { - return boundCidrList; + public List getTokenBoundCidrs() { + return tokenBoundCidrs; } /** * @param boundCidrList list of subnets in CIDR notation to bind role to - * @deprecated Use {@link #setSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault. + * @since 0.9 */ - @Deprecated - @JsonSetter("bound_cidr_list") - public void setBoundCidrList(final List boundCidrList) { - this.boundCidrList = boundCidrList; + @JsonSetter("token_bound_cidrs") + public void setBoundCidrs(final List boundCidrList) { + this.tokenBoundCidrs = boundCidrList; } /** * @return list of subnets in CIDR notation as comma-separated {@link String} - * @deprecated Use {@link #getSecretIdBoundCidrsString()} instead, as this parameter is deprecated in Vault. + * @since 0.9 */ - @Deprecated - @JsonGetter("bound_cidr_list") + @JsonGetter("token_bound_cidrs") @JsonInclude(JsonInclude.Include.NON_EMPTY) - public String getBoundCidrListString() { - if (boundCidrList == null || boundCidrList.isEmpty()) { + public String getTokenBoundCidrsString() { + if (tokenBoundCidrs == null || tokenBoundCidrs.isEmpty()) { return ""; } - return String.join(",", boundCidrList); + return String.join(",", tokenBoundCidrs); } /** * @return list of bound CIDR subnets - * @since 0.8 replaces {@link #getBoundCidrList()} + * @since 0.8 replaces {@code getBoundCidrList()} */ public List getSecretIdBoundCidrs() { return secretIdBoundCidrs; @@ -209,7 +237,7 @@ public final class AppRole { /** * @param secretIdBoundCidrs List of subnets in CIDR notation to bind secrets of this role to. - * @since 0.8 replaces {@link #setBoundCidrList(List)} + * @since 0.8 replaces {@code setBoundCidrList(List)} */ @JsonSetter("secret_id_bound_cidrs") public void setSecretIdBoundCidrs(final List secretIdBoundCidrs) { @@ -218,7 +246,7 @@ public final class AppRole { /** * @return List of subnets in CIDR notation as comma-separated {@link String} - * @since 0.8 replaces {@link #getBoundCidrListString()} ()} + * @since 0.8 replaces {@code getBoundCidrListString()} ()} */ @JsonGetter("secret_id_bound_cidrs") @JsonInclude(JsonInclude.Include.NON_EMPTY) @@ -230,30 +258,63 @@ public final class AppRole { } /** - * @return list of policies + * @return list of token policies + * @since 0.9 */ + public List getTokenPolicies() { + return tokenPolicies; + } + + /** + * @return list of token policies + * @deprecated Use {@link #getTokenPolicies()} instead. + */ + @Deprecated + @JsonIgnore public List getPolicies() { - return policies; + return getTokenPolicies(); + } + + /** + * @param tokenPolicies list of token policies + * @since 0.9 + */ + @JsonSetter("token_policies") + public void setTokenPolicies(final List tokenPolicies) { + this.tokenPolicies = tokenPolicies; } /** * @param policies list of policies + * @deprecated Use {@link #setTokenPolicies(List)} instead. */ - @JsonSetter("policies") + @Deprecated + @JsonIgnore public void setPolicies(final List policies) { - this.policies = policies; + setTokenPolicies(policies); } /** * @return list of policies as comma-separated {@link String} + * @since 0.9 */ - @JsonGetter("policies") + @JsonGetter("token_policies") @JsonInclude(JsonInclude.Include.NON_EMPTY) - public String getPoliciesString() { - if (policies == null || policies.isEmpty()) { + public String getTokenPoliciesString() { + if (tokenPolicies == null || tokenPolicies.isEmpty()) { return ""; } - return String.join(",", policies); + return String.join(",", tokenPolicies); + } + + /** + * @return list of policies as comma-separated {@link String} + * @deprecated Use {@link #getTokenPoliciesString()} instead. + */ + @Deprecated + @JsonIgnore + public String getPoliciesString() { + return getTokenPoliciesString(); } /** @@ -270,6 +331,14 @@ public final class AppRole { return secretIdTtl; } + /** + * @return Enable local secret IDs? + * @since 0.9 + */ + public Boolean getEnableLocalSecretIds() { + return enableLocalSecretIds; + } + /** * @return token TTL in seconds */ @@ -285,9 +354,391 @@ public final class AppRole { } /** - * @return duration in seconds, if specified + * @return explicit maximum token TTL in seconds, including renewals + * @since 0.9 */ + public Integer getTokenExplicitMaxTtl() { + return tokenExplicitMaxTtl; + } + + /** + * @return enable default policy for token? + * @since 0.9 + */ + public Boolean getTokenNoDefaultPolicy() { + return tokenNoDefaultPolicy; + } + + /** + * @return number of uses for token + * @since 0.9 + */ + public Integer getTokenNumUses() { + return tokenNumUses; + } + + /** + * @return duration in seconds, if specified + * @since 0.9 + */ + public Integer getTokenPeriod() { + return tokenPeriod; + } + + /** + * @return duration in seconds, if specified + * @deprecated Use {@link #getTokenPeriod()} instead. + */ + @Deprecated + @JsonIgnore public Integer getPeriod() { - return period; + return getTokenPeriod(); + } + + /** + * @return duration in seconds, if specified + * @since 0.9 + */ + public String getTokenType() { + return tokenType; + } + + + /** + * A builder for vault AppRole roles.. + * + * @author Stefan Kalscheuer + * @since 0.4.0 + * @since 0.9 Moved into subclass of {@link AppRole}. + */ + public static final class Builder { + private String name; + private String id; + private Boolean bindSecretId; + private List secretIdBoundCidrs; + private List tokenPolicies; + private Integer secretIdNumUses; + private Integer secretIdTtl; + private Boolean enableLocalSecretIds; + private Integer tokenTtl; + private Integer tokenMaxTtl; + private List tokenBoundCidrs; + private Integer tokenExplicitMaxTtl; + private Boolean tokenNoDefaultPolicy; + private Integer tokenNumUses; + private Integer tokenPeriod; + private Token.Type tokenType; + + /** + * Construct {@link Builder} with only the role name set. + * + * @param name Role name + */ + public Builder(final String name) { + this.name = name; + } + + /** + * Add role name. + * + * @param name Role name + * @return self + */ + public Builder withName(final String name) { + this.name = name; + return this; + } + + /** + * Add custom role ID. (optional) + * + * @param id the ID + * @return self + */ + public Builder 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 Builder withBindSecretID(final Boolean bindSecretId) { + this.bindSecretId = bindSecretId; + return this; + } + + /** + * Bind role to secret ID. + * Convenience method for {@link #withBindSecretID(Boolean)} + * + * @return self + */ + public Builder withBindSecretID() { + return withBindSecretID(true); + } + + /** + * Do not bind role to secret ID. + * Convenience method for {@link #withBindSecretID(Boolean)} + * + * @return self + */ + public Builder withoutBindSecretID() { + return withBindSecretID(false); + } + + /** + * Set bound CIDR blocks. + * + * @param secretIdBoundCidrs List of CIDR blocks which can perform login + * @return self + * @since 0.8 replaces {@code withBoundCidrList(List)} + */ + public Builder withSecretIdBoundCidrs(final List secretIdBoundCidrs) { + if (this.secretIdBoundCidrs == null) { + this.secretIdBoundCidrs = new ArrayList<>(); + } + this.secretIdBoundCidrs.addAll(secretIdBoundCidrs); + return this; + } + + /** + * Add a CIDR block to list of bound blocks for secret. + * + * @param secretBoundCidr the CIDR block + * @return self + * @since 0.9 + */ + public Builder withSecretBoundCidr(final String secretBoundCidr) { + if (secretIdBoundCidrs == null) { + secretIdBoundCidrs = new ArrayList<>(); + } + secretIdBoundCidrs.add(secretBoundCidr); + return this; + } + + /** + * Add given policies. + * + * @param tokenPolicies the token policies + * @return self + * @since 0.9 + */ + public Builder withTokenPolicies(final List tokenPolicies) { + if (this.tokenPolicies == null) { + this.tokenPolicies = new ArrayList<>(); + } + this.tokenPolicies.addAll(tokenPolicies); + return this; + } + + /** + * Add given policies. + * + * @param policies the policies + * @return self + * @deprecated Use {@link #withTokenPolicies(List)} instead. + */ + @Deprecated + public Builder withPolicies(final List policies) { + return withTokenPolicies(policies); + } + + /** + * Add a single policy. + * + * @param tokenPolicy the token policy + * @return self + * @since 0.9 + */ + public Builder withTokenPolicy(final String tokenPolicy) { + if (this.tokenPolicies == null) { + this.tokenPolicies = new ArrayList<>(); + } + tokenPolicies.add(tokenPolicy); + return this; + } + + /** + * Add a single policy. + * + * @param policy the policy + * @return self + * @deprecated Use {@link #withTokenPolicy(String)} instead. + */ + @Deprecated + public Builder withPolicy(final String policy) { + return withTokenPolicy(policy); + } + + /** + * Set number of uses for sectet IDs. + * + * @param secretIdNumUses the number of uses + * @return self + */ + public Builder withSecretIdNumUses(final Integer secretIdNumUses) { + this.secretIdNumUses = secretIdNumUses; + return this; + } + + /** + * Set default sectet ID TTL in seconds. + * + * @param secretIdTtl the TTL + * @return self + */ + public Builder withSecretIdTtl(final Integer secretIdTtl) { + this.secretIdTtl = secretIdTtl; + return this; + } + + /** + * Enable or disable local secret IDs. + * + * @param enableLocalSecretIds Enable local secret IDs? + * @return self + * @since 0.9 + */ + public Builder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) { + this.enableLocalSecretIds = enableLocalSecretIds; + return this; + } + + /** + * Set default token TTL in seconds. + * + * @param tokenTtl the TTL + * @return self + */ + public Builder withTokenTtl(final Integer tokenTtl) { + this.tokenTtl = tokenTtl; + return this; + } + + /** + * Set maximum token TTL in seconds. + * + * @param tokenMaxTtl the TTL + * @return self + */ + public Builder withTokenMaxTtl(final Integer tokenMaxTtl) { + this.tokenMaxTtl = tokenMaxTtl; + return this; + } + + /** + * Set bound CIDR blocks for associated tokens. + * + * @param tokenBoundCidrs List of CIDR blocks which can perform login + * @return self + * @since 0.9 + */ + public Builder withTokenBoundCidrs(final List tokenBoundCidrs) { + if (this.tokenBoundCidrs == null) { + this.tokenBoundCidrs = new ArrayList<>(); + } + this.tokenBoundCidrs.addAll(tokenBoundCidrs); + return this; + } + + /** + * Add a CIDR block to list of bound blocks for token. + * + * @param tokenBoundCidr the CIDR block + * @return self + * @since 0.9 + */ + public Builder withTokenBoundCidr(final String tokenBoundCidr) { + if (tokenBoundCidrs == null) { + tokenBoundCidrs = new ArrayList<>(); + } + tokenBoundCidrs.add(tokenBoundCidr); + return this; + } + + /** + * Set explicit maximum token TTL in seconds. + * + * @param tokenExplicitMaxTtl the TTL + * @return self + */ + public Builder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) { + this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; + return this; + } + + /** + * Enable or disable default policy for generated token. + * + * @param tokenNoDefaultPolicy Enable default policy for token? + * @return self + * @since 0.9 + */ + public Builder withTokenNoDefaultPolicy(final Boolean tokenNoDefaultPolicy) { + this.tokenNoDefaultPolicy = tokenNoDefaultPolicy; + return this; + } + + /** + * Set number of uses for generated tokens. + * + * @param tokenNumUses number of uses for tokens + * @return self + * @since 0.9 + */ + public Builder withTokenNumUses(final Integer tokenNumUses) { + this.tokenNumUses = tokenNumUses; + return this; + } + + /** + * Set renewal period for generated token in seconds. + * + * @param tokenPeriod period in seconds + * @return self + * @since 0.9 + */ + public Builder wit0hTokenPeriod(final Integer tokenPeriod) { + this.tokenPeriod = tokenPeriod; + return this; + } + + /** + * Set renewal period for generated token in seconds. + * + * @param period period in seconds + * @return self + * @deprecated Use {@link #wit0hTokenPeriod(Integer)} instead. + */ + @Deprecated + public Builder withPeriod(final Integer period) { + return wit0hTokenPeriod(period); + } + + /** + * Set type of generated token. + * + * @param tokenType token type + * @return self + * @since 0.9 + */ + public Builder withTokenType(final Token.Type tokenType) { + this.tokenType = tokenType; + return this; + } + + /** + * Build the AppRole role based on given parameters. + * + * @return the role + */ + public AppRole build() { + return new AppRole(this); + } } } diff --git a/src/main/java/de/stklcode/jvault/connector/model/AppRoleBuilder.java b/src/main/java/de/stklcode/jvault/connector/model/AppRoleBuilder.java index ae871cc..7267127 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/AppRoleBuilder.java +++ b/src/main/java/de/stklcode/jvault/connector/model/AppRoleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,19 +24,26 @@ import java.util.List; * * @author Stefan Kalscheuer * @since 0.4.0 + * @deprecated As of 0.9 in favor of {@link AppRole.Builder}. */ +@Deprecated public final class AppRoleBuilder { private String name; private String id; private Boolean bindSecretId; - private List boundCidrList; private List secretIdBoundCidrs; - private List policies; + private List tokenPolicies; private Integer secretIdNumUses; private Integer secretIdTtl; + private Boolean enableLocalSecretIds; private Integer tokenTtl; private Integer tokenMaxTtl; - private Integer period; + private List tokenBoundCidrs; + private Integer tokenExplicitMaxTtl; + private Boolean tokenNoDefaultPolicy; + private Integer tokenNumUses; + private Integer tokenPeriod; + private Token.Type tokenType; /** * Construct {@link AppRoleBuilder} with only the role name set. @@ -89,47 +96,48 @@ public final class AppRoleBuilder { return withBindSecretID(false); } - /** - * Set bound CIDR blocks. - * - * @param boundCidrList List of CIDR blocks which can perform login - * @return self - * @deprecated Use {@link #withSecretIdBoundCidrs(List)} instead, as this parameter is deprecated in Vault. - */ - @Deprecated - public AppRoleBuilder withBoundCidrList(final List boundCidrList) { - this.boundCidrList = boundCidrList; - return this; - } - /** * Set bound CIDR blocks. * * @param secretIdBoundCidrs List of CIDR blocks which can perform login * @return self - * @since 0.8 replaces {@link #withBoundCidrList(List)} + * @since 0.8 replaces {@code withBoundCidrList(List)} */ public AppRoleBuilder withSecretIdBoundCidrs(final List secretIdBoundCidrs) { - this.secretIdBoundCidrs = secretIdBoundCidrs; + if (this.secretIdBoundCidrs == null) { + this.secretIdBoundCidrs = new ArrayList<>(); + } + this.secretIdBoundCidrs.addAll(secretIdBoundCidrs); return this; } /** - * Add a CIDR block to list of bound blocks. + * Add a CIDR block to list of bound blocks for secret. * - * @param cidrBlock the CIDR block + * @param secretBoundCidr the CIDR block * @return self + * @since 0.9 */ - public AppRoleBuilder withCidrBlock(final String cidrBlock) { - if (boundCidrList == null) { - boundCidrList = new ArrayList<>(); - } - boundCidrList.add(cidrBlock); - + public AppRoleBuilder withSecretBoundCidr(final String secretBoundCidr) { if (secretIdBoundCidrs == null) { secretIdBoundCidrs = new ArrayList<>(); } - secretIdBoundCidrs.add(cidrBlock); + secretIdBoundCidrs.add(secretBoundCidr); + return this; + } + + /** + * Add given policies. + * + * @param tokenPolicies the token policies + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenPolicies(final List tokenPolicies) { + if (this.tokenPolicies == null) { + this.tokenPolicies = new ArrayList<>(); + } + this.tokenPolicies.addAll(tokenPolicies); return this; } @@ -138,12 +146,25 @@ public final class AppRoleBuilder { * * @param policies the policies * @return self + * @deprecated Use {@link #withTokenPolicies(List)} instead. */ + @Deprecated public AppRoleBuilder withPolicies(final List policies) { - if (this.policies == null) { - this.policies = new ArrayList<>(); + return withTokenPolicies(policies); + } + + /** + * Add a single policy. + * + * @param tokenPolicy the token policy + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenPolicy(final String tokenPolicy) { + if (this.tokenPolicies == null) { + this.tokenPolicies = new ArrayList<>(); } - this.policies.addAll(policies); + tokenPolicies.add(tokenPolicy); return this; } @@ -152,34 +173,44 @@ public final class AppRoleBuilder { * * @param policy the policy * @return self + * @deprecated Use {@link #withTokenPolicy(String)} instead. */ + @Deprecated public AppRoleBuilder withPolicy(final String policy) { - if (this.policies == null) { - this.policies = new ArrayList<>(); - } - policies.add(policy); + return withTokenPolicy(policy); + } + + /** + * Set number of uses for secret IDs. + * + * @param secretIdNumUses the number of uses + * @return self + */ + public AppRoleBuilder withSecretIdNumUses(final Integer secretIdNumUses) { + this.secretIdNumUses = secretIdNumUses; return this; } /** - * Set number of uses for sectet IDs. + * Set default secret ID TTL in seconds. * - * @param secredIdNumUses the number of uses + * @param secretIdTtl the TTL * @return self */ - public AppRoleBuilder withSecretIdNumUses(final Integer secredIdNumUses) { - this.secretIdNumUses = secredIdNumUses; + public AppRoleBuilder withSecretIdTtl(final Integer secretIdTtl) { + this.secretIdTtl = secretIdTtl; return this; } /** - * Set default sectet ID TTL in seconds. + * Enable or disable local secret IDs. * - * @param secredIdTtl the TTL + * @param enableLocalSecretIds Enable local secret IDs? * @return self + * @since 0.9 */ - public AppRoleBuilder withSecretIdTtl(final Integer secredIdTtl) { - this.secretIdTtl = secredIdTtl; + public AppRoleBuilder withEnableLocalSecretIds(final Boolean enableLocalSecretIds) { + this.enableLocalSecretIds = enableLocalSecretIds; return this; } @@ -205,17 +236,106 @@ public final class AppRoleBuilder { return this; } + /** + * Set bound CIDR blocks for associated tokens. + * + * @param tokenBoundCidrs List of CIDR blocks which can perform login + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenBoundCidrs(final List tokenBoundCidrs) { + if (this.tokenBoundCidrs == null) { + this.tokenBoundCidrs = new ArrayList<>(); + } + this.tokenBoundCidrs.addAll(tokenBoundCidrs); + return this; + } + + /** + * Add a CIDR block to list of bound blocks for token. + * + * @param tokenBoundCidr the CIDR block + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenBoundCidr(final String tokenBoundCidr) { + if (tokenBoundCidrs == null) { + tokenBoundCidrs = new ArrayList<>(); + } + tokenBoundCidrs.add(tokenBoundCidr); + return this; + } + + /** + * Set explicit maximum token TTL in seconds. + * + * @param tokenExplicitMaxTtl the TTL + * @return self + */ + public AppRoleBuilder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) { + this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; + return this; + } + + /** + * Enable or disable default policy for generated token. + * + * @param tokenNoDefaultPolicy Enable default policy for token? + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenNoDefaultPolicy(final Boolean tokenNoDefaultPolicy) { + this.tokenNoDefaultPolicy = tokenNoDefaultPolicy; + return this; + } + + /** + * Set number of uses for generated tokens. + * + * @param tokenNumUses number of uses for tokens + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenNumUses(final Integer tokenNumUses) { + this.tokenNumUses = tokenNumUses; + return this; + } + + /** + * Set renewal period for generated token in seconds. + * + * @param tokenPeriod period in seconds + * @return self + * @since 0.9 + */ + public AppRoleBuilder wit0hTokenPeriod(final Integer tokenPeriod) { + this.tokenPeriod = tokenPeriod; + return this; + } + /** * Set renewal period for generated token in seconds. * * @param period period in seconds * @return self + * @deprecated Use {@link #wit0hTokenPeriod(Integer)} instead. */ + @Deprecated public AppRoleBuilder withPeriod(final Integer period) { - this.period = period; - return this; + return wit0hTokenPeriod(period); } + /** + * Set type of generated token. + * + * @param tokenType token type + * @return self + * @since 0.9 + */ + public AppRoleBuilder withTokenType(final Token.Type tokenType) { + this.tokenType = tokenType; + return this; + } /** * Build the AppRole role based on given parameters. @@ -223,16 +343,23 @@ public final class AppRoleBuilder { * @return the role */ public AppRole build() { - return new AppRole(name, + return new AppRole( + name, id, bindSecretId, - boundCidrList, secretIdBoundCidrs, - policies, secretIdNumUses, secretIdTtl, + enableLocalSecretIds, tokenTtl, tokenMaxTtl, - period); + tokenPolicies, + tokenBoundCidrs, + tokenExplicitMaxTtl, + tokenNoDefaultPolicy, + tokenNumUses, + tokenPeriod, + tokenType != null ? tokenType.value() : null + ); } } diff --git a/src/main/java/de/stklcode/jvault/connector/model/AppRoleSecret.java b/src/main/java/de/stklcode/jvault/connector/model/AppRoleSecret.java index 6952074..8fa51f5 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/AppRoleSecret.java +++ b/src/main/java/de/stklcode/jvault/connector/model/AppRoleSecret.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/AuthBackend.java b/src/main/java/de/stklcode/jvault/connector/model/AuthBackend.java index d098fa1..6c2d3ea 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/AuthBackend.java +++ b/src/main/java/de/stklcode/jvault/connector/model/AuthBackend.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/Token.java b/src/main/java/de/stklcode/jvault/connector/model/Token.java index c6e2633..73bc25f 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/Token.java +++ b/src/main/java/de/stklcode/jvault/connector/model/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Vault Token metamodel. @@ -32,19 +31,23 @@ import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) public final class Token { /** - * Get {@link TokenBuilder} instance. + * Get {@link Builder} instance. * * @return Token Builder. * @since 0.8 */ - public static TokenBuilder builder() { - return new TokenBuilder(); + public static Builder builder() { + return new Builder(); } @JsonProperty("id") @JsonInclude(JsonInclude.Include.NON_NULL) private String id; + @JsonProperty("type") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String type; + @JsonProperty("display_name") @JsonInclude(JsonInclude.Include.NON_NULL) private String displayName; @@ -61,6 +64,10 @@ public final class Token { @JsonInclude(JsonInclude.Include.NON_NULL) private Integer ttl; + @JsonProperty("explicit_max_ttl") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer explicitMaxTtl; + @JsonProperty("num_uses") @JsonInclude(JsonInclude.Include.NON_NULL) private Integer numUses; @@ -77,8 +84,22 @@ public final class Token { @JsonInclude(JsonInclude.Include.NON_NULL) private Boolean renewable; + @JsonProperty("period") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer period; + + @JsonProperty("entity_alias") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String entityAlias; + /** - * Construct complete {@link Token} object. + * Construct empty {@link Token} object. + */ + public Token() { + } + + /** + * Construct complete {@link Token} object with default type. * * @param id Token ID (optional) * @param displayName Token display name (optional) @@ -89,7 +110,9 @@ public final class Token { * @param policies List of policies (optional) * @param meta Metadata (optional) * @param renewable Is the token renewable (optional) + * @deprecated As of 0.9 in favor of {@link #builder()}. Will be removed with next major release. */ + @Deprecated public Token(final String id, final String displayName, final Boolean noParent, @@ -99,7 +122,37 @@ public final class Token { final List policies, final Map meta, final Boolean renewable) { + this(id, Type.DEFAULT.value(), displayName, noParent, noDefaultPolicy, ttl, numUses, policies, meta, renewable); + } + + /** + * Construct complete {@link Token} object. + * + * @param id Token ID (optional) + * @param type Token type (optional) + * @param displayName Token display name (optional) + * @param noParent Token has no parent (optional) + * @param noDefaultPolicy Do not add default policy (optional) + * @param ttl Token TTL in seconds (optional) + * @param numUses Number of uses (optional) + * @param policies List of policies (optional) + * @param meta Metadata (optional) + * @param renewable Is the token renewable (optional) + * @deprecated As of 0.9 in favor of {@link #builder()}. Will be removed with next major release. + */ + @Deprecated + public Token(final String id, + final String type, + final String displayName, + final Boolean noParent, + final Boolean noDefaultPolicy, + final Integer ttl, + final Integer numUses, + final List policies, + final Map meta, + final Boolean renewable) { this.id = id; + this.type = type; this.displayName = displayName; this.ttl = ttl; this.numUses = numUses; @@ -110,6 +163,27 @@ public final class Token { this.renewable = renewable; } + /** + * Construct {@link Token} object from {@link Builder}. + * + * @param builder Token builder. + */ + public Token(final Builder builder) { + this.id = builder.id; + this.type = builder.type != null ? builder.type.value() : null; + this.displayName = builder.displayName; + this.noParent = builder.noParent; + this.noDefaultPolicy = builder.noDefaultPolicy; + this.ttl = builder.ttl; + this.explicitMaxTtl = builder.explicitMaxTtl; + this.numUses = builder.numUses; + this.policies = builder.policies; + this.meta = builder.meta; + this.renewable = builder.renewable; + this.period = builder.period; + this.entityAlias = builder.entityAlias; + } + /** * @return Token ID */ @@ -117,6 +191,14 @@ public final class Token { return id; } + /** + * @return Token type + * @since 0.9 + */ + public String getType() { + return type; + } + /** * @return Token display name */ @@ -145,6 +227,14 @@ public final class Token { return ttl; } + /** + * @return Explicit maximum time-to-live in seconds + * @since 0.9 + */ + public Integer getExplicitMaxTtl() { + return explicitMaxTtl; + } + /** * @return Number of uses */ @@ -172,4 +262,325 @@ public final class Token { public Boolean isRenewable() { return renewable; } + + /** + * @return Token period. + * @since 0.9 + */ + public Integer getPeriod() { + return period; + } + + /** + * @return Token entity alias. + * @since 0.9 + */ + public String getEntityAlias() { + return entityAlias; + } + + /** + * Constants for token types. + */ + public enum Type { + DEFAULT("default"), + BATCH("batch"), + SERVICE("service"), + DEFAULT_SERVICE("default-service"), + DEFAULT_BATCH("default-batch"); + + private final String value; + + Type(String value) { + this.value = value; + } + + public String value() { + return value; + } + } + + + /** + * A builder for vault tokens. + * + * @author Stefan Kalscheuer + * @since 0.4.0 + * @since 0.9 Moved into subclass of {@link Token}. + */ + public static final class Builder { + private String id; + private Type type; + private String displayName; + private Boolean noParent; + private Boolean noDefaultPolicy; + private Integer ttl; + private Integer explicitMaxTtl; + private Integer numUses; + private List policies; + private Map meta; + private Boolean renewable; + private Integer period; + private String entityAlias; + + /** + * Add token ID. (optional) + * + * @param id the ID + * @return self + */ + public Builder withId(final String id) { + this.id = id; + return this; + } + + /** + * Specify token type. + * + * @param type the type + * @return self + * @since 0.9 + */ + public Builder withType(final Token.Type type) { + this.type = type; + return this; + } + + /** + * Add display name. + * + * @param displayName the display name + * @return self + */ + public Builder withDisplayName(final String displayName) { + this.displayName = displayName; + return this; + } + + /** + * Set desired time to live. + * + * @param ttl the ttl + * @return self + */ + public Builder withTtl(final Integer ttl) { + this.ttl = ttl; + return this; + } + + /** + * Set desired explicit maximum time to live. + * + * @param explicitMaxTtl the explicit max. TTL + * @return self + */ + public Builder withExplicitMaxTtl(final Integer explicitMaxTtl) { + this.explicitMaxTtl = explicitMaxTtl; + return this; + } + + /** + * Set desired number of uses. + * + * @param numUses the number of uses + * @return self + */ + public Builder withNumUses(final Integer numUses) { + this.numUses = numUses; + return this; + } + + /** + * Set TRUE if the token should be created without parent. + * + * @param noParent if TRUE, token is created as orphan + * @return self + */ + public Builder withNoParent(final boolean noParent) { + this.noParent = noParent; + return this; + } + + /** + * Create token without parent. + * Convenience method for withNoParent() + * + * @return self + */ + public Builder asOrphan() { + return withNoParent(true); + } + + /** + * Create token with parent. + * Convenience method for withNoParent() + * + * @return self + */ + public Builder withParent() { + return withNoParent(false); + } + + /** + * Set TRUE if the default policy should not be part of this token. + * + * @param noDefaultPolicy if TRUE, default policy is not attached + * @return self + */ + public Builder withNoDefaultPolicy(final boolean noDefaultPolicy) { + this.noDefaultPolicy = noDefaultPolicy; + return this; + } + + /** + * Attach default policy to token. + * Convenience method for withNoDefaultPolicy() + * + * @return self + */ + public Builder withDefaultPolicy() { + return withNoDefaultPolicy(false); + } + + /** + * Do not attach default policy to token. + * Convenience method for withNoDefaultPolicy() + * + * @return self + */ + public Builder withoutDefaultPolicy() { + return withNoDefaultPolicy(true); + } + + /** + * Add given policies. + * + * @param policies the policies + * @return self + * @since 0.5.0 + */ + public Builder withPolicies(final String... policies) { + return withPolicies(Arrays.asList(policies)); + } + + /** + * Add given policies. + * + * @param policies the policies + * @return self + */ + public Builder withPolicies(final List 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 Builder withPolicy(final String policy) { + if (this.policies == null) { + this.policies = new ArrayList<>(); + } + policies.add(policy); + return this; + } + + /** + * Add meta data. + * + * @param meta the metadata + * @return self + */ + public Builder withMeta(final Map meta) { + if (this.meta == null) { + this.meta = new HashMap<>(); + } + this.meta.putAll(meta); + return this; + } + + /** + * Add meta data. + * + * @param key the key + * @param value the value + * @return self + */ + public Builder withMeta(final String key, final String value) { + if (this.meta == null) { + this.meta = new HashMap<>(); + } + this.meta.put(key, value); + return this; + } + + /** + * Set if token is renewable. + * + * @param renewable TRUE, if renewable + * @return self + */ + public Builder withRenewable(final Boolean renewable) { + this.renewable = renewable; + return this; + } + + /** + * Set token to be renewable. + * Convenience method for withRenewable() + * + * @return self + */ + public Builder renewable() { + return withRenewable(true); + } + + /** + * Set token to be not renewable. + * Convenience method for withRenewable() + * + * @return self + */ + public Builder notRenewable() { + return withRenewable(false); + } + + /** + * Set token period (former lease time). + * + * @param period Period in seconds. + * @return self + */ + public Builder withPeriod(final Integer period) { + this.period = period; + return this; + } + + /** + * Set entity alias for token. + * Only works in combination with an associated token role. + * + * @param entityAlias Entity alias. + * @return self + */ + public Builder withEntityAlias(final String entityAlias) { + this.entityAlias = entityAlias; + return this; + } + + /** + * Build the token based on given parameters. + * + * @return the token + */ + public Token build() { + return new Token(this); + } + } } diff --git a/src/main/java/de/stklcode/jvault/connector/model/TokenBuilder.java b/src/main/java/de/stklcode/jvault/connector/model/TokenBuilder.java index 8fed8dd..589a2d5 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/TokenBuilder.java +++ b/src/main/java/de/stklcode/jvault/connector/model/TokenBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +23,12 @@ import java.util.*; * * @author Stefan Kalscheuer * @since 0.4.0 + * @deprecated As of 0.9 in favor of {@link Token.Builder}. */ +@Deprecated public final class TokenBuilder { private String id; + private Token.Type type; private String displayName; private Boolean noParent; private Boolean noDefaultPolicy; @@ -46,6 +49,18 @@ public final class TokenBuilder { return this; } + /** + * Specify token type. + * + * @param type the type + * @return self + * @since 0.9 + */ + public TokenBuilder withType(final Token.Type type) { + this.type = type; + return this; + } + /** * Add display name. * @@ -247,6 +262,7 @@ public final class TokenBuilder { */ public Token build() { return new Token(id, + type != null ? type.value() : null, displayName, noParent, noDefaultPolicy, diff --git a/src/main/java/de/stklcode/jvault/connector/model/TokenRole.java b/src/main/java/de/stklcode/jvault/connector/model/TokenRole.java new file mode 100644 index 0000000..d32d087 --- /dev/null +++ b/src/main/java/de/stklcode/jvault/connector/model/TokenRole.java @@ -0,0 +1,465 @@ +/* + * Copyright 2016-2020 Stefan Kalscheuer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.stklcode.jvault.connector.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; + +/** + * Vault Token Role metamodel. + * + * @author Stefan Kalscheuer + * @since 0.9 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public final class TokenRole { + /** + * Get {@link Builder} instance. + * + * @return Token Role Builder. + */ + public static Builder builder() { + return new Builder(); + } + + @JsonProperty("name") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String name; + + @JsonProperty("allowed_policies") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List allowedPolicies; + + @JsonProperty("disallowed_policies") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List disallowedPolicies; + + @JsonProperty("orphan") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean orphan; + + @JsonProperty("renewable") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean renewable; + + @JsonProperty("path_suffix") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String pathSuffix; + + @JsonProperty("allowed_entity_aliases") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List allowedEntityAliases; + + @JsonProperty("token_bound_cidrs") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List tokenBoundCidrs; + + @JsonProperty("token_explicit_max_ttl") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenExplicitMaxTtl; + + @JsonProperty("token_no_default_policy") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean tokenNoDefaultPolicy; + + @JsonProperty("token_num_uses") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenNumUses; + + @JsonProperty("token_period") + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer tokenPeriod; + + @JsonProperty("token_type") + @JsonInclude(JsonInclude.Include.NON_NULL) + private String tokenType; + + /** + * Construct empty {@link TokenRole} object. + */ + public TokenRole() { + } + + public TokenRole(final Builder builder) { + this.name = builder.name; + this.allowedPolicies = builder.allowedPolicies; + this.disallowedPolicies = builder.disallowedPolicies; + this.orphan = builder.orphan; + this.renewable = builder.renewable; + this.pathSuffix = builder.pathSuffix; + this.allowedEntityAliases = builder.allowedEntityAliases; + this.tokenBoundCidrs = builder.tokenBoundCidrs; + this.tokenExplicitMaxTtl = builder.tokenExplicitMaxTtl; + this.tokenNoDefaultPolicy = builder.tokenNoDefaultPolicy; + this.tokenNumUses = builder.tokenNumUses; + this.tokenPeriod = builder.tokenPeriod; + this.tokenType = builder.tokenType != null ? builder.tokenType.value() : null; + } + + /** + * @return Token Role name + */ + public String getName() { + return name; + } + + /** + * @return List of allowed policies + */ + public List getAllowedPolicies() { + return allowedPolicies; + } + + /** + * @return List of disallowed policies + */ + public List getDisallowedPolicies() { + return disallowedPolicies; + } + + /** + * @return Is Token Role orphan? + */ + public Boolean getOrphan() { + return orphan; + } + + /** + * @return Is Token Role renewable? + */ + public Boolean getRenewable() { + return renewable; + } + + /** + * @return Path suffix + */ + public String getPathSuffix() { + return pathSuffix; + } + + /** + * @return List of allowed entity aliases + */ + public List getAllowedEntityAliases() { + return allowedEntityAliases; + } + + /** + * @return Token bound CIDR blocks + */ + public List getTokenBoundCidrs() { + return tokenBoundCidrs; + } + + /** + * @return Token explicit maximum TTL + */ + public Integer getTokenExplicitMaxTtl() { + return tokenExplicitMaxTtl; + } + + /** + * @return Token without default policy? + */ + public Boolean getTokenNoDefaultPolicy() { + return tokenNoDefaultPolicy; + } + + /** + * @return Token number of uses + */ + public Integer getTokenNumUses() { + return tokenNumUses; + } + + /** + * @return Token period + */ + public Integer getTokenPeriod() { + return tokenPeriod; + } + + /** + * @return Token type + */ + public String getTokenType() { + return tokenType; + } + + /** + * A builder for vault token roles. + * + * @author Stefan Kalscheuer + * @since 0.9 + */ + public static final class Builder { + private String name; + private List allowedPolicies; + private List disallowedPolicies; + private Boolean orphan; + private Boolean renewable; + private String pathSuffix; + private List allowedEntityAliases; + private List tokenBoundCidrs; + private Integer tokenExplicitMaxTtl; + private Boolean tokenNoDefaultPolicy; + private Integer tokenNumUses; + private Integer tokenPeriod; + private Token.Type tokenType; + + /** + * Add token role name. + * + * @param name role name + * @return self + */ + public Builder forName(final String name) { + this.name = name; + return this; + } + + /** + * Add an allowed policy. + * + * @param allowedPolicy allowed policy to add + * @return self + */ + public Builder withAllowedPolicy(final String allowedPolicy) { + if (allowedPolicy != null) { + if (this.allowedPolicies == null) { + this.allowedPolicies = new ArrayList<>(); + } + this.allowedPolicies.add(allowedPolicy); + } + return this; + } + + /** + * Add allowed policies. + * + * @param allowedPolicies list of allowed policies + * @return self + */ + public Builder withAllowedPolicies(final List allowedPolicies) { + if (allowedPolicies != null) { + if (this.allowedPolicies == null) { + this.allowedPolicies = new ArrayList<>(); + } + this.allowedPolicies.addAll(allowedPolicies); + } + return this; + } + + /** + * Add a disallowed policy. + * + * @param disallowedPolicy disallowed policy to add + * @return self + */ + public Builder withDisallowedPolicy(final String disallowedPolicy) { + if (disallowedPolicy != null) { + if (this.disallowedPolicies == null) { + this.disallowedPolicies = new ArrayList<>(); + } + this.disallowedPolicies.add(disallowedPolicy); + } + return this; + } + + /** + * Add disallowed policies. + * + * @param disallowedPolicies list of disallowed policies + * @return self + */ + public Builder withDisallowedPolicies(final List disallowedPolicies) { + if (disallowedPolicies != null) { + if (this.disallowedPolicies == null) { + this.disallowedPolicies = new ArrayList<>(); + } + this.disallowedPolicies.addAll(disallowedPolicies); + } + return this; + } + + /** + * Set TRUE if the token role should be created orphan. + * + * @param orphan if TRUE, token role is created as orphan + * @return self + */ + public Builder orphan(final Boolean orphan) { + this.orphan = orphan; + return this; + } + + /** + * Set TRUE if the token role should be created renewable. + * + * @param renewable if TRUE, token role is created renewable + * @return self + */ + public Builder renewable(final Boolean renewable) { + this.renewable = renewable; + return this; + } + + /** + * Set token role path suffix. + * + * @param pathSuffix path suffix to use + * @return self + */ + public Builder withPathSuffix(final String pathSuffix) { + this.pathSuffix = pathSuffix; + return this; + } + + /** + * Add an allowed entity alias. + * + * @param allowedEntityAlias allowed entity alias to add + * @return self + */ + public Builder withAllowedEntityAlias(final String allowedEntityAlias) { + if (allowedEntityAlias != null) { + if (this.allowedEntityAliases == null) { + this.allowedEntityAliases = new ArrayList<>(); + } + this.allowedEntityAliases.add(allowedEntityAlias); + } + return this; + } + + /** + * Add allowed entity aliases. + * + * @param allowedEntityAliases list of allowed entity aliases to add + * @return self + */ + public Builder withAllowedEntityAliases(final List allowedEntityAliases) { + if (allowedEntityAliases != null) { + if (this.allowedEntityAliases == null) { + this.allowedEntityAliases = new ArrayList<>(); + } + this.allowedEntityAliases.addAll(allowedEntityAliases); + } + return this; + } + + /** + * Add a single bound CIDR. + * + * @param tokenBoundCidr bound CIDR to add + * @return self + */ + public Builder withTokenBoundCidr(final String tokenBoundCidr) { + if (tokenBoundCidr != null) { + if (this.tokenBoundCidrs == null) { + this.tokenBoundCidrs = new ArrayList<>(); + } + this.tokenBoundCidrs.add(tokenBoundCidr); + } + return this; + } + + /** + * Add a list of bound CIDRs. + * + * @param tokenBoundCidrs list of bound CIDRs to add + * @return self + */ + public Builder withTokenBoundCidrs(final List tokenBoundCidrs) { + if (tokenBoundCidrs != null) { + if (this.tokenBoundCidrs == null) { + this.tokenBoundCidrs = new ArrayList<>(); + } + this.tokenBoundCidrs.addAll(tokenBoundCidrs); + } + return this; + } + + /** + * Set explicit max. TTL for token. + * + * @param tokenExplicitMaxTtl explicit maximum TTL + * @return self + */ + public Builder withTokenExplicitMaxTtl(final Integer tokenExplicitMaxTtl) { + this.tokenExplicitMaxTtl = tokenExplicitMaxTtl; + return this; + } + + /** + * Set TRUE if the token role should be created renewable. + * + * @param tokenNoDefaultPolicy if TRUE, token is created without default policy. + * @return self + */ + public Builder withTokenNoDefaultPolicy(final Boolean tokenNoDefaultPolicy) { + this.tokenNoDefaultPolicy = tokenNoDefaultPolicy; + return this; + } + + /** + * Set number of uses for tokens. + * + * @param tokenNumUses number of uses for associated tokens. + * @return self + */ + public Builder withTokenNumUses(final Integer tokenNumUses) { + this.tokenNumUses = tokenNumUses; + return this; + } + + /** + * Set token period. + * + * @param tokenPeriod token period + * @return self + */ + public Builder withTokenPeriod(final Integer tokenPeriod) { + this.tokenPeriod = tokenPeriod; + return this; + } + + /** + * Set token type. + * + * @param tokenType token type + * @return self + */ + public Builder withTokenType(final Token.Type tokenType) { + this.tokenType = tokenType; + return this; + } + + /** + * Build the token based on given parameters. + * + * @return the token + */ + public TokenRole build() { + return new TokenRole(this); + } + } +} diff --git a/src/main/java/de/stklcode/jvault/connector/model/package-info.java b/src/main/java/de/stklcode/jvault/connector/model/package-info.java index 6e87e2f..dce8c1b 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/model/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleResponse.java index b58e3f4..f3c19d5 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleSecretResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleSecretResponse.java index 869cbf7..35eb3b0 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleSecretResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/AppRoleSecretResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponse.java index da72378..58ebf36 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/AuthResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/AuthResponse.java index 67080ac..d5b35ca 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/AuthResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/AuthResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/CredentialsResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/CredentialsResponse.java index ed4b6e4..d524339 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/CredentialsResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/CredentialsResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/ErrorResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/ErrorResponse.java index 9b91b19..a1a04ef 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/ErrorResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/ErrorResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/HealthResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/HealthResponse.java index a8aa2d5..940ac5b 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/HealthResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/HealthResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/HelpResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/HelpResponse.java index 4aa9e75..f2dbfa5 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/HelpResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/HelpResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/MetadataResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/MetadataResponse.java index fda5f6d..89de0da 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/MetadataResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/MetadataResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/RawDataResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/RawDataResponse.java index 039a1f0..d959c96 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/RawDataResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/RawDataResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/SealResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/SealResponse.java index 052e3db..4ce5e39 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/SealResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/SealResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/SecretListResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/SecretListResponse.java index 5f46dbb..35699a3 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/SecretListResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/SecretListResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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 f4f3c1d..b670a5b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/SecretVersionResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/SecretVersionResponse.java index aa7a6db..2abd162 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/SecretVersionResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/SecretVersionResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import java.io.IOException; import java.util.Map; /** - * Vault response for a single secret version metatada, i.e. after update (KV v2). + * Vault response for a single secret version metadata, i.e. after update (KV v2). * * @author Stefan Kalscheuer * @since 0.8 diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/TokenResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/TokenResponse.java index 0cd2fe0..cabea7c 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/TokenResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/TokenResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/TokenRoleResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/TokenRoleResponse.java new file mode 100644 index 0000000..68c11cd --- /dev/null +++ b/src/main/java/de/stklcode/jvault/connector/model/response/TokenRoleResponse.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016-2020 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.TokenRole; +import de.stklcode.jvault.connector.model.response.embedded.TokenData; + +import java.io.IOException; +import java.util.Map; + +/** + * Vault response from token role lookup providing Token information in {@link TokenData} field. + * + * @author Stefan Kalscheuer + * @since 0.9 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public final class TokenRoleResponse extends VaultDataResponse { + private TokenRole data; + + /** + * Set data. Parses response data map to {@link TokenRole}. + * + * @param data Raw response data + * @throws InvalidResponseException on parsing errors + */ + @Override + public void setData(final Map data) throws InvalidResponseException { + ObjectMapper mapper = new ObjectMapper(); + try { + this.data = mapper.readValue(mapper.writeValueAsString(data), TokenRole.class); + } catch (IOException e) { + throw new InvalidResponseException("Failed deserializing response", e); + } + } + + /** + * @return TokenRole data + */ + public TokenRole getData() { + return data; + } +} diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/VaultDataResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/VaultDataResponse.java index 073d3ce..d0b5595 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/VaultDataResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/VaultDataResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/VaultResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/VaultResponse.java index c331205..bc82e40 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/VaultResponse.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/VaultResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthData.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthData.java index bf2d12f..d5ed06c 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthData.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthData.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,9 @@ public final class AuthData { @JsonProperty("policies") private List policies; + @JsonProperty("token_policies") + private List tokenPolicies; + @JsonProperty("metadata") private Map metadata; @@ -48,6 +51,15 @@ public final class AuthData { @JsonProperty("renewable") private boolean renewable; + @JsonProperty("entity_id") + private String entityId; + + @JsonProperty("token_type") + private String tokenType; + + @JsonProperty("orphan") + private boolean orphan; + /** * @return Client token */ @@ -56,10 +68,11 @@ public final class AuthData { } /** - * @return Token accessor + * @return Token type + * @since 0.9 */ - public String getAccessor() { - return accessor; + public String getTokenType() { + return tokenType; } /** @@ -69,6 +82,14 @@ public final class AuthData { return policies; } + /** + * @return List of policies associated with the token + * @since 0.9 + */ + public List getTokenPolicies() { + return tokenPolicies; + } + /** * @return Metadata */ @@ -89,4 +110,27 @@ public final class AuthData { public boolean isRenewable() { return renewable; } + + /** + * @return Entity ID + * @since 0.9 + */ + public String getEntityId() { + return entityId; + } + + /** + * @return Token accessor + */ + public String getAccessor() { + return accessor; + } + + /** + * @return Token is orphan + * @since 0.9 + */ + public boolean isOrphan() { + return orphan; + } } diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthMethod.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthMethod.java index aa4e87d..88b5b59 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthMethod.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/AuthMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java index 9a9233e..a248d77 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java index fb503c7..5e0f461 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,15 @@ package de.stklcode.jvault.connector.model.response.embedded; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; + /** * Embedded token information inside Vault response. * - * @author Stefan Kalscheuer - * @since 0.1 + * @author Stefan Kalscheuer + * @since 0.1 */ @JsonIgnoreProperties(ignoreUnknown = true) public final class TokenData { @@ -39,11 +43,23 @@ public final class TokenData { @JsonProperty("display_name") private String name; + @JsonProperty("entity_id") + private String entityId; + + @JsonProperty("expire_time") + private String expireTime; + + @JsonProperty("explicit_max_ttl") + private Integer explicitMaxTtl; + @JsonProperty("id") private String id; + @JsonProperty("issue_time") + private String issueTime; + @JsonProperty("meta") - private String meta; + private Map meta; @JsonProperty("num_uses") private Integer numUses; @@ -54,12 +70,18 @@ public final class TokenData { @JsonProperty("path") private String path; - @JsonProperty("role") - private String role; + @JsonProperty("policies") + private List policies; + + @JsonProperty("renewable") + private boolean renewable; @JsonProperty("ttl") private Integer ttl; + @JsonProperty("type") + private String type; + /** * @return Token accessor */ @@ -88,6 +110,42 @@ public final class TokenData { return name; } + /** + * @return Entity ID + * @since 0.9 + */ + public String getEntityId() { + return entityId; + } + + /** + * @return Expire time as raw string value + * @since 0.9 + */ + public String getExpireTimeString() { + return expireTime; + } + + /** + * @return Expire time (parsed) + * @since 0.9 + */ + public ZonedDateTime getExpireTime() { + if (expireTime == null) { + return null; + } else { + return ZonedDateTime.parse(expireTime); + } + } + + /** + * @return Explicit maximum TTL + * @since 0.9 + */ + public Integer getExplicitMaxTtl() { + return explicitMaxTtl; + } + /** * @return Token ID */ @@ -95,6 +153,34 @@ public final class TokenData { return id; } + /** + * @return Issue time as raw string value + * @since 0.9 + */ + public String getIssueTimeString() { + return issueTime; + } + + /** + * @return Expire time (parsed) + * @since 0.9 + */ + public ZonedDateTime getIssueTime() { + if (issueTime == null) { + return null; + } else { + return ZonedDateTime.parse(issueTime); + } + } + + /** + * @return Token type + * @since 0.9 + */ + public String getType() { + return type; + } + /** * @return Number of uses */ @@ -117,10 +203,19 @@ public final class TokenData { } /** - * @return Token role + * @return Token policies + * @since 0.9 */ - public String getRole() { - return role; + public List getPolicies() { + return policies; + } + + /** + * @return Token is renewable + * @since 0.9 + */ + public boolean isRenewable() { + return renewable; } /** @@ -133,7 +228,7 @@ public final class TokenData { /** * @return Metadata */ - public String getMeta() { + public Map getMeta() { return meta; } } diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java index 4fbbc4a..7f06d54 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/package-info.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/package-info.java index f2754ad..7d24785 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/package-info.java b/src/main/java/de/stklcode/jvault/connector/model/response/package-info.java index 3d41006..65ddb0a 100644 --- a/src/main/java/de/stklcode/jvault/connector/model/response/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/model/response/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/de/stklcode/jvault/connector/package-info.java b/src/main/java/de/stklcode/jvault/connector/package-info.java index 9417eb1..8e67bbd 100644 --- a/src/main/java/de/stklcode/jvault/connector/package-info.java +++ b/src/main/java/de/stklcode/jvault/connector/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java index b44c2dc..db06169 100644 --- a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java +++ b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -151,7 +151,7 @@ public class HTTPVaultConnectorOfflineTest { } /** - * Test constductors of the {@link HTTPVaultConnector} class. + * Test constructors of the {@link HTTPVaultConnector} class. */ @Test public void constructorTest() throws IOException, CertificateException { diff --git a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java index b9701db..c808f72 100644 --- a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java +++ b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import de.stklcode.jvault.connector.exception.*; import de.stklcode.jvault.connector.model.AppRole; import de.stklcode.jvault.connector.model.AuthBackend; import de.stklcode.jvault.connector.model.Token; +import de.stklcode.jvault.connector.model.TokenRole; import de.stklcode.jvault.connector.model.response.*; import de.stklcode.jvault.connector.test.Credentials; import de.stklcode.jvault.connector.test.VaultConfiguration; @@ -39,9 +40,9 @@ import static org.apache.commons.io.FileUtils.copyDirectory; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * JUnit test for HTTP Vault connector. @@ -52,7 +53,7 @@ import static org.junit.jupiter.api.Assumptions.*; */ @Tag("online") public class HTTPVaultConnectorTest { - private static String VAULT_VERSION = "1.3.0"; // the vault version this test is supposed to run against + private static String VAULT_VERSION = "1.4.0"; // the vault version this test is supposed to run against private static final String KEY1 = "E38bkCm0VhUvpdCKGQpcohhD9XmcHJ/2hreOSY019Lho"; private static final String KEY2 = "O5OHwDleY3IiPdgw61cgHlhsrEm6tVJkrxhF6QAnILd1"; private static final String KEY3 = "mw7Bm3nbt/UWa/juDjjL2EPQ04kiJ0saC5JEXwJvXYsB"; @@ -880,6 +881,28 @@ public class HTTPVaultConnectorTest { fail("Role ID lookup failed."); } + /* Update role model with custom flags */ + role = AppRole.builder(roleName) + .wit0hTokenPeriod(321) + .build(); + + /* Create role */ + try { + boolean res = connector.createAppRole(role); + assertThat("No result given.", res, is(notNullValue())); + } catch (VaultConnectorException e) { + fail("Role creation failed."); + } + + /* Lookup updated role */ + try { + AppRoleResponse res = connector.lookupAppRole(roleName); + assertThat("Role lookup returned no role.", res.getRole(), is(notNullValue())); + assertThat("Token period not set for role.", res.getRole().getTokenPeriod(), is(321)); + } catch (VaultConnectorException e) { + fail("Role lookup failed."); + } + /* Create role by name */ roleName = "RoleByName"; try { @@ -925,8 +948,8 @@ public class HTTPVaultConnectorTest { try { AppRoleResponse res = connector.lookupAppRole(roleName); // Note: As of Vault 0.8.3 default policy is not added automatically, so this test should return 1, not 2. - assertThat("Role lookuo returned wrong policy count (before Vault 0.8.3 is should be 2)", res.getRole().getPolicies(), hasSize(1)); - assertThat("Role lookuo returned wrong policies", res.getRole().getPolicies(), hasItem("testpolicy")); + assertThat("Role lookup returned wrong policy count (before Vault 0.8.3 is should be 2)", res.getRole().getPolicies(), hasSize(1)); + assertThat("Role lookup returned wrong policies", res.getRole().getPolicies(), hasItem("testpolicy")); } catch (VaultConnectorException e) { fail("Creation of role by name failed."); } @@ -1038,6 +1061,7 @@ public class HTTPVaultConnectorTest { /* Create token */ Token token = Token.builder() .withId("test-id") + .withType(Token.Type.SERVICE) .withDisplayName("test name") .build(); @@ -1048,10 +1072,14 @@ public class HTTPVaultConnectorTest { 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("Invalid number of token policies returned.", res.getAuth().getTokenPolicies(), hasSize(1)); + assertThat("Root policy not inherited for token.", res.getAuth().getTokenPolicies(), contains("root")); + assertThat("Unexpected token type.", res.getAuth().getTokenType(), is(Token.Type.SERVICE.value())); assertThat("Metadata unexpected.", res.getAuth().getMetadata(), is(nullValue())); assertThat("Root token should not be renewable", res.getAuth().isRenewable(), is(false)); + assertThat("Root token should not be orphan", res.getAuth().isOrphan(), is(false)); - // Starting with Vault 1.0 a warning "cusotm ID uses weaker SHA1..." is given. + // Starting with Vault 1.0 a warning "custom ID uses weaker SHA1..." is given. if (VAULT_VERSION.startsWith("1.")) { assertThat("Token creation did not return expected warning.", res.getWarnings(), hasSize(1)); } else { @@ -1073,12 +1101,12 @@ public class HTTPVaultConnectorTest { 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("Custom policy not set.", 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."); + fail("Token creation failed: " + e.getMessage()); } /* Overwrite token should fail as of Vault 0.8.0 */ @@ -1100,10 +1128,30 @@ public class HTTPVaultConnectorTest { /* Assert that the exception does not reveal token ID */ assertThat(stackTrace(e), not(stringContainsInOrder(token.getId()))); } + + /* Create token with batch type */ + token = Token.builder() + .withDisplayName("test name 3") + .withPolicy("batchpolicy") + .withoutDefaultPolicy() + .withType(Token.Type.BATCH) + .build(); + try { + AuthResponse res = connector.createToken(token); + assertThat("Unexpected token prefix", res.getAuth().getClientToken(), startsWith("b.")); + assertThat("Invalid number of policies returned.", res.getAuth().getPolicies(), hasSize(1)); + assertThat("Custom policy policy not set.", res.getAuth().getPolicies(), contains("batchpolicy")); + assertThat("Token should not be renewable", res.getAuth().isRenewable(), is(false)); + assertThat("Token should not be orphan", res.getAuth().isOrphan(), is(false)); + assertThat("Specified token Type not set", res.getAuth().getTokenType(), is(Token.Type.BATCH.value())); + + } catch (VaultConnectorException e) { + fail("Token creation failed: " + e.getMessage()); + } } /** - * Test token lookuo. + * Test token lookup. */ @Test @Order(30) @@ -1115,6 +1163,7 @@ public class HTTPVaultConnectorTest { /* Create token with attributes */ Token token = Token.builder() .withId("my-token") + .withType(Token.Type.SERVICE) .build(); try { connector.createToken(token); @@ -1128,10 +1177,100 @@ public class HTTPVaultConnectorTest { try { TokenResponse res = connector.lookupToken("my-token"); assertThat("Unexpected token ID", res.getData().getId(), is(token.getId())); + assertThat("Unexpected number of policies", res.getData().getPolicies(), hasSize(1)); + assertThat("Unexpected policy", res.getData().getPolicies(), contains("root")); + assertThat("Unexpected token type", res.getData().getType(), is(token.getType())); + assertThat("Issue time expected to be filled", res.getData().getIssueTime(), is(notNullValue())); } catch (VaultConnectorException e) { fail("Token creation failed."); } } + + /** + * Test token role handling. + */ + @Test + @Order(40) + @DisplayName("Token roles") + public void tokenRolesTest() { + authRoot(); + assumeTrue(connector.isAuthorized()); + + // Create token role. + final String roleName = "test-role"; + final TokenRole role = TokenRole.builder().build(); + + try { + assertThat(connector.createOrUpdateTokenRole(roleName, role), is(true)); + } catch (VaultConnectorException e) { + fail("Token role creation failed."); + } + + // Read the role. + TokenRoleResponse res = null; + try { + res = connector.readTokenRole(roleName); + } catch (VaultConnectorException e) { + fail("Reading token role failed."); + } + + assertThat("Token role response must not be null", res, is(notNullValue())); + assertThat("Token role must not be null", res.getData(), is(notNullValue())); + assertThat("Token role name not as expected", res.getData().getName(), is(roleName)); + assertThat("Token role expected to be renewable by default", res.getData().getRenewable(), is(true)); + assertThat("Token role not expected to be orphan by default", res.getData().getOrphan(), is(false)); + assertThat("Unexpected default token type", res.getData().getTokenType(), is(Token.Type.DEFAULT_SERVICE.value())); + + // Update the role, i.e. change some attributes. + final TokenRole role2 = TokenRole.builder() + .forName(roleName) + .withPathSuffix("suffix") + .orphan(true) + .renewable(false) + .withTokenNumUses(42) + .build(); + + try { + assertThat(connector.createOrUpdateTokenRole(role2), is(true)); + } catch (VaultConnectorException e) { + fail("Token role update failed."); + } + + try { + res = connector.readTokenRole(roleName); + } catch (VaultConnectorException e) { + fail("Reading token role failed."); + } + + assertThat("Token role response must not be null", res, is(notNullValue())); + assertThat("Token role must not be null", res.getData(), is(notNullValue())); + assertThat("Token role name not as expected", res.getData().getName(), is(roleName)); + assertThat("Token role not expected to be renewable after update", res.getData().getRenewable(), is(false)); + assertThat("Token role expected to be orphan after update", res.getData().getOrphan(), is(true)); + assertThat("Unexpected number of token uses after update", res.getData().getTokenNumUses(), is(42)); + + // List roles. + List listRes = null; + try { + listRes = connector.listTokenRoles(); + } catch (VaultConnectorException e) { + fail("Listing token roles failed."); + } + + assertThat("Token role list must not be null", listRes, is(notNullValue())); + assertThat("Unexpected number of token roles", listRes, hasSize(1)); + assertThat("Unexpected token role in list", listRes, contains(roleName)); + + // Delete the role. + try { + assertThat(connector.deleteTokenRole(roleName), is(true)); + } catch (VaultConnectorException e) { + fail("Token role deletion failed."); + } + + assertThrows(InvalidResponseException.class, () -> connector.readTokenRole(roleName), "Reading nonexistent token role should fail"); + assertThrows(InvalidResponseException.class, () -> connector.listTokenRoles(), "Listing nonexistent token roles should fail"); + } } @Nested @@ -1266,7 +1405,7 @@ public class HTTPVaultConnectorTest { try { connector.seal(); assumeTrue(connector.sealStatus().isSealed()); - connector.resetAuth(); // SHould work unauthenticated + connector.resetAuth(); // Should work unauthenticated } catch (VaultConnectorException e) { fail("Unexpected exception on sealing: " + e.getMessage()); } diff --git a/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java b/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java index 788301e..6a089b9 100644 --- a/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java +++ b/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/exception/VaultConnectorExceptionTest.java b/src/test/java/de/stklcode/jvault/connector/exception/VaultConnectorExceptionTest.java index d680f7a..6c15b4f 100644 --- a/src/test/java/de/stklcode/jvault/connector/exception/VaultConnectorExceptionTest.java +++ b/src/test/java/de/stklcode/jvault/connector/exception/VaultConnectorExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java b/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java index de4fb95..4435d2f 100644 --- a/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java +++ b/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/AppRoleBuilderTest.java b/src/test/java/de/stklcode/jvault/connector/model/AppRoleBuilderTest.java index 21a586b..2a98f7f 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/AppRoleBuilderTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/AppRoleBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,6 @@ import static org.hamcrest.Matchers.*; * @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; @@ -47,12 +45,17 @@ public class AppRoleBuilderTest { 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 Boolean ENABLE_LOCAL_SECRET_IDS = false; private static final Integer TOKEN_TTL = 4800; private static final Integer TOKEN_MAX_TTL = 9600; - private static final Integer PERIOD = 1234; + private static final Integer TOKEN_EXPLICIT_MAX_TTL = 14400; + private static final Boolean TOKEN_NO_DEFAULT_POLICY = false; + private static final Integer TOKEN_NUM_USES = 42; + private static final Integer TOKEN_PERIOD = 1234; + private static final Token.Type TOKEN_TYPE = Token.Type.DEFAULT_SERVICE; private static final String JSON_MIN = "{\"role_name\":\"" + NAME + "\"}"; - private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"bound_cidr_list\":\"%s\",\"secret_id_bound_cidrs\":\"%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, CIDR_1, POLICY, SECRET_ID_NUM_USES, SECRET_ID_TTL, TOKEN_TTL, TOKEN_MAX_TTL, PERIOD); + private static final String JSON_FULL = String.format("{\"role_name\":\"%s\",\"role_id\":\"%s\",\"bind_secret_id\":%s,\"secret_id_bound_cidrs\":\"%s\",\"secret_id_num_uses\":%d,\"secret_id_ttl\":%d,\"enable_local_secret_ids\":%s,\"token_ttl\":%d,\"token_max_ttl\":%d,\"token_policies\":\"%s\",\"token_bound_cidrs\":\"%s\",\"token_explicit_max_ttl\":%d,\"token_no_default_policy\":%s,\"token_num_uses\":%d,\"token_period\":%d,\"token_type\":\"%s\"}", + NAME, ID, BIND_SECRET_ID, CIDR_1, SECRET_ID_NUM_USES, SECRET_ID_TTL, ENABLE_LOCAL_SECRET_IDS, TOKEN_TTL, TOKEN_MAX_TTL, POLICY, CIDR_1, TOKEN_EXPLICIT_MAX_TTL, TOKEN_NO_DEFAULT_POLICY, TOKEN_NUM_USES, TOKEN_PERIOD, TOKEN_TYPE.value()); @BeforeAll public static void init() { @@ -65,17 +68,52 @@ public class AppRoleBuilderTest { */ @Test public void buildDefaultTest() throws JsonProcessingException { - AppRole role = new AppRoleBuilder(NAME).build(); + AppRole role = AppRole.builder(NAME).build(); assertThat(role.getId(), is(nullValue())); assertThat(role.getBindSecretId(), is(nullValue())); - assertThat(role.getBoundCidrList(), is(nullValue())); assertThat(role.getSecretIdBoundCidrs(), is(nullValue())); + assertThat(role.getTokenPolicies(), is(nullValue())); assertThat(role.getPolicies(), is(nullValue())); assertThat(role.getSecretIdNumUses(), is(nullValue())); assertThat(role.getSecretIdTtl(), is(nullValue())); + assertThat(role.getEnableLocalSecretIds(), is(nullValue())); assertThat(role.getTokenTtl(), is(nullValue())); assertThat(role.getTokenMaxTtl(), is(nullValue())); + assertThat(role.getTokenBoundCidrs(), is(nullValue())); + assertThat(role.getTokenExplicitMaxTtl(), is(nullValue())); + assertThat(role.getTokenNoDefaultPolicy(), is(nullValue())); + assertThat(role.getTokenNumUses(), is(nullValue())); + assertThat(role.getTokenPeriod(), is(nullValue())); assertThat(role.getPeriod(), is(nullValue())); + assertThat(role.getTokenType(), is(nullValue())); + + /* optional fields should be ignored, so JSON string should only contain role_name */ + assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN)); + } + + /** + * Build role with only a name. + */ + @Test + public void legacyBuildDefaultTest() throws JsonProcessingException { + AppRole role = new AppRoleBuilder(NAME).build(); + assertThat(role.getId(), is(nullValue())); + assertThat(role.getBindSecretId(), is(nullValue())); + assertThat(role.getSecretIdBoundCidrs(), is(nullValue())); + assertThat(role.getTokenPolicies(), is(nullValue())); + assertThat(role.getPolicies(), is(nullValue())); + assertThat(role.getSecretIdNumUses(), is(nullValue())); + assertThat(role.getSecretIdTtl(), is(nullValue())); + assertThat(role.getEnableLocalSecretIds(), is(nullValue())); + assertThat(role.getTokenTtl(), is(nullValue())); + assertThat(role.getTokenMaxTtl(), is(nullValue())); + assertThat(role.getTokenBoundCidrs(), is(nullValue())); + assertThat(role.getTokenExplicitMaxTtl(), is(nullValue())); + assertThat(role.getTokenNoDefaultPolicy(), is(nullValue())); + assertThat(role.getTokenNumUses(), is(nullValue())); + assertThat(role.getTokenPeriod(), is(nullValue())); + assertThat(role.getPeriod(), is(nullValue())); + assertThat(role.getTokenType(), is(nullValue())); /* optional fields should be ignored, so JSON string should only contain role_name */ assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_MIN)); @@ -86,29 +124,86 @@ public class AppRoleBuilderTest { */ @Test public void buildFullTest() throws JsonProcessingException { - AppRole role = new AppRoleBuilder(NAME) + AppRole role = AppRole.builder(NAME) .withId(ID) .withBindSecretID(BIND_SECRET_ID) - .withBoundCidrList(BOUND_CIDR_LIST) .withSecretIdBoundCidrs(BOUND_CIDR_LIST) - .withPolicies(POLICIES) + .withTokenPolicies(POLICIES) .withSecretIdNumUses(SECRET_ID_NUM_USES) .withSecretIdTtl(SECRET_ID_TTL) + .withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS) .withTokenTtl(TOKEN_TTL) .withTokenMaxTtl(TOKEN_MAX_TTL) - .withPeriod(PERIOD) + .withTokenBoundCidrs(BOUND_CIDR_LIST) + .withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL) + .withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY) + .withTokenNumUses(TOKEN_NUM_USES) + .wit0hTokenPeriod(TOKEN_PERIOD) + .withTokenType(TOKEN_TYPE) .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.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST)); - assertThat(role.getPolicies(), is(POLICIES)); + assertThat(role.getTokenPolicies(), is(POLICIES)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES)); assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL)); + assertThat(role.getEnableLocalSecretIds(), is(ENABLE_LOCAL_SECRET_IDS)); assertThat(role.getTokenTtl(), is(TOKEN_TTL)); assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL)); - assertThat(role.getPeriod(), is(PERIOD)); + assertThat(role.getTokenBoundCidrs(), is(BOUND_CIDR_LIST)); + assertThat(role.getTokenExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL)); + assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY)); + assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES)); + assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD)); + assertThat(role.getPeriod(), is(TOKEN_PERIOD)); + assertThat(role.getTokenType(), is(TOKEN_TYPE.value())); + + /* Verify that all parameters are included in JSON string */ + assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL)); + } + + /** + * Build token without all parameters set. + */ + @Test + public void legacyBuildFullTest() throws JsonProcessingException { + AppRole role = new AppRoleBuilder(NAME) + .withId(ID) + .withBindSecretID(BIND_SECRET_ID) + .withSecretIdBoundCidrs(BOUND_CIDR_LIST) + .withTokenPolicies(POLICIES) + .withSecretIdNumUses(SECRET_ID_NUM_USES) + .withSecretIdTtl(SECRET_ID_TTL) + .withEnableLocalSecretIds(ENABLE_LOCAL_SECRET_IDS) + .withTokenTtl(TOKEN_TTL) + .withTokenMaxTtl(TOKEN_MAX_TTL) + .withTokenBoundCidrs(BOUND_CIDR_LIST) + .withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL) + .withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY) + .withTokenNumUses(TOKEN_NUM_USES) + .wit0hTokenPeriod(TOKEN_PERIOD) + .withTokenType(TOKEN_TYPE) + .build(); + assertThat(role.getName(), is(NAME)); + assertThat(role.getId(), is(ID)); + assertThat(role.getBindSecretId(), is(BIND_SECRET_ID)); + assertThat(role.getSecretIdBoundCidrs(), is(BOUND_CIDR_LIST)); + assertThat(role.getTokenPolicies(), is(POLICIES)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); + assertThat(role.getSecretIdNumUses(), is(SECRET_ID_NUM_USES)); + assertThat(role.getSecretIdTtl(), is(SECRET_ID_TTL)); + assertThat(role.getEnableLocalSecretIds(), is(ENABLE_LOCAL_SECRET_IDS)); + assertThat(role.getTokenTtl(), is(TOKEN_TTL)); + assertThat(role.getTokenMaxTtl(), is(TOKEN_MAX_TTL)); + assertThat(role.getTokenBoundCidrs(), is(BOUND_CIDR_LIST)); + assertThat(role.getTokenExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL)); + assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY)); + assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES)); + assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD)); + assertThat(role.getPeriod(), is(TOKEN_PERIOD)); + assertThat(role.getTokenType(), is(TOKEN_TYPE.value())); /* Verify that all parameters are included in JSON string */ assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL)); @@ -119,6 +214,50 @@ public class AppRoleBuilderTest { */ @Test public void convenienceMethodsTest() { + /* bind_secret_id */ + AppRole role = AppRole.builder(NAME).build(); + assertThat(role.getBindSecretId(), is(nullValue())); + role = AppRole.builder(NAME).withBindSecretID().build(); + assertThat(role.getBindSecretId(), is(true)); + role = AppRole.builder(NAME).withoutBindSecretID().build(); + assertThat(role.getBindSecretId(), is(false)); + + /* Add single CIDR subnet */ + role = AppRole.builder(NAME).withSecretBoundCidr(CIDR_2).withTokenBoundCidr(CIDR_2).build(); + assertThat(role.getSecretIdBoundCidrs(), hasSize(1)); + assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_2)); + assertThat(role.getTokenBoundCidrs(), hasSize(1)); + assertThat(role.getTokenBoundCidrs(), contains(CIDR_2)); + role = AppRole.builder(NAME) + .withSecretIdBoundCidrs(BOUND_CIDR_LIST) + .withSecretBoundCidr(CIDR_2) + .withTokenBoundCidrs(BOUND_CIDR_LIST) + .withTokenBoundCidr(CIDR_2) + .build(); + assertThat(role.getSecretIdBoundCidrs(), hasSize(2)); + assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2)); + assertThat(role.getTokenBoundCidrs(), hasSize(2)); + assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2)); + + /* Add single policy */ + role = AppRole.builder(NAME).withTokenPolicy(POLICY_2).build(); + assertThat(role.getTokenPolicies(), hasSize(1)); + assertThat(role.getTokenPolicies(), contains(POLICY_2)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); + role = AppRole.builder(NAME) + .withTokenPolicies(POLICIES) + .withTokenPolicy(POLICY_2) + .build(); + assertThat(role.getTokenPolicies(), hasSize(2)); + assertThat(role.getTokenPolicies(), contains(POLICY, POLICY_2)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); + } + + /** + * Test convenience methods + */ + @Test + public void legacyConvenienceMethodsTest() { /* bind_secret_id */ AppRole role = new AppRoleBuilder(NAME).build(); assertThat(role.getBindSecretId(), is(nullValue())); @@ -128,29 +267,33 @@ public class AppRoleBuilderTest { 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).withSecretBoundCidr(CIDR_2).withTokenBoundCidr(CIDR_2).build(); assertThat(role.getSecretIdBoundCidrs(), hasSize(1)); assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_2)); + assertThat(role.getTokenBoundCidrs(), hasSize(1)); + assertThat(role.getTokenBoundCidrs(), contains(CIDR_2)); role = new AppRoleBuilder(NAME) .withSecretIdBoundCidrs(BOUND_CIDR_LIST) - .withCidrBlock(CIDR_2) + .withSecretBoundCidr(CIDR_2) + .withTokenBoundCidrs(BOUND_CIDR_LIST) + .withTokenBoundCidr(CIDR_2) .build(); - assertThat(role.getBoundCidrList(), hasSize(1)); - assertThat(role.getBoundCidrList(), contains(CIDR_2)); assertThat(role.getSecretIdBoundCidrs(), hasSize(2)); assertThat(role.getSecretIdBoundCidrs(), contains(CIDR_1, CIDR_2)); + assertThat(role.getTokenBoundCidrs(), hasSize(2)); + assertThat(role.getSecretIdBoundCidrs(), 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).withTokenPolicy(POLICY_2).build(); + assertThat(role.getTokenPolicies(), hasSize(1)); + assertThat(role.getTokenPolicies(), contains(POLICY_2)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); role = new AppRoleBuilder(NAME) - .withPolicies(POLICIES) - .withPolicy(POLICY_2) + .withTokenPolicies(POLICIES) + .withTokenPolicy(POLICY_2) .build(); - assertThat(role.getPolicies(), hasSize(2)); - assertThat(role.getPolicies(), contains(POLICY, POLICY_2)); + assertThat(role.getTokenPolicies(), hasSize(2)); + assertThat(role.getTokenPolicies(), contains(POLICY, POLICY_2)); + assertThat(role.getPolicies(), is(role.getTokenPolicies())); } } diff --git a/src/test/java/de/stklcode/jvault/connector/model/AppRoleSecretTest.java b/src/test/java/de/stklcode/jvault/connector/model/AppRoleSecretTest.java index fbabb32..27a4792 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/AppRoleSecretTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/AppRoleSecretTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/AuthBackendTest.java b/src/test/java/de/stklcode/jvault/connector/model/AuthBackendTest.java index b8fead6..a9b2ebb 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/AuthBackendTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/AuthBackendTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/TokenBuilderTest.java b/src/test/java/de/stklcode/jvault/connector/model/TokenBuilderTest.java index 30ca1d4..424558d 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/TokenBuilderTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/TokenBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,12 +36,12 @@ import static org.hamcrest.Matchers.*; * @since 0.4.0 */ public class TokenBuilderTest { - private static final String ID = "test-id"; private static final String DISPLAY_NAME = "display-name"; private static final Boolean NO_PARENT = false; private static final Boolean NO_DEFAULT_POLICY = false; private static final Integer TTL = 123; + private static final Integer EXPLICIT_MAX_TTL = 456; private static final Integer NUM_USES = 4; private static final List POLICIES = new ArrayList<>(); private static final String POLICY = "policy"; @@ -53,7 +53,10 @@ public class TokenBuilderTest { private static final String META_KEY_2 = "key2"; private static final String META_VALUE_2 = "value2"; private static final Boolean RENEWABLE = true; - private static final String JSON_FULL = "{\"id\":\"test-id\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}"; + private static final Integer PERIOD = 3600; + private static final String ENTITY_ALIAS = "alias-value"; + private static final String LEGACY_JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true}"; + private static final String JSON_FULL = "{\"id\":\"test-id\",\"type\":\"service\",\"display_name\":\"display-name\",\"no_parent\":false,\"no_default_policy\":false,\"ttl\":123,\"explicit_max_ttl\":456,\"num_uses\":4,\"policies\":[\"policy\"],\"meta\":{\"key\":\"value\"},\"renewable\":true,\"period\":3600,\"entity_alias\":\"alias-value\"}"; @BeforeAll public static void init() { @@ -66,8 +69,33 @@ public class TokenBuilderTest { */ @Test public void buildDefaultTest() throws JsonProcessingException { + Token token = Token.builder().build(); + assertThat(token.getId(), is(nullValue())); + assertThat(token.getType(), is(nullValue())); + assertThat(token.getDisplayName(), is(nullValue())); + assertThat(token.getNoParent(), is(nullValue())); + assertThat(token.getNoDefaultPolicy(), is(nullValue())); + assertThat(token.getTtl(), is(nullValue())); + assertThat(token.getExplicitMaxTtl(), is(nullValue())); + assertThat(token.getNumUses(), is(nullValue())); + assertThat(token.getPolicies(), is(nullValue())); + assertThat(token.getMeta(), is(nullValue())); + assertThat(token.isRenewable(), is(nullValue())); + assertThat(token.getPeriod(), is(nullValue())); + assertThat(token.getEntityAlias(), is(nullValue())); + + /* optional fields should be ignored, so JSON string should be empty */ + assertThat(new ObjectMapper().writeValueAsString(token), is("{}")); + } + + /** + * Build token without any parameters. + */ + @Test + public void legacyBuildDefaultTest() throws JsonProcessingException { Token token = new TokenBuilder().build(); assertThat(token.getId(), is(nullValue())); + assertThat(token.getType(), is(nullValue())); assertThat(token.getDisplayName(), is(nullValue())); assertThat(token.getNoParent(), is(nullValue())); assertThat(token.getNoDefaultPolicy(), is(nullValue())); @@ -86,8 +114,46 @@ public class TokenBuilderTest { */ @Test public void buildFullTest() throws JsonProcessingException { + Token token = Token.builder() + .withId(ID) + .withType(Token.Type.SERVICE) + .withDisplayName(DISPLAY_NAME) + .withNoParent(NO_PARENT) + .withNoDefaultPolicy(NO_DEFAULT_POLICY) + .withTtl(TTL) + .withExplicitMaxTtl(EXPLICIT_MAX_TTL) + .withNumUses(NUM_USES) + .withPolicies(POLICIES) + .withMeta(META) + .withRenewable(RENEWABLE) + .withPeriod(PERIOD) + .withEntityAlias(ENTITY_ALIAS) + .build(); + assertThat(token.getId(), is(ID)); + assertThat(token.getType(), is(Token.Type.SERVICE.value())); + assertThat(token.getDisplayName(), is(DISPLAY_NAME)); + assertThat(token.getNoParent(), is(NO_PARENT)); + assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY)); + assertThat(token.getTtl(), is(TTL)); + assertThat(token.getExplicitMaxTtl(), is(EXPLICIT_MAX_TTL)); + assertThat(token.getNumUses(), is(NUM_USES)); + assertThat(token.getPolicies(), is(POLICIES)); + assertThat(token.getMeta(), is(META)); + assertThat(token.isRenewable(), is(RENEWABLE)); + assertThat(token.getPeriod(), is(PERIOD)); + + /* Verify that all parameters are included in JSON string */ + assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL)); + } + + /** + * Build token without all parameters set. + */ + @Test + public void legacyBuildFullTest() throws JsonProcessingException { Token token = new TokenBuilder() .withId(ID) + .withType(Token.Type.SERVICE) .withDisplayName(DISPLAY_NAME) .withNoParent(NO_PARENT) .withNoDefaultPolicy(NO_DEFAULT_POLICY) @@ -98,6 +164,7 @@ public class TokenBuilderTest { .withRenewable(RENEWABLE) .build(); assertThat(token.getId(), is(ID)); + assertThat(token.getType(), is(Token.Type.SERVICE.value())); assertThat(token.getDisplayName(), is(DISPLAY_NAME)); assertThat(token.getNoParent(), is(NO_PARENT)); assertThat(token.getNoDefaultPolicy(), is(NO_DEFAULT_POLICY)); @@ -108,7 +175,7 @@ public class TokenBuilderTest { assertThat(token.isRenewable(), is(RENEWABLE)); /* Verify that all parameters are included in JSON string */ - assertThat(new ObjectMapper().writeValueAsString(token), is(JSON_FULL)); + assertThat(new ObjectMapper().writeValueAsString(token), is(LEGACY_JSON_FULL)); } /** @@ -116,6 +183,54 @@ public class TokenBuilderTest { */ @Test public void convenienceMethodsTest() { + /* Parent */ + Token token = Token.builder().asOrphan().build(); + assertThat(token.getNoParent(), is(true)); + token = Token.builder().withParent().build(); + assertThat(token.getNoParent(), is(false)); + + /* Default policy */ + token = Token.builder().withDefaultPolicy().build(); + assertThat(token.getNoDefaultPolicy(), is(false)); + token = Token.builder().withoutDefaultPolicy().build(); + assertThat(token.getNoDefaultPolicy(), is(true)); + + /* Renewability */ + token = Token.builder().renewable().build(); + assertThat(token.isRenewable(), is(true)); + token = Token.builder().notRenewable().build(); + assertThat(token.isRenewable(), is(false)); + + /* Add single policy */ + token = Token.builder().withPolicy(POLICY_2).build(); + assertThat(token.getPolicies(), hasSize(1)); + assertThat(token.getPolicies(), contains(POLICY_2)); + token = Token.builder() + .withPolicies(POLICY, POLICY_2) + .withPolicy(POLICY_3) + .build(); + assertThat(token.getPolicies(), hasSize(3)); + assertThat(token.getPolicies(), contains(POLICY, POLICY_2, POLICY_3)); + + /* Add single metadata */ + token = Token.builder().withMeta(META_KEY_2, META_VALUE_2).build(); + assertThat(token.getMeta().size(), is(1)); + assertThat(token.getMeta().keySet(), contains(META_KEY_2)); + assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2)); + token = Token.builder() + .withMeta(META) + .withMeta(META_KEY_2, META_VALUE_2) + .build(); + assertThat(token.getMeta().size(), is(2)); + assertThat(token.getMeta().get(META_KEY), is(META_VALUE)); + assertThat(token.getMeta().get(META_KEY_2), is(META_VALUE_2)); + } + + /** + * Test convenience methods + */ + @Test + public void legacyConvenienceMethodsTest() { /* Parent */ Token token = new TokenBuilder().asOrphan().build(); assertThat(token.getNoParent(), is(true)); diff --git a/src/test/java/de/stklcode/jvault/connector/model/TokenRoleBuilderTest.java b/src/test/java/de/stklcode/jvault/connector/model/TokenRoleBuilderTest.java new file mode 100644 index 0000000..e1b2bc7 --- /dev/null +++ b/src/test/java/de/stklcode/jvault/connector/model/TokenRoleBuilderTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2016-2020 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.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +/** + * Unit Test for {@link Token.Builder} + * + * @author Stefan Kalscheuer + * @since 0.9 + */ +public class TokenRoleBuilderTest { + private static final String NAME = "test-role"; + private static final String ALLOWED_POLICY_1 = "apol-1"; + private static final String ALLOWED_POLICY_2 = "apol-2"; + private static final String ALLOWED_POLICY_3 = "apol-3"; + private static final List ALLOWED_POLICIES = Arrays.asList(ALLOWED_POLICY_1, ALLOWED_POLICY_2); + private static final String DISALLOWED_POLICY_1 = "dpol-1"; + private static final String DISALLOWED_POLICY_2 = "dpol-2"; + private static final String DISALLOWED_POLICY_3 = "dpol-3"; + private static final List DISALLOWED_POLICIES = Arrays.asList(DISALLOWED_POLICY_2, DISALLOWED_POLICY_3); + private static final Boolean ORPHAN = false; + private static final Boolean RENEWABLE = true; + private static final String PATH_SUFFIX = "ps"; + private static final String ALLOWED_ENTITY_ALIAS_1 = "alias-1"; + private static final String ALLOWED_ENTITY_ALIAS_2 = "alias-2"; + private static final String ALLOWED_ENTITY_ALIAS_3 = "alias-3"; + private static final List ALLOWED_ENTITY_ALIASES = Arrays.asList(ALLOWED_ENTITY_ALIAS_1, ALLOWED_ENTITY_ALIAS_3); + private static final String TOKEN_BOUND_CIDR_1 = "192.0.2.0/24"; + private static final String TOKEN_BOUND_CIDR_2 = "198.51.100.0/24"; + private static final String TOKEN_BOUND_CIDR_3 = "203.0.113.0/24"; + private static final List TOKEN_BOUND_CIDRS = Arrays.asList(TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_1); + private static final Integer TOKEN_EXPLICIT_MAX_TTL = 1234; + private static final Boolean TOKEN_NO_DEFAULT_POLICY = false; + private static final Integer TOKEN_NUM_USES = 5; + private static final Integer TOKEN_PERIOD = 2345; + private static final Token.Type TOKEN_TYPE = Token.Type.SERVICE; + + private static final String JSON_FULL = "{" + + "\"name\":\"" + NAME + "\"," + + "\"allowed_policies\":[\"" + ALLOWED_POLICY_1 + "\",\"" + ALLOWED_POLICY_2 + "\",\"" + ALLOWED_POLICY_3 + "\"]," + + "\"disallowed_policies\":[\"" + DISALLOWED_POLICY_1 + "\",\"" + DISALLOWED_POLICY_2 + "\",\"" + DISALLOWED_POLICY_3 + "\"]," + + "\"orphan\":" + ORPHAN + "," + + "\"renewable\":" + RENEWABLE + "," + + "\"path_suffix\":\"" + PATH_SUFFIX + "\"," + + "\"allowed_entity_aliases\":[\"" + ALLOWED_ENTITY_ALIAS_1 + "\",\"" + ALLOWED_ENTITY_ALIAS_3 + "\",\"" + ALLOWED_ENTITY_ALIAS_2 + "\"]," + + "\"token_bound_cidrs\":[\"" + TOKEN_BOUND_CIDR_3 + "\",\"" + TOKEN_BOUND_CIDR_2 + "\",\"" + TOKEN_BOUND_CIDR_1 + "\"]," + + "\"token_explicit_max_ttl\":" + TOKEN_EXPLICIT_MAX_TTL + "," + + "\"token_no_default_policy\":" + TOKEN_NO_DEFAULT_POLICY + "," + + "\"token_num_uses\":" + TOKEN_NUM_USES + "," + + "\"token_period\":" + TOKEN_PERIOD + "," + + "\"token_type\":\"" + TOKEN_TYPE.value() + "\"}"; + + /** + * Build token without any parameters. + */ + @Test + public void buildDefaultTest() throws JsonProcessingException { + TokenRole role = TokenRole.builder().build(); + assertThat(role.getAllowedPolicies(), is(nullValue())); + assertThat(role.getDisallowedPolicies(), is(nullValue())); + assertThat(role.getOrphan(), is(nullValue())); + assertThat(role.getRenewable(), is(nullValue())); + assertThat(role.getAllowedEntityAliases(), is(nullValue())); + assertThat(role.getTokenBoundCidrs(), is(nullValue())); + assertThat(role.getTokenExplicitMaxTtl(), is(nullValue())); + assertThat(role.getTokenNoDefaultPolicy(), is(nullValue())); + assertThat(role.getTokenNumUses(), is(nullValue())); + assertThat(role.getTokenPeriod(), is(nullValue())); + assertThat(role.getTokenType(), is(nullValue())); + + /* optional fields should be ignored, so JSON string should be empty */ + assertThat(new ObjectMapper().writeValueAsString(role), is("{}")); + } + + /** + * Build token without all parameters NULL. + */ + @Test + public void buildNullTest() throws JsonProcessingException { + TokenRole role = TokenRole.builder() + .forName(null) + .withAllowedPolicies(null) + .withAllowedPolicy(null) + .withDisallowedPolicy(null) + .withDisallowedPolicies(null) + .orphan(null) + .renewable(null) + .withPathSuffix(null) + .withAllowedEntityAliases(null) + .withAllowedEntityAlias(null) + .withTokenBoundCidr(null) + .withTokenBoundCidrs(null) + .withTokenExplicitMaxTtl(null) + .withTokenNoDefaultPolicy(null) + .withTokenNumUses(null) + .withTokenPeriod(null) + .withTokenType(null) + .build(); + + assertThat(role.getAllowedPolicies(), is(nullValue())); + assertThat(role.getDisallowedPolicies(), is(nullValue())); + assertThat(role.getOrphan(), is(nullValue())); + assertThat(role.getRenewable(), is(nullValue())); + assertThat(role.getAllowedEntityAliases(), is(nullValue())); + assertThat(role.getTokenBoundCidrs(), is(nullValue())); + assertThat(role.getTokenExplicitMaxTtl(), is(nullValue())); + assertThat(role.getTokenNoDefaultPolicy(), is(nullValue())); + assertThat(role.getTokenNumUses(), is(nullValue())); + assertThat(role.getTokenPeriod(), is(nullValue())); + assertThat(role.getTokenType(), is(nullValue())); + + /* optional fields should be ignored, so JSON string should be empty */ + assertThat(new ObjectMapper().writeValueAsString(role), is("{}")); + } + + /** + * Build token without all parameters set. + */ + @Test + public void buildFullTest() throws JsonProcessingException { + TokenRole role = TokenRole.builder() + .forName(NAME) + .withAllowedPolicies(ALLOWED_POLICIES) + .withAllowedPolicy(ALLOWED_POLICY_3) + .withDisallowedPolicy(DISALLOWED_POLICY_1) + .withDisallowedPolicies(DISALLOWED_POLICIES) + .orphan(ORPHAN) + .renewable(RENEWABLE) + .withPathSuffix(PATH_SUFFIX) + .withAllowedEntityAliases(ALLOWED_ENTITY_ALIASES) + .withAllowedEntityAlias(ALLOWED_ENTITY_ALIAS_2) + .withTokenBoundCidr(TOKEN_BOUND_CIDR_3) + .withTokenBoundCidrs(TOKEN_BOUND_CIDRS) + .withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL) + .withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY) + .withTokenNumUses(TOKEN_NUM_USES) + .withTokenPeriod(TOKEN_PERIOD) + .withTokenType(TOKEN_TYPE) + .build(); + assertThat(role.getName(), is(NAME)); + assertThat(role.getAllowedPolicies(), hasSize(ALLOWED_POLICIES.size() + 1)); + assertThat(role.getAllowedPolicies(), containsInAnyOrder(ALLOWED_POLICY_1, ALLOWED_POLICY_2, ALLOWED_POLICY_3)); + assertThat(role.getDisallowedPolicies(), hasSize(DISALLOWED_POLICIES.size() + 1)); + assertThat(role.getDisallowedPolicies(), containsInAnyOrder(DISALLOWED_POLICY_1, DISALLOWED_POLICY_2, DISALLOWED_POLICY_3)); + assertThat(role.getOrphan(), is(ORPHAN)); + assertThat(role.getRenewable(), is(RENEWABLE)); + assertThat(role.getPathSuffix(), is(PATH_SUFFIX)); + assertThat(role.getAllowedEntityAliases(), hasSize(ALLOWED_ENTITY_ALIASES.size() + 1)); + assertThat(role.getAllowedEntityAliases(), containsInAnyOrder(ALLOWED_ENTITY_ALIAS_1, ALLOWED_ENTITY_ALIAS_2, ALLOWED_ENTITY_ALIAS_3)); + assertThat(role.getTokenBoundCidrs(), hasSize(TOKEN_BOUND_CIDRS.size() + 1)); + assertThat(role.getTokenBoundCidrs(), containsInAnyOrder(TOKEN_BOUND_CIDR_1, TOKEN_BOUND_CIDR_2, TOKEN_BOUND_CIDR_3)); + assertThat(role.getTokenNoDefaultPolicy(), is(TOKEN_NO_DEFAULT_POLICY)); + assertThat(role.getTokenNumUses(), is(TOKEN_NUM_USES)); + assertThat(role.getTokenPeriod(), is(TOKEN_PERIOD)); + assertThat(role.getTokenType(), is(TOKEN_TYPE.value())); + + /* Verify that all parameters are included in JSON string */ + assertThat(new ObjectMapper().writeValueAsString(role), is(JSON_FULL)); + } +} diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/AppRoleResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/AppRoleResponseTest.java index 2d02ba5..e428f2b 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/AppRoleResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/AppRoleResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,10 +53,10 @@ public class AppRoleResponseTest { " \"token_max_ttl\": " + ROLE_TOKEN_MAX_TTL + ",\n" + " \"secret_id_ttl\": " + ROLE_SECRET_TTL + ",\n" + " \"secret_id_num_uses\": " + ROLE_SECRET_NUM_USES + ",\n" + - " \"policies\": [\n" + + " \"token_policies\": [\n" + " \"" + ROLE_POLICY + "\"\n" + " ],\n" + - " \"period\": " + ROLE_PERIOD + ",\n" + + " \"token_period\": " + ROLE_PERIOD + ",\n" + " \"bind_secret_id\": " + ROLE_BIND_SECRET + ",\n" + " \"bound_cidr_list\": \"\"\n" + " },\n" + @@ -68,7 +68,7 @@ public class AppRoleResponseTest { private static final Map INVALID_DATA = new HashMap<>(); static { - INVALID_DATA.put("policies", "fancy-policy"); + INVALID_DATA.put("token_policies", "fancy-policy"); } /** @@ -104,12 +104,15 @@ public class AppRoleResponseTest { assertThat("Incorrect token max TTL", role.getTokenMaxTtl(), is(ROLE_TOKEN_MAX_TTL)); assertThat("Incorrect secret ID TTL", role.getSecretIdTtl(), is(ROLE_SECRET_TTL)); assertThat("Incorrect secret ID umber of uses", role.getSecretIdNumUses(), is(ROLE_SECRET_NUM_USES)); + assertThat("Incorrect number of policies", role.getTokenPolicies(), hasSize(1)); + assertThat("Incorrect role policies", role.getTokenPolicies(), contains(ROLE_POLICY)); assertThat("Incorrect number of policies", role.getPolicies(), hasSize(1)); assertThat("Incorrect role policies", role.getPolicies(), contains(ROLE_POLICY)); + assertThat("Incorrect role period", role.getTokenPeriod(), is(ROLE_PERIOD)); assertThat("Incorrect role period", role.getPeriod(), is(ROLE_PERIOD)); assertThat("Incorrect role bind secret ID flag", role.getBindSecretId(), is(ROLE_BIND_SECRET)); - assertThat("Incorrect biund CIDR list", role.getBoundCidrList(), is(nullValue())); - assertThat("Incorrect biund CIDR list string", role.getBoundCidrListString(), is(emptyString())); + assertThat("Incorrect bound CIDR list", role.getTokenBoundCidrs(), is(nullValue())); + assertThat("Incorrect bound CIDR list string", role.getTokenBoundCidrsString(), is(emptyString())); } catch (IOException e) { fail("AuthResponse deserialization failed: " + e.getMessage()); } diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponseTest.java index b93eaf2..a94d4f8 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/AuthMethodsResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/AuthResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/AuthResponseTest.java index a0f1e62..933aa6d 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/AuthResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/AuthResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,9 @@ public class AuthResponseTest { private static final String AUTH_META_VALUE = "armon"; private static final Integer AUTH_LEASE_DURATION = 3600; private static final Boolean AUTH_RENEWABLE = true; + private static final String AUTH_ENTITY_ID = ""; + private static final String AUTH_TOKEN_TYPE = "service"; + private static final Boolean AUTH_ORPHAN = false; private static final String RES_JSON = "{\n" + " \"auth\": {\n" + @@ -53,11 +56,18 @@ public class AuthResponseTest { " \"" + AUTH_POLICY_1 + "\", \n" + " \"" + AUTH_POLICY_2 + "\"\n" + " ],\n" + + " \"token_policies\": [\n" + + " \"" + AUTH_POLICY_2 + "\",\n" + + " \"" + AUTH_POLICY_1 + "\" \n" + + " ],\n" + " \"metadata\": {\n" + " \"" + AUTH_META_KEY + "\": \"" + AUTH_META_VALUE + "\"\n" + " },\n" + " \"lease_duration\": " + AUTH_LEASE_DURATION + ",\n" + - " \"renewable\": " + AUTH_RENEWABLE + "\n" + + " \"renewable\": " + AUTH_RENEWABLE + ",\n" + + " \"entity_id\": \"" + AUTH_ENTITY_ID + "\",\n" + + " \"token_type\": \"" + AUTH_TOKEN_TYPE + "\",\n" + + " \"orphan\": " + AUTH_ORPHAN + "\n" + " }\n" + "}"; @@ -104,8 +114,16 @@ public class AuthResponseTest { assertThat("Incorrect auth client token", data.getClientToken(), is(AUTH_CLIENT_TOKEN)); assertThat("Incorrect auth lease duration", data.getLeaseDuration(), is(AUTH_LEASE_DURATION)); assertThat("Incorrect auth renewable flag", data.isRenewable(), is(AUTH_RENEWABLE)); + assertThat("Incorrect auth orphan flag", data.isOrphan(), is(AUTH_ORPHAN)); + assertThat("Incorrect auth token type", data.getTokenType(), is(AUTH_TOKEN_TYPE)); + assertThat("Incorrect auth entity id", data.getEntityId(), is(AUTH_ENTITY_ID)); assertThat("Incorrect number of policies", data.getPolicies(), hasSize(2)); - assertThat("Incorrect auth policies", data.getPolicies(), containsInAnyOrder(AUTH_POLICY_1, AUTH_POLICY_2)); + assertThat("Incorrect auth policies", data.getPolicies(), containsInRelativeOrder(AUTH_POLICY_1, AUTH_POLICY_2)); + assertThat("Incorrect number of token policies", data.getTokenPolicies(), hasSize(2)); + assertThat("Incorrect token policies", data.getTokenPolicies(), containsInRelativeOrder(AUTH_POLICY_2, AUTH_POLICY_1)); + assertThat("Incorrect auth metadata size", data.getMetadata().entrySet(), hasSize(1)); + assertThat("Incorrect auth metadata", data.getMetadata().get(AUTH_META_KEY), is(AUTH_META_VALUE)); + } catch (IOException e) { fail("AuthResponse deserialization failed: " + e.getMessage()); } diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/CredentialsResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/CredentialsResponseTest.java index 38bea55..331d04a 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/CredentialsResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/CredentialsResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/HealthResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/HealthResponseTest.java index 1435c5e..f5b90f7 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/HealthResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/HealthResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/MetadataResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/MetadataResponseTest.java index 05a5402..a37f675 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/MetadataResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/MetadataResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ public class MetadataResponseTest { try { MetadataResponse res = new ObjectMapper().readValue(META_JSON, MetadataResponse.class); assertThat("Parsed response is NULL", res, is(notNullValue())); - assertThat("Parsed metadatra is NULL", res.getMetadata(), is(notNullValue())); + assertThat("Parsed metadata is NULL", res.getMetadata(), is(notNullValue())); assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(V1_TIME)); assertThat("Parting created time failed", res.getMetadata().getCreatedTime(), is(notNullValue())); assertThat("Incorrect current version", res.getMetadata().getCurrentVersion(), is(CURRENT_VERSION)); @@ -87,14 +87,14 @@ public class MetadataResponseTest { assertThat("Parting updated time failed", res.getMetadata().getUpdatedTime(), is(notNullValue())); assertThat("Incorrect number of versions", res.getMetadata().getVersions().size(), is(3)); assertThat("Incorrect version 1 delete time", res.getMetadata().getVersions().get(1).getDeletionTimeString(), is(V2_TIME)); - assertThat("Parsion version delete time failed", res.getMetadata().getVersions().get(1).getDeletionTime(), is(notNullValue())); + assertThat("Parsing version delete time failed", res.getMetadata().getVersions().get(1).getDeletionTime(), is(notNullValue())); assertThat("Incorrect version 1 destroyed state", res.getMetadata().getVersions().get(1).isDestroyed(), is(true)); assertThat("Incorrect version 2 created time", res.getMetadata().getVersions().get(2).getCreatedTimeString(), is(V2_TIME)); - assertThat("Parsion version created failed", res.getMetadata().getVersions().get(2).getCreatedTime(), is(notNullValue())); + assertThat("Parsing version created failed", res.getMetadata().getVersions().get(2).getCreatedTime(), is(notNullValue())); assertThat("Incorrect version 3 destroyed state", res.getMetadata().getVersions().get(3).isDestroyed(), is(false)); } catch (IOException e) { - fail("MetadataResoponse deserialization failed: " + e.getMessage()); + fail("MetadataResponse deserialization failed: " + e.getMessage()); } } } diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/SealResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/SealResponseTest.java index a57f4f9..e4eddd3 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/SealResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/SealResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/SecretListResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/SecretListResponseTest.java index 93dacb7..e282aa6 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/SecretListResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/SecretListResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/SecretResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/SecretResponseTest.java index cc66efe..6998cbb 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/SecretResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/SecretResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/SecretVersionResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/SecretVersionResponseTest.java index 99d5a62..ca76d7d 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/SecretVersionResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/SecretVersionResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ public class SecretVersionResponseTest { try { SecretVersionResponse res = new ObjectMapper().readValue(META_JSON, SecretVersionResponse.class); assertThat("Parsed response is NULL", res, is(notNullValue())); - assertThat("Parsed metadatra is NULL", res.getMetadata(), is(notNullValue())); + assertThat("Parsed metadata is NULL", res.getMetadata(), is(notNullValue())); assertThat("Incorrect created time", res.getMetadata().getCreatedTimeString(), is(CREATION_TIME)); assertThat("Incorrect deletion time", res.getMetadata().getDeletionTimeString(), is(DELETION_TIME)); assertThat("Incorrect destroyed state", res.getMetadata().isDestroyed(), is(false)); diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/TokenResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/TokenResponseTest.java index 272de50..e069500 100644 --- a/src/test/java/de/stklcode/jvault/connector/model/response/TokenResponseTest.java +++ b/src/test/java/de/stklcode/jvault/connector/model/response/TokenResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import de.stklcode.jvault.connector.model.response.embedded.TokenData; import org.junit.jupiter.api.Test; import java.io.IOException; +import java.time.ZonedDateTime; import java.util.HashMap; import java.util.Map; @@ -38,25 +39,43 @@ import static org.junit.jupiter.api.Assertions.fail; public class TokenResponseTest { private static final Integer TOKEN_CREATION_TIME = 1457533232; private static final Integer TOKEN_TTL = 2764800; + private static final Integer TOKEN_EXPLICIT_MAX_TTL = 0; private static final String TOKEN_DISPLAY_NAME = "token"; + private static final String TOKEN_META_KEY = "foo"; + private static final String TOKEN_META_VALUE = "bar"; private static final Integer TOKEN_NUM_USES = 0; private static final Boolean TOKEN_ORPHAN = false; + private static final Boolean TOKEN_RENEWABLE = true; private static final String TOKEN_PATH = "auth/token/create"; private static final String TOKEN_POLICY_1 = "default"; private static final String TOKEN_POLICY_2 = "web"; private static final Boolean RES_RENEWABLE = false; private static final Integer RES_TTL = 2591976; private static final Integer RES_LEASE_DURATION = 0; + private static final String TOKEN_ACCESSOR = "VKvzT2fKHFsZFUus9LyoXCvu"; + private static final String TOKEN_ENTITY_ID = "7d2e3179-f69b-450c-7179-ac8ee8bd8ca9"; + private static final String TOKEN_EXPIRE_TIME = "2018-05-19T11:35:54.466476215-04:00"; + private static final String TOKEN_ID = "my-token"; + private static final String TOKEN_ISSUE_TIME = "2018-04-17T11:35:54.466476078-04:00"; + private static final String TOKEN_TYPE = "service"; private static final String RES_JSON = "{\n" + " \"lease_id\": \"\",\n" + " \"renewable\": " + RES_RENEWABLE + ",\n" + " \"lease_duration\": " + RES_LEASE_DURATION + ",\n" + " \"data\": {\n" + + " \"accessor\": \"" + TOKEN_ACCESSOR + "\",\n" + " \"creation_time\": " + TOKEN_CREATION_TIME + ",\n" + " \"creation_ttl\": " + TOKEN_TTL + ",\n" + " \"display_name\": \"" + TOKEN_DISPLAY_NAME + "\",\n" + - " \"meta\": null,\n" + + " \"entity_id\": \"" + TOKEN_ENTITY_ID + "\",\n" + + " \"expire_time\": \"" + TOKEN_EXPIRE_TIME + "\",\n" + + " \"explicit_max_ttl\": \"" + TOKEN_EXPLICIT_MAX_TTL + "\",\n" + + " \"id\": \"" + TOKEN_ID + "\",\n" + + " \"issue_time\": \"" + TOKEN_ISSUE_TIME + "\",\n" + + " \"meta\": {\n" + + " \"" + TOKEN_META_KEY + "\": \"" + TOKEN_META_VALUE + "\"\n" + + " },\n" + " \"num_uses\": " + TOKEN_NUM_USES + ",\n" + " \"orphan\": " + TOKEN_ORPHAN + ",\n" + " \"path\": \"" + TOKEN_PATH + "\",\n" + @@ -64,7 +83,9 @@ public class TokenResponseTest { " \"" + TOKEN_POLICY_1 + "\", \n" + " \"" + TOKEN_POLICY_2 + "\"\n" + " ],\n" + - " \"ttl\": " + RES_TTL + "\n" + + " \"renewable\": " + TOKEN_RENEWABLE + ",\n" + + " \"ttl\": " + RES_TTL + ",\n" + + " \"type\": \"" + TOKEN_TYPE + "\"\n" + " },\n" + " \"warnings\": null,\n" + " \"auth\": null\n" + @@ -103,19 +124,32 @@ public class TokenResponseTest { TokenResponse res = new ObjectMapper().readValue(RES_JSON, TokenResponse.class); assertThat("Parsed response is NULL", res, is(notNullValue())); assertThat("Incorrect lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION)); - assertThat("Incorrect renewable status", res.isRenewable(), is(RES_RENEWABLE)); + assertThat("Incorrect response renewable flag", res.isRenewable(), is(RES_RENEWABLE)); + assertThat("Incorrect response lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION)); // Extract token data. TokenData data = res.getData(); assertThat("Token data is NULL", data, is(notNullValue())); + assertThat("Incorrect token accessor", data.getAccessor(), is(TOKEN_ACCESSOR)); assertThat("Incorrect token creation time", data.getCreationTime(), is(TOKEN_CREATION_TIME)); assertThat("Incorrect token creation TTL", data.getCreationTtl(), is(TOKEN_TTL)); assertThat("Incorrect token display name", data.getName(), is(TOKEN_DISPLAY_NAME)); + assertThat("Incorrect token entity ID", data.getEntityId(), is(TOKEN_ENTITY_ID)); + assertThat("Incorrect token expire time", data.getExpireTimeString(), is(TOKEN_EXPIRE_TIME)); + assertThat("Incorrect parsed token expire time", data.getExpireTime(), is(ZonedDateTime.parse(TOKEN_EXPIRE_TIME))); + assertThat("Incorrect token explicit max TTL", data.getExplicitMaxTtl(), is(TOKEN_EXPLICIT_MAX_TTL)); + assertThat("Incorrect token ID", data.getId(), is(TOKEN_ID)); + assertThat("Incorrect token issue time", data.getIssueTimeString(), is(TOKEN_ISSUE_TIME)); + assertThat("Incorrect parsed token issue time", data.getIssueTime(), is(ZonedDateTime.parse(TOKEN_ISSUE_TIME))); + assertThat("Incorrect token metadata size", data.getMeta().entrySet(), hasSize(1)); + assertThat("Incorrect token metadata", data.getMeta().get(TOKEN_META_KEY), is(TOKEN_META_VALUE)); assertThat("Incorrect token number of uses", data.getNumUses(), is(TOKEN_NUM_USES)); assertThat("Incorrect token orphan flag", data.isOrphan(), is(TOKEN_ORPHAN)); assertThat("Incorrect token path", data.getPath(), is(TOKEN_PATH)); - assertThat("Incorrect response renewable flag", res.isRenewable(), is(RES_RENEWABLE)); - assertThat("Incorrect response TTL", data.getTtl(), is(RES_TTL)); - assertThat("Incorrect response lease duration", res.getLeaseDuration(), is(RES_LEASE_DURATION)); + assertThat("Incorrect number of token policies", data.getPolicies(), hasSize(2)); + assertThat("Incorrect token policies", data.getPolicies(), contains(TOKEN_POLICY_1, TOKEN_POLICY_2)); + assertThat("Incorrect token renewable flag", data.isRenewable(), is(TOKEN_RENEWABLE)); + assertThat("Incorrect token TTL", data.getTtl(), is(RES_TTL)); + assertThat("Incorrect token type", data.getType(), is(TOKEN_TYPE)); } catch (IOException e) { fail("TokenResponse deserialization failed: " + e.getMessage()); } diff --git a/src/test/java/de/stklcode/jvault/connector/test/Credentials.java b/src/test/java/de/stklcode/jvault/connector/test/Credentials.java index b2031d7..9efd44d 100644 --- a/src/test/java/de/stklcode/jvault/connector/test/Credentials.java +++ b/src/test/java/de/stklcode/jvault/connector/test/Credentials.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/test/EnvironmentMock.java b/src/test/java/de/stklcode/jvault/connector/test/EnvironmentMock.java index 582e056..a8b24ad 100644 --- a/src/test/java/de/stklcode/jvault/connector/test/EnvironmentMock.java +++ b/src/test/java/de/stklcode/jvault/connector/test/EnvironmentMock.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/de/stklcode/jvault/connector/test/VaultConfiguration.java b/src/test/java/de/stklcode/jvault/connector/test/VaultConfiguration.java index 0aaa4d2..d95d0a0 100644 --- a/src/test/java/de/stklcode/jvault/connector/test/VaultConfiguration.java +++ b/src/test/java/de/stklcode/jvault/connector/test/VaultConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Stefan Kalscheuer + * Copyright 2016-2020 Stefan Kalscheuer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.