Skip to content
Merged
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 @@ -35,6 +35,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Replace AccessController and remove restriction on word Extension ([#5750](https://github.com/opensearch-project/security/pull/5750))
- Add security provider earlier in bootstrap process ([#5749](https://github.com/opensearch-project/security/pull/5749))
- [GRPC] Fix compilation errors from core protobuf version bump to 0.23.0 ([#5763](https://github.com/opensearch-project/security/pull/5763))
- Modularized PrivilegesEvaluator ([#5791](https://github.com/opensearch-project/security/pull/5791))

### Maintenance
- 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))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.security.privileges;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite;

import org.opensearch.common.settings.Settings;
import org.opensearch.core.common.transport.TransportAddress;
import org.opensearch.security.securityconf.impl.CType;
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration;
import org.opensearch.security.securityconf.impl.v7.RoleMappingsV7;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.support.HostResolverMode;
import org.opensearch.security.user.User;

import static org.junit.Assert.assertEquals;

@RunWith(Suite.class)
@Suite.SuiteClasses({ ConfigurableRoleMapperTest.ResolutionModeTest.class, ConfigurableRoleMapperTest.CompiledConfigurationTest.class, })
public class ConfigurableRoleMapperTest {

public static class ResolutionModeTest {
@Test
public void fromSettings_valid() {
Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "both").build();

assertEquals(ConfigurableRoleMapper.ResolutionMode.BOTH, ConfigurableRoleMapper.ResolutionMode.fromSettings(settings));
}

@Test
public void fromSettings_invalid() {
Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "totally_invalid_value").build();

// invalid -> fallback to MAPPING_ONLY
assertEquals(ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY, ConfigurableRoleMapper.ResolutionMode.fromSettings(settings));
}
}

@RunWith(Parameterized.class)
public static class CompiledConfigurationTest {

final static User USER_WITH_NO_ROLES = new User("user_no_roles");
final static User USER_WITH_BACKEND_ROLES = new User("user_with_backend_roles").withRoles("backend_role_1", "backend_role_2");
final static User USER_WITH_SECURITY_ROLES = new User("user_with_security_roles").withSecurityRoles(
Arrays.asList("effective_role_1", "effective_role_2")
);
final static User USER_WITH_BOTH = new User("user_with_both").withRoles("backend_role_1", "backend_role_2")
.withSecurityRoles(Arrays.asList("effective_role_1", "effective_role_2"));

final ConfigurableRoleMapper.ResolutionMode resolutionMode;
final User user;
final TransportAddress transportAddress;

@Test
public void map_simple() throws Exception {
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
backend_to_effective:
backend_roles:
- backend_role_1
""", CType.ROLESMAPPING);

ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
roleMapping,
HostResolverMode.IP_HOSTNAME,
resolutionMode
);

ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
if (user.getRoles().contains("backend_role_1")) {
expectedRoles.add("backend_to_effective");
}
}

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
expectedRoles.addAll(user.getRoles());
}

assertEquals(expectedRoles, mappedRoles);

}

@Test
public void map_username() throws Exception {
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
user_to_effective:
users:
- user_no_roles
""", CType.ROLESMAPPING);

ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
roleMapping,
HostResolverMode.IP_HOSTNAME,
resolutionMode
);

ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());

if (user == USER_WITH_NO_ROLES && resolutionMode != ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY) {
expectedRoles.add("user_to_effective");
}

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
expectedRoles.addAll(user.getRoles());
}

assertEquals(expectedRoles, mappedRoles);
}

@Test
public void map_host() throws Exception {
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
host_to_effective:
hosts:
- "127.0.0.1"
""", CType.ROLESMAPPING);

ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
roleMapping,
HostResolverMode.IP_HOSTNAME_LOOKUP,
resolutionMode
);

ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());

if (resolutionMode != ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY) {
expectedRoles.add("host_to_effective");
}

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
expectedRoles.addAll(user.getRoles());
}

assertEquals(expectedRoles, mappedRoles);
}

@Test
public void map_and() throws Exception {
SecurityDynamicConfiguration<RoleMappingsV7> roleMapping = SecurityDynamicConfiguration.fromYaml("""
backend_to_effective:
and_backend_roles:
- backend_role_1
- backend_role_2
""", CType.ROLESMAPPING);

ConfigurableRoleMapper.CompiledConfiguration compiled = new ConfigurableRoleMapper.CompiledConfiguration(
roleMapping,
HostResolverMode.IP_HOSTNAME,
resolutionMode
);

ImmutableSet<String> mappedRoles = compiled.map(user, transportAddress);
Set<String> expectedRoles = new HashSet<>(user.getSecurityRoles());

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.MAPPING_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
if (user.getRoles().contains("backend_role_1") && user.getRoles().contains("backend_role_2")) {
expectedRoles.add("backend_to_effective");
}
}

if (resolutionMode == ConfigurableRoleMapper.ResolutionMode.BACKENDROLES_ONLY
|| resolutionMode == ConfigurableRoleMapper.ResolutionMode.BOTH) {
expectedRoles.addAll(user.getRoles());
}

assertEquals(expectedRoles, mappedRoles);

}

public CompiledConfigurationTest(
ConfigurableRoleMapper.ResolutionMode resolutionMode,
User user,
TransportAddress transportAddress
) {
this.resolutionMode = resolutionMode;
this.user = user;
this.transportAddress = transportAddress;
}

@Parameterized.Parameters(name = "{0}, {1}")
public static Collection<Object[]> params() throws Exception {
List<Object[]> result = new ArrayList<>();

for (ConfigurableRoleMapper.ResolutionMode mode : ConfigurableRoleMapper.ResolutionMode.values()) {
for (User user : Arrays.asList(USER_WITH_NO_ROLES, USER_WITH_BACKEND_ROLES, USER_WITH_SECURITY_ROLES, USER_WITH_BOTH)) {
result.add(
new Object[] { mode, user, new TransportAddress(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 9300) }
);

}
}

return result;
}

}

}
Loading
Loading