Skip to content

Commit a41bd03

Browse files
authored
Modularized PrivilegesEvaluator (#5791)
Signed-off-by: Nils Bandener <[email protected]>
1 parent f4e573f commit a41bd03

File tree

45 files changed

+2142
-1500
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2142
-1500
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
3535
- Replace AccessController and remove restriction on word Extension ([#5750](https://github.com/opensearch-project/security/pull/5750))
3636
- Add security provider earlier in bootstrap process ([#5749](https://github.com/opensearch-project/security/pull/5749))
3737
- [GRPC] Fix compilation errors from core protobuf version bump to 0.23.0 ([#5763](https://github.com/opensearch-project/security/pull/5763))
38+
- Modularized PrivilegesEvaluator ([#5791](https://github.com/opensearch-project/security/pull/5791))
3839

3940
### Maintenance
4041
- Bump `org.junit.jupiter:junit-jupiter` from 5.13.4 to 5.14.1 ([#5678](https://github.com/opensearch-project/security/pull/5678), [#5764](https://github.com/opensearch-project/security/pull/5764))
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
package org.opensearch.security.privileges;
12+
13+
import java.net.InetAddress;
14+
import java.util.ArrayList;
15+
import java.util.Arrays;
16+
import java.util.Collection;
17+
import java.util.HashSet;
18+
import java.util.List;
19+
import java.util.Set;
20+
21+
import com.google.common.collect.ImmutableSet;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.junit.runners.Parameterized;
25+
import org.junit.runners.Suite;
26+
27+
import org.opensearch.common.settings.Settings;
28+
import org.opensearch.core.common.transport.TransportAddress;
29+
import org.opensearch.security.securityconf.impl.CType;
30+
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration;
31+
import org.opensearch.security.securityconf.impl.v7.RoleMappingsV7;
32+
import org.opensearch.security.support.ConfigConstants;
33+
import org.opensearch.security.support.HostResolverMode;
34+
import org.opensearch.security.user.User;
35+
36+
import static org.junit.Assert.assertEquals;
37+
38+
@RunWith(Suite.class)
39+
@Suite.SuiteClasses({ ConfigurableRoleMapperTest.ResolutionModeTest.class, ConfigurableRoleMapperTest.CompiledConfigurationTest.class, })
40+
public class ConfigurableRoleMapperTest {
41+
42+
public static class ResolutionModeTest {
43+
@Test
44+
public void fromSettings_valid() {
45+
Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "both").build();
46+
47+
assertEquals(ConfigurableRoleMapper.ResolutionMode.BOTH, ConfigurableRoleMapper.ResolutionMode.fromSettings(settings));
48+
}
49+
50+
@Test
51+
public void fromSettings_invalid() {
52+
Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "totally_invalid_value").build();
53+
54+
// invalid -> fallback to MAPPING_ONLY
55+
assertEquals(ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY, ConfigurableRoleMapper.ResolutionMode.fromSettings(settings));
56+
}
57+
}
58+
59+
@RunWith(Parameterized.class)
60+
public static class CompiledConfigurationTest {
61+
62+
final static User USER_WITH_NO_ROLES = new User("user_no_roles");
63+
final static User USER_WITH_BACKEND_ROLES = new User("user_with_backend_roles").withRoles("backend_role_1", "backend_role_2");
64+
final static User USER_WITH_SECURITY_ROLES = new User("user_with_security_roles").withSecurityRoles(
65+
Arrays.asList("effective_role_1", "effective_role_2")
66+
);
67+
final static User USER_WITH_BOTH = new User("user_with_both").withRoles("backend_role_1", "backend_role_2")
68+
.withSecurityRoles(Arrays.asList("effective_role_1", "effective_role_2"));
69+
70+
final ConfigurableRoleMapper.ResolutionMode resolutionMode;
71+
final User user;
72+
final TransportAddress transportAddress;
73+
74+
@Test
75+
public void map_simple() throws Exception {
76+
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
77+
backend_to_effective:
78+
backend_roles:
79+
- backend_role_1
80+
""", CType.ROLESMAPPING);
81+
82+
ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
83+
roleMapping,
84+
HostResolverMode.IP_HOSTNAME,
85+
resolutionMode
86+
);
87+
88+
ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
89+
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());
90+
91+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY
92+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
93+
if (user.getRoles().contains("backend_role_1")) {
94+
expectedRoles.add("backend_to_effective");
95+
}
96+
}
97+
98+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
99+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
100+
expectedRoles.addAll(user.getRoles());
101+
}
102+
103+
assertEquals(expectedRoles, mappedRoles);
104+
105+
}
106+
107+
@Test
108+
public void map_username() throws Exception {
109+
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
110+
user_to_effective:
111+
users:
112+
- user_no_roles
113+
""", CType.ROLESMAPPING);
114+
115+
ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
116+
roleMapping,
117+
HostResolverMode.IP_HOSTNAME,
118+
resolutionMode
119+
);
120+
121+
ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
122+
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());
123+
124+
if (user == USER_WITH_NO_ROLES && resolutionMode != ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY) {
125+
expectedRoles.add("user_to_effective");
126+
}
127+
128+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
129+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
130+
expectedRoles.addAll(user.getRoles());
131+
}
132+
133+
assertEquals(expectedRoles, mappedRoles);
134+
}
135+
136+
@Test
137+
public void map_host() throws Exception {
138+
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
139+
host_to_effective:
140+
hosts:
141+
- "127.0.0.1"
142+
""", CType.ROLESMAPPING);
143+
144+
ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
145+
roleMapping,
146+
HostResolverMode.IP_HOSTNAME_LOOKUP,
147+
resolutionMode
148+
);
149+
150+
ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
151+
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());
152+
153+
if (resolutionMode != ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY) {
154+
expectedRoles.add("host_to_effective");
155+
}
156+
157+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
158+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
159+
expectedRoles.addAll(user.getRoles());
160+
}
161+
162+
assertEquals(expectedRoles, mappedRoles);
163+
}
164+
165+
@Test
166+
public void map_and() throws Exception {
167+
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
168+
backend_to_effective:
169+
and_backend_roles:
170+
- backend_role_1
171+
- backend_role_2
172+
""", CType.ROLESMAPPING);
173+
174+
ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
175+
roleMapping,
176+
HostResolverMode.IP_HOSTNAME,
177+
resolutionMode
178+
);
179+
180+
ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
181+
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());
182+
183+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY
184+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
185+
if (user.getRoles().contains("backend_role_1") && user.getRoles().contains("backend_role_2")) {
186+
expectedRoles.add("backend_to_effective");
187+
}
188+
}
189+
190+
if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
191+
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
192+
expectedRoles.addAll(user.getRoles());
193+
}
194+
195+
assertEquals(expectedRoles, mappedRoles);
196+
197+
}
198+
199+
public CompiledConfigurationTest(
200+
ConfigurableRoleMapper.ResolutionMode resolutionMode,
201+
User user,
202+
TransportAddress transportAddress
203+
) {
204+
this.resolutionMode = resolutionMode;
205+
this.user = user;
206+
this.transportAddress = transportAddress;
207+
}
208+
209+
@Parameterized.Parameters(name = "{0}, {1}")
210+
public static Collection<Object[]> params() throws Exception {
211+
List<Object[]> result = new ArrayList<>();
212+
213+
for (ConfigurableRoleMapper.ResolutionMode mode : ConfigurableRoleMapper.ResolutionMode.values()) {
214+
for (User user : Arrays.asList(USER_WITH_NO_ROLES, USER_WITH_BACKEND_ROLES, USER_WITH_SECURITY_ROLES, USER_WITH_BOTH)) {
215+
result.add(
216+
new Object[] { mode, user, new TransportAddress(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 9300) }
217+
);
218+
219+
}
220+
}
221+
222+
return result;
223+
}
224+
225+
}
226+
227+
}

0 commit comments

Comments
 (0)