Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- WLM group custom search settings - groundwork and timeout ([#20536](https://github.com/opensearch-project/OpenSearch/issues/20536))
- Expose JVM runtime metrics via telemetry framework ([#20844](https://github.com/opensearch-project/OpenSearch/pull/20844))
- Add intra segment support for single-value metric aggregations ([#20503](https://github.com/opensearch-project/OpenSearch/pull/20503))
- Add new setting property 'Sensitive' for tiering dynamic settings ([#20901](https://github.com/opensearch-project/OpenSearch/pull/20901))
- Add ref_path support for package-based hunspell dictionary loading ([#20840](https://github.com/opensearch-project/OpenSearch/pull/20840))
- Add support for enabling pluggable data formats, starting with phase-1 of decoupling shard from engine, and introducing basic abstractions ([#20675](https://github.com/opensearch-project/OpenSearch/pull/20675))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ synchronized ClusterState updateSettings(
final Settings persistentToApply,
final Logger logger
) {
validateNoTransientSensitiveSettings(transientToApply);
boolean changed = false;

/*
Expand Down Expand Up @@ -212,4 +213,12 @@ private void logInvalidSetting(
);
}

private void validateNoTransientSensitiveSettings(final Settings transientSettings) {
for (String key : transientSettings.keySet()) {
if (clusterSettings.isSensitiveSetting(key)) {
throw new IllegalArgumentException("sensitive setting [" + key + "] must be updated using persistent settings");
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,15 @@ public boolean isUnmodifiableOnRestoreSetting(String key) {
return setting != null && setting.isUnmodifiableOnRestore();
}

/**
* Returns <code>true</code> if the setting for the given key is sensitive, meaning it requires
* security admin privileges to be updated dynamically. Otherwise <code>false</code>.
*/
public boolean isSensitiveSetting(String key) {
final Setting<?> setting = get(key);
return setting != null && setting.isSensitive();
}

/**
* Returns a settings object that contains all settings that are not
* already set in the given source. The diff contains either the default value for each
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,14 @@ public enum Property {
* Mark this setting as immutable on snapshot restore
* i.e. the setting will not be allowed to be removed or modified during restore
*/
UnmodifiableOnRestore
UnmodifiableOnRestore,

/**
* Mark this dynamic setting as sensitive. Sensitive settings require security admin
* privileges to be updated dynamically. This property can only be applied to settings
* that also have {@link Property#Dynamic}.
*/
Sensitive
}

private final Key key;
Expand Down Expand Up @@ -217,6 +224,9 @@ private Setting(
} else if (propertiesAsSet.contains(Property.UnmodifiableOnRestore) && propertiesAsSet.contains(Property.Dynamic)) {
throw new IllegalArgumentException("UnmodifiableOnRestore setting [" + key + "] cannot be dynamic");
}
if (propertiesAsSet.contains(Property.Sensitive) && propertiesAsSet.contains(Property.Dynamic) == false) {
throw new IllegalArgumentException("sensitive setting [" + key + "] must be dynamic");
}
checkPropertyRequiresIndexScope(propertiesAsSet, Property.NotCopyableOnResize);
checkPropertyRequiresIndexScope(propertiesAsSet, Property.InternalIndex);
checkPropertyRequiresIndexScope(propertiesAsSet, Property.PrivateIndex);
Expand Down Expand Up @@ -361,6 +371,14 @@ public final boolean isUnmodifiableOnRestore() {
return properties.contains(Property.UnmodifiableOnRestore);
}

/**
* Returns <code>true</code> if this setting is sensitive, meaning it requires security admin
* privileges to be updated dynamically. Otherwise <code>false</code>.
*/
public final boolean isSensitive() {
return properties.contains(Property.Sensitive);
}

public final boolean isInternalIndex() {
return properties.contains(Property.InternalIndex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,4 +670,24 @@ public void testUpdateOfValidationDependentSettings() {
assertThat(exception.getMessage(), equalTo("[high]=2 is lower than [low]=5"));
}

public void testRejectSensitiveSettingInTransient() {
Setting<String> sensitiveSetting = Setting.simpleString(
"sensitive.setting",
Property.Dynamic,
Property.NodeScope,
Property.Sensitive
);
final Set<Setting<?>> settingsSet = Stream.concat(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS.stream(), Stream.of(sensitiveSetting))
.collect(Collectors.toSet());
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, settingsSet);
SettingsUpdater updater = new SettingsUpdater(clusterSettings);
ClusterState state = ClusterState.builder(new ClusterName("foo")).metadata(Metadata.builder().build()).build();

IllegalArgumentException ex = expectThrows(
IllegalArgumentException.class,
() -> updater.updateSettings(state, Settings.builder().put("sensitive.setting", "value").build(), Settings.EMPTY, logger)
);
assertThat(ex.getMessage(), equalTo("sensitive setting [sensitive.setting] must be updated using persistent settings"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,14 @@ public void testRejectConflictingDynamicAndUnmodifiableOnRestoreProperties() {
assertThat(ex.getMessage(), containsString("UnmodifiableOnRestore setting [foo.bar] cannot be dynamic"));
}

public void testRejectSensitiveWithoutDynamic() {
IllegalArgumentException ex = expectThrows(
IllegalArgumentException.class,
() -> Setting.simpleString("foo.bar", Property.Sensitive, Property.NodeScope)
);
assertThat(ex.getMessage(), containsString("sensitive setting [foo.bar] must be dynamic"));
}

public void testRejectNonIndexScopedUnmodifiableOnRestoreSetting() {
final IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
Expand Down
Loading