Skip to content

Commit 190b7c7

Browse files
authored
Allow overlap of static and custom security configs, but prefer static (#5805)
Signed-off-by: Craig Perkins <[email protected]>
1 parent ba35e4b commit 190b7c7

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88

99
### Changed
1010
- Ensure all restHeaders from ActionPlugin.getRestHeaders are carried to threadContext for tracing ([#5396](https://github.com/opensearch-project/security/pull/5396))
11+
- Allow overlap of static and custom security configs, but prefer static ([#5805](https://github.com/opensearch-project/security/pull/5805))
12+
1113
### Features
1214

1315
### Enhancements

src/main/java/org/opensearch/security/securityconf/DynamicConfigFactory.java

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -240,32 +240,9 @@ public void onChange(ConfigurationMap typeToConfig) {
240240
final AllowlistingSettings allowlist = cr.getConfiguration(CType.ALLOWLIST).getCEntry("config");
241241
final AuditConfig audit = cr.getConfiguration(CType.AUDIT).getCEntry("config");
242242

243-
if (roles.containsAny(staticRoles)) {
244-
throw new StaticResourceException("Cannot override static roles");
245-
}
246-
if (!roles.add(staticRoles) && !staticRoles.getCEntries().isEmpty()) {
247-
throw new StaticResourceException("Unable to load static roles");
248-
}
249-
250-
log.debug("Static roles loaded ({})", staticRoles.getCEntries().size());
251-
252-
if (actionGroups.containsAny(staticActionGroups)) {
253-
throw new StaticResourceException("Cannot override static action groups");
254-
}
255-
if (!actionGroups.add(staticActionGroups) && !staticActionGroups.getCEntries().isEmpty()) {
256-
throw new StaticResourceException("Unable to load static action groups");
257-
}
258-
259-
log.debug("Static action groups loaded ({})", staticActionGroups.getCEntries().size());
260-
261-
if (tenants.containsAny(staticTenants)) {
262-
throw new StaticResourceException("Cannot override static tenants");
263-
}
264-
if (!tenants.add(staticTenants) && !staticTenants.getCEntries().isEmpty()) {
265-
throw new StaticResourceException("Unable to load static tenants");
266-
}
267-
268-
log.debug("Static tenants loaded ({})", staticTenants.getCEntries().size());
243+
mergeStaticConfigWithWarning("roles", roles, staticRoles, log);
244+
mergeStaticConfigWithWarning("action groups", actionGroups, staticActionGroups, log);
245+
mergeStaticConfigWithWarning("tenants", tenants, staticTenants, log);
269246

270247
log.debug(
271248
"Static configuration loaded (total roles: {}/total action groups: {}/total tenants: {})",
@@ -292,6 +269,44 @@ public void onChange(ConfigurationMap typeToConfig) {
292269
initialized.set(true);
293270
}
294271

272+
private static <T> void mergeStaticConfigWithWarning(
273+
String typeName,
274+
SecurityDynamicConfiguration<T> dynamicConfig,
275+
SecurityDynamicConfiguration<T> staticConfig,
276+
Logger log
277+
) {
278+
if (staticConfig == null || staticConfig.isEmpty()) {
279+
return;
280+
}
281+
282+
// Find overlapping keys between dynamic and static configs
283+
final Map<String, T> dynamicEntries = dynamicConfig.getCEntries();
284+
final Map<String, T> staticEntries = staticConfig.getCEntries();
285+
286+
final java.util.List<String> overlaps = dynamicEntries.keySet().stream().filter(staticEntries::containsKey).sorted().toList();
287+
288+
if (!overlaps.isEmpty()) {
289+
// Remove overlaps from the dynamic config so static definitions win
290+
dynamicConfig.remove(overlaps);
291+
292+
log.warn(
293+
"Detected overlap between dynamic {} configuration and static resources for entries: {}. "
294+
+ "Dynamic definitions have been removed in favor of static configuration.",
295+
typeName,
296+
overlaps
297+
);
298+
}
299+
300+
// Now add static entries; if this fails, it's a real structural problem (version/type)
301+
if (!dynamicConfig.add(staticConfig) && !staticConfig.getCEntries().isEmpty()) {
302+
throw new StaticResourceException("Unable to load static " + typeName);
303+
}
304+
305+
if (log.isDebugEnabled()) {
306+
log.debug("Static {} loaded ({} entries)", typeName, staticConfig.getCEntries().size());
307+
}
308+
}
309+
295310
private static ConfigV7 getConfigV7(SecurityDynamicConfiguration<?> sdc) {
296311
@SuppressWarnings("unchecked")
297312
SecurityDynamicConfiguration<ConfigV7> c = (SecurityDynamicConfiguration<ConfigV7>) sdc;

0 commit comments

Comments
 (0)