
com.bettercloud.vault.api.Logical Maven / Gradle / Ivy
Show all versions of vault-java-driver Show documentation
package com.bettercloud.vault.api;
import com.bettercloud.vault.VaultConfig;
import com.bettercloud.vault.VaultException;
import com.bettercloud.vault.json.Json;
import com.bettercloud.vault.json.JsonObject;
import com.bettercloud.vault.json.JsonValue;
import com.bettercloud.vault.response.LogicalResponse;
import com.bettercloud.vault.rest.Rest;
import com.bettercloud.vault.rest.RestException;
import com.bettercloud.vault.rest.RestResponse;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForDelete;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForList;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForReadOrWrite;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForVersionDelete;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForVersionDestroy;
import static com.bettercloud.vault.api.LogicalUtilities.adjustPathForVersionUnDelete;
import static com.bettercloud.vault.api.LogicalUtilities.jsonObjectToWriteFromEngineVersion;
/**
* The implementing class for Vault's core/logical operations (e.g. read, write).
*
* This class is not intended to be constructed directly. Rather, it is meant to used by way of Vault
* in a DSL-style builder pattern. See the Javadoc comments of each public
method for usage examples.
*/
public class Logical {
private final VaultConfig config;
private String nameSpace;
public enum logicalOperations {authentication, deleteV1, deleteV2, destroy, listV1, listV2, readV1, readV2, writeV1, writeV2, unDelete, mount}
public Logical(final VaultConfig config) {
this.config = config;
if (this.config.getNameSpace() != null && !this.config.getNameSpace().isEmpty()) {
this.nameSpace = this.config.getNameSpace();
}
}
/**
* Adds the requested namespace to the logical operation, which is then passed into the REST headers for said operation.
*
* @param nameSpace The Vault namespace to access (e.g. secret/
).
* @return The Logical instance, with the namespace set.
*/
public Logical withNameSpace(final String nameSpace) {
this.nameSpace = nameSpace;
return this;
}
/**
* Basic read operation to retrieve a secret. A single secret key can map to multiple name-value pairs,
* which can be retrieved from the response object. E.g.:
*
*
* {@code
* final LogicalResponse response = vault.logical().read("secret/hello");
*
* final String value = response.getData().get("value");
* final String otherValue = response.getData().get("other_value");
* }
*
*
* @param path The Vault key value from which to read (e.g. secret/hello
)
* @return The response information returned from Vault
* @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload,
* etc), and the maximum number of retries is exceeded.
*/
public LogicalResponse read(final String path) throws VaultException {
if (this.engineVersionForSecretPath(path).equals(2)) {
return read(path, true, logicalOperations.readV2);
} else return read(path, true, logicalOperations.readV1);
}
private LogicalResponse read(final String path, Boolean shouldRetry, final logicalOperations operation)
throws VaultException {
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForReadOrWrite(path, config.getPrefixPathDepth(), operation))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.get();
// Validate response - don't treat 4xx class errors as exceptions, we want to return an error as the response
if (restResponse.getStatus() != 200 && !(restResponse.getStatus() >= 400 && restResponse.getStatus() < 500)) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, operation);
} catch (RuntimeException | VaultException | RestException e) {
if (!shouldRetry)
throw new VaultException(e);
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
* Basic read operation to retrieve a specified secret version for KV engine version 2. A single secret key version
* can map to multiple name-value pairs, which can be retrieved from the response object. E.g.:
*
*
* {@code
* final LogicalResponse response = vault.logical().read("secret/hello", true, 1);
*
* final String value = response.getData().get("value");
* final String otherValue = response.getData().get("other_value");
* }
*
*
* @param path The Vault key value from which to read (e.g. secret/hello
* @param shouldRetry Whether to try more than once
* @param version The Integer version number of the secret to read, e.g. "1"
* @return The response information returned from Vault
* @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload,
* etc), and the maximum number of retries is exceeded.
*/
public LogicalResponse read(final String path, Boolean shouldRetry, final Integer version) throws VaultException {
if (this.engineVersionForSecretPath(path) != 2) {
throw new VaultException("Version reads are only supported in KV Engine version 2.");
}
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForReadOrWrite(path, config.getPrefixPathDepth(), logicalOperations.readV2))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.parameter("version", version.toString())
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.get();
// Validate response - don't treat 4xx class errors as exceptions, we want to return an error as the response
if (restResponse.getStatus() != 200 && !(restResponse.getStatus() >= 400 && restResponse.getStatus() < 500)) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, logicalOperations.readV2);
} catch (RuntimeException | VaultException | RestException e) {
if (!shouldRetry)
throw new VaultException(e);
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
* Basic operation to store secrets. Multiple name value pairs can be stored under the same secret key.
* E.g.:
*
*
* {@code
* final Map nameValuePairs = new HashMap();
* nameValuePairs.put("value", "foo");
* nameValuePairs.put("other_value", "bar");
*
* final LogicalResponse response = vault.logical().write("secret/hello", nameValuePairs);
* }
*
*
* The values in these name-value pairs may be booleans, numerics, strings, or nested JSON objects. However,
* be aware that this method does not recursively parse any nested structures. If you wish to write arbitrary
* JSON objects to Vault... then you should parse them to JSON outside of this method, and pass them here as JSON
* strings.
*
* @param path The Vault key value to which to write (e.g. secret/hello
)
* @param nameValuePairs Secret name and value pairs to store under this Vault key (can be null
for
* writing to keys that do not need or expect any fields to be specified)
* @return The response information received from Vault
* @throws VaultException If any errors occurs with the REST request, and the maximum number of retries is exceeded.
*/
public LogicalResponse write(final String path, final Map nameValuePairs) throws VaultException {
if (engineVersionForSecretPath(path).equals(2)) {
return write(path, nameValuePairs, logicalOperations.writeV2);
} else return write(path, nameValuePairs, logicalOperations.writeV1);
}
private LogicalResponse write(final String path, final Map nameValuePairs,
final logicalOperations operation) throws VaultException {
int retryCount = 0;
while (true) {
try {
JsonObject requestJson = Json.object();
if (nameValuePairs != null) {
for (final Map.Entry pair : nameValuePairs.entrySet()) {
final Object value = pair.getValue();
if (value == null) {
requestJson = requestJson.add(pair.getKey(), (String) null);
} else if (value instanceof Boolean) {
requestJson = requestJson.add(pair.getKey(), (Boolean) pair.getValue());
} else if (value instanceof Integer) {
requestJson = requestJson.add(pair.getKey(), (Integer) pair.getValue());
} else if (value instanceof Long) {
requestJson = requestJson.add(pair.getKey(), (Long) pair.getValue());
} else if (value instanceof Float) {
requestJson = requestJson.add(pair.getKey(), (Float) pair.getValue());
} else if (value instanceof Double) {
requestJson = requestJson.add(pair.getKey(), (Double) pair.getValue());
} else if (value instanceof JsonValue) {
requestJson = requestJson.add(pair.getKey(), (JsonValue) pair.getValue());
} else {
requestJson = requestJson.add(pair.getKey(), pair.getValue().toString());
}
}
}
// Make an HTTP request to Vault
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForReadOrWrite(path, config.getPrefixPathDepth(), operation))
.body(jsonObjectToWriteFromEngineVersion(operation, requestJson).toString().getBytes(StandardCharsets.UTF_8))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.post();
// HTTP Status should be either 200 (with content - e.g. PKI write) or 204 (no content)
final int restStatus = restResponse.getStatus();
if (restStatus == 200 || restStatus == 204 || (restResponse.getStatus() >= 400 && restResponse.getStatus() < 500)) {
return new LogicalResponse(restResponse, retryCount, operation);
} else {
throw new VaultException("Expecting HTTP status 204 or 200, but instead receiving " + restStatus
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8), restStatus);
}
} catch (Exception e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
* Retrieve a list of keys corresponding to key/value pairs at a given Vault path.
*
* Key values ending with a trailing-slash characters are sub-paths. Running a subsequent list()
* call, using the original path appended with this key, will retrieve all secret keys stored at that sub-path.
*
* This method returns only the secret keys, not values. To retrieve the actual stored value for a key,
* use read()
with the key appended onto the original base path.
*
* @param path The Vault key value at which to look for secrets (e.g. secret
)
* @return A list of keys corresponding to key/value pairs at a given Vault path, or an empty list if there are none
* @throws VaultException If any errors occur, or unexpected response received from Vault
*/
public LogicalResponse list(final String path) throws VaultException {
if (engineVersionForSecretPath(path).equals(2)) {
return list(path, logicalOperations.listV2);
} else return list(path, logicalOperations.listV1);
}
private LogicalResponse list(final String path, final logicalOperations operation) throws VaultException {
LogicalResponse response = null;
try {
response = read(adjustPathForList(path, config.getPrefixPathDepth(), operation), true, operation);
} catch (final VaultException e) {
if (e.getHttpStatusCode() != 404) {
throw e;
}
}
return response;
}
/**
* Deletes the key/value pair located at the provided path.
*
* If the path represents a sub-path, then all of its contents must be deleted prior to deleting the empty
* sub-path itself.
*
* @param path The Vault key value to delete (e.g. secret/hello
).
* @return The response information received from Vault
* @throws VaultException If any error occurs, or unexpected response received from Vault
*/
public LogicalResponse delete(final String path) throws VaultException {
if (engineVersionForSecretPath(path).equals(2)) {
return delete(path, logicalOperations.deleteV2);
} else return delete(path, logicalOperations.deleteV1);
}
private LogicalResponse delete(final String path, final Logical.logicalOperations operation) throws VaultException {
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForDelete(path, config.getPrefixPathDepth(), operation))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.delete();
// Validate response
if (restResponse.getStatus() != 204) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, operation);
} catch (RuntimeException | VaultException | RestException e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
* Soft deletes the specified version of the key/value pair located at the provided path.
*
* Only supported for KV Engine version 2. If the data is desired, it can be recovered with a matching unDelete operation.
*
*
If the path represents a sub-path, then all of its contents must be deleted prior to deleting the empty
* sub-path itself.
*
* @param path The Vault key value to delete (e.g. secret/hello
).
* @param versions An array of Integers corresponding to the versions you wish to delete, e.g. [1, 2] etc.
* @return The response information received from Vault
* @throws VaultException If any error occurs, or unexpected response received from Vault
*/
public LogicalResponse delete(final String path, final int[] versions) throws VaultException {
if (this.engineVersionForSecretPath(path) != 2) {
throw new VaultException("Version deletes are only supported for KV Engine 2.");
}
intArrayCheck(versions);
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
JsonObject versionsToDelete = new JsonObject().add("versions", versions);
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForVersionDelete(path,config.getPrefixPathDepth()))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.body(versionsToDelete.toString().getBytes(StandardCharsets.UTF_8))
.post();
// Validate response
return getLogicalResponse(retryCount, restResponse);
} catch (RuntimeException | VaultException | RestException e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
private LogicalResponse getLogicalResponse(int retryCount, RestResponse restResponse) throws VaultException {
if (restResponse.getStatus() != 204) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, logicalOperations.deleteV2);
}
private void intArrayCheck(int[] versions) {
for (int i : versions) {
if (i < 1) {
throw new IllegalArgumentException("The document version must be 1 or greater.");
}
}
Arrays.sort(versions);
}
/**
* Recovers a soft delete of the specified version of the key/value pair located at the provided path.
*
* Only supported for KV Engine version 2.
*
* @param path The Vault key value to undelete (e.g. secret/hello
).
* @param versions An array of Integers corresponding to the versions you wish to undelete, e.g. [1, 2] etc.
* @return The response information received from Vault
* @throws VaultException If any error occurs, or unexpected response received from Vault
*/
public LogicalResponse unDelete(final String path, final int[] versions) throws VaultException {
if (this.engineVersionForSecretPath(path) != 2) {
throw new VaultException("Version undeletes are only supported for KV Engine 2.");
}
intArrayCheck(versions);
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
JsonObject versionsToUnDelete = new JsonObject().add("versions", versions);
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForVersionUnDelete(path,config.getPrefixPathDepth()))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.body(versionsToUnDelete.toString().getBytes(StandardCharsets.UTF_8))
.post();
// Validate response
if (restResponse.getStatus() != 204) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, logicalOperations.unDelete);
} catch (RuntimeException | VaultException | RestException e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
*
Performs a hard delete of the specified version of the key/value pair located at the provided path.
*
* Only supported for KV Engine version 2. There are no recovery options for the specified version of the data deleted
* in this method.
*
* @param path The Vault key value to destroy (e.g. secret/hello
).
* @param versions An array of Integers corresponding to the versions you wish to destroy, e.g. [1, 2] etc.
* @return The response information received from Vault
* @throws VaultException If any error occurs, or unexpected response received from Vault
*/
public LogicalResponse destroy(final String path, final int[] versions) throws VaultException {
if (this.engineVersionForSecretPath(path) != 2) {
throw new VaultException("Secret destroys are only supported for KV Engine 2.");
}
intArrayCheck(versions);
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
JsonObject versionsToDestroy = new JsonObject().add("versions", versions);
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/" + adjustPathForVersionDestroy(path,config.getPrefixPathDepth()))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.body(versionsToDestroy.toString().getBytes(StandardCharsets.UTF_8))
.post();
// Validate response
return getLogicalResponse(retryCount, restResponse);
} catch (RuntimeException | VaultException | RestException e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
/**
*
Performs an upgrade of the secrets engine version of the specified KV store to version 2.
*
* There is no downgrading this operation back to version 1.
*
* @param kvPath The Vault kv engine to upgrade (e.g. secret/
).
* @return The response information received from Vault
* @throws VaultException If any error occurs, or unexpected response received from Vault
*/
public LogicalResponse upgrade(final String kvPath) throws VaultException {
if (this.engineVersionForSecretPath(kvPath) == 2) {
throw new VaultException("This KV engine is already version 2.");
}
int retryCount = 0;
while (true) {
try {
// Make an HTTP request to Vault
JsonObject kvToUpgrade = new JsonObject().add("options", new JsonObject().add("version", 2));
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/sys/mounts/" + (kvPath.replaceAll("/", "") + "/tune"))
.header("X-Vault-Token", config.getToken())
.header("X-Vault-Namespace", this.nameSpace)
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslVerification(config.getSslConfig().isVerify())
.sslContext(config.getSslConfig().getSslContext())
.body(kvToUpgrade.toString().getBytes(StandardCharsets.UTF_8))
.post();
// Validate response
if (restResponse.getStatus() != 200) {
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus()
+ "\nResponse body: " + new String(restResponse.getBody(), StandardCharsets.UTF_8),
restResponse.getStatus());
}
return new LogicalResponse(restResponse, retryCount, logicalOperations.authentication);
} catch (RuntimeException | VaultException | RestException e) {
// If there are retries to perform, then pause for the configured interval and then execute the loop again...
if (retryCount < config.getMaxRetries()) {
retryCount++;
try {
final int retryIntervalMilliseconds = config.getRetryIntervalMilliseconds();
Thread.sleep(retryIntervalMilliseconds);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} else if (e instanceof VaultException) {
// ... otherwise, give up.
throw (VaultException) e;
} else {
throw new VaultException(e);
}
}
}
}
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();
}
return this.config.getGlobalEngineVersion();
}
/**
*
Provides the version of the secrets engine of the specified path, e.g. 1 or 2.
* First checks if the Vault config secrets engine path map contains the path.
* If not, then defaults to the Global Engine version fallback.
*
*
* @param path The Vault secret path to check (e.g. secret/
).
* @return The response information received from Vault
*/
public Integer getEngineVersionForSecretPath(final String path) {
return this.engineVersionForSecretPath(path);
}
}