com.bettercloud.vault.api.Leases 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.response.VaultResponse;
import com.bettercloud.vault.rest.Rest;
import com.bettercloud.vault.rest.RestResponse;
/**
* The implementing class for operations on REST endpoints, under the "Leases" section of the Vault HTTP API
* docs (https://www.vaultproject.io/docs/http/index.html).
*
* 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 Leases {
private final VaultConfig config;
public Leases(final VaultConfig config) {
this.config = config;
}
/**
* Immediately revokes a secret associated with a given lease. E.g.:
*
*
* {@code
* final VaultResponse response = vault.leases().revoke("7c63da27-a56b-3e3b-377d-ef74630a6d0b");
* assertEquals(204, response.getRestResponse().getStatus());
* }
*
*
* @param leaseId A lease ID associated with the secret to be revoked
* @return The response information returned from Vault
* @throws VaultException If an error occurs, or unexpected reponse received from Vault
*/
public VaultResponse revoke(final String leaseId) throws VaultException {
int retryCount = 0;
while (true) {
try {
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/sys/revoke/" + leaseId)
.header("X-Vault-Token", config.getToken())
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslPemUTF8(config.getSslPemUTF8())
.sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null)
.put();
// Validate response
if (restResponse.getStatus() != 204) {
throw new VaultException("Expecting HTTP status 204, but instead receiving " + restResponse.getStatus(), restResponse.getStatus());
}
return new VaultResponse(restResponse, retryCount);
} 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);
}
}
}
}
/**
* Revokes all secrets (via a lease ID prefix) or tokens (via the tokens' path property) generated under a
* given prefix immediately. This requires sudo capability and access to it should be tightly controlled as it
* can be used to revoke very large numbers of secrets/tokens at once. E.g.:
*
*
* {@code
* final VaultResponse response = vault.leases().revokePrefix("aws");
* assertEquals(204, response.getRestResponse().getStatus());
* }
*
*
* @param prefix A Vault path prefix, for which all secrets beneath it should be revoked
* @return The response information returned from Vault
* @throws VaultException If an error occurs, or unexpected reponse received from Vault
*/
public VaultResponse revokePrefix(final String prefix) throws VaultException {
int retryCount = 0;
while (true) {
try {
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/sys/revoke-prefix/" + prefix)
.header("X-Vault-Token", config.getToken())
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslPemUTF8(config.getSslPemUTF8())
.sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null)
.put();
// Validate response
if (restResponse.getStatus() != 204) {
throw new VaultException("Expecting HTTP status 204, but instead receiving " + restResponse.getStatus(), restResponse.getStatus());
}
return new VaultResponse(restResponse, retryCount);
} 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);
}
}
}
}
/**
* Revokes all secrets or tokens generated under a given prefix immediately. Unlike revokePrefix(String),
* this method ignores backend errors encountered during revocation. This is potentially very dangerous and should
* only be used in specific emergency situations where errors in the backend or the connected backend service
* prevent normal revocation. By ignoring these errors, Vault abdicates responsibility for ensuring that the
* issued credentials or secrets are properly revoked and/or cleaned up. Access to this endpoint should be tightly
* controlled. E.g.:
*
*
* {@code
* final VaultResponse response = vault.leases().revokePrefix("aws");
* assertEquals(204, response.getRestResponse().getStatus());
* }
*
*
* @param prefix A Vault path prefix, for which all secrets beneath it should be revoked
* @return The response information returned from Vault
* @throws VaultException If an error occurs, or unexpected reponse received from Vault
*/
public VaultResponse revokeForce(final String prefix) throws VaultException {
int retryCount = 0;
while (true) {
try {
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/sys/revoke-force/" + prefix)
.header("X-Vault-Token", config.getToken())
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslPemUTF8(config.getSslPemUTF8())
.sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null)
.put();
// Validate response
if (restResponse.getStatus() != 204) {
throw new VaultException("Expecting HTTP status 204, but instead receiving " + restResponse.getStatus(), restResponse.getStatus());
}
return new VaultResponse(restResponse, retryCount);
} 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);
}
}
}
}
/**
* Renews a given secret lease.
*
*
* {@code
* final VaultResponse response = vault.leases().renew("mongodb/creds/myapp/cd7f9834-b870-9ebc-3da5-27bf9cdc42ad");
* assertEquals(200, response.getRestResponse().getStatus());
* }
*
*
* @param leaseId A lease ID associated with a secret
* @param increment A requested amount of time in seconds to extend the lease. This is advisory.
* @return The response information returned from Vault
* @throws VaultException The response information returned from Vault
*/
public VaultResponse renew(final String leaseId, final long increment) throws VaultException {
// TODO: Unfortunately, there is not currently a way to cover this in the integration test suite.
// The "generic" backend does not support support lease renewal. The only other backend
// currently available to the integration test suite is the "pki" backend, which does
// support renewal of credentials, etc. But lease renewal in this context is talking about
// secrets. Perhaps revisit this at some point in the future if other backends are available
// to the integration test suite (e.g. if we eventually start using Docker).
int retryCount = 0;
while (true) {
try {
final String requestJson = Json.object().add("increment", increment).toString();
final RestResponse restResponse = new Rest()//NOPMD
.url(config.getAddress() + "/v1/sys/renew/" + leaseId)
.header("X-Vault-Token", config.getToken())
.body(increment < 0 ? null : requestJson.getBytes("UTF-8"))
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslPemUTF8(config.getSslPemUTF8())
.sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null)
.put();
// Validate response
if (restResponse.getStatus() != 200) {
throw new VaultException("Expecting HTTP status 200, but instead receiving " + restResponse.getStatus(), restResponse.getStatus());
}
return new VaultResponse(restResponse, retryCount);
} catch (Exception e) {
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);
}
}
}
}
}