From 609f742e5f5d788cc496381c867403f49d735363 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 29 Nov 2018 18:06:52 +1100 Subject: [PATCH] Fix kerberos setting registration (#35986) In #30241 Realm settings were changed, but the Kerberos realm settings were not registered correctly. This change fixes the registration of those Kerberos settings. Also adds a new integration test that ensures every internal realm can be configured in a test cluster. Also fixes the QA test for kerberos. Resolves: #35942 --- .../authc/InternalRealmsSettings.java | 2 + .../authc/kerberos/KerberosRealmSettings.java | 1 + .../xpack/security/authc/InternalRealms.java | 5 + .../authc/SecurityRealmSettingsTests.java | 119 ++++++++++++++++++ .../authc/saml/SamlRealmTestHelper.java | 14 +++ x-pack/qa/kerberos-tests/build.gradle | 12 +- 6 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/SecurityRealmSettingsTests.java diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/InternalRealmsSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/InternalRealmsSettings.java index 707912fb202..8b2ef184068 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/InternalRealmsSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/InternalRealmsSettings.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.core.security.authc; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.xpack.core.security.authc.esnative.NativeRealmSettings; import org.elasticsearch.xpack.core.security.authc.file.FileRealmSettings; +import org.elasticsearch.xpack.core.security.authc.kerberos.KerberosRealmSettings; import org.elasticsearch.xpack.core.security.authc.ldap.LdapRealmSettings; import org.elasticsearch.xpack.core.security.authc.pki.PkiRealmSettings; import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings; @@ -32,6 +33,7 @@ public final class InternalRealmsSettings { set.addAll(LdapRealmSettings.getSettings(LdapRealmSettings.LDAP_TYPE)); set.addAll(PkiRealmSettings.getSettings()); set.addAll(SamlRealmSettings.getSettings()); + set.addAll(KerberosRealmSettings.getSettings()); return Collections.unmodifiableSet(set); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/kerberos/KerberosRealmSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/kerberos/KerberosRealmSettings.java index 1b1d44d2d11..739b70427b1 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/kerberos/KerberosRealmSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/kerberos/KerberosRealmSettings.java @@ -53,6 +53,7 @@ public final class KerberosRealmSettings { final Set> settings = Sets.newHashSet(HTTP_SERVICE_KEYTAB_PATH, CACHE_TTL_SETTING, CACHE_MAX_USERS_SETTING, SETTING_KRB_DEBUG_ENABLE, SETTING_REMOVE_REALM_NAME); settings.addAll(DelegatedAuthorizationSettings.getSettings(TYPE)); + settings.addAll(RealmSettings.getStandardSettings(TYPE)); return settings; } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalRealms.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalRealms.java index 7cd4fa96aa4..54bffd8a215 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalRealms.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalRealms.java @@ -33,6 +33,7 @@ import org.elasticsearch.xpack.security.authc.support.RoleMappingFileBootstrapCh import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore; import org.elasticsearch.xpack.security.support.SecurityIndexManager; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -73,6 +74,10 @@ public final class InternalRealms { return ReservedRealm.TYPE.equals(type); } + static Collection getConfigurableRealmsTypes() { + return Collections.unmodifiableSet(XPACK_TYPES); + } + /** * Determines whether type is an internal realm-type that is provided by x-pack, * excluding the {@link ReservedRealm} and realms that have extensive interaction with diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/SecurityRealmSettingsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/SecurityRealmSettingsTests.java new file mode 100644 index 00000000000..202467147cd --- /dev/null +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/SecurityRealmSettingsTests.java @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.security.authc; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.SecurityIntegTestCase; +import org.elasticsearch.xpack.core.security.action.user.AuthenticateAction; +import org.elasticsearch.xpack.core.security.action.user.AuthenticateRequest; +import org.elasticsearch.xpack.core.security.action.user.AuthenticateResponse; +import org.elasticsearch.xpack.core.security.authc.Realm; +import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; +import org.elasticsearch.xpack.security.authc.kerberos.KerberosRealmTestCase; +import org.elasticsearch.xpack.security.authc.saml.SamlRealmTestHelper; +import org.hamcrest.Matchers; +import org.junit.AfterClass; + +import java.io.Closeable; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +/** + * An integration test that configures one of each realm type. + * This acts as a basic smoke test that every realm is supported, and can be configured. + */ +public class SecurityRealmSettingsTests extends SecurityIntegTestCase { + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + final Settings settings; + try { + final String samlIdpEntityId = "urn:idp:entity"; + final Path samlIdpPath = createTempFile("idp", "xml"); + SamlRealmTestHelper.writeIdpMetaData(samlIdpPath, samlIdpEntityId); + + final Path kerbKeyTab = createTempFile("es", "keytab"); + KerberosRealmTestCase.writeKeyTab(kerbKeyTab, null); + + settings = Settings.builder() + .put(super.nodeSettings(nodeOrdinal).filter(s -> s.startsWith("xpack.security.authc.realms.") == false)) + .put("xpack.security.authc.token.enabled", true) + .put("xpack.security.authc.realms.file.file1.order", 1) + .put("xpack.security.authc.realms.native.native1.order", 2) + .put("xpack.security.authc.realms.ldap.ldap1.order", 3) + .put("xpack.security.authc.realms.ldap.ldap1.url", "ldap://127.0.0.1:389") + .put("xpack.security.authc.realms.ldap.ldap1.user_dn_templates", "cn={0},dc=example,dc=com") + .put("xpack.security.authc.realms.active_directory.ad1.order", 4) + .put("xpack.security.authc.realms.active_directory.ad1.url", "ldap://127.0.0.1:389") + .put("xpack.security.authc.realms.pki.pki1.order", 5) + .put("xpack.security.authc.realms.saml.saml1.order", 6) + .put("xpack.security.authc.realms.saml.saml1.idp.metadata.path", samlIdpPath.toAbsolutePath()) + .put("xpack.security.authc.realms.saml.saml1.idp.entity_id", samlIdpEntityId) + .put("xpack.security.authc.realms.saml.saml1.sp.entity_id", "urn:sp:entity") + .put("xpack.security.authc.realms.saml.saml1.sp.acs", "http://localhost/acs") + .put("xpack.security.authc.realms.saml.saml1.attributes.principal", "uid") + .put("xpack.security.authc.realms.kerberos.kerb1.order", 7) + .put("xpack.security.authc.realms.kerberos.kerb1.keytab.path", kerbKeyTab.toAbsolutePath()) + .build(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + final Set configuredRealmTypes = RealmSettings.getRealmSettings(settings) + .keySet() + .stream() + .map(RealmConfig.RealmIdentifier::getType) + .collect(Collectors.toSet()); + assertThat("One or more realm type are not configured " + configuredRealmTypes, + configuredRealmTypes, Matchers.containsInAnyOrder(InternalRealms.getConfigurableRealmsTypes().toArray(Strings.EMPTY_ARRAY))); + + return settings; + } + + /** + * Some realms (currently only SAML, but maybe more in the future) hold on to resources that may need to be explicitly closed. + */ + @AfterClass + public static void closeRealms() throws IOException { + final Logger logger = LogManager.getLogger(SecurityRealmSettingsTests.class); + final Iterable realms = internalCluster().getInstances(Realms.class); + for (Realms rx : realms) { + for (Realm r : rx) { + if (r instanceof Closeable) { + logger.info("Closing realm [{}] [{} @ {}]", r, r.getClass().getSimpleName(), System.identityHashCode(r)); + ((Closeable) r).close(); + } + } + } + } + + /** + * Always enable transport SSL so that it is possible to have a PKI Realm + */ + protected boolean transportSSLEnabled() { + return true; + } + + public void testClusterStarted() { + final AuthenticateRequest request = new AuthenticateRequest(); + request.username(nodeClientUsername()); + final AuthenticateResponse authenticate = client().execute(AuthenticateAction.INSTANCE, request).actionGet(10, TimeUnit.SECONDS); + assertThat(authenticate.authentication(), notNullValue()); + assertThat(authenticate.authentication().getUser(), notNullValue()); + assertThat(authenticate.authentication().getUser().enabled(), is(true)); + } + +} diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTestHelper.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTestHelper.java index 132a3b7bac9..9e1414b438d 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTestHelper.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTestHelper.java @@ -5,6 +5,9 @@ */ package org.elasticsearch.xpack.security.authc.saml; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; @@ -42,4 +45,15 @@ public class SamlRealmTestHelper { return new SamlRealm(realmConfig, mock(UserRoleMapper.class), mock(SamlAuthenticator.class), mock(SamlLogoutRequestHandler.class), () -> idpDescriptor, spConfiguration); } + + public static void writeIdpMetaData(Path path, String idpEntityId) throws IOException { + Files.write(path, Arrays.asList( + "", + "", + "", + "", + "", + "" + )); + } } diff --git a/x-pack/qa/kerberos-tests/build.gradle b/x-pack/qa/kerberos-tests/build.gradle index f680a45bd7f..5327fca1a68 100644 --- a/x-pack/qa/kerberos-tests/build.gradle +++ b/x-pack/qa/kerberos-tests/build.gradle @@ -87,16 +87,14 @@ integTestCluster { setting 'http.host', '127.0.0.1' setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.security.enabled', 'true' - setting 'xpack.security.authc.realms.file.type', 'file' - setting 'xpack.security.authc.realms.file.order', '0' + setting 'xpack.security.authc.realms.file.file1.order', '0' setting 'xpack.ml.enabled', 'false' setting 'xpack.security.audit.enabled', 'true' // Kerberos realm - setting 'xpack.security.authc.realms.kerberos.type', 'kerberos' - setting 'xpack.security.authc.realms.kerberos.order', '1' - setting 'xpack.security.authc.realms.kerberos.keytab.path', 'es.keytab' - setting 'xpack.security.authc.realms.kerberos.krb.debug', 'true' - setting 'xpack.security.authc.realms.kerberos.remove_realm_name', 'false' + setting 'xpack.security.authc.realms.kerberos.kerberos.order', '1' + setting 'xpack.security.authc.realms.kerberos.kerberos.keytab.path', 'es.keytab' + setting 'xpack.security.authc.realms.kerberos.kerberos.krb.debug', 'true' + setting 'xpack.security.authc.realms.kerberos.kerberos.remove_realm_name', 'false' Path krb5conf = project(':test:fixtures:krb5kdc-fixture').buildDir.toPath().resolve("conf").resolve("krb5.conf").toAbsolutePath() String jvmArgsStr = " -Djava.security.krb5.conf=${krb5conf}" + " -Dsun.security.krb5.debug=true"