Support realm validation when Keystore is closed (elastic/x-pack-elasticsearch#3096)

If the KeyStoreWrapper is closed, then we cannot validate secure settings (because we no longer have access to them)
The Realm group setting uses the "validate" method to ensure that child settings are correct, but it must ignore secure settings as it might get called
after startup (e.g. during a settings diff)

Original commit: elastic/x-pack-elasticsearch@b30db6bc62
This commit is contained in:
Tim Vernum 2017-11-30 11:22:17 +10:00 committed by GitHub
parent 90a1da82ee
commit c2ff796fea
2 changed files with 39 additions and 2 deletions

View File

@ -16,6 +16,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import org.elasticsearch.common.settings.AbstractScopedSettings;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.extensions.XPackExtension;
@ -167,6 +168,11 @@ public class RealmSettings {
// perfectly aligned
return;
}
// Don't validate secure settings because they might have been cleared already
settings = Settings.builder().put(settings, false).build();
validSettings.removeIf(s -> s instanceof SecureSetting);
Set<Setting<?>> settingSet = new HashSet<>(validSettings);
settingSet.add(TYPE_SETTING);
settingSet.add(ENABLED_SETTING);

View File

@ -11,6 +11,8 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.SecureSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
@ -94,6 +96,13 @@ public class RealmSettingsTests extends ESTestCase {
assertError("pki3", realm.build());
}
public void testPkiRealmWithClosedSecurePasswordValidatesSuccessfully() throws Exception {
final Settings.Builder builder = pkiRealm("pki4", true);
builder.getSecureSettings().close();
final Settings settings = builder.build();
assertSuccess(settings);
}
public void testSettingsWithMultipleRealmsValidatesSuccessfully() throws Exception {
final Settings settings = Settings.builder()
.put(fileRealm("file1").build())
@ -201,7 +210,7 @@ public class RealmSettingsTests extends ESTestCase {
if (useTrustStore) {
builder.put("truststore.path", randomAlphaOfLengthBetween(8, 32));
SecuritySettingsSource.addSecureSettings(builder, secureSettings -> {
secureSettings.setString("keystore.secure_password", randomAlphaOfLength(8));
secureSettings.setString("truststore.secure_password", randomAlphaOfLength(8));
});
builder.put("truststore.algorithm", randomAlphaOfLengthBetween(6, 10));
} else {
@ -254,7 +263,29 @@ public class RealmSettingsTests extends ESTestCase {
}
private Settings.Builder realm(String name, Settings.Builder settings) {
return settings.normalizePrefix(realmPrefix(name));
final String prefix = realmPrefix(name);
final MockSecureSettings secureSettings = normaliseSecureSettingPrefix(prefix, settings.getSecureSettings());
final Settings.Builder builder = Settings.builder().put(settings.normalizePrefix(prefix).build(), false);
if (secureSettings != null) {
builder.setSecureSettings(secureSettings);
}
return builder;
}
private MockSecureSettings normaliseSecureSettingPrefix(String prefix, SecureSettings settings) {
if (settings == null) {
return null;
}
if (settings instanceof MockSecureSettings) {
final MockSecureSettings source = (MockSecureSettings) settings;
final MockSecureSettings target = new MockSecureSettings();
for (String key : settings.getSettingNames()) {
target.setString(prefix + key, source.getString(key).toString());
}
return target;
} else {
throw new IllegalArgumentException("Source settings " + settings.getClass() + " is not a " + MockSecureSettings.class);
}
}
private String realmPrefix(String name) {