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

madhan 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 5da81ab22 RANGER-5295: fix GDS policy evaluation handling of 
row-filters (#646)
5da81ab22 is described below

commit 5da81ab22e0086a89334d613f322be6650bae210
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Thu Aug 28 12:50:16 2025 -0700

    RANGER-5295: fix GDS policy evaluation handling of row-filters (#646)
---
 .../policyengine/RangerPolicyEngineImpl.java       | 33 +++++++++++++---
 .../plugin/policyengine/gds/GdsPolicyEngine.java   | 21 +++++++++-
 .../policyengine/gds/gds_info_hive_row_filter.json |  5 +++
 .../gds/test_gds_policy_hive_row_filter.json       | 45 +++++++++++++++++++---
 4 files changed, 92 insertions(+), 12 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 15628e458..3ae85edf8 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -1072,12 +1072,25 @@ private void updateFromGdsResult(RangerAccessResult 
result) {
 
         if (gdsResult != null) {
             if (result.getPolicyType() == RangerPolicy.POLICY_TYPE_ACCESS) {
+                // pick access result from GDS policies only if there is no 
decision yet
                 if (!result.getIsAccessDetermined() && 
gdsResult.getIsAllowed()) {
-                    result.setIsAllowed(true);
-                    result.setIsAccessDetermined(true);
-                    result.setPolicyId(gdsResult.getPolicyId());
-                    result.setPolicyVersion(gdsResult.getPolicyVersion());
-                    
result.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_NORMAL);
+                    copyFromGdsResult(gdsResult, result);
+                }
+            } else if (result.getPolicyType() == 
RangerPolicy.POLICY_TYPE_ROWFILTER) {
+                // pick row-filter from GDS policies only if there is no 
decision yet
+                if (result.getPolicyId() == -1 && 
CollectionUtils.isNotEmpty(gdsResult.getRowFilters())) {
+                    copyFromGdsResult(gdsResult, result);
+
+                    result.setFilterExpr(gdsResult.getRowFilters().get(0));
+                }
+            } else if (result.getPolicyType() == 
RangerPolicy.POLICY_TYPE_DATAMASK) {
+                // pick data-mask from GDS policies only if there is no 
decision yet
+                if (result.getPolicyId() == -1 && 
StringUtils.isNotEmpty(gdsResult.getMaskType())) {
+                    copyFromGdsResult(gdsResult, result);
+
+                    result.setMaskType(gdsResult.getMaskType());
+                    result.setMaskedValue(gdsResult.getMaskedValue());
+                    result.setMaskCondition(gdsResult.getMaskCondition());
                 }
             }
 
@@ -1094,6 +1107,16 @@ private void updateFromGdsResult(RangerAccessResult 
result) {
         LOG.debug("<== updateFromGdsResult(result={})", result);
     }
 
+    private void copyFromGdsResult(GdsAccessResult gdsResult, 
RangerAccessResult result) {
+        if (gdsResult != null && result != null) {
+            result.setIsAllowed(true);
+            result.setIsAccessDetermined(true);
+            result.setPolicyId(gdsResult.getPolicyId());
+            result.setPolicyVersion(gdsResult.getPolicyVersion());
+            result.setPolicyPriority(RangerPolicy.POLICY_PRIORITY_NORMAL);
+        }
+    }
+
     private static class ServiceConfig {
         private final Set<String> auditExcludedUsers;
         private final Set<String> auditExcludedGroups;
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java
index 4bc1dc68b..2540eec96 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/gds/GdsPolicyEngine.java
@@ -62,6 +62,7 @@ public class GdsPolicyEngine {
     public static final String RESOURCE_NAME_PROJECT_ID = "project-id";
 
     private final ServiceGdsInfo                   gdsInfo;
+    private final RangerServiceDefHelper           serviceDefHelper;
     private final Set<String>                      allAccessTypes;
     private final Map<Long, GdsProjectEvaluator>   projects      = new 
HashMap<>();
     private final Map<Long, GdsDatasetEvaluator>   datasets      = new 
HashMap<>();
@@ -71,8 +72,9 @@ public class GdsPolicyEngine {
     public GdsPolicyEngine(ServiceGdsInfo gdsInfo, RangerServiceDefHelper 
serviceDefHelper, RangerPluginContext pluginContext) {
         LOG.debug("==> RangerGdsPolicyEngine()");
 
-        this.gdsInfo        = gdsInfo;
-        this.allAccessTypes = serviceDefHelper.getAllAccessTypes();
+        this.gdsInfo          = gdsInfo;
+        this.serviceDefHelper = serviceDefHelper;
+        this.allAccessTypes   = serviceDefHelper.getAllAccessTypes();
 
         init(serviceDefHelper, pluginContext);
 
@@ -95,7 +97,22 @@ public GdsAccessResult evaluate(RangerAccessRequest request) 
{
 
             if (ret.getIsAllowed()) {
                 evaluate(request, RangerPolicy.POLICY_TYPE_DATAMASK, ret);
+            }
+
+            // consider the following:
+            //   1. accessed resource is table table1
+            //   2. a shared-resource allows the user access to only few 
columns in table1
+            // In this case ret.getIsAllowed() will be false, since the user 
doesn't have access
+            // to all columns of table1; still, row-filter specified in the 
shared-resource must
+            // be included in the result.
+            if 
(serviceDefHelper.isRowFilterSupported(request.getResource().getKeys())) {
+                boolean isAccessAllowed = ret.getIsAllowed();
+
                 evaluate(request, RangerPolicy.POLICY_TYPE_ROWFILTER, ret);
+
+                if (!isAccessAllowed) {
+                    ret.setIsAllowed(false);
+                }
             }
         } else {
             ret = null;
diff --git 
a/agents-common/src/test/resources/policyengine/gds/gds_info_hive_row_filter.json
 
b/agents-common/src/test/resources/policyengine/gds/gds_info_hive_row_filter.json
index 76a2fe894..9b313fc7d 100644
--- 
a/agents-common/src/test/resources/policyengine/gds/gds_info_hive_row_filter.json
+++ 
b/agents-common/src/test/resources/policyengine/gds/gds_info_hive_row_filter.json
@@ -169,6 +169,11 @@
       "id": 61, "dataShareId": 6, "conditionExpr": "", "accessTypes": [ 
"select" ],
       "resource": { "database": { "values": [ "customers" ] }, "table": { 
"values": [ "contact_info" ] } }, "rowFilter": { "filterExpr": "country = 'US'" 
},
       "subResourceType": "column", "subResource": { "values": [ "*" ] }, 
"subResourceMasks": null
+    },
+    {
+      "id": 71, "dataShareId": 6, "conditionExpr": "", "accessTypes": [ 
"select" ],
+      "resource": { "database": { "values": [ "customers" ] }, "table": { 
"values": [ "shipping_address" ] } }, "rowFilter": { "filterExpr": "country = 
'US'" },
+      "subResourceType": "column", "subResource": { "values": [ "phone", 
"city", "zip" ] }, "subResourceMasks": [ { "values": [ "phone" ], "maskInfo": { 
"dataMaskType": "MASK_SHOW_LAST_4" } }]
     }
   ],
   "gdsVersion": 1
diff --git 
a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_row_filter.json
 
b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_row_filter.json
index 619eb3a14..4dbc256e6 100644
--- 
a/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_row_filter.json
+++ 
b/agents-common/src/test/resources/policyengine/gds/test_gds_policy_hive_row_filter.json
@@ -29,7 +29,7 @@
         "resource":   { "elements": { "database": "sales" } },
         "accessType": "", "user": "ds-user", "userGroups": []
       },
-      "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], 
"allowedByDatasets": [ "dataset-1" ], "isAllowed": true, "isAudited": true, 
"policyId": 2001, "rowFilters": [ "created_time >= '2023-01-01' and 
created_time < '2024-01-01'" ] }
+      "result": { "datasets": [ "dataset-1" ], "projects": [ "project-1" ], 
"allowedByDatasets": [ "dataset-1" ], "isAllowed": true, "isAudited": true, 
"policyId": 2001, "rowFilters": null }
     },
     {
       "name":    "table: finance.invoices, user: ds-user, access: select",
@@ -69,7 +69,7 @@
         "resource":   { "elements": { "database": "finance" } },
         "accessType": "", "user": "ds-user", "userGroups": []
       },
-      "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ 
"project-1" ], "allowedByDatasets": [ "dataset-1", "dataset-2" ], "isAllowed": 
true, "isAudited": true, "policyId": 2001, "rowFilters": [ "created_time >= 
'2023-01-01' and created_time < '2024-01-01'" ] }
+      "result": { "datasets": [ "dataset-1", "dataset-2" ], "projects": [ 
"project-1" ], "allowedByDatasets": [ "dataset-1", "dataset-2" ], "isAllowed": 
true, "isAudited": true, "policyId": 2001, "rowFilters": null }
     },
     {
       "name":    "table: shipping.shipments, user: ds-user, access: select",
@@ -85,7 +85,7 @@
         "resource":   { "elements": { "database": "shipping" } },
         "accessType": "", "user": "ds-user", "userGroups": []
       },
-      "result": { "datasets": [ "dataset-2" ], "projects": [ "project-1" ], 
"allowedByDatasets": [ "dataset-2" ], "isAllowed": true, "isAudited": true, 
"policyId": 2002, "rowFilters": [ "created_time >= '2023-01-01' and 
created_time < '2024-01-01'" ] }
+      "result": { "datasets": [ "dataset-2" ], "projects": [ "project-1" ], 
"allowedByDatasets": [ "dataset-2" ], "isAllowed": true, "isAudited": true, 
"policyId": 2002, "rowFilters": null }
     },
     {
       "name":    "table: customers.contact_info, user: ds-user, access: 
select",
@@ -117,8 +117,43 @@
         "resource":   { "elements": { "database": "customers" } },
         "accessType": "", "user": "ds-user", "userGroups": []
       },
-      "result": { "datasets": [ "dataset-3", "dataset-6" ], "projects": [ 
"project-2", "project-4" ], "allowedByDatasets": [ "dataset-3", "dataset-6" ], 
"isAllowed": true, "isAudited": true, "policyId": 2003, "rowFilters": [ 
"created_time >= '2023-01-01' and created_time < '2024-01-01'", "country = 
'US'" ] }
+      "result": { "datasets": [ "dataset-3", "dataset-6" ], "projects": [ 
"project-2", "project-4" ], "allowedByDatasets": [ "dataset-3", "dataset-6" ], 
"isAllowed": true, "isAudited": true, "policyId": 2003, "rowFilters": null }
+    },
+
+    {
+      "name":    "table: customers.shipping_address, user: ds-user, access: 
select",
+      "request": {
+        "resource":   { "elements": { "database": "customers", "table": 
"shipping_address" } },
+        "accessType": "select", "user": "ds-user", "userGroups": []
+      },
+      "result": { "datasets": [ "dataset-6" ], "projects": [ "project-4" ], 
"allowedByDatasets": [ "dataset-6" ], "isAllowed": false, "isAudited": true, 
"policyId": 2006, "rowFilters": [ "country = 'US'" ] }
+    },
+    {
+      "name":    "table: customers.shipping_address, user: ds3-user, access: 
select",
+      "request": {
+        "resource":   { "elements": { "database": "customers", "table": 
"shipping_address" } },
+        "accessType": "select", "user": "ds3-user", "userGroups": []
+      },
+      "result": { "datasets": [ "dataset-6" ], "projects": [ "project-4" ], 
"allowedByDatasets": null, "isAllowed": false, "isAudited": true, "policyId": 
-1, "rowFilters": null }
     },
+    {
+      "name":    "table: customers.shipping_address, user: ds6-user, access: 
select",
+      "request": {
+        "resource":   { "elements": { "database": "customers", "table": 
"shipping_address" } },
+        "accessType": "select", "user": "ds6-user", "userGroups": []
+      },
+      "result": { "datasets": [ "dataset-6" ], "projects": [ "project-4" ], 
"allowedByDatasets": [ "dataset-6" ], "isAllowed": false, "isAudited": true, 
"policyId": 2006, "rowFilters": [ "country = 'US'" ] }
+    },
+    {
+      "name":    "database: customers, user: ds-user, access: _any",
+      "request": {
+        "resource":   { "elements": { "database": "customers" } },
+        "accessType": "", "user": "ds-user", "userGroups": []
+      },
+      "result": { "datasets": [ "dataset-3", "dataset-6" ], "projects": [ 
"project-2", "project-4" ], "allowedByDatasets": [ "dataset-3", "dataset-6" ], 
"isAllowed": true, "isAudited": true, "policyId": 2003, "rowFilters": null }
+    },
+
+
     {
       "name":    "table: operations.facilities, user: ds-user, access: select",
       "request": {
@@ -133,7 +168,7 @@
         "resource":   { "elements": { "database": "operations" } },
         "accessType": "", "user": "ds-user", "userGroups": []
       },
-      "result": { "datasets": [ "dataset-4" ], "projects": null, 
"allowedByDatasets": [ "dataset-4" ], "isAllowed": true, "isAudited": true, 
"policyId": 2004, "rowFilters": [ "country = 'US'" ] }
+      "result": { "datasets": [ "dataset-4" ], "projects": null, 
"allowedByDatasets": [ "dataset-4" ], "isAllowed": true, "isAudited": true, 
"policyId": 2004, "rowFilters": null }
     },
 
 

Reply via email to