Skip to content

Commit 8c69314

Browse files
authored
Add user custom attributes to thread context (#5491)
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
1 parent 9f38313 commit 8c69314

File tree

7 files changed

+39
-7
lines changed

7 files changed

+39
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
3737
* Fix usage of jwt_clock_skew_tolerance_seconds in HTTPJwtAuthenticator ([#5506](https://github.com/opensearch-project/security/pull/5506))
3838
* Always install demo certs if configured with demo certs ([#5517](https://github.com/opensearch-project/security/pull/5517))
3939
* [Resource Sharing] Restores client accessor pattern to fix compilation issues when security plugin is not installed ([#5541](https://github.com/opensearch-project/security/pull/5541))
40+
* Add serialized user custom attributes to the the thread context ([#5491](https://github.com/opensearch-project/security/pull/5491))
4041

4142
### Refactoring
4243

sample-resource-plugin/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ext {
3838
licenseFile = rootProject.file('LICENSE.txt')
3939
noticeFile = rootProject.file('NOTICE.txt')
4040

41-
common_utils_version = System.getProperty("common_utils.version", "3.1.0.0")
41+
common_utils_version = System.getProperty("common_utils.version", "3.2.0.0-SNAPSHOT")
4242
}
4343

4444
repositories {
@@ -80,6 +80,7 @@ dependencies {
8080
integrationTestImplementation rootProject.sourceSets.integrationTest.output
8181
integrationTestImplementation rootProject.sourceSets.main.output
8282
integrationTestImplementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}"
83+
integrationTestImplementation 'org.ldaptive:ldaptive:1.2.3'
8384

8485
// To be removed once integration test framework supports extended plugins
8586
integrationTestImplementation project(path: ":${rootProject.name}-spi", configuration: 'shadow')

src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,8 @@ public int hashCode() {
449449

450450
public static final class User implements UserCredentialsHolder, ToXContentObject {
451451

452-
public final static TestSecurityConfig.User USER_ADMIN = new User("admin").roles(
453-
new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*")
454-
);
452+
public final static TestSecurityConfig.User USER_ADMIN = new User("admin").attr("attr1", "val1")
453+
.roles(new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*"));
455454

456455
String name;
457456
private String password;

src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,6 +2248,15 @@ public List<Setting<?>> getSettings() {
22482248
Property.Final
22492249
)
22502250
);
2251+
2252+
settings.add(
2253+
Setting.boolSetting(
2254+
ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED,
2255+
ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT,
2256+
Property.NodeScope,
2257+
Property.Filtered
2258+
)
2259+
);
22512260
}
22522261

22532262
return settings;

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
package org.opensearch.security.privileges;
2828

29+
import java.io.Serializable;
2930
import java.util.ArrayList;
3031
import java.util.Arrays;
3132
import java.util.Collections;
@@ -103,6 +104,7 @@
103104
import org.opensearch.security.securityconf.impl.v7.ActionGroupsV7;
104105
import org.opensearch.security.securityconf.impl.v7.RoleV7;
105106
import org.opensearch.security.securityconf.impl.v7.TenantV7;
107+
import org.opensearch.security.support.Base64Helper;
106108
import org.opensearch.security.support.ConfigConstants;
107109
import org.opensearch.security.support.WildcardMatcher;
108110
import org.opensearch.security.user.User;
@@ -113,6 +115,8 @@
113115

114116
import static org.opensearch.security.OpenSearchSecurityPlugin.traceAction;
115117
import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT;
118+
import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED;
119+
import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT;
116120
import static org.opensearch.security.support.SecurityUtils.escapePipe;
117121

118122
public class PrivilegesEvaluator {
@@ -283,6 +287,10 @@ public boolean isInitialized() {
283287
return configModel != null && dcm != null && actionPrivileges.get() != null;
284288
}
285289

290+
private boolean isUserAttributeSerializationEnabled() {
291+
return this.settings.getAsBoolean(USER_ATTRIBUTE_SERIALIZATION_ENABLED, USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT);
292+
}
293+
286294
private void setUserInfoInThreadContext(PrivilegesEvaluationContext context) {
287295
if (threadContext.getTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT) == null) {
288296
StringJoiner joiner = new StringJoiner("|");
@@ -293,9 +301,15 @@ private void setUserInfoInThreadContext(PrivilegesEvaluationContext context) {
293301

294302
String requestedTenant = context.getUser().getRequestedTenant();
295303
joiner.add(requestedTenant);
304+
296305
String tenantAccessToCheck = getTenancyAccess(context);
297306
joiner.add(tenantAccessToCheck);
298307
log.debug(joiner);
308+
309+
if (this.isUserAttributeSerializationEnabled()) {
310+
joiner.add(Base64Helper.serializeObject((Serializable) context.getUser().getCustomAttributesMap()));
311+
}
312+
299313
threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString());
300314
}
301315
}

src/main/java/org/opensearch/security/support/ConfigConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ public enum RolesMappingResolution {
409409
public static final String SECURITY_CONFIG_VERSION_RETENTION_COUNT = SECURITY_SETTINGS_PREFIX + "config_version.retention_count";
410410
public static final int SECURITY_CONFIG_VERSION_RETENTION_COUNT_DEFAULT = 10;
411411

412+
public static final String USER_ATTRIBUTE_SERIALIZATION_ENABLED = SECURITY_SETTINGS_PREFIX + "user_attribute_serialization.enabled";
413+
public static final boolean USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT = false;
414+
412415
// On-behalf-of endpoints settings
413416
// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings
414417
public static final String EXTENSIONS_BWC_PLUGIN_MODE = "bwcPluginMode";

src/main/java/org/opensearch/security/support/SafeSerializationUtils.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
import java.net.InetSocketAddress;
1717
import java.net.SocketAddress;
1818
import java.util.Collection;
19-
import java.util.Collections;
2019
import java.util.Map;
2120
import java.util.Set;
2221
import java.util.concurrent.ConcurrentHashMap;
2322
import java.util.regex.Pattern;
2423

24+
import com.google.common.collect.ImmutableMap;
2525
import com.google.common.collect.ImmutableSet;
2626

2727
import com.amazon.dlic.auth.ldap.LdapUser;
@@ -58,10 +58,15 @@ public final class SafeSerializationUtils {
5858
Number.class,
5959
Collection.class,
6060
Map.class,
61-
Enum.class
61+
Enum.class,
62+
ImmutableMap.class
6263
);
6364

64-
private static final Set<String> SAFE_CLASS_NAMES = Collections.singleton("org.ldaptive.LdapAttribute$LdapAttributeValues");
65+
private static final Set<String> SAFE_CLASS_NAMES = Set.of(
66+
"org.ldaptive.LdapAttribute$LdapAttributeValues",
67+
"com.google.common.collect.ImmutableBiMap$SerializedForm",
68+
"com.google.common.collect.ImmutableMap$SerializedForm"
69+
);
6570
static final Map<Class<?>, Boolean> safeClassCache = new ConcurrentHashMap<>();
6671

6772
static boolean isSafeClass(Class<?> cls) {

0 commit comments

Comments
 (0)