Extract common base class for LifecycleAwareSessionManager.

See gh-159.
This commit is contained in:
Mark Paluch
2018-01-16 14:54:17 +01:00
parent ca874a6a31
commit 0710ae838a
4 changed files with 389 additions and 253 deletions

View File

@@ -16,24 +16,15 @@
package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.http.HttpEntity;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.vault.VaultException;
@@ -46,41 +37,35 @@ import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestOperations;
/**
* Lifecycle-aware Session Manager. This {@link SessionManager} obtains tokens from a
* {@link ClientAuthentication} upon {@link #getSessionToken() request}. Tokens are
* renewed asynchronously if a token has a lease duration. This happens 5 seconds before
* the token expires, see {@link #REFRESH_PERIOD_BEFORE_EXPIRY}.
* Lifecycle-aware {@link SessionManager Session Manager}. This {@link SessionManager}
* obtains tokens from a {@link ClientAuthentication} upon {@link #getSessionToken()
* request} synchronizing multiple threads attempting to obtain a token concurrently.
* <p>
* Tokens are renewed asynchronously if a token has a lease duration. This happens 5
* seconds before the token expires, see {@link #REFRESH_PERIOD_BEFORE_EXPIRY}.
* <p>
* This {@link SessionManager} also implements {@link DisposableBean} to revoke the
* {@link LoginToken} once it's not required anymore. Token revocation will stop regular
* token refresh. Tokens are only revoked only if the associated
* {@link ClientAuthentication} returned a {@link LoginToken}.
* {@link ClientAuthentication} returns a {@link LoginToken}.
* <p>
* If Token renewal runs into a client-side error, it assumes the token was
* revoked/expired and discards the token state so the next attempt will lead to another
* revoked/expired. It discards the token state so the next attempt will lead to another
* login attempt.
* <p>
* By default, {@link VaultToken} are looked up in Vault to determine renewability and the
* remaining TTL, see {@link #setTokenSelfLookupEnabled(boolean)}.
* <p>
* This class is thread-safe.
*
* @author Mark Paluch
* @author Steven Swor
* @see LoginToken
* @see SessionManager
* @see AsyncTaskExecutor
* @see TaskScheduler
*/
public class LifecycleAwareSessionManager implements SessionManager, DisposableBean {
/**
* Refresh 5 seconds before the token expires.
*/
public static final int REFRESH_PERIOD_BEFORE_EXPIRY = 5;
private static final RefreshTrigger DEFAULT_TRIGGER = new FixedTimeoutRefreshTrigger(
REFRESH_PERIOD_BEFORE_EXPIRY, TimeUnit.SECONDS);
private static final Log logger = LogFactory
.getLog(LifecycleAwareSessionManager.class);
public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSupport
implements SessionManager, DisposableBean {
/**
* Client authentication mechanism. Used to obtain a {@link VaultToken} or
@@ -93,27 +78,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
*/
private final RestOperations restOperations;
/**
* Threading infrastructure for token renewal/refresh.
*/
private final TaskScheduler taskScheduler;
/**
* Trigger to calculate the next renewal time.
*/
private final RefreshTrigger refreshTrigger;
private final Object lock = new Object();
/**
* Controls whether to perform a token self-lookup using
* {@code auth/token/lookup-self} for {@link VaultToken}s obtained from a
* {@link ClientAuthentication}. Self-lookup determines whether a token is renewable
* and its TTL. Self lookup is skipped for {@link LoginToken}. Self-lookup requests
* decrement token usage count by one. Skipped for {@link LoginToken}.
*/
private boolean tokenSelfLookupEnabled = true;
/**
* The token state: Contains the currently valid token that identifies the Vault
* session.
@@ -122,21 +88,29 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
/**
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication},
* {@link AsyncTaskExecutor} and {@link RestOperations}.
* {@link TaskScheduler} and {@link RestOperations}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
* @param restOperations must not be {@literal null}.
* @since 1.0.1
*/
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication,
TaskScheduler taskScheduler, RestOperations restOperations) {
this(clientAuthentication, taskScheduler, restOperations, DEFAULT_TRIGGER);
super(taskScheduler);
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
this.clientAuthentication = clientAuthentication;
this.restOperations = restOperations;
}
/**
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication},
* {@link AsyncTaskExecutor} and {@link RestOperations}.
* {@link TaskScheduler} and {@link RestOperations}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
@@ -148,6 +122,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
TaskScheduler taskScheduler, RestOperations restOperations,
RefreshTrigger refreshTrigger) {
super(taskScheduler, refreshTrigger);
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -155,39 +131,6 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
this.clientAuthentication = clientAuthentication;
this.restOperations = restOperations;
this.taskScheduler = taskScheduler;
this.refreshTrigger = refreshTrigger;
}
/**
* Returns whether token self-lookup is enabled to augment {@link VaultToken} obtained
* from a {@link ClientAuthentication}. Self-lookup determines whether a token is
* renewable and its TTL. Self lookup is skipped for {@link LoginToken}. Self-lookup
* requests decrement token usage count by one. Skipped for {@link LoginToken}.
* <p/>
* Self-lookup for tokens without a permission to access
* {@code auth/token/lookup-self} will fail gracefully and continue without token
* renewal.
*
* @return {@literal true} to enable self-lookup, {@literal false} to disable
* self-lookup. Enabled by default.
* @since 2.0
*/
public boolean isTokenSelfLookupEnabled() {
return tokenSelfLookupEnabled;
}
/**
* Enables/disables token self-lookup. Self-lookup augments {@link VaultToken}
* obtained from a {@link ClientAuthentication}. Self-lookup determines whether a
* token is renewable and its TTL.
*
* @param tokenSelfLookupEnabled {@literal true} to enable self-lookup,
* {@literal false} to disable self-lookup. Enabled by default.
* @since 2.0
*/
public void setTokenSelfLookupEnabled(boolean tokenSelfLookupEnabled) {
this.tokenSelfLookupEnabled = tokenSelfLookupEnabled;
}
@Override
@@ -247,7 +190,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
LoginToken renewed = LoginTokenUtil.from(vaultResponse.getRequiredAuth());
Duration validTtlThreshold = refreshTrigger.getValidTtlThreshold(renewed);
Duration validTtlThreshold = getRefreshTrigger()
.getValidTtlThreshold(renewed);
if (renewed.getLeaseDuration().compareTo(validTtlThreshold) <= 0) {
if (logger.isDebugEnabled()) {
@@ -348,161 +292,33 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
logger.info("Scheduling Token renewal");
final Runnable task = new Runnable() {
@Override
public void run() {
try {
if (LifecycleAwareSessionManager.this.token.isPresent()
&& isTokenRenewable()) {
if (renewToken()) {
scheduleRenewal();
}
Runnable task = () -> {
try {
if (LifecycleAwareSessionManager.this.token.isPresent()
&& isTokenRenewable()) {
if (renewToken()) {
scheduleRenewal();
}
}
catch (Exception e) {
logger.error("Cannot renew VaultToken", e);
}
}
catch (Exception e) {
logger.error("Cannot renew VaultToken", e);
}
};
Optional<TokenWrapper> token = this.token;
token.ifPresent(tokenWrapper -> taskScheduler.schedule(task,
token.ifPresent(tokenWrapper -> getTaskScheduler().schedule(task,
createTrigger(tokenWrapper)));
}
private OneShotTrigger createTrigger(TokenWrapper tokenWrapper) {
return new OneShotTrigger(
refreshTrigger.nextExecutionTime((LoginToken) tokenWrapper.getToken()));
getRefreshTrigger().nextExecutionTime(
(LoginToken) tokenWrapper.getToken()));
}
/**
* This one-shot trigger creates only one execution time to trigger an execution only
* once.
*/
@RequiredArgsConstructor
private static class OneShotTrigger implements Trigger {
private final AtomicBoolean fired = new AtomicBoolean();
private final Date nextExecutionTime;
@Nullable
public Date nextExecutionTime(TriggerContext triggerContext) {
if (fired.compareAndSet(false, true)) {
return nextExecutionTime;
}
return null;
}
}
/**
* Common interface for trigger objects that determine the next execution time of a
* refresh task.
*/
public interface RefreshTrigger {
/**
* Determine the next execution time according to the given trigger context.
*
* @param loginToken login token encapsulating renewability and lease duration.
* @return the next execution time as defined by the trigger, or {@code null} if
* the trigger won't fire anymore
*/
Date nextExecutionTime(LoginToken loginToken);
/**
* Returns the minimum TTL duration to consider a token valid after renewal.
* Tokens with a shorter TTL are revoked and considered expired.
*
* @param loginToken the login token after renewal.
* @return minimum TTL {@link Duration} to consider a token valid.
* @since 2.0
*/
Duration getValidTtlThreshold(LoginToken loginToken);
}
/**
* {@link RefreshTrigger} implementation using a fixed timeout to schedule renewal
* before a {@link LoginToken} expires.
*
* @author Mark Paluch
* @since 1.0.1
*/
public static class FixedTimeoutRefreshTrigger implements RefreshTrigger {
private static final Duration ONE_SECOND = Duration.ofSeconds(1);
private final Duration duration;
private final Duration validTtlThreshold;
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires
*
* @param timeout timeout value, non-negative long value.
* @param timeUnit must not be {@literal null}.
*/
public FixedTimeoutRefreshTrigger(long timeout, TimeUnit timeUnit) {
Assert.isTrue(timeout >= 0,
"Timeout duration must be greater or equal to zero");
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.duration = Duration.ofMillis(timeUnit.toMillis(timeout));
this.validTtlThreshold = Duration.ofMillis(timeUnit.toMillis(timeout) + 2000);
}
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires. Valid TTL threshold is
* set to two seconds longer to compensate for timing issues during scheduling.
*
* @param timeout timeout value.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout) {
this(timeout, timeout.plus(Duration.ofSeconds(2)));
}
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires.
*
* @param timeout timeout value.
* @param validTtlThreshold minimum TTL duration to consider a Token as valid.
* Tokens with a shorter TTL are not used anymore. Should be greater than
* {@code timeout} to prevent token expiry.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout, Duration validTtlThreshold) {
Assert.isTrue(timeout.toMillis() >= 0,
"Timeout duration must be greater or equal to zero");
Assert.notNull(validTtlThreshold, "Valid TTL threshold must not be null");
this.duration = timeout;
this.validTtlThreshold = validTtlThreshold;
}
@Override
public Date nextExecutionTime(LoginToken loginToken) {
long milliseconds = Math.max(ONE_SECOND.toMillis(), loginToken
.getLeaseDuration().toMillis() - duration.toMillis());
return new Date(System.currentTimeMillis() + milliseconds);
}
@Override
public Duration getValidTtlThreshold(LoginToken loginToken) {
return validTtlThreshold;
}
}
/**
* Wraps a {@link VaultToken} and specifies whether the token is revocable on factory

View File

@@ -0,0 +1,289 @@
/*
* Copyright 2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.RequiredArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.util.Assert;
import org.springframework.vault.support.VaultToken;
/**
* Support class to build Lifecycle-aware Session Manager implementations, defining common
* properties such as the {@link TaskScheduler} and {@link RefreshTrigger}. Typically used
* within the framework itself.
* <p>
* Not intended to be used directly.
*
* @author Mark Paluch
* @since 2.0
*/
public abstract class LifecycleAwareSessionManagerSupport {
/**
* Refresh 5 seconds before the token expires.
*/
public static final int REFRESH_PERIOD_BEFORE_EXPIRY = 5;
private static final RefreshTrigger DEFAULT_TRIGGER = new FixedTimeoutRefreshTrigger(
REFRESH_PERIOD_BEFORE_EXPIRY, TimeUnit.SECONDS);
/**
* Logger available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* Threading infrastructure for token renewal/refresh.
*/
private final TaskScheduler taskScheduler;
/**
* Trigger to calculate the next renewal time.
*/
private final RefreshTrigger refreshTrigger;
/**
* Controls whether to perform a token self-lookup using
* {@code auth/token/lookup-self} for {@link VaultToken}s obtained from a
* {@link ClientAuthentication}. Self-lookup determines whether a token is renewable
* and its TTL. Self lookup is skipped for {@link LoginToken}. Self-lookup requests
* decrement token usage count by one. Skipped for {@link LoginToken}.
*/
private boolean tokenSelfLookupEnabled = true;
/**
* Create a {@link LifecycleAwareSessionManager} given {@link TaskScheduler}. Using
* {@link #DEFAULT_TRIGGER} to trigger refresh.
*
* @param taskScheduler must not be {@literal null}.
*/
public LifecycleAwareSessionManagerSupport(TaskScheduler taskScheduler) {
this(taskScheduler, DEFAULT_TRIGGER);
}
/**
* Create a {@link LifecycleAwareSessionManager} given {@link TaskScheduler} and
* {@link RefreshTrigger}.
*
* @param taskScheduler must not be {@literal null}.
* @param refreshTrigger must not be {@literal null}.
*/
public LifecycleAwareSessionManagerSupport(TaskScheduler taskScheduler,
RefreshTrigger refreshTrigger) {
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
Assert.notNull(refreshTrigger, "RefreshTrigger must not be null");
this.taskScheduler = taskScheduler;
this.refreshTrigger = refreshTrigger;
}
/**
* Returns whether token self-lookup is enabled to augment {@link VaultToken} obtained
* from a {@link ClientAuthentication}. Self-lookup determines whether a token is
* renewable and its TTL. Self lookup is skipped for {@link LoginToken}. Self-lookup
* requests decrement token usage count by one. Skipped for {@link LoginToken}.
* <p>
* Self-lookup for tokens without a permission to access
* {@code auth/token/lookup-self} will fail gracefully and continue without token
* renewal.
*
* @return {@literal true} to enable self-lookup, {@literal false} to disable
* self-lookup. Enabled by default.
*/
protected boolean isTokenSelfLookupEnabled() {
return tokenSelfLookupEnabled;
}
/**
* Enables/disables token self-lookup. Self-lookup augments {@link VaultToken}
* obtained from a {@link ClientAuthentication}. Self-lookup determines whether a
* token is renewable and its TTL.
*
* @param tokenSelfLookupEnabled {@literal true} to enable self-lookup,
* {@literal false} to disable self-lookup. Enabled by default.
*/
public void setTokenSelfLookupEnabled(boolean tokenSelfLookupEnabled) {
this.tokenSelfLookupEnabled = tokenSelfLookupEnabled;
}
/**
* @return the underlying {@link TaskScheduler}.
*/
protected TaskScheduler getTaskScheduler() {
return taskScheduler;
}
/**
* @return the underlying {@link RefreshTrigger}.
*/
protected RefreshTrigger getRefreshTrigger() {
return refreshTrigger;
}
/**
* Check whether the Token falls below its
* {@link RefreshTrigger#getValidTtlThreshold(LoginToken) validity threshold}.
* Typically used to discard a token.
*
* @param loginToken must not be {@literal null}.
* @return {@literal true} if token validity falls below validity threshold,
* {@literal false} if still valid.
*/
protected boolean isExpired(LoginToken loginToken) {
Duration validTtlThreshold = getRefreshTrigger().getValidTtlThreshold(loginToken);
return loginToken.getLeaseDuration().compareTo(validTtlThreshold) <= 0;
}
/**
* This one-shot trigger creates only one execution time to trigger an execution only
* once.
*/
@RequiredArgsConstructor
static class OneShotTrigger implements Trigger {
private final AtomicBoolean fired = new AtomicBoolean();
private final Date nextExecutionTime;
@Nullable
public Date nextExecutionTime(TriggerContext triggerContext) {
if (fired.compareAndSet(false, true)) {
return nextExecutionTime;
}
return null;
}
}
/**
* Common interface for trigger objects that determine the next execution time of a
* refresh task.
*/
public interface RefreshTrigger {
/**
* Determine the next execution time according to the given trigger context.
*
* @param loginToken login token encapsulating renewability and lease duration.
* @return the next execution time as defined by the trigger, or {@code null} if
* the trigger won't fire anymore
*/
Date nextExecutionTime(LoginToken loginToken);
/**
* Returns the minimum TTL duration to consider a token valid after renewal.
* Tokens with a shorter TTL are revoked and considered expired.
*
* @param loginToken the login token after renewal.
* @return minimum TTL {@link Duration} to consider a token valid.
* @since 2.0
*/
Duration getValidTtlThreshold(LoginToken loginToken);
}
/**
* {@link RefreshTrigger} implementation using a fixed timeout to schedule renewal
* before a {@link LoginToken} expires.
*
* @author Mark Paluch
* @since 1.0.1
*/
public static class FixedTimeoutRefreshTrigger implements RefreshTrigger {
private static final Duration ONE_SECOND = Duration.ofSeconds(1);
private final Duration duration;
private final Duration validTtlThreshold;
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires
*
* @param timeout timeout value, non-negative long value.
* @param timeUnit must not be {@literal null}.
*/
public FixedTimeoutRefreshTrigger(long timeout, TimeUnit timeUnit) {
Assert.isTrue(timeout >= 0,
"Timeout duration must be greater or equal to zero");
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.duration = Duration.ofMillis(timeUnit.toMillis(timeout));
this.validTtlThreshold = Duration.ofMillis(timeUnit.toMillis(timeout) + 2000);
}
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires. Valid TTL threshold is
* set to two seconds longer to compensate for timing issues during scheduling.
*
* @param timeout timeout value.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout) {
this(timeout, timeout.plus(Duration.ofSeconds(2)));
}
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires.
*
* @param timeout timeout value.
* @param validTtlThreshold minimum TTL duration to consider a Token as valid.
* Tokens with a shorter TTL are not used anymore. Should be greater than
* {@code timeout} to prevent token expiry.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout, Duration validTtlThreshold) {
Assert.isTrue(timeout.toMillis() >= 0,
"Timeout duration must be greater or equal to zero");
Assert.notNull(validTtlThreshold, "Valid TTL threshold must not be null");
this.duration = timeout;
this.validTtlThreshold = validTtlThreshold;
}
@Override
public Date nextExecutionTime(LoginToken loginToken) {
long milliseconds = Math.max(ONE_SECOND.toMillis(), loginToken
.getLeaseDuration().toMillis() - duration.toMillis());
return new Date(System.currentTimeMillis() + milliseconds);
}
@Override
public Duration getValidTtlThreshold(LoginToken loginToken) {
return validTtlThreshold;
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.vault.authentication.LifecycleAwareSessionManagerSupport.FixedTimeoutRefreshTrigger;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link LifecycleAwareSessionManagerSupport} .
*
* @author Mark Paluch
*/
public class LifecycleAwareSessionManagerSupportUnitTests {
@Test
public void shouldScheduleNextExecutionTimeCorrectly() {
FixedTimeoutRefreshTrigger trigger = new FixedTimeoutRefreshTrigger(5,
TimeUnit.SECONDS);
Date nextExecutionTime = trigger.nextExecutionTime(LoginToken.of(
"foo".toCharArray(), Duration.ofMinutes(1)));
assertThat(nextExecutionTime).isBetween(
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(52)),
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(56)));
}
@Test
public void shouldScheduleNextExecutionIfValidityLessThanTimeout() {
FixedTimeoutRefreshTrigger trigger = new FixedTimeoutRefreshTrigger(5,
TimeUnit.SECONDS);
Date nextExecutionTime = trigger.nextExecutionTime(LoginToken.of(
"foo".toCharArray(), Duration.ofSeconds(2)));
assertThat(nextExecutionTime).isBetween(
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(0)),
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(2)));
}
}

View File

@@ -17,10 +17,8 @@ package org.springframework.vault.authentication;
import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +34,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.vault.authentication.LifecycleAwareSessionManager.FixedTimeoutRefreshTrigger;
import org.springframework.vault.client.VaultHttpHeaders;
import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultToken;
@@ -333,32 +330,6 @@ public class LifecycleAwareSessionManagerUnitTests {
verify(clientAuthentication, times(1)).login();
}
@Test
public void shouldScheduleNextExecutionTimeCorrectly() {
FixedTimeoutRefreshTrigger trigger = new FixedTimeoutRefreshTrigger(5,
TimeUnit.SECONDS);
Date nextExecutionTime = trigger.nextExecutionTime(LoginToken.of(
"foo".toCharArray(), Duration.ofMinutes(1)));
assertThat(nextExecutionTime).isBetween(
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(52)),
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(56)));
}
@Test
public void shouldScheduleNextExecutionIfValidityLessThanTimeout() {
FixedTimeoutRefreshTrigger trigger = new FixedTimeoutRefreshTrigger(5,
TimeUnit.SECONDS);
Date nextExecutionTime = trigger.nextExecutionTime(LoginToken.of(
"foo".toCharArray(), Duration.ofSeconds(2)));
assertThat(nextExecutionTime).isBetween(
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(0)),
new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(2)));
}
private static VaultResponse fromToken(LoginToken loginToken) {
Map<String, Object> auth = new HashMap<>();