From cbb404714d1e0adb2177f989609bab893b8ea076 Mon Sep 17 00:00:00 2001 From: Derek Wickern Date: Tue, 11 Nov 2025 16:55:10 -0800 Subject: [PATCH] improve engine version detection --- .../github/jopenlibs/vault/api/Logical.java | 36 ++++++++++++++++--- .../io/github/jopenlibs/vault/VaultTests.java | 29 +++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) 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: + * + * + * @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,