diff --git a/server/src/main/java/org/elasticsearch/common/settings/Setting.java b/server/src/main/java/org/elasticsearch/common/settings/Setting.java index fe847ea591392..aa53efb7f5779 100644 --- a/server/src/main/java/org/elasticsearch/common/settings/Setting.java +++ b/server/src/main/java/org/elasticsearch/common/settings/Setting.java @@ -1367,6 +1367,12 @@ public static Setting timeSetting( return new Setting<>(simpleKey, s -> defaultValue.apply(s).getStringRep(), minTimeValueParser(key, minValue), properties); } + public static Setting timeSetting( + final String key, TimeValue defaultValue, final TimeValue minValue, final TimeValue maxValue, final Property... properties) { + final SimpleKey simpleKey = new SimpleKey(key); + return new Setting<>(simpleKey, s -> defaultValue.getStringRep(), minMaxTimeValueParser(key, minValue, maxValue), properties); + } + private static Function minTimeValueParser(final String key, final TimeValue minValue) { return s -> { final TimeValue value = TimeValue.parseTimeValue(s, null, key); @@ -1383,6 +1389,22 @@ private static Function minTimeValueParser(final String key, }; } + private static Function minMaxTimeValueParser(final String key, final TimeValue minValue, final TimeValue maxValue) { + return s -> { + final TimeValue value = minTimeValueParser(key, minValue).apply(s); + if (value.millis() > maxValue.millis()) { + final String message = String.format( + Locale.ROOT, + "failed to parse value [%s] for setting [%s], must be <= [%s]", + s, + key, + maxValue.getStringRep()); + throw new IllegalArgumentException(message); + } + return value; + }; + } + public static Setting timeSetting(String key, TimeValue defaultValue, TimeValue minValue, Property... properties) { return timeSetting(key, (s) -> defaultValue, minValue, properties); } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java index b8e40fa6803df..b951b90ce698d 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java @@ -161,7 +161,7 @@ public final class TokenService extends AbstractComponent { public static final Setting TOKEN_PASSPHRASE = SecureSetting.secureString("xpack.security.authc.token.passphrase", null, Property.Deprecated); public static final Setting TOKEN_EXPIRATION = Setting.timeSetting("xpack.security.authc.token.timeout", - TimeValue.timeValueMinutes(20L), TimeValue.timeValueSeconds(1L), Property.NodeScope); + TimeValue.timeValueMinutes(20L), TimeValue.timeValueSeconds(1L), TimeValue.timeValueHours(1L), Property.NodeScope); public static final Setting DELETE_INTERVAL = Setting.timeSetting("xpack.security.authc.token.delete.interval", TimeValue.timeValueMinutes(30L), Property.NodeScope); public static final Setting DELETE_TIMEOUT = Setting.timeSetting("xpack.security.authc.token.delete.timeout", diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java index e0cdfbbc0f6d9..21e29142b9871 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java @@ -81,6 +81,7 @@ import static java.time.Clock.systemUTC; import static org.elasticsearch.repositories.ESBlobStoreTestCase.randomBytes; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.Matchers.any; @@ -496,6 +497,29 @@ public void testComputeSecretKeyIsConsistent() throws Exception { assertArrayEquals(key.getEncoded(), key2.getEncoded()); } + public void testTokenExpiryConfig() { + TimeValue expiration = TokenService.TOKEN_EXPIRATION.get(tokenServiceEnabledSettings); + assertThat(expiration, equalTo(TimeValue.timeValueMinutes(20L))); + // Configure Minimum expiration + tokenServiceEnabledSettings = Settings.builder().put(TokenService.TOKEN_EXPIRATION.getKey(), "1s").build(); + expiration = TokenService.TOKEN_EXPIRATION.get(tokenServiceEnabledSettings); + assertThat(expiration, equalTo(TimeValue.timeValueSeconds(1L))); + // Configure Maximum expiration + tokenServiceEnabledSettings = Settings.builder().put(TokenService.TOKEN_EXPIRATION.getKey(), "60m").build(); + expiration = TokenService.TOKEN_EXPIRATION.get(tokenServiceEnabledSettings); + assertThat(expiration, equalTo(TimeValue.timeValueHours(1L))); + // Outside range should fail + tokenServiceEnabledSettings = Settings.builder().put(TokenService.TOKEN_EXPIRATION.getKey(), "1ms").build(); + IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, + () -> TokenService.TOKEN_EXPIRATION.get(tokenServiceEnabledSettings)); + assertThat(ile.getMessage(), + containsString("failed to parse value [1ms] for setting [xpack.security.authc.token.timeout], must be >= [1s]")); + tokenServiceEnabledSettings = Settings.builder().put(TokenService.TOKEN_EXPIRATION.getKey(), "120m").build(); + ile = expectThrows(IllegalArgumentException.class, () -> TokenService.TOKEN_EXPIRATION.get(tokenServiceEnabledSettings)); + assertThat(ile.getMessage(), + containsString("failed to parse value [120m] for setting [xpack.security.authc.token.timeout], must be <= [1h]")); + } + public void testTokenExpiry() throws Exception { ClockMock clock = ClockMock.frozen(); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, clock, client, securityIndex, clusterService);