This is an automated email from the ASF dual-hosted git repository.

dineshkumar-yadav pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 37b6e02c4 RANGER-5687: Add feature flag to artifacts for RANGER-5628 
(#1073)
37b6e02c4 is described below

commit 37b6e02c4d3b989790bbd669b7d5d4366f7f7644
Author: fmorg-git <[email protected]>
AuthorDate: Mon Jul 20 02:25:51 2026 -0700

    RANGER-5687: Add feature flag to artifacts for RANGER-5628 (#1073)
    
    * add feature flag to artifacts for RANGER-5628
    
    * bug fixes - missing flag on patch and if flag is on and condition set on 
resource policy, then flag is off, ui hangs
    
    (cherry picked from commit e25cdb00df8ca54a75bb998863ede76e8d52148f)
    
    * fix checkstyle issue
    
    (cherry picked from commit d06e4049a352ee3caad45a561098a7031ada557f)
    
    * Confine Ozone action-policy gating to plugin-ozone module.
    
    Move enableOzoneActionPolicy handling out of RangerInlinePolicyEvaluator
    into RangerOzoneAuthorizer, including legacy session-policy sanitization
    and a unit test for flag-off behavior with embedded grant actions.
    
    * RANGER-5687: read ozone action-policy flag without agents-common changes.
    
    Use ServiceDefUtil.getBooleanValue in plugin-ozone and security-admin per 
PR review, and revert agents-common ozone-specific additions.
    
    * Scope action-matcher option to ozone service-def only.
    
    Rename enableOzoneActionPolicy to enableActionMatcherInPoliciesCondition and
    admin config to 
ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition.
    Non-ozone service defs always get false; ozone reads site config.
    Addresses PR review from fimugdha.
    
    * fix checkstyle issues
    
    * remove agents-common modification per mneethiraj and address fimugdha 
comments
    
    * Persist ozone action-matcher flag in J10065 def_options upgrade.
    
    On upgrade, sync enableActionMatcherInPoliciesCondition from admin config 
into ozone def_options only, alongside existing policyConditions updates for 
action-matches.
    
    * Add ozone action-matcher docker flag and align J10065 def_options sync.
    
    Wire RANGER_OZONE_ENABLE_ACTION_MATCHER into ranger-docker so admin setup
    reads the flag before J10065 runs, fix the def_options constant, and update
    patch unit tests after E2E validation on Mac with fresh Postgres installs.
    
    * Simplify ozone docker flag script and restore generic BUILD_OPTS.
    
    Use update_property.py from the admin tarball instead of inline Python,
    and keep BUILD_OPTS empty so ranger-docker builds remain full by default.
    
    * Fix ImportOrder checkstyle violation in J10065 patch.
    
    * Make ozone action-matcher flag follow admin config at runtime.
    
    Stale def_options from an earlier J10065 run or the pre-rename 
enableOzoneActionPolicy
    option could override 
ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition,
    hiding action-matches in Admin UI and ozone authorizer even when the flag 
was set true.
    
    Admin config is now authoritative when serving the ozone service-def, and 
action-matches
    is restored from the embedded def when enabled but missing from DB.
    
    * Remove legacy enableOzoneActionPolicy handling.
    
    The renamed enableActionMatcherInPoliciesCondition option and admin runtime
    overlay make enableOzoneActionPolicy obsolete for 3.0.
    
    * pr review comment for mneethiraj - don't automatically disable 
action-matches for non-Ozone service definition
    
    * pr review comments for mneethiraj - don't reference feature flag in ui
    
    * pr review comment for mneethiraj - revert updates to patch
    
    * pr review comment for mneethiraj - rename 
PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION to 
PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE
    
    * add clarification statement for docker
    
    * Update RangerOzoneAuthorizer.java
    
    * pr review update for mneethiraj - revamp Docker handling
    
    * remove no longer valid unit test
    
    * renamed FF_ENAB_OZONE_ACTION_MATCHES_CONDITION to 
FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION
    
    ---------
    
    Co-authored-by: Fabian Morgan <[email protected]>
    Co-authored-by: ramk <[email protected]>
    Co-authored-by: Madhan Neethiraj <[email protected]>
---
 dev-support/ranger-docker/.env                     |   2 +-
 dev-support/ranger-docker/README.md                |  46 ++++++++
 .../admin/ranger-admin-install-mysql.properties    |   3 +
 .../admin/ranger-admin-install-oracle.properties   |   3 +
 .../admin/ranger-admin-install-postgres.properties |   3 +
 .../ranger-admin-install-sqlserver.properties      |   3 +
 .../ozone/authorizer/RangerOzoneAuthorizer.java    |  43 ++++++-
 .../authorizer/TestRangerOzoneAuthorizer.java      | 131 +++++++++++++++++++++
 security-admin/scripts/install.properties          |   3 +
 security-admin/scripts/setup.sh                    |  11 ++
 .../ranger/service/RangerServiceDefService.java    | 112 ++++++++++++++++++
 .../conf.dist/ranger-admin-default-site.xml        |   8 ++
 .../main/resources/conf.dist/ranger-admin-site.xml |   4 +
 .../main/webapp/react-webapp/src/utils/XAUtils.js  |   2 +-
 .../views/GovernedData/Dataset/AccessGrantForm.jsx |   6 +-
 .../views/PolicyListing/AddUpdatePolicyForm.jsx    |  12 +-
 .../service/TestRangerServiceDefService.java       | 116 +++++++++++++++++-
 17 files changed, 493 insertions(+), 15 deletions(-)

diff --git a/dev-support/ranger-docker/.env b/dev-support/ranger-docker/.env
index 8ca362eab..c6439db0e 100644
--- a/dev-support/ranger-docker/.env
+++ b/dev-support/ranger-docker/.env
@@ -6,7 +6,7 @@ PROFILE=
 BUILD_OPTS=
 
 # Java Opts Configuration in JDK17
-JAVA_OPTS=--add-opens=java.base/java.nio=ALL-UNNAMED 
--add-exports=java.base/sun.net.dns=ALL-UNNAMED 
--add-exports=java.base/sun.net.util=ALL-UNNAMED 
--add-opens=java.base/java.lang=ALL-UNNAMED 
--add-exports=java.base/java.util.logging=ALL-UNNAMED 
--add-opens=java.base/java.io=ALL-UNNAMED
+JAVA_OPTS="--add-opens=java.base/java.nio=ALL-UNNAMED 
--add-exports=java.base/sun.net.dns=ALL-UNNAMED 
--add-exports=java.base/sun.net.util=ALL-UNNAMED 
--add-opens=java.base/java.lang=ALL-UNNAMED 
--add-exports=java.xml.crypto/com.sun.org.apache.xml.internal.security.utils=ALL-UNNAMED"
 
 # DockerHub Ranger Base Image
 RANGER_BASE_IMAGE=apache/ranger-base
diff --git a/dev-support/ranger-docker/README.md 
b/dev-support/ranger-docker/README.md
index 1ddd9c3fd..4c09881c5 100644
--- a/dev-support/ranger-docker/README.md
+++ b/dev-support/ranger-docker/README.md
@@ -94,10 +94,56 @@ docker compose -f docker-compose.ranger.yml -f 
docker-compose.ranger-hadoop.yml
 docker compose -f docker-compose.ranger.yml -f 
docker-compose.ranger-hadoop.yml -f docker-compose.ranger-hbase.yml up -d
 ~~~
 #### Bring up ozone containers
+
+##### Ozone action-matcher feature flag
+
+The flag is controlled at runtime by
+`ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition` in
+`ranger-admin-site.xml`. Docker maps it from
+`FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION` in
+`scripts/admin/ranger-admin-install-*.properties` during Admin setup.
+
+**Prerequisite:** the admin distribution must include an uncommented property
+entry in `conf.dist/ranger-admin-site.xml`. Rebuild dist before building the
+Admin image:
+
+~~~
+docker compose -f docker-compose.ranger-build.yml build
+docker compose -f docker-compose.ranger-build.yml up
+~~~
+
+**First-time setup:** set `FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=true` in
+`scripts/admin/ranger-admin-install-<db>.properties`, then bring up services.
+
+**Changing the flag later** (choose one):
+
+1. Edit `FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION` in
+   `scripts/admin/ranger-admin-install-<db>.properties` and recreate Admin so
+   setup runs again:
+   ~~~
+   docker compose -f docker-compose.ranger.yml -f 
docker-compose.ranger-ozone.yml \
+     up -d --build --force-recreate ranger
+   ~~~
+   Works even if the DB already exists; setup re-runs on a fresh container.
+
+2. Edit the live value in the container's
+   `ranger-admin-site.xml` and restart Admin.
+
+`install.properties` is not re-read on restart alone — only when setup runs.
+`RangerServiceDefService` applies the site.xml value when serving the ozone
+service-def.
+
 ~~~
 ./scripts/ozone/ozone-plugin-docker-setup.sh
 docker compose -f docker-compose.ranger.yml -f docker-compose.ranger-ozone.yml 
up -d
 ~~~
+
+Verify (after login):
+
+~~~
+curl -s -u admin:rangerR0cks! 
http://localhost:6080/service/plugins/definitions/name/ozone \
+  | python3 -c "import json,sys; d=json.load(sys.stdin); print('options', 
d.get('options')); print('conditions', [c['name'] for c in 
d.get('policyConditions',[])])"
+~~~
 #### Bring up trino container (requires docker build with jdk 11):
 ~~~
 docker compose -f docker-compose.ranger.yml -f docker-compose.ranger-trino.yml 
up -d
diff --git 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-mysql.properties 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-mysql.properties
index 18a4c8da7..14b4330ad 100644
--- 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-mysql.properties
+++ 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-mysql.properties
@@ -59,6 +59,9 @@ audit_elasticsearch_bootstrap_enabled=true
 policymgr_external_url=http://ranger-admin:6080
 policymgr_http_enabled=true
 
+# Enable Ozone action-matches policy condition (maps to ranger-admin-site.xml 
at setup)
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=false
+
 unix_user=ranger
 unix_user_pwd=ranger
 unix_group=ranger
diff --git 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-oracle.properties
 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-oracle.properties
index 22b177c02..4748dc0dc 100644
--- 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-oracle.properties
+++ 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-oracle.properties
@@ -61,6 +61,9 @@ audit_elasticsearch_bootstrap_enabled=true
 policymgr_external_url=http://ranger-admin:6080
 policymgr_http_enabled=true
 
+# Enable Ozone action-matches policy condition (maps to ranger-admin-site.xml 
at setup)
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=false
+
 unix_user=ranger
 unix_user_pwd=ranger
 unix_group=ranger
diff --git 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-postgres.properties
 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-postgres.properties
index fc8e8682a..80c18df4e 100644
--- 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-postgres.properties
+++ 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-postgres.properties
@@ -74,6 +74,9 @@ audit_opensearch_bootstrap_enabled=true
 policymgr_external_url=http://ranger-admin:6080
 policymgr_http_enabled=true
 
+# Enable Ozone action-matches policy condition (maps to ranger-admin-site.xml 
at setup)
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=false
+
 unix_user=ranger
 unix_user_pwd=ranger
 unix_group=ranger
diff --git 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-sqlserver.properties
 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-sqlserver.properties
index 8a1919374..40f77c3fd 100644
--- 
a/dev-support/ranger-docker/scripts/admin/ranger-admin-install-sqlserver.properties
+++ 
b/dev-support/ranger-docker/scripts/admin/ranger-admin-install-sqlserver.properties
@@ -68,6 +68,9 @@ audit_elasticsearch_bootstrap_enabled=true
 policymgr_external_url=http://ranger-admin:6080
 policymgr_http_enabled=true
 
+# Enable Ozone action-matches policy condition (maps to ranger-admin-site.xml 
at setup)
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=false
+
 unix_user=ranger
 unix_user_pwd=ranger
 unix_group=ranger
diff --git 
a/plugin-ozone/src/main/java/org/apache/ranger/authorization/ozone/authorizer/RangerOzoneAuthorizer.java
 
b/plugin-ozone/src/main/java/org/apache/ranger/authorization/ozone/authorizer/RangerOzoneAuthorizer.java
index f7d61fec2..95094bd10 100644
--- 
a/plugin-ozone/src/main/java/org/apache/ranger/authorization/ozone/authorizer/RangerOzoneAuthorizer.java
+++ 
b/plugin-ozone/src/main/java/org/apache/ranger/authorization/ozone/authorizer/RangerOzoneAuthorizer.java
@@ -41,6 +41,7 @@
 import org.apache.ranger.plugin.service.RangerBasePlugin;
 import org.apache.ranger.plugin.util.JsonUtilsV2;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -74,6 +75,8 @@ public class RangerOzoneAuthorizer implements 
IAccessAuthorizer {
 
     private static final String S3_VOLUME_NAME = "s3Vol";
 
+    private static final String 
OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION = 
"enableActionMatcherInPoliciesCondition";
+
     private static volatile RangerBasePlugin rangerPlugin;
 
     public RangerOzoneAuthorizer() {
@@ -168,7 +171,11 @@ public boolean checkAccess(IOzoneObj ozoneObject, 
RequestContext context) {
         rangerResource.setOwnerUser(context.getOwnerName());
         rangerRequest.setResource(rangerResource);
         rangerRequest.setAccessType(accessType);
-        rangerRequest.setAction(context.getS3Action());
+        if (isOzoneActionPolicyEnabled(plugin)) {
+            rangerRequest.setAction(context.getS3Action());
+        } else {
+            rangerRequest.setAction(accessType);
+        }
         rangerRequest.setRequestData(resource);
         rangerRequest.setClusterName(clusterName);
 
@@ -192,7 +199,8 @@ public boolean checkAccess(IOzoneObj ozoneObject, 
RequestContext context) {
 
         try {
             if (StringUtils.isNotBlank(context.getSessionPolicy())) {
-                
rangerRequest.setInlinePolicy(JsonUtilsV2.jsonToObj(context.getSessionPolicy(), 
RangerInlinePolicy.class));
+                RangerInlinePolicy inlinePolicy = 
JsonUtilsV2.jsonToObj(context.getSessionPolicy(), RangerInlinePolicy.class);
+                
rangerRequest.setInlinePolicy(sanitizeInlinePolicyForActionFlag(inlinePolicy, 
plugin));
             }
 
             RangerAccessResult result = plugin.isAccessAllowed(rangerRequest);
@@ -313,9 +321,12 @@ private static RangerInlinePolicy.Grant 
toRangerGrant(OzoneGrant ozoneGrant, Ran
             
ret.setPermissions(ozoneGrant.getPermissions().stream().map(RangerOzoneAuthorizer::toRangerPermission).filter(Objects::nonNull).collect(Collectors.toSet()));
         }
 
-        final Set<String> s3Actions = ozoneGrant.getS3Actions();
-        if (s3Actions != null && !s3Actions.isEmpty()) {
-            ret.setActions(s3Actions);
+        if (isOzoneActionPolicyEnabled(plugin)) {
+            final Set<String> s3Actions = ozoneGrant.getS3Actions();
+
+            if (s3Actions != null && !s3Actions.isEmpty()) {
+                ret.setActions(s3Actions);
+            }
         }
 
         LOG.debug("toRangerGrant(ozoneGrant={}): ret={}", ozoneGrant, ret);
@@ -384,4 +395,26 @@ private static String toRangerPermission(ACLType acl) {
 
         return null;
     }
+
+    private static boolean isOzoneActionPolicyEnabled(final RangerBasePlugin 
plugin) {
+        return plugin != null
+                && plugin.getServiceDef() != null
+                && 
ServiceDefUtil.getBooleanValue(plugin.getServiceDef().getOptions(), 
OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, false);
+    }
+
+    /**
+     * When action-policy is disabled, strip grant actions so generic inline 
evaluation
+     * does not enforce S3 actions (same effect as omitting actions in {@link 
#toRangerGrant}).
+     */
+    static RangerInlinePolicy 
sanitizeInlinePolicyForActionFlag(RangerInlinePolicy policy, RangerBasePlugin 
plugin) {
+        if (policy != null && policy.getGrants() != null && 
!isOzoneActionPolicyEnabled(plugin)) {
+            for (RangerInlinePolicy.Grant grant : policy.getGrants()) {
+                if (grant != null) {
+                    grant.setActions(null);
+                }
+            }
+        }
+
+        return policy;
+    }
 }
diff --git 
a/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
 
b/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
index a715e9c6f..7a90e758d 100644
--- 
a/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
+++ 
b/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
@@ -37,7 +37,9 @@
 import java.net.InetAddress;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -53,8 +55,10 @@ public class TestRangerOzoneAuthorizer {
     private static final String RANGER_APP_ID       = "om";
     private static final String OZONE_SERVICE_ID    = "om";
     private static final String OWNER_NAME          = "ozone";
+    private static final String 
OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION = 
"enableActionMatcherInPoliciesCondition";
 
     private static RangerOzoneAuthorizer ozoneAuthorizer;
+    private static RangerBasePlugin    testPlugin;
 
     private final String               hostname  = "localhost";
     private final InetAddress          ipAddress = 
InetAddress.getLoopbackAddress();
@@ -85,7 +89,9 @@ public static void setUpBeforeClass() {
 
         // loads policies from om_dev_ozone.json, by 
EmbeddedResourcePolicySource configured in ranger-ozone-security.xml
         plugin.init();
+        setOzoneActionPolicyEnabled(plugin);
 
+        testPlugin      = plugin;
         ozoneAuthorizer = new RangerOzoneAuthorizer(plugin);
 
         assertNotNull(ozoneAuthorizer);
@@ -273,4 +279,129 @@ public void testCheckAccessWithS3Action() throws 
Exception {
         assertFalse(ozoneAuthorizer.checkAccess(key1, ctxWriteNoAction),
                 "session-policy should deny write on key1 when no S3 action is 
specified and grant has S3 actions");
     }
+
+    @Test
+    public void testAssumeRoleWithS3ActionsNotPropagatedWhenFlagDisabled() 
throws Exception {
+        final String previous = setOzoneActionPolicyDisabled();
+
+        try {
+            final Set<OzoneGrant>   grants  = 
Collections.singleton(grantWriteWithS3Actions);
+            final AssumeRoleRequest request = new AssumeRoleRequest(hostname, 
ipAddress, user1, role1, grants);
+
+            final String sessionPolicy = 
ozoneAuthorizer.generateAssumeRoleSessionPolicy(request);
+
+            assertNotNull(sessionPolicy);
+
+            final RangerInlinePolicy inlinePolicy = 
JsonUtilsV2.jsonToObj(sessionPolicy, RangerInlinePolicy.class);
+            final RangerInlinePolicy.Grant grant  = 
inlinePolicy.getGrants().iterator().next();
+
+            assertNull(grant.getActions(), "S3 actions should not be 
propagated when ozone action policy is disabled");
+        } finally {
+            restoreOzoneActionPolicyEnabled(previous);
+        }
+    }
+
+    @Test
+    public void testCheckAccessIgnoresS3ActionWhenFlagDisabled() throws 
Exception {
+        final String previous = setOzoneActionPolicyDisabled();
+
+        try {
+            final Set<OzoneGrant>   grants  = 
Collections.singleton(grantWriteWithS3Actions);
+            final AssumeRoleRequest request = new AssumeRoleRequest(hostname, 
ipAddress, user1, role1, grants);
+
+            final String sessionPolicy = 
ozoneAuthorizer.generateAssumeRoleSessionPolicy(request);
+
+            assertNotNull(sessionPolicy);
+
+            final RequestContext ctxWriteGetObject = reqCtxBuilder
+                    .setAclRights(IAccessAuthorizer.ACLType.WRITE)
+                    .setRecursiveAccessCheck(false)
+                    .setSessionPolicy(sessionPolicy)
+                    .setS3Action("GetObject")
+                    .build();
+
+            assertTrue(ozoneAuthorizer.checkAccess(key1, ctxWriteGetObject),
+                    "session-policy should allow write when S3 action 
enforcement is disabled");
+
+            final RequestContext ctxWriteNoAction = reqCtxBuilder
+                    .setAclRights(IAccessAuthorizer.ACLType.WRITE)
+                    .setRecursiveAccessCheck(false)
+                    .setSessionPolicy(sessionPolicy)
+                    .setS3Action(null)
+                    .build();
+
+            assertTrue(ozoneAuthorizer.checkAccess(key1, ctxWriteNoAction),
+                    "session-policy should allow write when S3 action 
enforcement is disabled");
+        } finally {
+            restoreOzoneActionPolicyEnabled(previous);
+        }
+    }
+
+    @Test
+    public void testLegacySessionPolicyActionsStrippedWhenFlagDisabled() 
throws Exception {
+        // Simulate a session policy issued when action-policy was enabled 
(actions embedded in JSON).
+        Set<OzoneGrant>   grants  = 
Collections.singleton(grantWriteWithS3Actions);
+        AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, 
user1, role1, grants);
+
+        String legacySessionPolicy = 
ozoneAuthorizer.generateAssumeRoleSessionPolicy(request);
+
+        RangerInlinePolicy legacyPolicy = 
JsonUtilsV2.jsonToObj(legacySessionPolicy, RangerInlinePolicy.class);
+        RangerInlinePolicy.Grant legacyGrant = 
legacyPolicy.getGrants().iterator().next();
+
+        assertNotNull(legacyGrant.getActions(),
+                "legacy session policy should contain S3 actions as if created 
with flag enabled");
+
+        final String previous = setOzoneActionPolicyDisabled();
+
+        try {
+            RangerInlinePolicy sanitized = 
RangerOzoneAuthorizer.sanitizeInlinePolicyForActionFlag(legacyPolicy, 
testPlugin);
+
+            assertNull(sanitized.getGrants().iterator().next().getActions(),
+                    "sanitizeInlinePolicyForActionFlag should strip grant 
actions when flag is disabled");
+
+            RequestContext ctxWriteGetObject = reqCtxBuilder
+                    .setAclRights(IAccessAuthorizer.ACLType.WRITE)
+                    .setRecursiveAccessCheck(false)
+                    .setSessionPolicy(legacySessionPolicy)
+                    .setS3Action("GetObject")
+                    .build();
+
+            assertTrue(ozoneAuthorizer.checkAccess(key1, ctxWriteGetObject),
+                    "legacy session-policy with embedded S3 actions should 
allow write when flag is disabled");
+        } finally {
+            restoreOzoneActionPolicyEnabled(previous);
+        }
+    }
+
+    private static void setOzoneActionPolicyEnabled(RangerBasePlugin plugin) {
+        if (plugin == null || plugin.getServiceDef() == null) {
+            return;
+        }
+
+        Map<String, String> options = plugin.getServiceDef().getOptions();
+
+        if (options == null) {
+            options = new HashMap<>();
+            plugin.getServiceDef().setOptions(options);
+        }
+
+        options.put(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, 
Boolean.toString(true));
+    }
+
+    private static String setOzoneActionPolicyDisabled() {
+        final Map<String, String> options = 
testPlugin.getServiceDef().getOptions();
+        final String previous = 
options.put(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, 
Boolean.toString(false));
+
+        return previous;
+    }
+
+    private static void restoreOzoneActionPolicyEnabled(String previous) {
+        final Map<String, String> options = 
testPlugin.getServiceDef().getOptions();
+
+        if (previous == null) {
+            options.remove(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION);
+        } else {
+            options.put(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, 
previous);
+        }
+    }
 }
diff --git a/security-admin/scripts/install.properties 
b/security-admin/scripts/install.properties
index e8a9f2f81..6a6ababc0 100644
--- a/security-admin/scripts/install.properties
+++ b/security-admin/scripts/install.properties
@@ -152,6 +152,9 @@ policymgr_https_keystore_password=
 #Example :  policymgr_supportedcomponents=hive,hbase,hdfs
 policymgr_supportedcomponents=
 
+# Enable Ozone action-matches policy condition in Admin UI and authorizer
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=false
+
 #
 # ------- PolicyManager CONFIG - END ---------------
 #
diff --git a/security-admin/scripts/setup.sh b/security-admin/scripts/setup.sh
index ae2048edc..b0bc26214 100755
--- a/security-admin/scripts/setup.sh
+++ b/security-admin/scripts/setup.sh
@@ -175,6 +175,7 @@ cred_keystore_filename=$(eval echo "$(get_prop 
'cred_keystore_filename' $PROPFIL
 sso_enabled=$(get_prop 'sso_enabled' $PROPFILE)
 sso_providerurl=$(get_prop 'sso_providerurl' $PROPFILE)
 sso_publickey=$(get_prop 'sso_publickey' $PROPFILE)
+FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION=$(get_prop_or_default 
'FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION' $PROPFILE 'false')
 RANGER_ADMIN_LOG_DIR=$(eval echo "$(get_prop 'RANGER_ADMIN_LOG_DIR' 
$PROPFILE)")
 RANGER_ADMIN_LOGBACK_CONF_FILE=$(eval echo "$(get_prop 
'RANGER_ADMIN_LOGBACK_CONF_FILE' $PROPFILE)")
 RANGER_PID_DIR_PATH=$(eval echo "$(get_prop 'RANGER_PID_DIR_PATH' $PROPFILE)")
@@ -1090,6 +1091,16 @@ update_properties() {
                 updatePropertyToFilePy $propertyName "${newPropertyValue}" 
$to_file_ranger
 
        fi
+
+       ff_enable_ozone_action_matches_condition=$(echo 
"${FF_ENABLE_OZONE_ACTION_MATCHES_CONDITION}" | tr '[:upper:]' '[:lower:]')
+       if [ "${ff_enable_ozone_action_matches_condition}" != "true" ]
+       then
+               ff_enable_ozone_action_matches_condition=false
+       fi
+       
propertyName=ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition
+       newPropertyValue="${ff_enable_ozone_action_matches_condition}"
+       updatePropertyToFilePy $propertyName "${newPropertyValue}" 
$to_file_ranger
+
        if [ "${javax_net_ssl_keyStore}" != "" ]  && [ 
"${javax_net_ssl_keyStorePassword}" != "" ]
        then
                javax_net_ssl_keyStoreAlias=keyStoreAlias
diff --git 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefService.java
 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefService.java
index 5bdd3ad90..78e269aa6 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefService.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefService.java
@@ -21,17 +21,24 @@
 import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
 import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import 
org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 @Service
 @Scope("singleton")
 public class RangerServiceDefService extends 
RangerServiceDefServiceBase<XXServiceDef, RangerServiceDef> {
+    public static final String 
PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE = 
"ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition";
+    public static final String 
OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION = 
"enableActionMatcherInPoliciesCondition";
+
+    private static final String POLICY_CONDITION_ACTION_MATCHES = 
"action-matches";
+
     private final RangerAdminConfig config;
 
     public RangerServiceDefService() {
@@ -101,4 +108,109 @@ protected RangerServiceDef 
mapEntityToViewBean(RangerServiceDef vObj, XXServiceD
 
         return ret;
     }
+
+    @Override
+    protected RangerServiceDef populateViewBean(XXServiceDef xServiceDef) {
+        final RangerServiceDef ret = super.populateViewBean(xServiceDef);
+
+        applyActionMatcherInPoliciesConditionHiddenOption(ret);
+
+        return ret;
+    }
+
+    void applyActionMatcherInPoliciesConditionHiddenOption(RangerServiceDef 
serviceDef) {
+        if (serviceDef == null) {
+            return;
+        }
+
+        final boolean isOzoneServiceDef = 
StringUtils.equalsIgnoreCase(serviceDef.getName(), 
EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+
+        if (!isOzoneServiceDef) {
+            return;
+        }
+
+        Map<String, String> serviceDefOptions = serviceDef.getOptions();
+
+        if (serviceDefOptions == null) {
+            serviceDefOptions = new HashMap<>();
+            serviceDef.setOptions(serviceDefOptions);
+        }
+
+        // Admin site config is authoritative at runtime; stale def_options 
must not override it.
+        boolean enabled = 
config.getBoolean(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE, 
false);
+
+        
serviceDefOptions.put(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, 
Boolean.toString(enabled));
+        serviceDef.setOptions(serviceDefOptions);
+
+        if (enabled) {
+            ensureActionMatchesPolicyCondition(serviceDef);
+        } else {
+            removeActionMatchesPolicyCondition(serviceDef);
+        }
+    }
+
+    private void ensureActionMatchesPolicyCondition(RangerServiceDef 
serviceDef) {
+        if (hasActionMatchesPolicyCondition(serviceDef)) {
+            return;
+        }
+
+        try {
+            final RangerServiceDef embeddedOzoneServiceDef = 
EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+
+            if (embeddedOzoneServiceDef == null || 
embeddedOzoneServiceDef.getPolicyConditions() == null) {
+                return;
+            }
+
+            for (RangerPolicyConditionDef embeddedPolicyConditionDef : 
embeddedOzoneServiceDef.getPolicyConditions()) {
+                if (StringUtils.equals(embeddedPolicyConditionDef.getName(), 
POLICY_CONDITION_ACTION_MATCHES)) {
+                    List<RangerPolicyConditionDef> policyConditions = 
serviceDef.getPolicyConditions();
+
+                    if (policyConditions == null) {
+                        policyConditions = new ArrayList<>();
+                        serviceDef.setPolicyConditions(policyConditions);
+                    }
+
+                    policyConditions.add(embeddedPolicyConditionDef);
+
+                    return;
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to restore ozone action-matches 
policy condition", e);
+        }
+    }
+
+    private void removeActionMatchesPolicyCondition(RangerServiceDef 
serviceDef) {
+        List<RangerPolicyConditionDef> policyConditions = 
serviceDef.getPolicyConditions();
+
+        if (policyConditions == null || policyConditions.isEmpty()) {
+            return;
+        }
+
+        List<RangerPolicyConditionDef> filteredPolicyConditions = new 
ArrayList<>();
+
+        for (RangerPolicyConditionDef policyConditionDef : policyConditions) {
+            if (!StringUtils.equals(policyConditionDef.getName(), 
POLICY_CONDITION_ACTION_MATCHES)) {
+                filteredPolicyConditions.add(policyConditionDef);
+            }
+        }
+
+        serviceDef.setPolicyConditions(filteredPolicyConditions);
+    }
+
+    private static boolean hasActionMatchesPolicyCondition(RangerServiceDef 
serviceDef) {
+        List<RangerPolicyConditionDef> policyConditions = 
serviceDef.getPolicyConditions();
+
+        if (policyConditions == null || policyConditions.isEmpty()) {
+            return false;
+        }
+
+        for (RangerPolicyConditionDef policyConditionDef : policyConditions) {
+            if (StringUtils.equals(policyConditionDef.getName(), 
POLICY_CONDITION_ACTION_MATCHES)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
diff --git 
a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml 
b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
index a69d5886d..164b63d02 100644
--- a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
+++ b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
@@ -152,6 +152,14 @@
                <name>ranger.resource.accessControl.enabled</name>
                <value>true</value>
        </property>
+       <property>
+               
<name>ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition</name>
+               <value>false</value>
+               <description>
+                       When true, enables Ozone action-matches 
(RangerActionMatcher) policy conditions
+                       in the Admin UI and applies S3 action-based evaluation 
in the Ozone authorizer.
+               </description>
+       </property>
        <property>
                <name>ranger.xuser.createdByUserId</name>
                <value>1</value>
diff --git a/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml 
b/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml
index 4effba2da..388ce1674 100644
--- a/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml
+++ b/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml
@@ -506,4 +506,8 @@
                <name>xasecure.audit.jaas.Client.option.principal</name>
                <value></value>
        </property>
+    <property>
+        
<name>ranger.servicedef.ozone.enableActionMatcherInPoliciesCondition</name>
+        <value>false</value>
+    </property>
 </configuration>
diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js 
b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
index a39a24f45..382305c7f 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
@@ -1495,7 +1495,7 @@ export const requestDataTitle = (serviceType) => {
 //Policy condition evaluation
 
 export const policyConditionUpdatedJSON = (policyCond) => {
-  let newPolicyConditionJSON = [...policyCond];
+  let newPolicyConditionJSON = [...(Array.isArray(policyCond) ? policyCond : 
[])];
   newPolicyConditionJSON.filter(function (key) {
     if (!key?.uiHint || key?.uiHint == "") {
       if (
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
index aed34bddb..e53402f6c 100755
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
@@ -268,7 +268,7 @@ function AccessGrantForm({
 
         for (let data of val.conditions) {
           let conditionObj = find(
-            policyConditionUpdatedJSON(serviceCompDetails?.policyConditions),
+            policyConditionUpdatedJSON(serviceCompDetails?.policyConditions || 
[]),
             function (m) {
               if (m.name == data.type) {
                 return m;
@@ -276,7 +276,9 @@ function AccessGrantForm({
             }
           );
 
-          if (!isEmpty(conditionObj.uiHint)) {
+          // Ignore policy conditions that are not defined in the service-def.
+          // Without this guard, form initialization can fail and crash the 
page.
+          if (conditionObj?.uiHint && !isEmpty(conditionObj.uiHint)) {
             obj.conditions[data?.type] = JSON.parse(conditionObj.uiHint)
               .isMultiValue
               ? data?.values.map((m) => {
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
index b4e6f03ab..5957f7658 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
@@ -512,7 +512,7 @@ export default function AddUpdatePolicyForm() {
         data.conditions = {};
         for (let val of policyData.conditions) {
           let conditionObj = find(
-            policyConditionUpdatedJSON(serviceCompData?.policyConditions),
+            policyConditionUpdatedJSON(serviceCompData?.policyConditions || 
[]),
             function (m) {
               if (m.name == val.type) {
                 return m;
@@ -520,7 +520,9 @@ export default function AddUpdatePolicyForm() {
             }
           );
 
-          if (!isEmpty(conditionObj.uiHint)) {
+          // Ignore policy conditions that are not defined in the service-def.
+          // Without this guard, form initialization can fail and leave the 
page on the loader.
+          if (conditionObj?.uiHint && !isEmpty(conditionObj.uiHint)) {
             data.conditions[val?.type] = JSON.parse(conditionObj.uiHint)
               .isMultiValue
               ? val?.values
@@ -702,7 +704,7 @@ export default function AddUpdatePolicyForm() {
 
         for (let data of val.conditions) {
           let conditionObj = find(
-            policyConditionUpdatedJSON(serviceData?.policyConditions),
+            policyConditionUpdatedJSON(serviceData?.policyConditions || []),
             function (m) {
               if (m.name == data.type) {
                 return m;
@@ -710,7 +712,9 @@ export default function AddUpdatePolicyForm() {
             }
           );
 
-          if (!isEmpty(conditionObj.uiHint)) {
+          // Ignore policy conditions that are not defined in the service-def.
+          // Without this guard, form initialization can fail and leave the 
page on the loader.
+          if (conditionObj?.uiHint && !isEmpty(conditionObj.uiHint)) {
             obj.conditions[data?.type] = JSON.parse(conditionObj.uiHint)
               .isMultiValue
               ? data?.values
diff --git 
a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceDefService.java
 
b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceDefService.java
index c536f9942..41d0be2d9 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceDefService.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceDefService.java
@@ -17,6 +17,7 @@
 package org.apache.ranger.service;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
 import org.apache.ranger.biz.RangerBizUtil;
 import org.apache.ranger.common.ContextUtil;
 import org.apache.ranger.common.PropertiesUtil;
@@ -54,6 +55,7 @@
 import 
org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.apache.ranger.security.context.RangerContextHolder;
 import org.apache.ranger.security.context.RangerSecurityContext;
@@ -71,8 +73,10 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 
+import static 
org.apache.ranger.service.RangerServiceDefService.PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE;
 import static 
org.apache.ranger.service.RangerServiceDefService.PROP_ENABLE_IMPLICIT_CONDITION_EXPRESSION;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -92,7 +96,8 @@
 @ExtendWith(MockitoExtension.class)
 @TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerServiceDefService {
-    private static final Long Id = 8L;
+    private static final Long   Id                                = 8L;
+    private static final String 
OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION = 
RangerServiceDefService.OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION;
     @InjectMocks
     RangerServiceDefService               serviceDefService;
     @Mock
@@ -764,7 +769,7 @@ public void testMapViewToEntityBean() throws 
NoSuchMethodException {
         v.setRbKeyLabel("rbl");
         v.setRbKeyDescription("rbd");
         v.setIsEnabled(Boolean.TRUE);
-        v.setOptions(new java.util.HashMap<>());
+        v.setOptions(new HashMap<>());
 
         try {
             method.invoke(rangerServiceDefWithAssignedIdService, v, 
xxServiceDefWithAssignedId, 1);
@@ -782,6 +787,80 @@ public void testMapViewToEntityBean() throws 
NoSuchMethodException {
         }
     }
 
+    @Test
+    public void testOzoneActionPolicyOptionDisabled() {
+        
RangerAdminConfig.getInstance().set(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE,
 Boolean.FALSE.toString());
+
+        try {
+            RangerServiceDef serviceDef = 
buildOzoneServiceDefWithActionMatches();
+
+            
serviceDefService.applyActionMatcherInPoliciesConditionHiddenOption(serviceDef);
+
+            assertEquals("false", 
serviceDef.getOptions().get(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION));
+            assertFalse(hasActionMatchesCondition(serviceDef));
+        } finally {
+            
RangerAdminConfig.getInstance().unset(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE);
+        }
+    }
+
+    @Test
+    public void testOzoneActionPolicyOptionEnabled() {
+        
RangerAdminConfig.getInstance().set(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE,
 Boolean.TRUE.toString());
+
+        try {
+            RangerServiceDef serviceDef = 
buildOzoneServiceDefWithActionMatches();
+
+            
serviceDefService.applyActionMatcherInPoliciesConditionHiddenOption(serviceDef);
+
+            assertEquals("true", 
serviceDef.getOptions().get(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION));
+            assertTrue(hasActionMatchesCondition(serviceDef));
+        } finally {
+            
RangerAdminConfig.getInstance().unset(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE);
+        }
+    }
+
+    @Test
+    public void testOzoneActionPolicyConfigTrueOverridesStoredFalseOption() {
+        
RangerAdminConfig.getInstance().set(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE,
 Boolean.TRUE.toString());
+
+        try {
+            RangerServiceDef serviceDef = 
buildOzoneServiceDefWithActionMatches();
+            
serviceDef.getOptions().put(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION, 
Boolean.FALSE.toString());
+
+            
serviceDefService.applyActionMatcherInPoliciesConditionHiddenOption(serviceDef);
+
+            assertEquals("true", 
serviceDef.getOptions().get(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION));
+            assertTrue(hasActionMatchesCondition(serviceDef));
+        } finally {
+            
RangerAdminConfig.getInstance().unset(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE);
+        }
+    }
+
+    @Test
+    public void 
testOzoneActionPolicyConfigTrueRestoresMissingActionMatchesCondition() {
+        
RangerAdminConfig.getInstance().set(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE,
 Boolean.TRUE.toString());
+
+        try {
+            RangerPolicyConditionDef ipRange = new RangerPolicyConditionDef();
+            ipRange.setName("ip-range");
+
+            List<RangerPolicyConditionDef> policyConditions = new 
ArrayList<>();
+            policyConditions.add(ipRange);
+
+            RangerServiceDef serviceDef = new RangerServiceDef();
+            
serviceDef.setName(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+            serviceDef.setOptions(new HashMap<>());
+            serviceDef.setPolicyConditions(policyConditions);
+
+            
serviceDefService.applyActionMatcherInPoliciesConditionHiddenOption(serviceDef);
+
+            assertEquals("true", 
serviceDef.getOptions().get(OPTION_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION));
+            assertTrue(hasActionMatchesCondition(serviceDef));
+        } finally {
+            
RangerAdminConfig.getInstance().unset(PROP_ENABLE_ACTION_MATCHER_IN_POLICIES_CONDITION_FOR_OZONE);
+        }
+    }
+
     @Test
     public void testMapViewToEntityBean_intOverload_executes() throws 
Exception {
         Method method = 
RangerServiceDefWithAssignedIdService.class.getDeclaredMethod("mapViewToEntityBean",
 RangerServiceDef.class, XXServiceDefWithAssignedId.class, int.class);
@@ -832,6 +911,39 @@ public void testValidateForUpdate() throws 
NoSuchMethodException {
         }
     }
 
+    private boolean hasActionMatchesCondition(RangerServiceDef serviceDef) {
+        if (serviceDef.getPolicyConditions() == null) {
+            return false;
+        }
+
+        for (RangerPolicyConditionDef conditionDef : 
serviceDef.getPolicyConditions()) {
+            if (StringUtils.equals(conditionDef.getName(), "action-matches")) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private RangerServiceDef buildOzoneServiceDefWithActionMatches() {
+        RangerPolicyConditionDef ipRange = new RangerPolicyConditionDef();
+        ipRange.setName("ip-range");
+
+        RangerPolicyConditionDef actionMatches = new 
RangerPolicyConditionDef();
+        actionMatches.setName("action-matches");
+
+        List<RangerPolicyConditionDef> policyConditions = new ArrayList<>();
+        policyConditions.add(ipRange);
+        policyConditions.add(actionMatches);
+
+        RangerServiceDef serviceDef = new RangerServiceDef();
+        
serviceDef.setName(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+        serviceDef.setOptions(new HashMap<>());
+        serviceDef.setPolicyConditions(policyConditions);
+
+        return serviceDef;
+    }
+
     private RangerServiceDef rangerServiceDef() {
         List<RangerServiceConfigDef>   configs          = new ArrayList<>();
         List<RangerResourceDef>        resources        = new ArrayList<>();


Reply via email to