You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by an...@apache.org on 2020/05/21 11:45:29 UTC

[hive] branch master updated: HIVE-23433: Add Deny Policy on Target Database After Ranger Replication to avoid writes (Aasha Medhi, reviewed by Pravin Kumar Sinha)

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

anishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new b047cfa  HIVE-23433: Add Deny Policy on Target Database After Ranger Replication to avoid writes (Aasha Medhi, reviewed by Pravin Kumar Sinha)
b047cfa is described below

commit b047cfae872244e769f5d1c3c11811d1c49c19ad
Author: Anishek Agarwal <an...@gmail.com>
AuthorDate: Thu May 21 17:15:14 2020 +0530

    HIVE-23433: Add Deny Policy on Target Database After Ranger Replication to avoid writes (Aasha Medhi, reviewed by Pravin Kumar Sinha)
---
 .../java/org/apache/hadoop/hive/conf/HiveConf.java |   4 +
 .../hadoop/hive/ql/exec/repl/RangerLoadTask.java   |  12 ++-
 .../ql/exec/repl/ranger/NoOpRangerRestClient.java  |   7 ++
 .../hive/ql/exec/repl/ranger/RangerRestClient.java |   3 +
 .../ql/exec/repl/ranger/RangerRestClientImpl.java  |  77 ++++++++++++--
 .../hive/ql/exec/repl/TestRangerLoadTask.java      | 115 +++++++++++++++++++--
 6 files changed, 203 insertions(+), 15 deletions(-)

diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
index 26eeeb7..bd884a9 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
@@ -542,6 +542,10 @@ public class HiveConf extends Configuration {
             "hive",
             "This configuration will define the service name for which the ranger authorization"
                     + " policies needs to be replicated"),
+    REPL_RANGER_ADD_DENY_POLICY_TARGET("hive.repl.ranger.target.deny.policy",
+      true,
+      "This configuration will add a deny policy on the target database for all users except hive"
+        + " to avoid any update to the target database"),
     LOCALSCRATCHDIR("hive.exec.local.scratchdir",
         "${system:java.io.tmpdir}" + File.separator + "${system:user.name}",
         "Local scratch space for Hive jobs"),
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/RangerLoadTask.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/RangerLoadTask.java
index 4d62a51..2c216ff 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/RangerLoadTask.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/RangerLoadTask.java
@@ -41,6 +41,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_AUTHORIZATION_PROVIDER_SERVICE_ENDPOINT;
+import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_RANGER_ADD_DENY_POLICY_TARGET;
 import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_RANGER_SERVICE_NAME;
 
 /**
@@ -104,8 +105,15 @@ public class RangerLoadTask extends Task<RangerLoadWork> implements Serializable
         LOG.info("There are no ranger policies to import");
         rangerPolicies = new ArrayList<>();
       }
-      List<RangerPolicy> updatedRangerPolicies = rangerRestClient.changeDataSet(rangerPolicies, work.getSourceDbName(),
-              work.getTargetDbName());
+      List<RangerPolicy> rangerPoliciesWithDenyPolicy = rangerPolicies;
+      if (conf.getBoolVar(REPL_RANGER_ADD_DENY_POLICY_TARGET)) {
+        rangerPoliciesWithDenyPolicy = rangerRestClient.addDenyPolicies(rangerPolicies,
+          conf.getVar(REPL_RANGER_SERVICE_NAME), work.getSourceDbName(), work.getTargetDbName());
+      }
+
+      List<RangerPolicy> updatedRangerPolicies = rangerRestClient.changeDataSet(rangerPoliciesWithDenyPolicy,
+          work.getSourceDbName(), work.getTargetDbName());
+
       long importCount = 0;
       if (!CollectionUtils.isEmpty(updatedRangerPolicies)) {
         if (rangerExportPolicyList == null) {
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/NoOpRangerRestClient.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/NoOpRangerRestClient.java
index b0fdff4..5a11430 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/NoOpRangerRestClient.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/NoOpRangerRestClient.java
@@ -68,4 +68,11 @@ public class NoOpRangerRestClient implements RangerRestClient {
   public boolean checkConnection(String url) throws Exception {
     return true;
   }
+
+  @Override
+  public List<RangerPolicy> addDenyPolicies(List<RangerPolicy> rangerPolicies, String rangerServiceName,
+                                            String sourceDb, String targetDb) throws SemanticException {
+    return rangerPolicies;
+  }
+
 }
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClient.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClient.java
index eab20f4..f85c3af 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClient.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClient.java
@@ -47,4 +47,7 @@ public interface RangerRestClient {
                                                         HiveConf conf) throws SemanticException;
 
   boolean checkConnection(String url) throws Exception;
+
+  List<RangerPolicy> addDenyPolicies(List<RangerPolicy> rangerPolicies, String rangerServiceName,
+                                     String sourceDb, String targetDb) throws SemanticException;
 }
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClientImpl.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClientImpl.java
index c535f9e..1b17632 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClientImpl.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/repl/ranger/RangerRestClientImpl.java
@@ -49,12 +49,15 @@ import java.io.File;
 import java.io.InputStreamReader;
 import java.io.InputStream;
 import java.io.Reader;
+import java.io.FileNotFoundException;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Arrays;
 
 /**
  * RangerRestClientImpl to connect to Ranger and export policies.
@@ -225,12 +228,6 @@ public class RangerRestClientImpl implements RangerRestClient {
   @Override
   public List<RangerPolicy> changeDataSet(List<RangerPolicy> rangerPolicies, String sourceDbName,
                                           String targetDbName) {
-    if (sourceDbName.endsWith("/")) {
-      sourceDbName = StringUtils.removePattern(sourceDbName, "/+$");
-    }
-    if (targetDbName.endsWith("/")) {
-      targetDbName = StringUtils.removePattern(targetDbName, "/+$");
-    }
     if (targetDbName.equals(sourceDbName)) {
       return rangerPolicies;
     }
@@ -335,6 +332,9 @@ public class RangerRestClientImpl implements RangerRestClient {
       InputStream inputStream = fs.open(filePath);
       Reader reader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
       rangerExportPolicyList = gsonBuilder.fromJson(reader, RangerExportPolicyList.class);
+    } catch (FileNotFoundException e) {
+      //If the ranger policies are not present, json file will not be present
+      return rangerExportPolicyList;
     } catch (Exception ex) {
       throw new SemanticException("Error reading file :" + filePath, ex);
     }
@@ -349,6 +349,69 @@ public class RangerRestClientImpl implements RangerRestClient {
     return (clientResp.getStatus() < HttpServletResponse.SC_UNAUTHORIZED);
   }
 
+  @Override
+  public List<RangerPolicy> addDenyPolicies(List<RangerPolicy> rangerPolicies, String rangerServiceName,
+                                            String sourceDb, String targetDb) throws SemanticException {
+    if (StringUtils.isEmpty(rangerServiceName)) {
+      throw new SemanticException("Ranger Service Name cannot be empty");
+    }
+    RangerPolicy denyRangerPolicy = new RangerPolicy();
+    denyRangerPolicy.setService(rangerServiceName);
+    denyRangerPolicy.setName(sourceDb + "_replication deny policy for " + targetDb);
+    Map<String, RangerPolicy.RangerPolicyResource> rangerPolicyResourceMap = new HashMap<String,
+        RangerPolicy.RangerPolicyResource>();
+    RangerPolicy.RangerPolicyResource rangerPolicyResource = new RangerPolicy.RangerPolicyResource();
+    List<String> resourceNameList = new ArrayList<String>();
+
+    List<RangerPolicy.RangerPolicyItem> denyPolicyItemsForPublicGroup = denyRangerPolicy.getDenyPolicyItems();
+    RangerPolicy.RangerPolicyItem denyPolicyItem = new RangerPolicy.RangerPolicyItem();
+    List<RangerPolicy.RangerPolicyItemAccess> denyPolicyItemAccesses = new ArrayList<RangerPolicy.
+        RangerPolicyItemAccess>();
+
+    List<RangerPolicy.RangerPolicyItem> denyExceptionsItemsForBeaconUser = denyRangerPolicy.getDenyExceptions();
+    RangerPolicy.RangerPolicyItem denyExceptionsPolicyItem = new RangerPolicy.RangerPolicyItem();
+    List<RangerPolicy.RangerPolicyItemAccess> denyExceptionsPolicyItemAccesses = new ArrayList<RangerPolicy.
+        RangerPolicyItemAccess>();
+
+    resourceNameList.add(sourceDb);
+    rangerPolicyResource.setValues(resourceNameList);
+    RangerPolicy.RangerPolicyResource rangerPolicyResourceColumn =new RangerPolicy.RangerPolicyResource();
+    rangerPolicyResourceColumn.setValues(new ArrayList<String>(){{add("*"); }});
+    RangerPolicy.RangerPolicyResource rangerPolicyResourceTable =new RangerPolicy.RangerPolicyResource();
+    rangerPolicyResourceTable.setValues(new ArrayList<String>(){{add("*"); }});
+    rangerPolicyResourceMap.put("database", rangerPolicyResource);
+    rangerPolicyResourceMap.put("table", rangerPolicyResourceTable);
+    rangerPolicyResourceMap.put("column", rangerPolicyResourceColumn);
+    denyRangerPolicy.setResources(rangerPolicyResourceMap);
+
+    List<String> accessTypes = Arrays.asList("create", "update", "drop", "alter",
+        "index", "lock", "write", "ReplAdmin");
+    for (String access : accessTypes) {
+      denyPolicyItemAccesses.add(new RangerPolicy.RangerPolicyItemAccess(access, true));
+    }
+    denyPolicyItem.setAccesses(denyPolicyItemAccesses);
+    denyPolicyItemsForPublicGroup.add(denyPolicyItem);
+    List<String> denyPolicyItemsGroups = new ArrayList<String>();
+    denyPolicyItemsGroups.add("public");
+    denyPolicyItem.setGroups(denyPolicyItemsGroups);
+    denyRangerPolicy.setDenyPolicyItems(denyPolicyItemsForPublicGroup);
+
+    List<String> denyExcludeAccessTypes = Arrays.asList("create", "update", "drop", "alter", "index", "lock", "write",
+        "ReplAdmin", "select", "read");
+    for (String access : denyExcludeAccessTypes) {
+      denyExceptionsPolicyItemAccesses.add(new RangerPolicy.RangerPolicyItemAccess(access, true));
+    }
+    denyExceptionsPolicyItem.setAccesses(denyExceptionsPolicyItemAccesses);
+    denyExceptionsItemsForBeaconUser.add(denyExceptionsPolicyItem);
+    List<String> denyExceptionsPolicyItemsUsers = new ArrayList<String>();
+    denyExceptionsPolicyItemsUsers.add("hive");
+    denyExceptionsPolicyItem.setUsers(denyExceptionsPolicyItemsUsers);
+    denyRangerPolicy.setDenyExceptions(denyExceptionsItemsForBeaconUser);
+
+    rangerPolicies.add(denyRangerPolicy);
+    return rangerPolicies;
+  }
+
 
   private WebResource.Builder getRangerResourceBuilder(String url) {
     Client client = getRangerClient();
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/exec/repl/TestRangerLoadTask.java b/ql/src/test/org/apache/hadoop/hive/ql/exec/repl/TestRangerLoadTask.java
index 296bd38..8ff2961 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/exec/repl/TestRangerLoadTask.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/exec/repl/TestRangerLoadTask.java
@@ -21,8 +21,8 @@ import com.google.gson.Gson;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.ql.exec.repl.ranger.RangerExportPolicyList;
+import org.apache.hadoop.hive.ql.exec.repl.ranger.RangerPolicy;
 import org.apache.hadoop.hive.ql.exec.repl.ranger.RangerRestClientImpl;
-import org.apache.hadoop.hive.ql.exec.repl.util.ReplUtils;
 import org.apache.hadoop.hive.ql.parse.repl.ReplState;
 import org.junit.Assert;
 import org.junit.Before;
@@ -37,6 +37,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_AUTHORIZATION_PROVIDER_SERVICE_ENDPOINT;
+import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_RANGER_SERVICE_NAME;
+import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.REPL_RANGER_ADD_DENY_POLICY_TARGET;
 
 /**
  * Unit test class for testing Ranger Dump.
@@ -61,6 +63,8 @@ public class TestRangerLoadTask {
     task = new RangerLoadTask(mockClient, conf, work);
     Mockito.when(mockClient.changeDataSet(Mockito.anyList(), Mockito.anyString(), Mockito.anyString()))
       .thenCallRealMethod();
+    Mockito.when(mockClient.addDenyPolicies(Mockito.anyList(), Mockito.anyString(), Mockito.anyString(),
+      Mockito.anyString())).thenCallRealMethod();
     Mockito.when(mockClient.checkConnection(Mockito.anyString())).thenReturn(true);
   }
 
@@ -84,7 +88,7 @@ public class TestRangerLoadTask {
   public void testSuccessNonEmptyRangerPolicies() throws Exception {
     String rangerResponse = "{\"metaDataInfo\":{\"Host name\":\"ranger.apache.org\","
         + "\"Exported by\":\"hive\",\"Export time\":\"May 5, 2020, 8:55:03 AM\",\"Ranger apache version\""
-        + ":\"2.0.0.7.2.0.0-61\"},\"policies\":[{\"service\":\"cm_hive\",\"name\":\"db-level\",\"policyType\":0,"
+        + ":\"2.0.0.7.2.0.0-61\"},\"policies\":[{\"service\":\"hive\",\"name\":\"db-level\",\"policyType\":0,"
         + "\"description\":\"\",\"isAuditEnabled\":true,\"resources\":{\"database\":{\"values\":[\"aa\"],"
         + "\"isExcludes\":false,\"isRecursive\":false},\"column\":{\"values\":[\"id\"],\"isExcludes\":false,"
         + "\"isRecursive\":false},\"table\":{\"values\":[\"*\"],\"isExcludes\":false,\"isRecursive\":false}},"
@@ -99,8 +103,6 @@ public class TestRangerLoadTask {
     Mockito.when(work.getTargetDbName()).thenReturn("tgtdb");
     Path rangerDumpPath = new Path("/tmp");
     Mockito.when(work.getCurrentDumpPath()).thenReturn(rangerDumpPath);
-    mockClient.saveRangerPoliciesToFile(rangerPolicyList,
-        rangerDumpPath, ReplUtils.HIVE_RANGER_POLICIES_FILE_NAME, new HiveConf());
     Mockito.when(mockClient.readRangerPoliciesFromJsonFile(Mockito.any(), Mockito.any())).thenReturn(rangerPolicyList);
     int status = task.execute();
     Assert.assertEquals(0, status);
@@ -127,8 +129,6 @@ public class TestRangerLoadTask {
     Mockito.when(work.getTargetDbName()).thenReturn("tgtdb");
     Path rangerDumpPath = new Path("/tmp");
     Mockito.when(work.getCurrentDumpPath()).thenReturn(rangerDumpPath);
-    mockClient.saveRangerPoliciesToFile(rangerPolicyList,
-        rangerDumpPath, ReplUtils.HIVE_RANGER_POLICIES_FILE_NAME, new HiveConf());
     Mockito.when(mockClient.readRangerPoliciesFromJsonFile(Mockito.any(), Mockito.any())).thenReturn(rangerPolicyList);
     int status = task.execute();
     Assert.assertEquals(0, status);
@@ -148,4 +148,107 @@ public class TestRangerLoadTask {
         .getAllValues().get(1).toString().contains("{\"sourceDbName\":\"srcdb\",\"targetDbName\""
         + ":\"tgtdb\",\"actualNumPolicies\":1,\"loadEndTime\""));
   }
+
+  @Test
+  public void testSuccessAddDenyRangerPolicies() throws Exception {
+    String rangerResponse = "{\"metaDataInfo\":{\"Host name\":\"ranger.apache.org\","
+        + "\"Exported by\":\"hive\",\"Export time\":\"May 5, 2020, 8:55:03 AM\",\"Ranger apache version\""
+        + ":\"2.0.0.7.2.0.0-61\"},\"policies\":[{\"service\":\"hive\",\"name\":\"db-level\",\"policyType\":0,"
+        + "\"description\":\"\",\"isAuditEnabled\":true,\"resources\":{\"database\":{\"values\":[\"aa\"],"
+        + "\"isExcludes\":false,\"isRecursive\":false},\"column\":{\"values\":[\"id\"],\"isExcludes\":false,"
+        + "\"isRecursive\":false},\"table\":{\"values\":[\"*\"],\"isExcludes\":false,\"isRecursive\":false}},"
+        + "\"policyItems\":[{\"accesses\":[{\"type\":\"select\",\"isAllowed\":true},{\"type\":\"update\","
+        + "\"isAllowed\":true}],\"users\":[\"admin\"],\"groups\":[\"public\"],\"conditions\":[],"
+        + "\"delegateAdmin\":false}],\"denyPolicyItems\":[],\"allowExceptions\":[],\"denyExceptions\":[],"
+        + "\"dataMaskPolicyItems\":[],\"rowFilterPolicyItems\":[],\"id\":40,\"guid\":"
+        + "\"4e2b3406-7b9a-4004-8cdf-7a239c8e2cae\",\"isEnabled\":true,\"version\":1}]}";
+    RangerExportPolicyList rangerPolicyList = new Gson().fromJson(rangerResponse, RangerExportPolicyList.class);
+    Mockito.when(conf.getVar(REPL_AUTHORIZATION_PROVIDER_SERVICE_ENDPOINT)).thenReturn("rangerEndpoint");
+    Mockito.when(work.getSourceDbName()).thenReturn("srcdb");
+    Mockito.when(work.getTargetDbName()).thenReturn("tgtdb");
+    Mockito.when(conf.getVar(REPL_RANGER_SERVICE_NAME)).thenReturn("hive");
+    Mockito.when(conf.getBoolVar(REPL_RANGER_ADD_DENY_POLICY_TARGET)).thenReturn(true);
+    Path rangerDumpPath = new Path("/tmp");
+    Mockito.when(work.getCurrentDumpPath()).thenReturn(rangerDumpPath);
+    Mockito.when(mockClient.readRangerPoliciesFromJsonFile(Mockito.any(), Mockito.any())).thenReturn(rangerPolicyList);
+    int status = task.execute();
+    Assert.assertEquals(0, status);
+    ArgumentCaptor<RangerExportPolicyList> rangerPolicyCapture = ArgumentCaptor.forClass(RangerExportPolicyList.class);
+    ArgumentCaptor<String> rangerEndpoint = ArgumentCaptor.forClass(String.class);
+    ArgumentCaptor<String> serviceName = ArgumentCaptor.forClass(String.class);
+    ArgumentCaptor<String> targetDb = ArgumentCaptor.forClass(String.class);
+    Mockito.verify(mockClient,
+        Mockito.times(1)).importRangerPolicies(rangerPolicyCapture.capture(),
+        targetDb.capture(), rangerEndpoint.capture(), serviceName.capture());
+    Assert.assertEquals("tgtdb", targetDb.getAllValues().get(0));
+    Assert.assertEquals("rangerEndpoint", rangerEndpoint.getAllValues().get(0));
+    Assert.assertEquals("hive", serviceName.getAllValues().get(0));
+    RangerExportPolicyList actualPolicyList = rangerPolicyCapture.getAllValues().get(0);
+    Assert.assertEquals(rangerPolicyList.getMetaDataInfo(), actualPolicyList.getMetaDataInfo());
+    //Deny policy is added
+    Assert.assertEquals(2, actualPolicyList.getListSize());
+    RangerPolicy denyPolicy = actualPolicyList.getPolicies().get(1);
+    Assert.assertEquals("hive", denyPolicy.getService());
+    Assert.assertEquals("srcdb_replication deny policy for tgtdb", denyPolicy.getName());
+    Assert.assertEquals(1, denyPolicy.getDenyExceptions().size());
+    Assert.assertEquals("public", denyPolicy.getDenyPolicyItems().get(0).getGroups().get(0));
+    Assert.assertEquals(8, denyPolicy.getDenyPolicyItems().get(0).getAccesses().size());
+    boolean isReplAdminDenied = false;
+    for (RangerPolicy.RangerPolicyItemAccess access : denyPolicy.getDenyPolicyItems().get(0).getAccesses()) {
+      if (access.getType().equalsIgnoreCase("ReplAdmin")) {
+        isReplAdminDenied = true;
+      }
+    }
+    Assert.assertTrue(isReplAdminDenied);
+    //Deny exception is for hive user. Deny exception is not for repl admin permission
+    Assert.assertEquals("hive", denyPolicy.getDenyExceptions().get(0).getUsers().get(0));
+    Assert.assertEquals(10, denyPolicy.getDenyExceptions().get(0).getAccesses().size());
+    isReplAdminDenied = false;
+    for (RangerPolicy.RangerPolicyItemAccess access : denyPolicy.getDenyExceptions().get(0).getAccesses()) {
+      if (access.getType().equalsIgnoreCase("ReplAdmin")) {
+        isReplAdminDenied = true;
+      }
+    }
+    Assert.assertTrue(isReplAdminDenied);
+  }
+
+  @Test
+  public void testSuccessDisableDenyRangerPolicies() throws Exception {
+    String rangerResponse = "{\"metaDataInfo\":{\"Host name\":\"ranger.apache.org\","
+        + "\"Exported by\":\"hive\",\"Export time\":\"May 5, 2020, 8:55:03 AM\",\"Ranger apache version\""
+        + ":\"2.0.0.7.2.0.0-61\"},\"policies\":[{\"service\":\"hive\",\"name\":\"db-level\",\"policyType\":0,"
+        + "\"description\":\"\",\"isAuditEnabled\":true,\"resources\":{\"database\":{\"values\":[\"aa\"],"
+        + "\"isExcludes\":false,\"isRecursive\":false},\"column\":{\"values\":[\"id\"],\"isExcludes\":false,"
+        + "\"isRecursive\":false},\"table\":{\"values\":[\"*\"],\"isExcludes\":false,\"isRecursive\":false}},"
+        + "\"policyItems\":[{\"accesses\":[{\"type\":\"select\",\"isAllowed\":true},{\"type\":\"update\","
+        + "\"isAllowed\":true}],\"users\":[\"admin\"],\"groups\":[\"public\"],\"conditions\":[],"
+        + "\"delegateAdmin\":false}],\"denyPolicyItems\":[],\"allowExceptions\":[],\"denyExceptions\":[],"
+        + "\"dataMaskPolicyItems\":[],\"rowFilterPolicyItems\":[],\"id\":40,\"guid\":"
+        + "\"4e2b3406-7b9a-4004-8cdf-7a239c8e2cae\",\"isEnabled\":true,\"version\":1}]}";
+    RangerExportPolicyList rangerPolicyList = new Gson().fromJson(rangerResponse, RangerExportPolicyList.class);
+    Mockito.when(conf.getVar(REPL_AUTHORIZATION_PROVIDER_SERVICE_ENDPOINT)).thenReturn("rangerEndpoint");
+    Mockito.when(work.getSourceDbName()).thenReturn("srcdb");
+    Mockito.when(work.getTargetDbName()).thenReturn("tgtdb");
+    Mockito.when(conf.getVar(REPL_RANGER_SERVICE_NAME)).thenReturn("hive");
+    Mockito.when(conf.getBoolVar(REPL_RANGER_ADD_DENY_POLICY_TARGET)).thenReturn(false);
+    Path rangerDumpPath = new Path("/tmp");
+    Mockito.when(work.getCurrentDumpPath()).thenReturn(rangerDumpPath);
+    Mockito.when(mockClient.readRangerPoliciesFromJsonFile(Mockito.any(), Mockito.any())).thenReturn(rangerPolicyList);
+    int status = task.execute();
+    Assert.assertEquals(0, status);
+    ArgumentCaptor<RangerExportPolicyList> rangerPolicyCapture = ArgumentCaptor.forClass(RangerExportPolicyList.class);
+    ArgumentCaptor<String> rangerEndpoint = ArgumentCaptor.forClass(String.class);
+    ArgumentCaptor<String> serviceName = ArgumentCaptor.forClass(String.class);
+    ArgumentCaptor<String> targetDb = ArgumentCaptor.forClass(String.class);
+    Mockito.verify(mockClient,
+        Mockito.times(1)).importRangerPolicies(rangerPolicyCapture.capture(),
+        targetDb.capture(), rangerEndpoint.capture(), serviceName.capture());
+    Assert.assertEquals("tgtdb", targetDb.getAllValues().get(0));
+    Assert.assertEquals("rangerEndpoint", rangerEndpoint.getAllValues().get(0));
+    Assert.assertEquals("hive", serviceName.getAllValues().get(0));
+    RangerExportPolicyList actualPolicyList = rangerPolicyCapture.getAllValues().get(0);
+    Assert.assertEquals(rangerPolicyList.getMetaDataInfo(), actualPolicyList.getMetaDataInfo());
+    //Deny policy is added
+    Assert.assertEquals(1, actualPolicyList.getListSize());
+  }
 }