Skip to content

Commit 59cee02

Browse files
cwperksnibix
authored andcommitted
Reinstated " Implement new extension points in IdentityPlugin and add ContextProvidingPluginSubject (opensearch-project#4896)"
Signed-off-by: Nils Bandener <[email protected]>
1 parent 1872df1 commit 59cee02

File tree

2 files changed

+95
-5
lines changed

2 files changed

+95
-5
lines changed

src/integrationTest/java/org/opensearch/security/privileges/ActionPrivilegesTest.java

+39-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,28 @@ public void wildcard() throws Exception {
126126
);
127127
}
128128

129+
@Test
130+
public void wildcardByUsername() throws Exception {
131+
SecurityDynamicConfiguration<RoleV7> roles = SecurityDynamicConfiguration.empty(CType.ROLES);
132+
133+
ActionPrivileges subject = new ActionPrivileges(
134+
roles,
135+
FlattenedActionGroups.EMPTY,
136+
null,
137+
Settings.EMPTY,
138+
Map.of("plugin:org.opensearch.sample.SamplePlugin", Set.of("*"))
139+
);
140+
141+
assertThat(
142+
subject.hasClusterPrivilege(ctxByUsername("plugin:org.opensearch.sample.SamplePlugin"), "cluster:whatever"),
143+
isAllowed()
144+
);
145+
assertThat(
146+
subject.hasClusterPrivilege(ctx("plugin:org.opensearch.other.OtherPlugin"), "cluster:whatever"),
147+
isForbidden(missingPrivileges("cluster:whatever"))
148+
);
149+
}
150+
129151
@Test
130152
public void explicit_wellKnown() throws Exception {
131153
SecurityDynamicConfiguration<RoleV7> roles = SecurityDynamicConfiguration.fromYaml("non_explicit_role:\n" + //
@@ -455,7 +477,8 @@ public IndicesAndAliases(IndexSpec indexSpec, ActionSpec actionSpec, Statefulnes
455477
settings,
456478
WellKnownActions.CLUSTER_ACTIONS,
457479
WellKnownActions.INDEX_ACTIONS,
458-
WellKnownActions.INDEX_ACTIONS
480+
WellKnownActions.INDEX_ACTIONS,
481+
Map.of()
459482
);
460483

461484
if (statefulness == Statefulness.STATEFUL || statefulness == Statefulness.STATEFUL_LIMITED) {
@@ -1030,4 +1053,19 @@ static PrivilegesEvaluationContext ctx(String... roles) {
10301053
null
10311054
);
10321055
}
1056+
1057+
static PrivilegesEvaluationContext ctxByUsername(String username) {
1058+
User user = new User(username);
1059+
user.addAttributes(ImmutableMap.of("attrs.dept_no", "a11"));
1060+
return new PrivilegesEvaluationContext(
1061+
user,
1062+
ImmutableSet.of(),
1063+
null,
1064+
null,
1065+
null,
1066+
null,
1067+
new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)),
1068+
null
1069+
);
1070+
}
10331071
}

src/main/java/org/opensearch/security/privileges/ActionPrivileges.java

+56-4
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ public ActionPrivileges(
9090
Settings settings,
9191
ImmutableSet<String> wellKnownClusterActions,
9292
ImmutableSet<String> wellKnownIndexActions,
93-
ImmutableSet<String> explicitlyRequiredIndexActions
93+
ImmutableSet<String> explicitlyRequiredIndexActions,
94+
Map<String, Set<String>> pluginToClusterActions
9495
) {
95-
this.cluster = new ClusterPrivileges(roles, actionGroups, wellKnownClusterActions);
96+
this.cluster = new ClusterPrivileges(roles, actionGroups, wellKnownClusterActions, pluginToClusterActions);
9697
this.index = new IndexPrivileges(roles, actionGroups, wellKnownIndexActions, explicitlyRequiredIndexActions);
9798
this.roles = roles;
9899
this.actionGroups = actionGroups;
@@ -115,7 +116,27 @@ public ActionPrivileges(
115116
settings,
116117
WellKnownActions.CLUSTER_ACTIONS,
117118
WellKnownActions.INDEX_ACTIONS,
118-
WellKnownActions.EXPLICITLY_REQUIRED_INDEX_ACTIONS
119+
WellKnownActions.EXPLICITLY_REQUIRED_INDEX_ACTIONS,
120+
Map.of()
121+
);
122+
}
123+
124+
public ActionPrivileges(
125+
SecurityDynamicConfiguration<RoleV7> roles,
126+
FlattenedActionGroups actionGroups,
127+
Supplier<Map<String, IndexAbstraction>> indexMetadataSupplier,
128+
Settings settings,
129+
Map<String, Set<String>> pluginToClusterActions
130+
) {
131+
this(
132+
roles,
133+
actionGroups,
134+
indexMetadataSupplier,
135+
settings,
136+
WellKnownActions.CLUSTER_ACTIONS,
137+
WellKnownActions.INDEX_ACTIONS,
138+
WellKnownActions.EXPLICITLY_REQUIRED_INDEX_ACTIONS,
139+
pluginToClusterActions
119140
);
120141
}
121142

@@ -297,6 +318,8 @@ static class ClusterPrivileges {
297318
*/
298319
private final ImmutableMap<String, WildcardMatcher> rolesToActionMatcher;
299320

321+
private final ImmutableMap<String, WildcardMatcher> usersToActionMatcher;
322+
300323
private final ImmutableSet<String> wellKnownClusterActions;
301324

302325
/**
@@ -310,14 +333,16 @@ static class ClusterPrivileges {
310333
ClusterPrivileges(
311334
SecurityDynamicConfiguration<RoleV7> roles,
312335
FlattenedActionGroups actionGroups,
313-
ImmutableSet<String> wellKnownClusterActions
336+
ImmutableSet<String> wellKnownClusterActions,
337+
Map<String, Set<String>> pluginToClusterActions
314338
) {
315339
DeduplicatingCompactSubSetBuilder<String> roleSetBuilder = new DeduplicatingCompactSubSetBuilder<>(
316340
roles.getCEntries().keySet()
317341
);
318342
Map<String, DeduplicatingCompactSubSetBuilder.SubSetBuilder<String>> actionToRoles = new HashMap<>();
319343
ImmutableSet.Builder<String> rolesWithWildcardPermissions = ImmutableSet.builder();
320344
ImmutableMap.Builder<String, WildcardMatcher> rolesToActionMatcher = ImmutableMap.builder();
345+
ImmutableMap.Builder<String, WildcardMatcher> usersToActionMatcher = ImmutableMap.builder();
321346

322347
for (Map.Entry<String, RoleV7> entry : roles.getCEntries().entrySet()) {
323348
try {
@@ -367,13 +392,22 @@ static class ClusterPrivileges {
367392
}
368393
}
369394

395+
if (pluginToClusterActions != null) {
396+
for (String pluginIdentifier : pluginToClusterActions.keySet()) {
397+
Set<String> clusterActions = pluginToClusterActions.get(pluginIdentifier);
398+
WildcardMatcher matcher = WildcardMatcher.from(clusterActions);
399+
usersToActionMatcher.put(pluginIdentifier, matcher);
400+
}
401+
}
402+
370403
DeduplicatingCompactSubSetBuilder.Completed<String> completedRoleSetBuilder = roleSetBuilder.build();
371404

372405
this.actionToRoles = actionToRoles.entrySet()
373406
.stream()
374407
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().build(completedRoleSetBuilder)));
375408
this.rolesWithWildcardPermissions = rolesWithWildcardPermissions.build();
376409
this.rolesToActionMatcher = rolesToActionMatcher.build();
410+
this.usersToActionMatcher = usersToActionMatcher.build();
377411
this.wellKnownClusterActions = wellKnownClusterActions;
378412
}
379413

@@ -407,6 +441,14 @@ PrivilegesEvaluatorResponse providesPrivilege(PrivilegesEvaluationContext contex
407441
}
408442
}
409443

444+
// 4: If plugin is performing the action, check if plugin has permission
445+
if (context.getUser().isPluginUser() && this.usersToActionMatcher.containsKey(context.getUser().getName())) {
446+
WildcardMatcher matcher = this.usersToActionMatcher.get(context.getUser().getName());
447+
if (matcher != null && matcher.test(action)) {
448+
return PrivilegesEvaluatorResponse.ok();
449+
}
450+
}
451+
410452
return PrivilegesEvaluatorResponse.insufficient(action);
411453
}
412454

@@ -476,6 +518,16 @@ PrivilegesEvaluatorResponse providesAnyPrivilege(PrivilegesEvaluationContext con
476518
}
477519
}
478520

521+
// 4: If plugin is performing the action, check if plugin has permission
522+
if (this.usersToActionMatcher.containsKey(context.getUser().getName())) {
523+
WildcardMatcher matcher = this.usersToActionMatcher.get(context.getUser().getName());
524+
for (String action : actions) {
525+
if (matcher != null && matcher.test(action)) {
526+
return PrivilegesEvaluatorResponse.ok();
527+
}
528+
}
529+
}
530+
479531
if (actions.size() == 1) {
480532
return PrivilegesEvaluatorResponse.insufficient(actions.iterator().next());
481533
} else {

0 commit comments

Comments
 (0)