From 0710ae838aaa3941af449ca20399046bc001369f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 16 Jan 2018 14:54:17 +0100 Subject: [PATCH] Extract common base class for LifecycleAwareSessionManager. See gh-159. --- .../LifecycleAwareSessionManager.java | 264 +++------------- .../LifecycleAwareSessionManagerSupport.java | 289 ++++++++++++++++++ ...leAwareSessionManagerSupportUnitTests.java | 60 ++++ ...LifecycleAwareSessionManagerUnitTests.java | 29 -- 4 files changed, 389 insertions(+), 253 deletions(-) create mode 100644 spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupport.java create mode 100644 spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupportUnitTests.java diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java index 1d7c873a..70a6bedf 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java @@ -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. + *

+ * 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}. *

* 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}. *

* 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. *

* By default, {@link VaultToken} are looked up in Vault to determine renewability and the * remaining TTL, see {@link #setTokenSelfLookupEnabled(boolean)}. + *

+ * 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}. - *

- * 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 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 diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupport.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupport.java new file mode 100644 index 00000000..4111427c --- /dev/null +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupport.java @@ -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. + *

+ * 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}. + *

+ * 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; + } + } +} diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupportUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupportUnitTests.java new file mode 100644 index 00000000..2867630b --- /dev/null +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerSupportUnitTests.java @@ -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))); + } +} diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerUnitTests.java index 804288df..f89ce722 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/LifecycleAwareSessionManagerUnitTests.java @@ -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 auth = new HashMap<>();