diff --git a/src/main/java/io/github/jopenlibs/vault/api/Logical.java b/src/main/java/io/github/jopenlibs/vault/api/Logical.java
index 9a4bd129..8499ec09 100644
--- a/src/main/java/io/github/jopenlibs/vault/api/Logical.java
+++ b/src/main/java/io/github/jopenlibs/vault/api/Logical.java
@@ -596,11 +596,39 @@ public LogicalResponse upgrade(final String kvPath) throws VaultException {
});
}
+ /**
+ *
Searches the secrets engine path map for the specified path.
+ *
+ * For example, if the path map contains:
+ *
+ * "cubbyhole/" -> "unknown"
+ * "identity/" -> "unknown"
+ * "sys/" -> "unknown"
+ * "secret/" -> "2"
+ *
+ *
+ * and the secret path is "secret/myapp/config", this method will check, in order:
+ *
+ * - "secret/myapp/config/" - not found
+ * - "secret/myapp/" - not found
+ * - "secret/" - found, engine version 2
+ *
+ *
+ * @param secretPath The Vault secret path to check (e.g. secret/hello).
+ * @return the detected engine version (1 or 2), or the global default if not found
+ */
private Integer engineVersionForSecretPath(final String secretPath) {
- if (!this.config.getSecretsEnginePathMap().isEmpty()) {
- return this.config.getSecretsEnginePathMap().containsKey(secretPath + "/") ?
- Integer.valueOf(this.config.getSecretsEnginePathMap().get(secretPath + "/"))
- : this.config.getGlobalEngineVersion();
+ final Map pathMap = this.config.getSecretsEnginePathMap();
+ if (!pathMap.isEmpty()) {
+ int idx = secretPath.length();
+ do {
+ final String prefix = secretPath.substring(0, idx);
+ final String version = pathMap.get(prefix + '/');
+ if (version != null && !version.equals("unknown")) {
+ return Integer.parseInt(version);
+ }
+ idx = prefix.lastIndexOf('/');
+ } while (idx != -1);
}
return this.config.getGlobalEngineVersion();
}
diff --git a/src/test/java/io/github/jopenlibs/vault/VaultTests.java b/src/test/java/io/github/jopenlibs/vault/VaultTests.java
index 8ce1e8e7..6e14f406 100644
--- a/src/test/java/io/github/jopenlibs/vault/VaultTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/VaultTests.java
@@ -70,6 +70,17 @@ public void testVaultWithEmptyKVEnginePathMap() throws VaultException {
Assert.assertNull(vault);
}
+ @Test
+ public void testVaultWithUnknownKVEnginePathMap() throws VaultException {
+ Map engineKVMap = new HashMap<>();
+ engineKVMap.put("secret/", "unknown");
+ VaultConfig vaultConfig = new VaultConfig().secretsEnginePathMap(engineKVMap);
+ Vault vault = Vault.create(vaultConfig, true, 1);
+ Assert.assertNotNull(vault);
+ Assert.assertEquals(String.valueOf(1),
+ vault.logical().getEngineVersionForSecretPath("secret").toString());
+ }
+
@Test
public void testVaultWithoutKVEnginePathMap() throws VaultException {
Map engineKVMap = new HashMap<>();
@@ -97,6 +108,24 @@ public void kvEngineMapIsHonored() throws VaultException {
vault.logical().getEngineVersionForSecretPath("notInMap").toString());
}
+ @Test
+ public void testVaultWithPrefixedKVEnginePathMap() throws VaultException {
+ Map engineKVMap = new HashMap<>();
+ engineKVMap.put("secret/", "2");
+ engineKVMap.put("other/mount/", "2");
+ VaultConfig vaultConfig = new VaultConfig().secretsEnginePathMap(engineKVMap);
+ Vault vault = Vault.create(vaultConfig, true, 1);
+ Assert.assertNotNull(vault);
+ Assert.assertEquals(String.valueOf(2),
+ vault.logical().getEngineVersionForSecretPath("secret/path/to/credential").toString());
+ Assert.assertEquals(String.valueOf(2),
+ vault.logical().getEngineVersionForSecretPath("other/mount/path/to/credential").toString());
+ Assert.assertEquals(String.valueOf(1),
+ vault.logical().getEngineVersionForSecretPath("other").toString());
+ Assert.assertEquals(String.valueOf(1),
+ vault.logical().getEngineVersionForSecretPath("notInMap").toString());
+ }
+
@Test
public void testConfigBuiler_WithInvalidRequestAsNonError() throws Exception {
final MockVault mockVault = new MockVault(403,