TOKEN_SERVICE_ENABLED_SETTING enabled if HTTP_SSL_ENABLED (elastic/x-pack-elasticsearch#2321)

`authc.token.enabled` is true unless `http.ssl.enabled` is `false` and `http.enabled` is `true`.

* TokenService default enabled if HTTP_ENABLED == false

* Fixed tests that need TokenService explicitly enabled

* [DOC] Default value for `xpack.security.authc.token.enabled`

Original commit: elastic/x-pack-elasticsearch@bd154d16eb
This commit is contained in:
Albert Zaharovits 2017-08-23 13:21:30 +03:00 committed by GitHub
parent de6c275dca
commit 026729e911
11 changed files with 74 additions and 29 deletions

View File

@ -143,6 +143,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant ->
integTestCluster {
plugin ':x-pack-elasticsearch:plugin'
setting 'xpack.security.authc.token.enabled', 'true'
setupCommand 'setupTestAdmin',
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'x-pack-test-password', '-r', 'superuser'
waitCondition = waitWithAuth

View File

@ -72,7 +72,9 @@ You can set the following token service settings in
`elasticsearch.yml`.
`xpack.security.authc.token.enabled`::
Set to `false` to disable the built-in token service. Defaults to `true`.
Set to `false` to disable the built-in token service. Defaults to `true` unless
`xpack.security.http.ssl.enabled` is `false` and `http.enabled` is `true`.
This prevents sniffing the token from a connection over plain http.
`xpack.security.authc.token.passphrase`::
A secure passphrase that must be the same on each node and greater than

View File

@ -204,6 +204,7 @@ integTestCluster {
setting 'xpack.monitoring.exporters._local.type', 'local'
setting 'xpack.monitoring.exporters._local.enabled', 'false'
setting 'xpack.monitoring.collection.interval', '-1'
setting 'xpack.security.authc.token.enabled', 'true'
keystoreSetting 'bootstrap.password', 'x-pack-test-password'
keystoreSetting 'xpack.security.authc.token.passphrase', 'x-pack-token-service-password'
distribution = 'zip' // this is important since we use the reindex module in ML

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.xpack.security.Security;
@ -79,8 +80,13 @@ public class XPackSettings {
true, Setting.Property.NodeScope);
/** Setting for enabling or disabling the token service. Defaults to true */
public static final Setting<Boolean> TOKEN_SERVICE_ENABLED_SETTING = Setting.boolSetting("xpack.security.authc.token.enabled", true,
Setting.Property.NodeScope);
public static final Setting<Boolean> TOKEN_SERVICE_ENABLED_SETTING = Setting.boolSetting("xpack.security.authc.token.enabled", (s) -> {
if (NetworkModule.HTTP_ENABLED.get(s)) {
return XPackSettings.HTTP_SSL_ENABLED.getRaw(s);
} else {
return Boolean.TRUE.toString();
}
}, Setting.Property.NodeScope);
/*
* SSL settings. These are the settings that are specifically registered for SSL. Many are private as we do not explicitly use them

View File

@ -6,11 +6,10 @@
package org.elasticsearch.xpack.security;
import org.elasticsearch.bootstrap.BootstrapCheck;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.XPackSettings;
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
/**
* Bootstrap check to ensure that the user has enabled HTTPS when using the token service
*/
@ -24,12 +23,16 @@ final class TokenSSLBootstrapCheck implements BootstrapCheck {
@Override
public boolean check() {
return XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.get(settings) && HTTP_SSL_ENABLED.get(settings) == false;
if (NetworkModule.HTTP_ENABLED.get(settings)) {
return XPackSettings.HTTP_SSL_ENABLED.get(settings) == false && XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.get(settings);
}
return false;
}
@Override
public String errorMessage() {
return "HTTPS is required in order to use the token service. Please enable HTTPS using the [" + HTTP_SSL_ENABLED.getKey() +
"] setting or disable the token service using the [" + XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey() + "] setting.";
return "HTTPS is required in order to use the token service. Please enable HTTPS using the [" +
XPackSettings.HTTP_SSL_ENABLED.getKey() + "] setting or disable the token service using the [" +
XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey() + "] setting.";
}
}

View File

@ -20,7 +20,8 @@ public class TokenPassphraseBootstrapCheckTests extends ESTestCase {
assertFalse(new TokenPassphraseBootstrapCheck(Settings.EMPTY).check());
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("foo", "bar"); // leniency in setSecureSettings... if its empty it's skipped
Settings settings = Settings.builder().setSecureSettings(secureSettings).build();
Settings settings = Settings.builder()
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).setSecureSettings(secureSettings).build();
assertFalse(new TokenPassphraseBootstrapCheck(settings).check());
secureSettings.setString(TokenService.TOKEN_PASSPHRASE.getKey(), randomAlphaOfLengthBetween(MINIMUM_PASSPHRASE_LENGTH, 30));
@ -31,7 +32,8 @@ public class TokenPassphraseBootstrapCheckTests extends ESTestCase {
}
public void testTokenPassphraseCheckServiceDisabled() throws Exception {
Settings settings = Settings.builder().put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false).build();
Settings settings = Settings.builder().put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false)
.put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true).build();
assertFalse(new TokenPassphraseBootstrapCheck(settings).check());
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("foo", "bar"); // leniency in setSecureSettings... if its empty it's skipped
@ -40,11 +42,10 @@ public class TokenPassphraseBootstrapCheckTests extends ESTestCase {
secureSettings.setString(TokenService.TOKEN_PASSPHRASE.getKey(), randomAlphaOfLengthBetween(1, 30));
assertFalse(new TokenPassphraseBootstrapCheck(settings).check());
}
public void testTokenPassphraseCheckAfterSecureSettingsClosed() throws Exception {
Settings settings = Settings.builder().put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
Settings settings = Settings.builder().put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true).build();
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("foo", "bar"); // leniency in setSecureSettings... if its empty it's skipped
settings = Settings.builder().put(settings).setSecureSettings(secureSettings).build();

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.security;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.XPackSettings;
@ -14,15 +15,29 @@ public class TokenSSLBootsrapCheckTests extends ESTestCase {
public void testTokenSSLBootstrapCheck() {
Settings settings = Settings.EMPTY;
assertTrue(new TokenSSLBootstrapCheck(settings).check());
assertFalse(new TokenSSLBootstrapCheck(settings).check());
settings = Settings.builder().put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false).build();
settings = Settings.builder()
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
assertFalse(new TokenSSLBootstrapCheck(settings).check());
settings = Settings.builder().put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true).build();
assertFalse(new TokenSSLBootstrapCheck(settings).check());
settings = Settings.builder().put(XPackSettings.HTTP_SSL_ENABLED.getKey(), false).build();
// XPackSettings.HTTP_SSL_ENABLED default false
settings = Settings.builder().put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
assertTrue(new TokenSSLBootstrapCheck(settings).check());
settings = Settings.builder()
.put(XPackSettings.HTTP_SSL_ENABLED.getKey(), false)
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
assertTrue(new TokenSSLBootstrapCheck(settings).check());
settings = Settings.builder()
.put(XPackSettings.HTTP_SSL_ENABLED.getKey(), false)
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true)
.put(NetworkModule.HTTP_ENABLED.getKey(), false).build();
assertFalse(new TokenSSLBootstrapCheck(settings).check());
}
}

View File

@ -46,6 +46,7 @@ import org.elasticsearch.threadpool.FixedExecutorBuilder;
import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
@ -121,6 +122,7 @@ public class AuthenticationServiceTests extends ESTestCase {
Settings settings = Settings.builder()
.put("path.home", createTempDir())
.put("node.name", "authc_test")
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true)
.build();
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.allowedRealmType()).thenReturn(XPackLicenseState.AllowedRealmType.ALL);

View File

@ -18,6 +18,7 @@ import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.action.token.CreateTokenResponse;
import org.elasticsearch.xpack.security.action.token.InvalidateTokenResponse;
@ -44,6 +45,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
.put(TokenService.TOKEN_EXPIRATION.getKey(), TimeValue.timeValueSeconds(1L))
.put(TokenService.DELETE_INTERVAL.getKey(), TimeValue.timeValueSeconds(1L))
.put(TokenService.DELETE_TIMEOUT.getKey(), TimeValue.timeValueSeconds(2L))
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true)
.build();
}

View File

@ -31,7 +31,6 @@ import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.security.authc.TokenService.BytesKey;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.support.clock.ClockMock;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@ -56,14 +55,17 @@ public class TokenServiceTests extends ESTestCase {
private InternalClient internalClient;
private static ThreadPool threadPool;
private static final Settings settings = Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "TokenServiceTests").build();
private static final Settings settings = Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "TokenServiceTests")
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
private Client client;
private SecurityLifecycleService lifecycleService;
private ClusterService clusterService;
private Settings tokenServiceEnabledSettings = Settings.builder()
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
@Before
public void setupClient() {
public void setupClient() throws GeneralSecurityException {
client = mock(Client.class);
internalClient = new InternalClient(settings, threadPool, client);
lifecycleService = mock(SecurityLifecycleService.class);
@ -93,7 +95,8 @@ public class TokenServiceTests extends ESTestCase {
}
public void testAttachAndGetToken() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -110,7 +113,7 @@ public class TokenServiceTests extends ESTestCase {
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
// verify a second separate token service with its own salt can also verify
TokenService anotherService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService
, clusterService);
anotherService.refreshMetaData(tokenService.getTokenMetaData());
PlainActionFuture<UserToken> future = new PlainActionFuture<>();
@ -121,7 +124,8 @@ public class TokenServiceTests extends ESTestCase {
}
public void testRotateKey() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -167,12 +171,13 @@ public class TokenServiceTests extends ESTestCase {
}
public void testKeyExchange() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
int numRotations = 0;randomIntBetween(1, 5);
for (int i = 0; i < numRotations; i++) {
rotateKeys(tokenService);
}
TokenService otherTokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService,
TokenService otherTokenService = new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService,
clusterService);
otherTokenService.refreshMetaData(tokenService.getTokenMetaData());
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
@ -201,7 +206,8 @@ public class TokenServiceTests extends ESTestCase {
}
public void testPruneKeys() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -257,7 +263,8 @@ public class TokenServiceTests extends ESTestCase {
}
public void testPassphraseWorks() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -286,7 +293,8 @@ public class TokenServiceTests extends ESTestCase {
public void testInvalidatedToken() throws Exception {
when(lifecycleService.isSecurityIndexAvailable()).thenReturn(true);
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -323,7 +331,7 @@ public class TokenServiceTests extends ESTestCase {
public void testTokenExpiry() throws Exception {
ClockMock clock = ClockMock.frozen();
TokenService tokenService = new TokenService(Settings.EMPTY, clock, internalClient, lifecycleService, clusterService);
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, clock, internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
@ -426,7 +434,8 @@ public class TokenServiceTests extends ESTestCase {
}
public void testIndexNotAvailable() throws Exception {
TokenService tokenService = new TokenService(Settings.EMPTY, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
TokenService tokenService =
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
final UserToken token = tokenService.createUserToken(authentication);
assertNotNull(token);
@ -454,7 +463,7 @@ public class TokenServiceTests extends ESTestCase {
"J1fxg/JZNQDPufePg1GxV/RAQm2Gr8mYAelijEVlWIdYaQ3R76U+P/w6Q1v90dGVZQn6DKMOfgmkfwAFNY";
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString(TokenService.TOKEN_PASSPHRASE.getKey(), "xpack_token_passpharse");
Settings settings = Settings.builder().setSecureSettings(secureSettings).build();
Settings settings = Settings.builder().put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true).setSecureSettings(secureSettings).build();
TokenService tokenService = new TokenService(settings, Clock.systemUTC(), internalClient, lifecycleService, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
ThreadContext requestContext = new ThreadContext(Settings.EMPTY);

View File

@ -122,6 +122,7 @@ subprojects {
clusterName = 'rolling-upgrade'
waitCondition = waitWithAuth
setting 'xpack.security.transport.ssl.enabled', 'true'
setting 'xpack.security.authc.token.enabled', 'true'
setting 'xpack.ssl.keystore.path', 'testnode.jks'
setting 'xpack.ssl.keystore.password', 'testnode'
dependsOn copyTestNodeKeystore
@ -161,6 +162,7 @@ subprojects {
setting 'xpack.ssl.keystore.path', 'testnode.jks'
keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode'
setting 'node.attr.upgraded', 'first'
setting 'xpack.security.authc.token.enabled', 'true'
dependsOn copyTestNodeKeystore
extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks')
if (withSystemKey) {
@ -190,6 +192,7 @@ subprojects {
waitCondition = waitWithAuth
setting 'xpack.ssl.keystore.path', 'testnode.jks'
keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode'
setting 'xpack.security.authc.token.enabled', 'true'
dependsOn copyTestNodeKeystore
extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks')
if (withSystemKey) {