Skip to content

Commit de9851a

Browse files
Don't allow secure settings in YML config (109115) (#115779)
* Don't allow secure settings in YML config (109115) Elasticsearch should refuse to start if a secure setting is defined in elasticsearch.yml, in order to protect users from accidentally putting their secrets in a place where they are unexpectedly visible Fixes #109115
1 parent 9658940 commit de9851a

File tree

5 files changed

+54
-17
lines changed

5 files changed

+54
-17
lines changed

docs/changelog/115779.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 115779
2+
summary: Don't allow secure settings in YML config (109115)
3+
area: Infra/Settings
4+
type: bug
5+
issues:
6+
- 109115

server/src/main/java/org/elasticsearch/common/settings/AbstractScopedSettings.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,15 @@ void validate(final String key, final Settings settings, final boolean validateV
599599
);
600600
}
601601
}
602+
603+
if (setting instanceof SecureSetting && settings.hasValue(key)) {
604+
throw new IllegalArgumentException(
605+
"Setting ["
606+
+ key
607+
+ "] is a secure setting"
608+
+ " and must be stored inside the Elasticsearch keystore, but was found inside elasticsearch.yml"
609+
);
610+
}
602611
}
603612
if (validateValue) {
604613
setting.get(settings);

server/src/main/java/org/elasticsearch/common/settings/SecureSetting.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,14 @@ public boolean exists(Settings.Builder builder) {
8282
public T get(Settings settings) {
8383
checkDeprecation(settings);
8484
final SecureSettings secureSettings = settings.getSecureSettings();
85-
if (secureSettings == null || secureSettings.getSettingNames().contains(getKey()) == false) {
86-
if (super.exists(settings)) {
87-
throw new IllegalArgumentException(
88-
"Setting ["
89-
+ getKey()
90-
+ "] is a secure setting"
91-
+ " and must be stored inside the Elasticsearch keystore, but was found inside elasticsearch.yml"
92-
);
93-
}
85+
String key = getKey();
86+
if (secureSettings == null || secureSettings.getSettingNames().contains(key) == false) {
9487
return getFallback(settings);
9588
}
9689
try {
9790
return getSecret(secureSettings);
9891
} catch (GeneralSecurityException e) {
99-
throw new RuntimeException("failed to read secure setting " + getKey(), e);
92+
throw new RuntimeException("failed to read secure setting " + key, e);
10093
}
10194
}
10295

server/src/test/java/org/elasticsearch/common/settings/ScopedSettingsTests.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,42 @@ public void testDiffSecureSettings() {
11381138
assertTrue(diffed.isEmpty());
11391139
}
11401140

1141+
public void testValidateSecureSettingInsecureOverride() {
1142+
MockSecureSettings secureSettings = new MockSecureSettings();
1143+
String settingName = "something.secure";
1144+
secureSettings.setString(settingName, "secure");
1145+
Settings settings = Settings.builder().put(settingName, "notreallysecure").setSecureSettings(secureSettings).build();
1146+
1147+
ClusterSettings clusterSettings = new ClusterSettings(
1148+
settings,
1149+
Collections.singleton(SecureSetting.secureString(settingName, null))
1150+
);
1151+
1152+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.validate(settings, false));
1153+
assertEquals(
1154+
e.getMessage(),
1155+
"Setting [something.secure] is a secure setting "
1156+
+ "and must be stored inside the Elasticsearch keystore, but was found inside elasticsearch.yml"
1157+
);
1158+
}
1159+
1160+
public void testValidateSecureSettingInInsecureSettings() {
1161+
String settingName = "something.secure";
1162+
Settings settings = Settings.builder().put(settingName, "notreallysecure").build();
1163+
1164+
ClusterSettings clusterSettings = new ClusterSettings(
1165+
settings,
1166+
Collections.singleton(SecureSetting.secureString(settingName, null))
1167+
);
1168+
1169+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.validate(settings, false));
1170+
assertEquals(
1171+
e.getMessage(),
1172+
"Setting [something.secure] is a secure setting "
1173+
+ "and must be stored inside the Elasticsearch keystore, but was found inside elasticsearch.yml"
1174+
);
1175+
}
1176+
11411177
public static IndexMetadata newIndexMeta(String name, Settings indexSettings) {
11421178
return IndexMetadata.builder(name).settings(indexSettings(IndexVersion.current(), 1, 0).put(indexSettings)).build();
11431179
}

server/src/test/java/org/elasticsearch/common/settings/SettingsTests.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,13 +473,6 @@ public void testDiff() throws IOException {
473473
}
474474
}
475475

476-
public void testSecureSettingConflict() {
477-
Setting<SecureString> setting = SecureSetting.secureString("something.secure", null);
478-
Settings settings = Settings.builder().put("something.secure", "notreallysecure").build();
479-
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> setting.get(settings));
480-
assertTrue(e.getMessage().contains("must be stored inside the Elasticsearch keystore"));
481-
}
482-
483476
public void testSecureSettingIllegalName() {
484477
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> SecureSetting.secureString("*IllegalName", null));
485478
assertTrue(e.getMessage().contains("does not match the allowed setting name pattern"));

0 commit comments

Comments
 (0)