From 00d4e856dea546d40c2a5205d6504b7adbf8fa0f Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Fri, 9 May 2025 12:57:20 -0400 Subject: [PATCH 01/12] add user attributes to thread context attempt reading injected attributes in RolesInjector add custom attributes to user information in thread context add more logging to injectUserAndRoles add debugging statements update serialization to include only custom attribute name revert changes to RolesInjector revert changes to UserInjector revert changes to SecurityFilter Signed-off-by: Mark Boyd update setUserInfoInThreadContext to base64 encode the serialized map of user custom attributes Signed-off-by: Mark Boyd add null tenant to user context when none is available Signed-off-by: Mark Boyd Immutable user object (#5212) Signed-off-by: Nils Bandener Signed-off-by: Mark Boyd apply spotless formatting Signed-off-by: Mark Boyd --- .../org/opensearch/security/privileges/PrivilegesEvaluator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index af5c3c3124..d3639a9396 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -103,6 +103,7 @@ import org.opensearch.security.securityconf.impl.v7.ActionGroupsV7; import org.opensearch.security.securityconf.impl.v7.RoleV7; import org.opensearch.security.securityconf.impl.v7.TenantV7; +import org.opensearch.security.support.Base64Helper; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.support.WildcardMatcher; import org.opensearch.security.user.User; From fe5b743ded71620f24ab870d9dc707f5fdf3cf3a Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 11:07:17 -0400 Subject: [PATCH 02/12] re-add base64 encoding of serialized user custom attributes & null when requested tenant is empty Signed-off-by: Mark Boyd --- .../opensearch/security/privileges/PrivilegesEvaluator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index d3639a9396..b6c4d09e95 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -26,6 +26,7 @@ package org.opensearch.security.privileges; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -290,7 +291,12 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { String requestedTenant = user.getRequestedTenant(); if (!Strings.isNullOrEmpty(requestedTenant)) { joiner.add(escapePipe(requestedTenant)); + } else { + joiner.add("null"); } + + joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); + threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); } } From 600c01ec1d6fea204d9bd0a4d2ab69d220bfe974 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 11:16:49 -0400 Subject: [PATCH 03/12] add entry to CHANGELOG Signed-off-by: Mark Boyd --- CHANGELOG.md | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 803a09b10a..ca249d49f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # CHANGELOG + All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to the [Semantic Versioning](https://semver.org/spec/v2.0.0.html). See the [CONTRIBUTING guide](./CONTRIBUTING.md#Changelog) for instructions on how to add changelog entries. @@ -7,9 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Features -* Introduced new experimental versioned security configuration management feature ([#5357] (https://github.com/opensearch-project/security/pull/5357)) +* Introduced new experimental versioned security configuration management feature ([#5357] ()) * [Resource Sharing] Adds migrate API to move resource-sharing info to security plugin ([#5389](https://github.com/opensearch-project/security/pull/5389)) -* Introduces support for the Argon2 Password Hashing Algorithm ([#5441] (https://github.com/opensearch-project/security/pull/5441)) +* Introduces support for the Argon2 Password Hashing Algorithm ([#5441] ()) ### Enhancements @@ -26,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * Provide SecureHttpTransportParameters to complement SecureTransportParameters counterpart ([#5432](https://github.com/opensearch-project/security/pull/5432)) * Use isClusterPerm instead of requestedResolved.isLocalAll() to determine if action is a cluster action ([#5445](https://github.com/opensearch-project/security/pull/5445)) * Fix config update with deprecated config types failing in mixed clusters ([#5456](https://github.com/opensearch-project/security/pull/5456)) +* Add serialized user custom attributes to the the thread context ([#5491](https://github.com/opensearch-project/security/pull/5491)) ### Refactoring @@ -34,23 +36,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * Remove provider reflection code ([#5457](https://github.com/opensearch-project/security/pull/5457)) ### Maintenance -- Bump `org.eclipse.platform:org.eclipse.core.runtime` from 3.33.0 to 3.33.100 ([#5400](https://github.com/opensearch-project/security/pull/5400)) -- Bump `org.eclipse.platform:org.eclipse.equinox.common` from 3.20.0 to 3.20.100 ([#5402](https://github.com/opensearch-project/security/pull/5402)) -- Bump `spring_version` from 6.2.7 to 6.2.8 ([#5403](https://github.com/opensearch-project/security/pull/5403)) -- Bump `stefanzweifel/git-auto-commit-action` from 5 to 6 ([#5401](https://github.com/opensearch-project/security/pull/5401)) -- Bump `com.github.spotbugs` from 5.2.5 to 6.2.2 ([#5409](https://github.com/opensearch-project/security/pull/5409), [#5450](https://github.com/opensearch-project/security/pull/5450), [#5474](https://github.com/opensearch-project/security/pull/5474)) -- Bump `org.codehaus.plexus:plexus-utils` from 3.3.0 to 3.6.0 ([#5429](https://github.com/opensearch-project/security/pull/5429)) -- Bump `net.bytebuddy:byte-buddy` from 1.17.5 to 1.17.6 ([#5427](https://github.com/opensearch-project/security/pull/5427)) -- Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) -- Bump `org.junit.jupiter:junit-jupiter-api` from 5.13.1 to 5.13.2 ([#5446](https://github.com/opensearch-project/security/pull/5446)) -- Bump `com.google.errorprone:error_prone_annotations` from 2.38.0 to 2.40.0 ([#5447](https://github.com/opensearch-project/security/pull/5447), [#5477](https://github.com/opensearch-project/security/pull/5477)) -- Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) -- Bump `org.junit.jupiter:junit-jupiter` from 5.13.2 to 5.13.3 ([#5460](https://github.com/opensearch-project/security/pull/5460)) -- Bump `org.checkerframework:checker-qual` from 3.49.4 to 3.49.5 ([#5462](https://github.com/opensearch-project/security/pull/5462)) -- Bump `com.google.googlejavaformat:google-java-format` from 1.27.0 to 1.28.0 ([#5475](https://github.com/opensearch-project/security/pull/5475)) -- Bump `commons-validator:commons-validator` from 1.9.0 to 1.10.0 ([#5476](https://github.com/opensearch-project/security/pull/5476)) -- Bumps checkstyle to 10.26.1 that fixes CVE-2025-48734 ([#5485](https://github.com/opensearch-project/security/pull/5485)) -- Bump `commons-io:commons-io` from 2.19.0 to 2.20.0 ([#5494](https://github.com/opensearch-project/security/pull/5494)) + +* Bump `org.eclipse.platform:org.eclipse.core.runtime` from 3.33.0 to 3.33.100 ([#5400](https://github.com/opensearch-project/security/pull/5400)) + +* Bump `org.eclipse.platform:org.eclipse.equinox.common` from 3.20.0 to 3.20.100 ([#5402](https://github.com/opensearch-project/security/pull/5402)) +* Bump `spring_version` from 6.2.7 to 6.2.8 ([#5403](https://github.com/opensearch-project/security/pull/5403)) +* Bump `stefanzweifel/git-auto-commit-action` from 5 to 6 ([#5401](https://github.com/opensearch-project/security/pull/5401)) +* Bump `com.github.spotbugs` from 5.2.5 to 6.2.2 ([#5409](https://github.com/opensearch-project/security/pull/5409), [#5450](https://github.com/opensearch-project/security/pull/5450), [#5474](https://github.com/opensearch-project/security/pull/5474)) +* Bump `org.codehaus.plexus:plexus-utils` from 3.3.0 to 3.6.0 ([#5429](https://github.com/opensearch-project/security/pull/5429)) +* Bump `net.bytebuddy:byte-buddy` from 1.17.5 to 1.17.6 ([#5427](https://github.com/opensearch-project/security/pull/5427)) +* Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) +* Bump `org.junit.jupiter:junit-jupiter-api` from 5.13.1 to 5.13.2 ([#5446](https://github.com/opensearch-project/security/pull/5446)) +* Bump `com.google.errorprone:error_prone_annotations` from 2.38.0 to 2.40.0 ([#5447](https://github.com/opensearch-project/security/pull/5447), [#5477](https://github.com/opensearch-project/security/pull/5477)) +* Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) +* Bump `org.junit.jupiter:junit-jupiter` from 5.13.2 to 5.13.3 ([#5460](https://github.com/opensearch-project/security/pull/5460)) +* Bump `org.checkerframework:checker-qual` from 3.49.4 to 3.49.5 ([#5462](https://github.com/opensearch-project/security/pull/5462)) +* Bump `com.google.googlejavaformat:google-java-format` from 1.27.0 to 1.28.0 ([#5475](https://github.com/opensearch-project/security/pull/5475)) +* Bump `commons-validator:commons-validator` from 1.9.0 to 1.10.0 ([#5476](https://github.com/opensearch-project/security/pull/5476)) +* Bumps checkstyle to 10.26.1 that fixes CVE-2025-48734 ([#5485](https://github.com/opensearch-project/security/pull/5485)) +* Bump `commons-io:commons-io` from 2.19.0 to 2.20.0 ([#5494](https://github.com/opensearch-project/security/pull/5494)) ### Documentation From 40c6910ef8729fbcb7ab02c724f4b331d2cae840 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 11:58:48 -0400 Subject: [PATCH 04/12] remove extraneous edits to CHANGELOG Signed-off-by: Mark Boyd --- CHANGELOG.md | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca249d49f2..e9fe78b38b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,4 @@ # CHANGELOG - All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to the [Semantic Versioning](https://semver.org/spec/v2.0.0.html). See the [CONTRIBUTING guide](./CONTRIBUTING.md#Changelog) for instructions on how to add changelog entries. @@ -8,9 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Features -* Introduced new experimental versioned security configuration management feature ([#5357] ()) +* Introduced new experimental versioned security configuration management feature ([#5357] (https://github.com/opensearch-project/security/pull/5357)) * [Resource Sharing] Adds migrate API to move resource-sharing info to security plugin ([#5389](https://github.com/opensearch-project/security/pull/5389)) -* Introduces support for the Argon2 Password Hashing Algorithm ([#5441] ()) +* Introduces support for the Argon2 Password Hashing Algorithm ([#5441] (https://github.com/opensearch-project/security/pull/5441)) ### Enhancements @@ -36,25 +35,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * Remove provider reflection code ([#5457](https://github.com/opensearch-project/security/pull/5457)) ### Maintenance - -* Bump `org.eclipse.platform:org.eclipse.core.runtime` from 3.33.0 to 3.33.100 ([#5400](https://github.com/opensearch-project/security/pull/5400)) - -* Bump `org.eclipse.platform:org.eclipse.equinox.common` from 3.20.0 to 3.20.100 ([#5402](https://github.com/opensearch-project/security/pull/5402)) -* Bump `spring_version` from 6.2.7 to 6.2.8 ([#5403](https://github.com/opensearch-project/security/pull/5403)) -* Bump `stefanzweifel/git-auto-commit-action` from 5 to 6 ([#5401](https://github.com/opensearch-project/security/pull/5401)) -* Bump `com.github.spotbugs` from 5.2.5 to 6.2.2 ([#5409](https://github.com/opensearch-project/security/pull/5409), [#5450](https://github.com/opensearch-project/security/pull/5450), [#5474](https://github.com/opensearch-project/security/pull/5474)) -* Bump `org.codehaus.plexus:plexus-utils` from 3.3.0 to 3.6.0 ([#5429](https://github.com/opensearch-project/security/pull/5429)) -* Bump `net.bytebuddy:byte-buddy` from 1.17.5 to 1.17.6 ([#5427](https://github.com/opensearch-project/security/pull/5427)) -* Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) -* Bump `org.junit.jupiter:junit-jupiter-api` from 5.13.1 to 5.13.2 ([#5446](https://github.com/opensearch-project/security/pull/5446)) -* Bump `com.google.errorprone:error_prone_annotations` from 2.38.0 to 2.40.0 ([#5447](https://github.com/opensearch-project/security/pull/5447), [#5477](https://github.com/opensearch-project/security/pull/5477)) -* Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) -* Bump `org.junit.jupiter:junit-jupiter` from 5.13.2 to 5.13.3 ([#5460](https://github.com/opensearch-project/security/pull/5460)) -* Bump `org.checkerframework:checker-qual` from 3.49.4 to 3.49.5 ([#5462](https://github.com/opensearch-project/security/pull/5462)) -* Bump `com.google.googlejavaformat:google-java-format` from 1.27.0 to 1.28.0 ([#5475](https://github.com/opensearch-project/security/pull/5475)) -* Bump `commons-validator:commons-validator` from 1.9.0 to 1.10.0 ([#5476](https://github.com/opensearch-project/security/pull/5476)) -* Bumps checkstyle to 10.26.1 that fixes CVE-2025-48734 ([#5485](https://github.com/opensearch-project/security/pull/5485)) -* Bump `commons-io:commons-io` from 2.19.0 to 2.20.0 ([#5494](https://github.com/opensearch-project/security/pull/5494)) +- Bump `org.eclipse.platform:org.eclipse.core.runtime` from 3.33.0 to 3.33.100 ([#5400](https://github.com/opensearch-project/security/pull/5400)) +- Bump `org.eclipse.platform:org.eclipse.equinox.common` from 3.20.0 to 3.20.100 ([#5402](https://github.com/opensearch-project/security/pull/5402)) +- Bump `spring_version` from 6.2.7 to 6.2.8 ([#5403](https://github.com/opensearch-project/security/pull/5403)) +- Bump `stefanzweifel/git-auto-commit-action` from 5 to 6 ([#5401](https://github.com/opensearch-project/security/pull/5401)) +- Bump `com.github.spotbugs` from 5.2.5 to 6.2.2 ([#5409](https://github.com/opensearch-project/security/pull/5409), [#5450](https://github.com/opensearch-project/security/pull/5450), [#5474](https://github.com/opensearch-project/security/pull/5474)) +- Bump `org.codehaus.plexus:plexus-utils` from 3.3.0 to 3.6.0 ([#5429](https://github.com/opensearch-project/security/pull/5429)) +- Bump `net.bytebuddy:byte-buddy` from 1.17.5 to 1.17.6 ([#5427](https://github.com/opensearch-project/security/pull/5427)) +- Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) +- Bump `org.junit.jupiter:junit-jupiter-api` from 5.13.1 to 5.13.2 ([#5446](https://github.com/opensearch-project/security/pull/5446)) +- Bump `com.google.errorprone:error_prone_annotations` from 2.38.0 to 2.40.0 ([#5447](https://github.com/opensearch-project/security/pull/5447), [#5477](https://github.com/opensearch-project/security/pull/5477)) +- Bump `io.dropwizard.metrics:metrics-core` from 4.2.32 to 4.2.33 ([#5428](https://github.com/opensearch-project/security/pull/5428)) +- Bump `org.junit.jupiter:junit-jupiter` from 5.13.2 to 5.13.3 ([#5460](https://github.com/opensearch-project/security/pull/5460)) +- Bump `org.checkerframework:checker-qual` from 3.49.4 to 3.49.5 ([#5462](https://github.com/opensearch-project/security/pull/5462)) +- Bump `com.google.googlejavaformat:google-java-format` from 1.27.0 to 1.28.0 ([#5475](https://github.com/opensearch-project/security/pull/5475)) +- Bump `commons-validator:commons-validator` from 1.9.0 to 1.10.0 ([#5476](https://github.com/opensearch-project/security/pull/5476)) +- Bumps checkstyle to 10.26.1 that fixes CVE-2025-48734 ([#5485](https://github.com/opensearch-project/security/pull/5485)) +- Bump `commons-io:commons-io` from 2.19.0 to 2.20.0 ([#5494](https://github.com/opensearch-project/security/pull/5494)) ### Documentation From 2ec314c7560dd51a3c5dd0a6d4ff1a87305069a7 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 12:37:05 -0400 Subject: [PATCH 05/12] remove change to add null requested tenant Signed-off-by: Mark Boyd --- .../org/opensearch/security/privileges/PrivilegesEvaluator.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index b6c4d09e95..c88697a5f0 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -291,8 +291,6 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { String requestedTenant = user.getRequestedTenant(); if (!Strings.isNullOrEmpty(requestedTenant)) { joiner.add(escapePipe(requestedTenant)); - } else { - joiner.add("null"); } joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); From f8664cdb4e2ab589f2bfe5c41a1daba42f5aec56 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:26:08 -0400 Subject: [PATCH 06/12] add ImmutableMap to SAFE_ASSIGNABLE_FROM_CLASSES in SafeSerializationUtils Signed-off-by: Mark Boyd --- .../opensearch/security/support/SafeSerializationUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java index e3ac97ddb7..34542041bd 100644 --- a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java +++ b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java @@ -23,6 +23,7 @@ import java.util.regex.Pattern; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableMap; import com.amazon.dlic.auth.ldap.LdapUser; import org.ldaptive.AbstractLdapBean; @@ -58,7 +59,8 @@ public final class SafeSerializationUtils { Number.class, Collection.class, Map.class, - Enum.class + Enum.class, + ImmutableMap.class ); private static final Set SAFE_CLASS_NAMES = Collections.singleton("org.ldaptive.LdapAttribute$LdapAttributeValues"); From 328e9986273f400864c66d29b022a5642afdd6e0 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:32:11 -0400 Subject: [PATCH 07/12] add plugins.security.user_attribute_serialization.enabled setting to control whether user attributes are serialized Signed-off-by: Mark Boyd --- .../opensearch/security/OpenSearchSecurityPlugin.java | 9 +++++++++ .../org/opensearch/security/support/ConfigConstants.java | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 04ef048965..46e14ff289 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -2222,6 +2222,15 @@ public List> getSettings() { Property.Final ) ); + + settings.add( + Setting.boolSetting( + ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED, + ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT, + Property.NodeScope, + Property.Filtered + ) + ); } return settings; diff --git a/src/main/java/org/opensearch/security/support/ConfigConstants.java b/src/main/java/org/opensearch/security/support/ConfigConstants.java index 2f542724b9..374549584b 100644 --- a/src/main/java/org/opensearch/security/support/ConfigConstants.java +++ b/src/main/java/org/opensearch/security/support/ConfigConstants.java @@ -404,6 +404,9 @@ public enum RolesMappingResolution { public static final String SECURITY_CONFIG_VERSION_RETENTION_COUNT = SECURITY_SETTINGS_PREFIX + "config_version.retention_count"; public static final int SECURITY_CONFIG_VERSION_RETENTION_COUNT_DEFAULT = 10; + public static final String USER_ATTRIBUTE_SERIALIZATION_ENABLED = SECURITY_SETTINGS_PREFIX + "user_attribute_serialization.enabled"; + public static final boolean USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT = false; + // On-behalf-of endpoints settings // CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings public static final String EXTENSIONS_BWC_PLUGIN_MODE = "bwcPluginMode"; From 0ec33da3dd52e9af34f4b773bb97f80953f8403d Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:36:44 -0400 Subject: [PATCH 08/12] add PrivilegesEvaluator.isUserAttributeSerializationEnabled() to check if user attribute serialization is enabled before adding serialized user attributes to the thread context Signed-off-by: Mark Boyd --- .../security/privileges/PrivilegesEvaluator.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index c88697a5f0..6d7b645904 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -117,6 +117,9 @@ import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT; import static org.opensearch.security.support.SecurityUtils.escapePipe; +import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED; +import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT; + public class PrivilegesEvaluator { static final WildcardMatcher DNFOF_MATCHER = WildcardMatcher.from( @@ -280,6 +283,13 @@ public boolean isInitialized() { return configModel != null && dcm != null && actionPrivileges.get() != null; } + private boolean isUserAttributeSerializationEnabled() { + return this.settings.getAsBoolean( + USER_ATTRIBUTE_SERIALIZATION_ENABLED, + USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT + ); + } + private void setUserInfoInThreadContext(User user, Set mappedRoles) { if (threadContext.getTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT) == null) { StringJoiner joiner = new StringJoiner("|"); @@ -295,7 +305,9 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); - threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); + if (this.isUserAttributeSerializationEnabled()) { + threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); + } } } From a68f55cfaa733c049224b93605abc02fe2b5d627 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:50:59 -0400 Subject: [PATCH 09/12] apply feedback and spotless formatting Signed-off-by: Mark Boyd --- .../security/privileges/PrivilegesEvaluator.java | 14 +++++--------- .../security/support/SafeSerializationUtils.java | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index 6d7b645904..89e23c5a28 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -115,10 +115,9 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.traceAction; import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT; -import static org.opensearch.security.support.SecurityUtils.escapePipe; - import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED; import static org.opensearch.security.support.ConfigConstants.USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT; +import static org.opensearch.security.support.SecurityUtils.escapePipe; public class PrivilegesEvaluator { @@ -284,10 +283,7 @@ public boolean isInitialized() { } private boolean isUserAttributeSerializationEnabled() { - return this.settings.getAsBoolean( - USER_ATTRIBUTE_SERIALIZATION_ENABLED, - USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT - ); + return this.settings.getAsBoolean(USER_ATTRIBUTE_SERIALIZATION_ENABLED, USER_ATTRIBUTE_SERIALIZATION_ENABLED_DEFAULT); } private void setUserInfoInThreadContext(User user, Set mappedRoles) { @@ -303,11 +299,11 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { joiner.add(escapePipe(requestedTenant)); } - joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); - if (this.isUserAttributeSerializationEnabled()) { - threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); + joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); } + + threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); } } diff --git a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java index 34542041bd..e02e3d6e4a 100644 --- a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java +++ b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java @@ -22,8 +22,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.amazon.dlic.auth.ldap.LdapUser; import org.ldaptive.AbstractLdapBean; From 90a680c4efdfe0ab5c3e149ee9077bd27d4d16cd Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:58:27 -0400 Subject: [PATCH 10/12] re-add null requested tenant to keep number of items in thread context consistent Signed-off-by: Mark Boyd --- .../org/opensearch/security/privileges/PrivilegesEvaluator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index 89e23c5a28..377ed57775 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -297,6 +297,8 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { String requestedTenant = user.getRequestedTenant(); if (!Strings.isNullOrEmpty(requestedTenant)) { joiner.add(escapePipe(requestedTenant)); + } else { + joiner.add("null") } if (this.isUserAttributeSerializationEnabled()) { From c90eae9190e114a2b6fdafb88352550987cf4f33 Mon Sep 17 00:00:00 2001 From: Mark Boyd Date: Mon, 21 Jul 2025 14:59:10 -0400 Subject: [PATCH 11/12] fix typo Signed-off-by: Mark Boyd --- .../org/opensearch/security/privileges/PrivilegesEvaluator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index 377ed57775..d94eff9af5 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -298,7 +298,7 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { if (!Strings.isNullOrEmpty(requestedTenant)) { joiner.add(escapePipe(requestedTenant)); } else { - joiner.add("null") + joiner.add("null"); } if (this.isUserAttributeSerializationEnabled()) { From 8ce3859621f13565f7f0548ceb573dc553a549a5 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 22 Jul 2025 17:48:01 -0400 Subject: [PATCH 12/12] Show e2e test of serialization and deserialization changes to User Signed-off-by: Craig Perkins --- sample-resource-plugin/build.gradle | 3 +- .../sample/SampleResourcePluginTests.java | 39 ++++++++++++++++++- .../CreateResourceTransportAction.java | 1 + .../test/framework/TestSecurityConfig.java | 5 +-- .../privileges/PrivilegesEvaluator.java | 3 +- .../support/SafeSerializationUtils.java | 8 +++- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/sample-resource-plugin/build.gradle b/sample-resource-plugin/build.gradle index 9ae6afba2d..f8b0c79b93 100644 --- a/sample-resource-plugin/build.gradle +++ b/sample-resource-plugin/build.gradle @@ -38,7 +38,7 @@ ext { licenseFile = rootProject.file('LICENSE.txt') noticeFile = rootProject.file('NOTICE.txt') - common_utils_version = System.getProperty("common_utils.version", "3.1.0.0") + common_utils_version = System.getProperty("common_utils.version", "3.2.0.0-SNAPSHOT") } repositories { @@ -71,6 +71,7 @@ dependencies { integrationTestImplementation rootProject.sourceSets.integrationTest.output integrationTestImplementation rootProject.sourceSets.main.output integrationTestImplementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" + integrationTestImplementation 'org.ldaptive:ldaptive:1.2.3' // To be removed once integration test framework supports extended plugins integrationTestImplementation project(path: ":${rootProject.name}-spi", configuration: 'shadow') diff --git a/sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginTests.java b/sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginTests.java index b3d74ae0ef..3500346871 100644 --- a/sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginTests.java +++ b/sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginTests.java @@ -77,7 +77,16 @@ public class SampleResourcePluginTests { .anonymousAuth(true) .authc(AUTHC_HTTPBASIC_INTERNAL) .users(USER_ADMIN, SHARED_WITH_USER) - .nodeSettings(Map.of(SECURITY_SYSTEM_INDICES_ENABLED_KEY, true, OPENSEARCH_RESOURCE_SHARING_ENABLED, true)) + .nodeSettings( + Map.of( + SECURITY_SYSTEM_INDICES_ENABLED_KEY, + true, + OPENSEARCH_RESOURCE_SHARING_ENABLED, + true, + "plugins.security.user_attribute_serialization.enabled", + true + ) + ) .build(); @After @@ -97,6 +106,34 @@ public void testPluginInstalledCorrectly() { } } + @Test + public void testUserSerializationAndDeserialization() throws Exception { + String resourceId; + // create sample resource + try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { + String sampleResource = """ + {"name":"sample"} + """; + + TestRestClient.HttpResponse response = client.putJson(SAMPLE_RESOURCE_CREATE_ENDPOINT, sampleResource); + response.assertStatusCode(HttpStatus.SC_OK); + + resourceId = response.getTextFromJsonBody("/message").split(":")[1].trim(); + + Awaitility.await() + .alias("Wait until resource data is populated") + .until(() -> client.get(SAMPLE_RESOURCE_GET_ENDPOINT + "/" + resourceId).getStatusCode(), equalTo(200)); + } + + try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) { + Awaitility.await() + .alias("Wait until resource-sharing data is populated") + .until(() -> client.get(RESOURCE_SHARING_INDEX + "/_search").bodyAsJsonNode().get("hits").get("hits").size(), equalTo(1)); + HttpResponse sharingEntry = client.get(RESOURCE_SHARING_INDEX + "/_doc/" + resourceId); + System.out.println("sharingEntry: " + sharingEntry.getBody()); + } + } + @Test public void testCreateUpdateDeleteSampleResource() throws Exception { String resourceId; diff --git a/sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/transport/CreateResourceTransportAction.java b/sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/transport/CreateResourceTransportAction.java index e3de36f7cd..946336bb39 100644 --- a/sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/transport/CreateResourceTransportAction.java +++ b/sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/transport/CreateResourceTransportAction.java @@ -56,6 +56,7 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionListene ThreadContext threadContext = transportService.getThreadPool().getThreadContext(); String userStr = threadContext.getTransient(ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT); User user = User.parse(userStr); + System.out.println("Parsed User: " + user); try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { createResource(request, user, listener); } catch (Exception e) { diff --git a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java index 57aac53b6f..ea93ca1061 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java +++ b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java @@ -449,9 +449,8 @@ public int hashCode() { public static final class User implements UserCredentialsHolder, ToXContentObject { - public final static TestSecurityConfig.User USER_ADMIN = new User("admin").roles( - new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*") - ); + public final static TestSecurityConfig.User USER_ADMIN = new User("admin").attr("attr1", "val1") + .roles(new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*")); String name; private String password; diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index d94eff9af5..2f586d090c 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -26,7 +26,6 @@ package org.opensearch.security.privileges; -import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -302,7 +301,7 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { } if (this.isUserAttributeSerializationEnabled()) { - joiner.add(Base64Helper.serializeObject((Serializable) user.getCustomAttributesMap())); + joiner.add(Base64Helper.serializeObject(user.getCustomAttributesMap())); } threadContext.putTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString()); diff --git a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java index e02e3d6e4a..20ae8d112a 100644 --- a/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java +++ b/src/main/java/org/opensearch/security/support/SafeSerializationUtils.java @@ -16,7 +16,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collection; -import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -63,7 +63,11 @@ public final class SafeSerializationUtils { ImmutableMap.class ); - private static final Set SAFE_CLASS_NAMES = Collections.singleton("org.ldaptive.LdapAttribute$LdapAttributeValues"); + private static final Set SAFE_CLASS_NAMES = Set.of( + "org.ldaptive.LdapAttribute$LdapAttributeValues", + "com.google.common.collect.ImmutableBiMap$SerializedForm", + "com.google.common.collect.ImmutableMap$SerializedForm" + ); static final Map, Boolean> safeClassCache = new ConcurrentHashMap<>(); static boolean isSafeClass(Class cls) {