Use Duration instead of numeric durations.

Use Duration type to express time durations. Refactor all long/int fields to Duration and deprecate methods accepting a single number in favor of methods accepting Duration/a time number and TimeUnit.

We also use Duration internally to ease time unit conversion within our client code.

Fixes gh-109.
This commit is contained in:
Mark Paluch
2017-06-28 10:15:31 +02:00
parent 2fadfaefd0
commit ac05794421
17 changed files with 449 additions and 156 deletions

View File

@@ -203,7 +203,7 @@ public class CubbyholeAuthentication implements ClientAuthentication {
LoginToken loginToken = (LoginToken) token;
if (loginToken.getLeaseDuration() == 0) {
if (loginToken.getLeaseDuration().isZero()) {
return false;
}
}
@@ -221,9 +221,10 @@ public class CubbyholeAuthentication implements ClientAuthentication {
}
if (data == null || data.isEmpty()) {
throw new VaultException(String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain a token",
options.getPath()));
throw new VaultException(
String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain a token",
options.getPath()));
}
if (data.size() == 1) {
@@ -231,8 +232,9 @@ public class CubbyholeAuthentication implements ClientAuthentication {
return VaultToken.of(token);
}
throw new VaultException(String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain an unique token",
options.getPath()));
throw new VaultException(
String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain an unique token",
options.getPath()));
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
@@ -216,7 +217,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
.filter(it -> {
LoginToken loginToken = (LoginToken) it;
return loginToken.getLeaseDuration() > 0 && loginToken.isRenewable();
return !loginToken.getLeaseDuration().isZero()
&& loginToken.isRenewable();
}).isPresent();
}
@@ -245,7 +247,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
}
private OneShotTrigger createTrigger() {
return new OneShotTrigger(refreshTrigger.nextExecutionTime((LoginToken) token.get()));
return new OneShotTrigger(refreshTrigger.nextExecutionTime((LoginToken) token
.get()));
}
/**
@@ -293,9 +296,9 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
*/
public static class FixedTimeoutRefreshTrigger implements RefreshTrigger {
private final long duration;
private static final Duration ONE_SECOND = Duration.ofSeconds(1);
private final TimeUnit timeUnit;
private final Duration duration;
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
@@ -309,17 +312,28 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
"Timeout duration must be greater or equal to zero");
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.duration = Duration.ofMillis(timeUnit.toMillis(timeout));
}
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires
* @param timeout timeout value.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout) {
Assert.isTrue(timeout.toMillis() >= 0,
"Timeout duration must be greater or equal to zero");
this.duration = timeout;
this.timeUnit = timeUnit;
}
@Override
public Date nextExecutionTime(LoginToken loginToken) {
long milliseconds = Math.max(
TimeUnit.SECONDS.toMillis(1),
TimeUnit.SECONDS.toMillis(loginToken.getLeaseDuration())
- timeUnit.toMillis(duration));
long milliseconds = Math.max(ONE_SECOND.toMillis(), loginToken
.getLeaseDuration().toMillis() - duration.toMillis());
return new Date(System.currentTimeMillis() + milliseconds);
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import lombok.ToString;
import org.springframework.util.Assert;
@@ -33,13 +35,13 @@ public class LoginToken extends VaultToken {
/**
* Duration in seconds.
*/
private final long leaseDuration;
private final Duration leaseDuration;
private LoginToken(char[] token, long leaseDurationSeconds, boolean renewable) {
private LoginToken(char[] token, Duration duration, boolean renewable) {
super(token);
this.leaseDuration = leaseDurationSeconds;
this.leaseDuration = duration;
this.renewable = renewable;
}
@@ -53,7 +55,7 @@ public class LoginToken extends VaultToken {
Assert.hasText(token, "Token must not be empty");
return of(token, 0);
return of(token.toCharArray(), Duration.ZERO);
}
/**
@@ -64,73 +66,125 @@ public class LoginToken extends VaultToken {
* @since 1.1
*/
public static LoginToken of(char[] token) {
return of(token, 0);
return of(token, Duration.ZERO);
}
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
* @deprecated since 2.0, use {@link #of(char[], Duration)} for time unit safety.
*/
@Deprecated
public static LoginToken of(String token, long leaseDurationSeconds) {
Assert.hasText(token, "Token must not be empty");
Assert.isTrue(leaseDurationSeconds >= 0, "Lease duration must not be negative");
return of(token.toCharArray(), leaseDurationSeconds);
return of(token.toCharArray(), Duration.ofSeconds(leaseDurationSeconds));
}
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
* @since 1.1
* @deprecated since 2.0, use {@link #of(char[], Duration)} for time unit safety.
*/
@Deprecated
public static LoginToken of(char[] token, long leaseDurationSeconds) {
Assert.notNull(token, "Token must not be null");
Assert.isTrue(token.length > 0, "Token must not be empty");
Assert.isTrue(leaseDurationSeconds >= 0, "Lease duration must not be negative");
return new LoginToken(token, leaseDurationSeconds, false);
return new LoginToken(token, Duration.ofSeconds(leaseDurationSeconds), false);
}
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
*
* @param leaseDuration the lease duration, must not be negative and not be
* {@literal null}.
* @return the created {@link VaultToken}
* @since 2.0
*/
public static LoginToken of(char[] token, Duration leaseDuration) {
Assert.notNull(token, "Token must not be null");
Assert.isTrue(token.length > 0, "Token must not be empty");
Assert.notNull(leaseDuration, "Lease duration must not be null");
Assert.isTrue(!leaseDuration.isNegative(), "Lease duration must not be negative");
return new LoginToken(token, leaseDuration, false);
}
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
* @deprecated since 2.0, use {@link #renewable(char[], Duration)} for time unit
* safety.
*/
@Deprecated
public static LoginToken renewable(String token, long leaseDurationSeconds) {
Assert.hasText(token, "Token must not be empty");
Assert.isTrue(leaseDurationSeconds >= 0, "Lease duration must not be negative");
return renewable(token.toCharArray(), leaseDurationSeconds);
return renewable(token.toCharArray(), Duration.ofSeconds(leaseDurationSeconds));
}
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
* @since 1.1
* @since 2.0
* @deprecated since 2.0, use {@link #renewable(char[], Duration)} for time unit
* safety.
*/
@Deprecated
public static LoginToken renewable(char[] token, long leaseDurationSeconds) {
Assert.notNull(token, "Token must not be null");
Assert.isTrue(token.length > 0, "Token must not be empty");
Assert.isTrue(leaseDurationSeconds >= 0, "Lease duration must not be negative");
return new LoginToken(token, leaseDurationSeconds, true);
return new LoginToken(token, Duration.ofSeconds(leaseDurationSeconds), true);
}
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDuration the lease duration, must not be {@literal null} or negative.
* @return the created {@link VaultToken}
* @since 2.0
*/
public static LoginToken renewable(char[] token, Duration leaseDuration) {
Assert.notNull(token, "Token must not be null");
Assert.isTrue(token.length > 0, "Token must not be empty");
Assert.notNull(leaseDuration, "Lease duration must not be null");
Assert.isTrue(!leaseDuration.isNegative(), "Lease duration must not be negative");
return new LoginToken(token, leaseDuration, true);
}
/**
* @return the lease duration in seconds. May be {@literal 0} if none.
*/
public long getLeaseDuration() {
public Duration getLeaseDuration() {
return leaseDuration;
}

View File

@@ -125,14 +125,12 @@ public class ClientHttpRequestFactoryFactory {
static SSLContext getSSLContext(SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
KeyManager[] keyManagers = sslConfiguration.getKeyStore() != null
? createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration())
.getKeyManagers()
KeyManager[] keyManagers = sslConfiguration.getKeyStore() != null ? createKeyManagerFactory(
sslConfiguration.getKeyStoreConfiguration()).getKeyManagers()
: null;
TrustManager[] trustManagers = sslConfiguration.getTrustStore() != null
? createTrustManagerFactory(sslConfiguration.getTrustStoreConfiguration())
.getTrustManagers()
TrustManager[] trustManagers = sslConfiguration.getTrustStore() != null ? createTrustManagerFactory(
sslConfiguration.getTrustStoreConfiguration()).getTrustManagers()
: null;
SSLContext sslContext = SSLContext.getInstance("TLS");
@@ -142,32 +140,31 @@ public class ClientHttpRequestFactoryFactory {
}
private static KeyManagerFactory createKeyManagerFactory(
KeyStoreConfiguration keyStoreConfiguration)
throws GeneralSecurityException, IOException {
KeyStoreConfiguration keyStoreConfiguration) throws GeneralSecurityException,
IOException {
KeyStore keyStore = KeyStore
.getInstance(StringUtils.hasText(keyStoreConfiguration.getStoreType())
? keyStoreConfiguration.getStoreType()
: KeyStore.getDefaultType());
KeyStore keyStore = KeyStore.getInstance(StringUtils
.hasText(keyStoreConfiguration.getStoreType()) ? keyStoreConfiguration
.getStoreType() : KeyStore.getDefaultType());
loadKeyStore(keyStoreConfiguration, keyStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStoreConfiguration.getStorePassword() == null
? new char[0] : keyStoreConfiguration.getStorePassword());
keyManagerFactory.init(keyStore,
keyStoreConfiguration.getStorePassword() == null ? new char[0]
: keyStoreConfiguration.getStorePassword());
return keyManagerFactory;
}
private static TrustManagerFactory createTrustManagerFactory(
KeyStoreConfiguration keyStoreConfiguration)
throws GeneralSecurityException, IOException {
KeyStoreConfiguration keyStoreConfiguration) throws GeneralSecurityException,
IOException {
KeyStore trustStore = KeyStore
.getInstance(StringUtils.hasText(keyStoreConfiguration.getStoreType())
? keyStoreConfiguration.getStoreType()
: KeyStore.getDefaultType());
KeyStore trustStore = KeyStore.getInstance(StringUtils
.hasText(keyStoreConfiguration.getStoreType()) ? keyStoreConfiguration
.getStoreType() : KeyStore.getDefaultType());
loadKeyStore(keyStoreConfiguration, trustStore);
@@ -179,8 +176,8 @@ public class ClientHttpRequestFactoryFactory {
}
private static void loadKeyStore(KeyStoreConfiguration keyStoreConfiguration,
KeyStore keyStore)
throws IOException, NoSuchAlgorithmException, CertificateException {
KeyStore keyStore) throws IOException, NoSuchAlgorithmException,
CertificateException {
InputStream inputStream = null;
try {
@@ -207,8 +204,8 @@ public class ClientHttpRequestFactoryFactory {
static class HttpComponents {
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options,
SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
SslConfiguration sslConfiguration) throws GeneralSecurityException,
IOException {
HttpClientBuilder httpClientBuilder = HttpClients.custom();
@@ -224,9 +221,13 @@ public class ClientHttpRequestFactoryFactory {
httpClientBuilder.setSSLContext(sslContext);
}
RequestConfig requestConfig = RequestConfig.custom() //
.setConnectTimeout(options.getConnectionTimeout()) //
.setSocketTimeout(options.getReadTimeout()) //
RequestConfig requestConfig = RequestConfig
.custom()
//
.setConnectTimeout(
Math.toIntExact(options.getConnectionTimeout().toMillis())) //
.setSocketTimeout(
Math.toIntExact(options.getReadTimeout().toMillis())) //
.setAuthenticationEnabled(true) //
.build();
@@ -244,18 +245,19 @@ public class ClientHttpRequestFactoryFactory {
static class OkHttp3 {
static ClientHttpRequestFactory usingOkHttp3(ClientOptions options,
SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
SslConfiguration sslConfiguration) throws GeneralSecurityException,
IOException {
Builder builder = new Builder();
if (hasSslConfiguration(sslConfiguration)) {
builder.sslSocketFactory(
getSSLContext(sslConfiguration).getSocketFactory());
builder.sslSocketFactory(getSSLContext(sslConfiguration)
.getSocketFactory());
}
builder.connectTimeout(options.getConnectionTimeout(), TimeUnit.MILLISECONDS)
.readTimeout(options.getReadTimeout(), TimeUnit.MILLISECONDS);
builder.connectTimeout(options.getConnectionTimeout().toMillis(),
TimeUnit.MILLISECONDS).readTimeout(
options.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS);
return new OkHttp3ClientHttpRequestFactory(builder.build());
}
@@ -269,8 +271,8 @@ public class ClientHttpRequestFactoryFactory {
static class Netty {
static ClientHttpRequestFactory usingNetty(ClientOptions options,
SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
SslConfiguration sslConfiguration) throws GeneralSecurityException,
IOException {
final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
@@ -280,21 +282,24 @@ public class ClientHttpRequestFactoryFactory {
.forClient();
if (sslConfiguration.getTrustStore() != null) {
sslContextBuilder.trustManager(createTrustManagerFactory(
sslConfiguration.getTrustStoreConfiguration()));
sslContextBuilder
.trustManager(createTrustManagerFactory(sslConfiguration
.getTrustStoreConfiguration()));
}
if (sslConfiguration.getKeyStore() != null) {
sslContextBuilder.keyManager(createKeyManagerFactory(
sslConfiguration.getKeyStoreConfiguration()));
sslContextBuilder.keyManager(createKeyManagerFactory(sslConfiguration
.getKeyStoreConfiguration()));
}
requestFactory.setSslContext(
sslContextBuilder.sslProvider(SslProvider.JDK).build());
requestFactory.setSslContext(sslContextBuilder.sslProvider(
SslProvider.JDK).build());
}
requestFactory.setConnectTimeout(options.getConnectionTimeout());
requestFactory.setReadTimeout(options.getReadTimeout());
requestFactory.setConnectTimeout(Math.toIntExact(options
.getConnectionTimeout().toMillis()));
requestFactory.setReadTimeout(Math.toIntExact(options.getReadTimeout()
.toMillis()));
return requestFactory;
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.core.lease;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -133,9 +134,9 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
private final VaultOperations operations;
private int minRenewalSeconds = 10;
private Duration minRenewal = Duration.ofSeconds(10);
private int expiryThresholdSeconds = 60;
private Duration expiryThreshold = Duration.ofSeconds(60);
private TaskScheduler taskScheduler;
@@ -173,33 +174,89 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
setTaskScheduler(taskScheduler);
}
/**
* Set the expiry threshold. {@link Lease} is renewed the given seconds before it
* expires.
*
* @param expiryThresholdSeconds number of seconds before {@link Lease} expiry.
*/
public void setExpiryThresholdSeconds(int expiryThresholdSeconds) {
this.expiryThresholdSeconds = expiryThresholdSeconds;
}
/**
* Sets the amount of seconds that is at least required before renewing a lease.
* {@code minRenewalSeconds} prevents renewals to happen too often.
*
* @param minRenewalSeconds number of seconds that is at least required before
* renewing a {@link Lease}.
* renewing a {@link Lease}, must not be negative.
* @deprecated since 2.0, use {@link #setMinRenewal(Duration)} for time unit safety.
*/
@Deprecated
public void setMinRenewalSeconds(int minRenewalSeconds) {
this.minRenewalSeconds = minRenewalSeconds;
setMinRenewal(Duration.ofSeconds(minRenewalSeconds));
}
/**
* Sets the amount of seconds that is at least required before renewing a lease.
* {@code minRenewal} prevents renewals to happen too often.
*
* @param minRenewal duration that is at least required before renewing a
* {@link Lease}, must not be {@literal null} or negative.
* @since 2.0
*/
public void setMinRenewal(Duration minRenewal) {
Assert.notNull(minRenewal, "Minimal renewal time must not be null");
Assert.isTrue(!minRenewal.isNegative(),
"Minimal renewal time must not be negative");
this.minRenewal = minRenewal;
}
/**
* Set the expiry threshold. {@link Lease} is renewed the given seconds before it
* expires.
*
* @param expiryThresholdSeconds number of seconds before {@link Lease} expiry, must
* not be negative.
* @deprecated since 2.0, use {@link #setExpiryThreshold(Duration)} for time unit
* safety.
*/
@Deprecated
public void setExpiryThresholdSeconds(int expiryThresholdSeconds) {
setExpiryThreshold(Duration.ofSeconds(expiryThresholdSeconds));
}
/**
* Set the expiry threshold. {@link Lease} is renewed the given time before it
* expires.
*
* @param expiryThreshold duration before {@link Lease} expiry, must not be
* {@literal null} or negative.
* @since 2.0
*/
public void setExpiryThreshold(Duration expiryThreshold) {
Assert.notNull(expiryThreshold, "Expiry threshold must not be null");
Assert.isTrue(!expiryThreshold.isNegative(),
"Expiry threshold must not be negative");
this.expiryThreshold = expiryThreshold;
}
public int getMinRenewalSeconds() {
return minRenewalSeconds;
return Math.toIntExact(minRenewal.getSeconds());
}
/**
* @return minimum renewal timeout.
* @since 2.0
*/
public Duration getMinRenewal() {
return minRenewal;
}
public int getExpiryThresholdSeconds() {
return expiryThresholdSeconds;
return Math.toIntExact(expiryThreshold.getSeconds());
}
/**
* @return expiry threshold.
* @since 2.0
*/
public Duration getExpiryThreshold() {
return expiryThreshold;
}
/**
@@ -300,11 +357,13 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
Lease lease;
if (StringUtils.hasText(secrets.getLeaseId())) {
lease = Lease.of(secrets.getLeaseId(), secrets.getLeaseDuration(),
lease = Lease.of(secrets.getLeaseId(),
Duration.ofSeconds(secrets.getLeaseDuration()),
secrets.isRenewable());
}
else if (isRotatingGenericSecret(requestedSecret, secrets)) {
lease = Lease.fromTimeToLive(secrets.getLeaseDuration());
lease = Lease.fromTimeToLive(Duration.ofSeconds(secrets
.getLeaseDuration()));
}
else {
lease = Lease.none();
@@ -440,7 +499,7 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
}
return newLease;
}, lease, getMinRenewalSeconds(), getExpiryThresholdSeconds());
}, lease, getMinRenewal(), getExpiryThreshold());
}
@@ -480,8 +539,8 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
try {
Lease renewed = lease.hasLeaseId() ? renew(lease) : lease;
if (!renewed.hasLeaseId() || renewed.getLeaseDuration() == 0
|| renewed.getLeaseDuration() < minRenewalSeconds) {
if (!renewed.hasLeaseId() || renewed.getLeaseDuration().isZero()
|| renewed.getLeaseDuration().getSeconds() < minRenewal.getSeconds()) {
onLeaseExpired(requestedSecret, lease);
return Lease.none();
@@ -599,25 +658,26 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
* @param requestedSecret the requested secret.
* @param renewLease strategy to renew a {@link Lease}.
* @param lease the current {@link Lease}.
* @param minRenewalSeconds minimum number of seconds before renewing a
* {@link Lease}. This is to prevent too many renewals in a very short timeframe.
* @param expiryThresholdSeconds number of seconds to renew before {@link Lease}.
* @param minRenewal minimum duration before renewing a {@link Lease}. This is to
* prevent too many renewals in a very short timeframe.
* @param expiryThreshold duration to renew before {@link Lease}.
*/
void scheduleRenewal(final RequestedSecret requestedSecret,
final RenewLease renewLease, final Lease lease,
final int minRenewalSeconds, final int expiryThresholdSeconds) {
final Duration minRenewal, final Duration expiryThreshold) {
if (log.isDebugEnabled()) {
if (lease.hasLeaseId()) {
log.debug(String
.format("Scheduling renewal for secret %s with lease %s, lease duration %d",
requestedSecret.getPath(), lease.getLeaseId(),
lease.getLeaseDuration()));
requestedSecret.getPath(), lease.getLeaseId(), lease
.getLeaseDuration().getSeconds()));
}
else {
log.debug(String
.format("Scheduling renewal for secret %s, with cache hint duration %d",
requestedSecret.getPath(), lease.getLeaseDuration()));
requestedSecret.getPath(), lease.getLeaseDuration()
.getSeconds()));
}
}
@@ -664,8 +724,8 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(
task,
new OneShotTrigger(getRenewalSeconds(lease, minRenewalSeconds,
expiryThresholdSeconds)));
new OneShotTrigger(getRenewalSeconds(lease, minRenewal,
expiryThreshold)));
schedules.put(lease, scheduledFuture);
}
@@ -699,10 +759,10 @@ public class SecretLeaseContainer extends SecretLeaseEventPublisher implements
}
}
private long getRenewalSeconds(Lease lease, int minRenewalSeconds,
int expiryThresholdSeconds) {
return Math.max(minRenewalSeconds, lease.getLeaseDuration()
- expiryThresholdSeconds);
private long getRenewalSeconds(Lease lease, Duration minRenewal,
Duration expiryThreshold) {
return Math.max(minRenewal.getSeconds(), lease.getLeaseDuration()
.getSeconds() - expiryThreshold.getSeconds());
}
private boolean isLeaseRenewable(Lease lease, RequestedSecret requestedSecret) {

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.vault.core.lease.domain;
import java.time.Duration;
import org.springframework.util.Assert;
/**
@@ -25,15 +27,15 @@ import org.springframework.util.Assert;
*/
public class Lease {
private static final Lease NONE = new Lease(null, 0, false);
private static final Lease NONE = new Lease(null, Duration.ZERO, false);
private final String leaseId;
private final long leaseDuration;
private final Duration leaseDuration;
private final boolean renewable;
private Lease(String leaseId, long leaseDuration, boolean renewable) {
private Lease(String leaseId, Duration leaseDuration, boolean renewable) {
this.leaseId = leaseId;
this.leaseDuration = leaseDuration;
@@ -44,13 +46,34 @@ public class Lease {
* Create a new {@link Lease}.
*
* @param leaseId must not be empty or {@literal null}.
* @param leaseDuration the lease duration in seconds
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @param renewable {@literal true} if this lease is renewable.
* @return the created {@link Lease}
* @deprecated since 2.0, use {@link #of(String, Duration, boolean)} for time unit
* safety.
*/
public static Lease of(String leaseId, long leaseDuration, boolean renewable) {
@Deprecated
public static Lease of(String leaseId, long leaseDurationSeconds, boolean renewable) {
Assert.isTrue(leaseDurationSeconds >= 0, "Lease duration must not be negative");
return of(leaseId, Duration.ofSeconds(leaseDurationSeconds), renewable);
}
/**
* Create a new {@link Lease}.
*
* @param leaseId must not be empty or {@literal null}.
* @param leaseDuration the lease duration, must not be {@literal null} or negative.
* @param renewable {@literal true} if this lease is renewable.
* @return the created {@link Lease}
* @since 2.0
*/
public static Lease of(String leaseId, Duration leaseDuration, boolean renewable) {
Assert.hasText(leaseId, "LeaseId must not be empty");
Assert.notNull(leaseDuration, "Lease duration must not be null");
Assert.isTrue(!leaseDuration.isNegative(), "Lease duration must not be negative");
return new Lease(leaseId, leaseDuration, renewable);
}
@@ -59,11 +82,32 @@ public class Lease {
* Create a new non-renewable {@link Lease}, without a {@code leaseId} and specified
* duration.
*
* @param leaseDuration the lease duration in seconds.
* @param leaseDuration the lease duration in seconds, must not be negative.
* @return the created {@link Lease}
* @since 1.1
* @deprecated since 2.0, use {@link #fromTimeToLive(Duration)} for time unit safety.
*/
@Deprecated
public static Lease fromTimeToLive(long leaseDuration) {
Assert.isTrue(leaseDuration >= 0, "Lease duration must not be negative");
return new Lease(null, Duration.ofSeconds(leaseDuration), false);
}
/**
* Create a new non-renewable {@link Lease}, without a {@code leaseId} and specified
* duration.
*
* @param leaseDuration the lease duration, must not be {@literal null} or negative.
* @return the created {@link Lease}
* @since 2.0
*/
public static Lease fromTimeToLive(Duration leaseDuration) {
Assert.notNull(leaseDuration, "Lease duration must not be null");
Assert.isTrue(!leaseDuration.isNegative(), "Lease duration must not be negative");
return new Lease(null, leaseDuration, false);
}
@@ -94,7 +138,7 @@ public class Lease {
/**
* @return the lease duration in seconds.
*/
public long getLeaseDuration() {
public Duration getLeaseDuration() {
return leaseDuration;
}
@@ -126,7 +170,7 @@ public class Lease {
public int hashCode() {
int result = leaseId != null ? leaseId.hashCode() : 0;
result = 31 * result + (int) (leaseDuration ^ (leaseDuration >>> 32));
result = 31 * result + (leaseDuration != null ? leaseDuration.hashCode() : 0);
result = 31 * result + (renewable ? 1 : 0);
return result;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,11 @@
*/
package org.springframework.vault.support;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.springframework.util.Assert;
/**
* Client options for Vault.
*
@@ -27,12 +30,12 @@ public class ClientOptions {
/**
* Connection timeout;
*/
private final int connectionTimeout;
private final Duration connectionTimeout;
/**
* Read timeout;
*/
private final int readTimeout;
private final Duration readTimeout;
/**
* Create new {@link ClientOptions} with default timeouts of {@literal 5}
@@ -40,18 +43,36 @@ public class ClientOptions {
* {@link TimeUnit#SECONDS} read timeout.
*/
public ClientOptions() {
this((int) TimeUnit.SECONDS.toMillis(5), (int) TimeUnit.SECONDS.toMillis(15));
this(Duration.ofSeconds(5), Duration.ofSeconds(15));
}
/**
* Create new {@link ClientOptions}.
*
* @param connectionTimeout connection timeout in {@link TimeUnit#MILLISECONDS}, must
* be greater {@literal 0}.
* @param readTimeout read timeout in {@link TimeUnit#MILLISECONDS}, must be greater
* {@literal 0}.
* not be negative.
* @param readTimeout read timeout in {@link TimeUnit#MILLISECONDS}, must not be
* negative.
* @deprecated since 2.0, use {@link #ClientOptions(Duration, Duration)} for time unit
* safety.
*/
@Deprecated
public ClientOptions(int connectionTimeout, int readTimeout) {
this(Duration.ofMillis(connectionTimeout), Duration.ofMillis(readTimeout));
}
/**
* Create new {@link ClientOptions}.
*
* @param connectionTimeout connection timeout, must not be {@literal null}.
* @param readTimeout read timeout in, must not be {@literal null}.
* @since 2.0
*/
public ClientOptions(Duration connectionTimeout, Duration readTimeout) {
Assert.notNull(connectionTimeout, "Connection timeout must not be null");
Assert.notNull(readTimeout, "Read timeout must not be null");
this.connectionTimeout = connectionTimeout;
this.readTimeout = readTimeout;
}
@@ -59,15 +80,14 @@ public class ClientOptions {
/**
* @return the connection timeout in {@link TimeUnit#MILLISECONDS}.
*/
public int getConnectionTimeout() {
public Duration getConnectionTimeout() {
return connectionTimeout;
}
/**
* @return the read timeout in {@link TimeUnit#MILLISECONDS}.
*/
public int getReadTimeout() {
public Duration getReadTimeout() {
return readTimeout;
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.support;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -44,9 +45,9 @@ public class VaultCertificateRequest {
private final List<String> ipSubjectAltNames;
/**
* Requested Time To Live
* Requested Time to Live
*/
private final Integer ttl;
private final Duration ttl;
/**
* If {@literal true}, the given common name will not be included in DNS or Email
@@ -56,7 +57,7 @@ public class VaultCertificateRequest {
private final boolean excludeCommonNameFromSubjectAltNames;
VaultCertificateRequest(String commonName, List<String> altNames,
List<String> ipSubjectAltNames, Integer ttl,
List<String> ipSubjectAltNames, Duration ttl,
Boolean excludeCommonNameFromSubjectAltNames) {
this.commonName = commonName;
@@ -96,7 +97,7 @@ public class VaultCertificateRequest {
return ipSubjectAltNames;
}
public Integer getTtl() {
public Duration getTtl() {
return ttl;
}
@@ -109,7 +110,7 @@ public class VaultCertificateRequest {
private String commonName;
private List<String> altNames = new ArrayList<>();
private List<String> ipSubjectAltNames = new ArrayList<>();
private Integer ttl;
private Duration ttl;
private Boolean excludeCommonNameFromSubjectAltNames;
VaultCertificateRequestBuilder() {
@@ -190,30 +191,48 @@ public class VaultCertificateRequest {
/**
* Configure a TTL.
*
* @param ttl the TTL, must be a positive number.
* @param ttl the time to live, in seconds, must not be negative.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
* @deprecated since 2.0, use {@link #ttl(Duration)} for time unit safety.
*/
@Deprecated
public VaultCertificateRequestBuilder ttl(int ttl) {
Assert.isTrue(ttl > 0, "TTL must be greater 0");
Assert.isTrue(ttl > 0, "TTL must not be negative");
this.ttl = ttl;
this.ttl = Duration.ofSeconds(ttl);
return this;
}
/**
* Configure a TTL.
*
* @param ttl the TTL, must be a positive number.
* @param ttl the time to live, must not be negative.
* @param timeUnit must not be {@literal null}
* @return {@code this} {@link VaultCertificateRequestBuilder}.
*/
public VaultCertificateRequestBuilder ttl(long ttl, TimeUnit timeUnit) {
Assert.isTrue(ttl > 0, "TTL must be greater 0");
Assert.isTrue(ttl > 0, "TTL must not be negative");
Assert.notNull(timeUnit, "TimeUnit must be greater 0");
this.ttl = (int) timeUnit.toSeconds(ttl);
this.ttl = Duration.ofSeconds(timeUnit.toSeconds(ttl));
return this;
}
/**
* Configure a TTL.
*
* @param ttl the time to live, must not be {@literal null} or negative.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
* @since 2.0
*/
public VaultCertificateRequestBuilder ttl(Duration ttl) {
Assert.notNull(ttl, "TTL must not be null");
Assert.isTrue(!ttl.isNegative(), "TTL must not be negative");
this.ttl = ttl;
return this;
}
@@ -249,8 +268,7 @@ public class VaultCertificateRequest {
altNames = java.util.Collections.singletonList(this.altNames.get(0));
break;
default:
altNames = java.util.Collections
.unmodifiableList(new ArrayList<>(
altNames = java.util.Collections.unmodifiableList(new ArrayList<>(
this.altNames));
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.support;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -313,7 +314,9 @@ public class VaultTokenRequest {
*
* @param ttl the time to live in seconds, must not be negative.
* @return {@code this} {@link VaultTokenRequestBuilder}.
* @deprecated since 2.0, use {@link #ttl(Duration)} for time unit safety.
*/
@Deprecated
public VaultTokenRequestBuilder ttl(long ttl) {
return ttl(ttl, TimeUnit.SECONDS);
}
@@ -322,7 +325,7 @@ public class VaultTokenRequest {
* Configure a TTL (seconds) for the token.
*
* @param ttl the time to live, must not be negative.
* @param timeUnit the time to live, must not be {@literal null}.
* @param timeUnit the time to live time unit, must not be {@literal null}.
* @return {@code this} {@link VaultTokenRequestBuilder}.
*/
public VaultTokenRequestBuilder ttl(long ttl, TimeUnit timeUnit) {
@@ -334,6 +337,23 @@ public class VaultTokenRequest {
return this;
}
/**
* Configure a TTL for the token using
* {@link java.time.temporal.ChronoUnit#SECONDS} resolution.
*
* @param ttl the time to live, must not be {@literal null} or negative.
* @return {@code this} {@link VaultTokenRequestBuilder}.
* @since 2.0
*/
public VaultTokenRequestBuilder ttl(Duration ttl) {
Assert.notNull(ttl, "TTL must not be null");
Assert.isTrue(!ttl.isNegative(), "TTL must not be negative");
this.ttl = String.format("%ss", ttl.getSeconds());
return this;
}
/**
* Configure the explicit maximum TTL (seconds) for the token. This maximum token
* TTL cannot be changed later, and unlike with normal tokens, updates to the
@@ -342,7 +362,10 @@ public class VaultTokenRequest {
*
* @param explicitMaxTtl the time to live in seconds, must not be negative.
* @return {@code this} {@link VaultTokenRequestBuilder}.
* @deprecated since 2.0, use {@link #explicitMaxTtl(Duration)} for time unit
* safety.
*/
@Deprecated
public VaultTokenRequestBuilder explicitMaxTtl(long explicitMaxTtl) {
return explicitMaxTtl(explicitMaxTtl, TimeUnit.SECONDS);
}
@@ -368,6 +391,26 @@ public class VaultTokenRequest {
return this;
}
/**
* Configure the explicit maximum TTL for the token. This maximum token TTL cannot
* be changed later, and unlike with normal tokens, updates to the system/mount
* max TTL value will have no effect at renewal time - the token will never be
* able to be renewed or used past the value set at issue time.
*
* @param explicitMaxTtl the time to live, must not be {@literal null} or
* negative.
* @return {@code this} {@link VaultTokenRequestBuilder}.
* @since 2.0
*/
public VaultTokenRequestBuilder explicitMaxTtl(Duration explicitMaxTtl) {
Assert.notNull(explicitMaxTtl, "Explicit max TTL must not be null");
Assert.isTrue(!explicitMaxTtl.isNegative(), "TTL must not be negative");
this.explicitMaxTtl = String.format("%ss", explicitMaxTtl.getSeconds());
return this;
}
/**
* Configure the maximum uses for the token. This can be used to create a
* one-time-token or limited use token. Defaults to {@literal 0}, which has no
@@ -414,8 +457,7 @@ public class VaultTokenRequest {
policies = Collections.singletonList(this.policies.get(0));
break;
default:
policies = Collections.unmodifiableList(new ArrayList<>(
this.policies));
policies = Collections.unmodifiableList(new ArrayList<>(this.policies));
}
Map<String, String> meta;
@@ -424,8 +466,7 @@ public class VaultTokenRequest {
meta = Collections.emptyMap();
break;
default:
meta = Collections
.unmodifiableMap(new LinkedHashMap<>(this.meta));
meta = Collections.unmodifiableMap(new LinkedHashMap<>(this.meta));
}
return new VaultTokenRequest(id, policies, meta, noParent, noDefaultPolicy,

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import org.junit.Before;
import org.junit.Test;
@@ -102,7 +104,8 @@ public class AppRoleAuthenticationUnitTests {
assertThat(login).isInstanceOf(LoginToken.class);
assertThat(login.getToken()).isEqualTo("my-token");
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(10);
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(
Duration.ofSeconds(10));
assertThat(((LoginToken) login).isRenewable()).isTrue();
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
@@ -123,7 +124,8 @@ public class AwsEc2AuthenticationUnitTests {
assertThat(login).isInstanceOf(LoginToken.class);
assertThat(login.getToken()).isEqualTo("my-token");
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(20);
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(
Duration.ofSeconds(20));
assertThat(((LoginToken) login).isRenewable()).isFalse();
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import org.junit.Before;
import org.junit.Test;
@@ -72,7 +74,8 @@ public class ClientCertificateAuthenticationUnitTests {
assertThat(login).isInstanceOf(LoginToken.class);
assertThat(login.getToken()).isEqualTo("my-token");
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(10);
assertThat(((LoginToken) login).getLeaseDuration()).isEqualTo(
Duration.ofSeconds(10));
assertThat(((LoginToken) login).isRenewable()).isTrue();
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
@@ -23,8 +25,8 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.vault.VaultException;
import org.springframework.vault.client.VaultClients.PrefixAwareUriTemplateHandler;
import org.springframework.vault.client.VaultHttpHeaders;
import org.springframework.vault.client.VaultClients.PrefixAwareUriTemplateHandler;
import org.springframework.vault.support.VaultToken;
import org.springframework.web.client.RestTemplate;
@@ -86,7 +88,7 @@ public class CubbyholeAuthenticationUnitTests {
LoginToken loginToken = (LoginToken) login;
assertThat(loginToken.isRenewable()).isFalse();
assertThat(loginToken.getLeaseDuration()).isEqualTo(0);
assertThat(loginToken.getLeaseDuration()).isEqualTo(Duration.ZERO);
}
@Test
@@ -126,7 +128,7 @@ public class CubbyholeAuthenticationUnitTests {
LoginToken loginToken = (LoginToken) login;
assertThat(loginToken.isRenewable()).isFalse();
assertThat(loginToken.getLeaseDuration()).isEqualTo(456);
assertThat(loginToken.getLeaseDuration()).isEqualTo(Duration.ofSeconds(456));
}
@Test
@@ -179,7 +181,7 @@ public class CubbyholeAuthenticationUnitTests {
LoginToken loginToken = (LoginToken) login;
assertThat(loginToken.isRenewable()).isTrue();
assertThat(loginToken.getLeaseDuration()).isEqualTo(456);
assertThat(loginToken.getLeaseDuration()).isEqualTo(Duration.ofSeconds(456));
}
@Test

View File

@@ -76,7 +76,7 @@ public class LoginTokenAdapterUnitTests {
LoginToken loginToken = (LoginToken) login;
assertThat(loginToken.isRenewable()).isFalse();
assertThat(loginToken.getLeaseDuration()).isEqualTo(456);
assertThat(loginToken.getLeaseDuration().getSeconds()).isEqualTo(456);
}
}

View File

@@ -21,7 +21,7 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link LoginToken}.
*
*
* @author Mark Paluch
*/
public class LoginTokenUnitTests {
@@ -38,10 +38,10 @@ public class LoginTokenUnitTests {
public void toStringShouldPrintFields() {
assertThat(LoginToken.of("token").toString()).isEqualTo(
"LoginToken(renewable=false, leaseDuration=0)");
"LoginToken(renewable=false, leaseDuration=PT0S)");
assertThat(LoginToken.of("token", 1).toString()).isEqualTo(
"LoginToken(renewable=false, leaseDuration=1)");
"LoginToken(renewable=false, leaseDuration=PT1S)");
assertThat(LoginToken.renewable("token", 1).toString()).isEqualTo(
"LoginToken(renewable=true, leaseDuration=1)");
"LoginToken(renewable=true, leaseDuration=PT1S)");
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.core.lease;
import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -100,6 +101,18 @@ public class SecretLeaseContainerUnitTests {
secretLeaseContainer.afterPropertiesSet();
}
@Test
public void shouldSetProperties() {
secretLeaseContainer.setMinRenewal(Duration.ofMinutes(2));
secretLeaseContainer.setExpiryThreshold(Duration.ofMinutes(3));
assertThat(secretLeaseContainer.getMinRenewal().getSeconds()).isEqualTo(120);
assertThat(secretLeaseContainer.getMinRenewalSeconds()).isEqualTo(120);
assertThat(secretLeaseContainer.getExpiryThreshold().getSeconds()).isEqualTo(180);
assertThat(secretLeaseContainer.getExpiryThresholdSeconds()).isEqualTo(180);
}
@Test
public void shouldWorkIfNoSecretsRequested() {

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.support;
import java.time.Duration;
import java.util.Collections;
import org.junit.Test;
@@ -54,4 +55,15 @@ public class VaultTokenRequestUnitTests {
assertThat(tokenRequest.getPolicies()).containsOnly("foo");
}
@Test
public void shouldRequestWithDuration() {
VaultTokenRequest tokenRequest = VaultTokenRequest.builder()
.ttl(Duration.ofSeconds(10)).explicitMaxTtl(Duration.ofSeconds(20))
.build();
assertThat(tokenRequest.getTtl()).isEqualTo("10s");
assertThat(tokenRequest.getExplicitMaxTtl()).isEqualTo("20s");
}
}