Skip to content

Commit 59da7c3

Browse files
authored
Improve error message for 6.x style realm settings (#36876)
Realm settings were changed in #30241 in a non-BWC way. If you try and start a 7.x node using a 6.x config style, then the default error messages do not adequately describe the cause of the problem, or the solution. This change detects the when realms are using the 6.x style and fails with a specific error message. This detection is a best-effort, and will detect issues when the realms have not been modified to use the 7.x style, but may not detect situations where the configuration was partially changed. e.g. We can detect this: xpack.security.authc: realms.pki1.type: pki realms.pki1.order: 3 realms.pki1.ssl.certificate_authorities: [ "ca.crt" ] But this (where the "order" has been updated, but the "ssl.*" has not) will fall back to the standard "unknown setting" check xpack.security.authc: realms.pki.pki1.order: 3 realms.pki1.ssl.certificate_authorities: [ "ca.crt" ] Closes: #36026
1 parent d9b2ed6 commit 59da7c3

File tree

3 files changed

+127
-55
lines changed

3 files changed

+127
-55
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -619,12 +619,19 @@ private static Map<String, Settings> getRealmsSSLSettings(Settings settings) {
619619
final Map<String, Settings> sslSettings = new HashMap<>();
620620
final String prefix = "xpack.security.authc.realms.";
621621
final Map<String, Settings> settingsByRealmType = settings.getGroups(prefix);
622-
settingsByRealmType.forEach((realmType, typeSettings) ->
623-
typeSettings.getAsGroups().forEach((realmName, realmSettings) -> {
624-
Settings realmSSLSettings = realmSettings.getByPrefix("ssl.");
625-
// Put this even if empty, so that the name will be mapped to the global SSL configuration
626-
sslSettings.put(prefix + realmType + "." + realmName + ".ssl", realmSSLSettings);
627-
})
622+
settingsByRealmType.forEach((realmType, typeSettings) -> {
623+
final Optional<String> nonDottedSetting = typeSettings.keySet().stream().filter(k -> k.indexOf('.') == -1).findAny();
624+
if (nonDottedSetting.isPresent()) {
625+
logger.warn("Skipping any SSL configuration from realm [{}{}] because the key [{}] is not in the correct format",
626+
prefix, realmType, nonDottedSetting.get());
627+
} else {
628+
typeSettings.getAsGroups().forEach((realmName, realmSettings) -> {
629+
Settings realmSSLSettings = realmSettings.getByPrefix("ssl.");
630+
// Put this even if empty, so that the name will be mapped to the global SSL configuration
631+
sslSettings.put(prefix + realmType + "." + realmName + ".ssl", realmSSLSettings);
632+
});
633+
}
634+
}
628635
);
629636
return sslSettings;
630637
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@
115115
import org.elasticsearch.xpack.core.security.authc.DefaultAuthenticationFailureHandler;
116116
import org.elasticsearch.xpack.core.security.authc.InternalRealmsSettings;
117117
import org.elasticsearch.xpack.core.security.authc.Realm;
118+
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
119+
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
118120
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
119121
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
120122
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
@@ -244,6 +246,7 @@
244246
import java.util.function.Predicate;
245247
import java.util.function.Supplier;
246248
import java.util.function.UnaryOperator;
249+
import java.util.stream.Collectors;
247250

248251
import static java.util.Collections.emptyList;
249252
import static java.util.Collections.singletonList;
@@ -296,7 +299,7 @@ public Security(Settings settings, final Path configPath) {
296299
this.env = transportClientMode ? null : new Environment(settings, configPath);
297300
this.enabled = XPackSettings.SECURITY_ENABLED.get(settings);
298301
if (enabled && transportClientMode == false) {
299-
validateAutoCreateIndex(settings);
302+
runStartupChecks(settings);
300303
// we load them all here otherwise we can't access secure settings since they are closed once the checks are
301304
// fetched
302305
final List<BootstrapCheck> checks = new ArrayList<>();
@@ -315,6 +318,12 @@ public Security(Settings settings, final Path configPath) {
315318
this.bootstrapChecks = Collections.emptyList();
316319
}
317320
this.securityExtensions.addAll(extensions);
321+
322+
}
323+
324+
private static void runStartupChecks(Settings settings) {
325+
validateAutoCreateIndex(settings);
326+
validateRealmSettings(settings);
318327
}
319328

320329
@Override
@@ -781,6 +790,40 @@ public Map<String, Processor.Factory> getProcessors(Processor.Parameters paramet
781790
return Collections.singletonMap(SetSecurityUserProcessor.TYPE, new SetSecurityUserProcessor.Factory(parameters.threadContext));
782791
}
783792

793+
/**
794+
* Realm settings were changed in 7.0. This method validates that the settings in use on this node match the new style of setting.
795+
* In 6.x a realm config would be
796+
* <pre>
797+
* xpack.security.authc.realms.file1.type: file
798+
* xpack.security.authc.realms.file1.order: 0
799+
* </pre>
800+
* In 7.x this realm should be
801+
* <pre>
802+
* xpack.security.authc.realms.file.file1.order: 0
803+
* </pre>
804+
* If confronted with an old style config, the ES Settings validation would simply fail with an error such as
805+
* <em>unknown setting [xpack.security.authc.realms.file1.order]</em>. This validation method provides an error that is easier to
806+
* understand and take action on.
807+
*/
808+
static void validateRealmSettings(Settings settings) {
809+
final Set<String> badRealmSettings = settings.keySet().stream()
810+
.filter(k -> k.startsWith(RealmSettings.PREFIX))
811+
.filter(key -> {
812+
final String suffix = key.substring(RealmSettings.PREFIX.length());
813+
// suffix-part, only contains a single '.'
814+
return suffix.indexOf('.') == suffix.lastIndexOf('.');
815+
})
816+
.collect(Collectors.toSet());
817+
if (badRealmSettings.isEmpty() == false) {
818+
String sampleRealmSetting = RealmSettings.realmSettingPrefix(new RealmConfig.RealmIdentifier("file", "my_file")) + "order";
819+
throw new IllegalArgumentException("Incorrect realm settings found. " +
820+
"Realm settings have been changed to include the type as part of the setting key.\n" +
821+
"For example '" + sampleRealmSetting + "'\n" +
822+
"Found invalid config: " + Strings.collectionToDelimitedString(badRealmSettings, ", ") + "\n" +
823+
"Please see the breaking changes documentation."
824+
);
825+
}
826+
}
784827

785828
static boolean indexAuditLoggingEnabled(Settings settings) {
786829
if (XPackSettings.AUDIT_ENABLED.get(settings)) {

0 commit comments

Comments
 (0)