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

commit f3e8e0a648e33fdcd947136a1d7308db9fbe5109
Author: Madhan Neethiraj <mad...@apache.org>
AuthorDate: Tue Sep 5 16:45:12 2023 -0700

    RANGER-4398: security-zone API enhancements to support incremental updates 
and resource pagination
---
 .../ranger/plugin/model/RangerPrincipal.java       |  97 ++++
 .../ranger/plugin/model/RangerSecurityZone.java    |  46 +-
 .../ranger/plugin/model/RangerSecurityZoneV2.java  | 507 +++++++++++++++++++++
 .../plugin/util/RangerSecurityZoneHelper.java      | 399 ++++++++++++++++
 .../python/apache_ranger/client/ranger_client.py   |  72 ++-
 .../main/python/apache_ranger/model/ranger_base.py |  22 +
 .../python/apache_ranger/model/ranger_principal.py |  59 +++
 .../apache_ranger/model/ranger_security_zone.py    | 105 ++++-
 intg/src/main/python/setup.py                      |   2 +-
 .../src/main/python/security_zone_v2.py            | 149 ++++++
 .../java/org/apache/ranger/rest/PublicAPIsv2.java  |  63 +++
 .../org/apache/ranger/rest/SecurityZoneREST.java   | 140 +++++-
 12 files changed, 1640 insertions(+), 21 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
new file mode 100644
index 000000000..226dc4d7c
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model;
+
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.Objects;
+
+@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RangerPrincipal implements java.io.Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public enum PrincipalType { USER, GROUP, ROLE }
+
+    private PrincipalType type;
+    private String        name;
+
+    public RangerPrincipal() {
+        this(null, null);
+    }
+
+    public RangerPrincipal(PrincipalType type, String name) {
+        setType(type);
+        setName(name);
+    }
+
+    public PrincipalType getType() {
+        return type;
+    }
+
+    public void setType(PrincipalType type) {
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, name);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        final boolean ret;
+
+        if (this == obj) {
+            ret = true;
+        } else if (obj == null) {
+            ret = false;
+        } else if (getClass() != obj.getClass()) {
+            ret = false;
+        } else {
+            RangerPrincipal other = (RangerPrincipal) obj;
+
+            ret = Objects.equals(type, other.type) && Objects.equals(name, 
other.name);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public String toString() {
+        return "{type=" + type + ", name=" + name + "}";
+    }
+}
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZone.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZone.java
index 71d64ca83..47f8041b7 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZone.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZone.java
@@ -23,6 +23,8 @@ import org.codehaus.jackson.annotate.JsonAutoDetect;
 import org.codehaus.jackson.annotate.JsonIgnoreProperties;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResourceBase;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -147,14 +149,20 @@ public class RangerSecurityZone extends 
RangerBaseModelObject implements java.io
        @JsonIgnoreProperties(ignoreUnknown=true)
        public static class RangerSecurityZoneService implements 
java.io.Serializable {
        private static final long serialVersionUID = 1L;
-        private List<HashMap<String, List<String>>> resources;
+        private List<HashMap<String, List<String>>>  resources;
+        private List<RangerSecurityZoneResourceBase> resourcesBaseInfo;
 
         public RangerSecurityZoneService() {
-            this(null);
+            this(null, null);
         }
 
         public RangerSecurityZoneService(List<HashMap<String, List<String>>> 
resources) {
+            this(resources, null);
+        }
+
+        public RangerSecurityZoneService(List<HashMap<String, List<String>>> 
resources, List<RangerSecurityZoneResourceBase> resourcesBaseInfo) {
             setResources(resources);
+            setResourcesBaseInfo(resourcesBaseInfo);
         }
 
         public List<HashMap<String, List<String>>> getResources() { return 
resources; }
@@ -163,22 +171,40 @@ public class RangerSecurityZone extends 
RangerBaseModelObject implements java.io
             this.resources = resources == null ? new ArrayList<>() : resources;
         }
 
+        public List<RangerSecurityZoneResourceBase> getResourcesBaseInfo() { 
return resourcesBaseInfo; }
+
+        public void setResourcesBaseInfo(List<RangerSecurityZoneResourceBase> 
resourcesBaseInfo) {
+            this.resourcesBaseInfo = resourcesBaseInfo == null ? new 
ArrayList<>() : resourcesBaseInfo;
+        }
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
-            sb.append("{resources={");
-            for (Map<String, List<String>> resource : resources) {
-                sb.append("[ ");
-                for (Map.Entry<String, List<String>> entry : 
resource.entrySet()) {
-                    
sb.append("{resource-def-name=").append(entry.getKey()).append(", 
values=").append(entry.getValue()).append("},");
+            sb.append("{resources=[");
+            if (resources != null) {
+                for (int i = 0; i < resources.size(); i++) {
+                    HashMap<String, List<String>>  resource = resources.get(i);
+                    RangerSecurityZoneResourceBase baseInfo = 
(resourcesBaseInfo != null && resourcesBaseInfo.size() > i) ? 
resourcesBaseInfo.get(i) : null;
+
+                    sb.append("{resource=");
+                    if (resource != null) {
+                        for (Map.Entry<String, List<String>> entry : 
resource.entrySet()) {
+                            
sb.append("{resource-def-name=").append(entry.getKey()).append(", 
values=").append(entry.getValue()).append("} ");
+                        }
+                    }
+                    sb.append("} ");
+
+                    sb.append("{baseInfo=");
+                    if (baseInfo != null) {
+                        baseInfo.toString(sb);
+                    }
+                    sb.append("} ");
                 }
-                sb.append(" ],");
             }
-            sb.append("}}");
+            sb.append("]}");
 
             return sb.toString();
         }
-
     }
 }
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneV2.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneV2.java
new file mode 100644
index 000000000..329780c15
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneV2.java
@@ -0,0 +1,507 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model;
+
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import 
org.apache.ranger.plugin.model.RangerSecurityZone.RangerSecurityZoneService;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+@JsonIgnoreProperties(ignoreUnknown=true)
+public class RangerSecurityZoneV2 extends RangerBaseModelObject implements 
java.io.Serializable {
+       private static final long serialVersionUID = 1L;
+
+    private String                                   name;
+    private String                                   description;
+    private Map<String, RangerSecurityZoneServiceV2> services;
+    private List<String>                             tagServices;
+    private List<RangerPrincipal>                    admins;
+    private List<RangerPrincipal>                    auditors;
+
+    public RangerSecurityZoneV2() {
+        this(null, null, null, null, null, null);
+    }
+
+    public RangerSecurityZoneV2(String name, String description, Map<String, 
RangerSecurityZoneServiceV2> services, List<String> tagServices, 
List<RangerPrincipal> admins, List<RangerPrincipal> auditors) {
+        setName(name);
+        setDescription(description);
+        setServices(services);
+        setTagServices(tagServices);
+        setAdmins(admins);
+        setAuditors(auditors);
+    }
+
+    public RangerSecurityZoneV2(RangerSecurityZone other) {
+        setId(other.getId());
+        setGuid(other.getGuid());
+        setIsEnabled(other.getIsEnabled());
+        setCreatedBy(other.getCreatedBy());
+        setUpdatedBy(other.getUpdatedBy());
+        setCreateTime(other.getCreateTime());
+        setUpdateTime(other.getUpdateTime());
+        setVersion(other.getVersion());
+        setName(other.getName());
+        setDescription(other.getDescription());
+        setTagServices((other.getTagServices() != null) ? new 
ArrayList<>(other.getTagServices()) : new ArrayList<>());
+        setAdmins(toPrincipals(other.getAdminUsers(), 
other.getAdminUserGroups(), other.getAdminRoles()));
+        setAuditors(toPrincipals(other.getAuditUsers(), 
other.getAuditUserGroups(), other.getAuditRoles()));
+
+        services = new HashMap<>();
+
+        if (other.getServices() != null) {
+            for (Map.Entry<String, RangerSecurityZoneService> entry : 
other.getServices().entrySet()) {
+                services.put(entry.getKey(), new 
RangerSecurityZoneServiceV2(entry.getValue()));
+            }
+        }
+    }
+
+    public String getName() { return name; }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() { return description; }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Map<String, RangerSecurityZoneServiceV2> getServices() { return 
services; }
+
+    public void setServices(Map<String, RangerSecurityZoneServiceV2> services) 
{
+        this.services = services == null ? new HashMap<>() : services;
+    }
+
+    public List<String> getTagServices() {
+        return tagServices;
+    }
+
+    public void setTagServices(List<String> tagServices) {
+        this.tagServices = (tagServices != null) ? tagServices : new 
ArrayList<>();
+    }
+
+    public List<RangerPrincipal> getAdmins() { return admins; }
+
+    public void setAdmins(List<RangerPrincipal> admins) {
+        this.admins = admins == null ? new ArrayList<>() : admins;
+    }
+
+    public List<RangerPrincipal> getAuditors() { return auditors; }
+
+    public void setAuditors(List<RangerPrincipal> auditors) {
+        this.auditors = auditors == null ? new ArrayList<>() : auditors;
+    }
+
+    public RangerSecurityZone toV1() {
+        RangerSecurityZone ret = new RangerSecurityZone();
+
+        ret.setId(getId());
+        ret.setGuid(getGuid());
+        ret.setIsEnabled(getIsEnabled());
+        ret.setCreatedBy(getCreatedBy());
+        ret.setUpdatedBy(getUpdatedBy());
+        ret.setCreateTime(getCreateTime());
+        ret.setUpdateTime(getUpdateTime());
+        ret.setVersion(getVersion());
+        ret.setName(name);
+        ret.setDescription(description);
+
+        if (services != null) {
+            for (Map.Entry<String, RangerSecurityZoneServiceV2> entry : 
services.entrySet()) {
+                ret.getServices().put(entry.getKey(), entry.getValue().toV1());
+            }
+        }
+
+        if (tagServices != null) {
+            ret.getTagServices().addAll(tagServices);
+        }
+
+        fromPrincipals(admins, ret.getAdminUsers(), ret.getAdminUserGroups(), 
ret.getAdminRoles());
+        fromPrincipals(auditors, ret.getAuditUsers(), 
ret.getAuditUserGroups(), ret.getAuditRoles());
+
+        return ret;
+    }
+
+    @Override
+    public String toString() {
+        return    "{name=" + name
+                + ", description="+ description
+                + ", services=" + services
+                + ", tagServices=" + tagServices
+                + ", admins=" + admins
+                + ", auditors=" + auditors
+                +"}";
+    }
+
+    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+    @JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+    @JsonIgnoreProperties(ignoreUnknown=true)
+    public static class RangerSecurityZoneServiceV2 implements 
java.io.Serializable {
+        private static final long serialVersionUID = 1L;
+
+        private List<RangerSecurityZoneResource> resources;
+
+        public RangerSecurityZoneServiceV2() {
+            this((List<RangerSecurityZoneResource>) null);
+        }
+
+        public RangerSecurityZoneServiceV2(List<RangerSecurityZoneResource> 
resources) {
+            setResources(resources);
+        }
+
+        public RangerSecurityZoneServiceV2(RangerSecurityZoneService other) {
+            resources = new ArrayList<>();
+
+            if (other != null && other.getResources() != null) {
+                for (int i = 0; i < other.getResources().size(); i++) {
+                    RangerSecurityZoneResource resource = getResourceAt(other, 
i);
+
+                    if (resource != null) {
+                        resources.add(resource);
+                    }
+                }
+            }
+        }
+
+        public List<RangerSecurityZoneResource> getResources() { return 
resources; }
+
+        public void setResources(List<RangerSecurityZoneResource> resources) {
+            this.resources = resources == null ? new ArrayList<>() : resources;
+        }
+
+        public RangerSecurityZoneService toV1() {
+            RangerSecurityZoneService ret = new RangerSecurityZoneService();
+
+            if (resources != null) {
+                for (RangerSecurityZoneResource resource : resources) {
+                    ret.getResources().add((HashMap<String, List<String>> ) 
resource.getResource());
+                    ret.getResourcesBaseInfo().add(new 
RangerSecurityZoneResourceBase(resource));
+                }
+            }
+            return ret;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("{resources=[");
+            if (resources != null) {
+                for (RangerSecurityZoneResource resource : resources) {
+                    if (resource != null) {
+                        resource.toString(sb).append(" ");
+                    }
+                }
+            }
+            sb.append("]}");
+
+            return sb.toString();
+        }
+
+        private RangerSecurityZoneResource 
getResourceAt(RangerSecurityZoneService zoneService, int idx) {
+            Map<String, List<String>>      resource = 
zoneService.getResources() != null && zoneService.getResources().size() > idx ? 
zoneService.getResources().get(idx) : null;
+            RangerSecurityZoneResourceBase baseInfo = 
zoneService.getResourcesBaseInfo() != null && 
zoneService.getResourcesBaseInfo().size() > idx ? 
zoneService.getResourcesBaseInfo().get(idx) : null;
+
+            return resource != null ? new RangerSecurityZoneResource(resource, 
baseInfo) : null;
+        }
+    }
+
+    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+    @JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+    @JsonIgnoreProperties(ignoreUnknown=true)
+    public static class RangerSecurityZoneResourceBase implements 
java.io.Serializable {
+        private Long    id;
+        private String  createdBy;
+        private String  updatedBy;
+        private Date    createTime;
+        private Date    updateTime;
+
+        public RangerSecurityZoneResourceBase() { }
+
+        public RangerSecurityZoneResourceBase(RangerSecurityZoneResourceBase 
other) {
+            if (other != null) {
+                setId(other.getId());
+                setCreatedBy(other.getCreatedBy());
+                setCreateTime(other.getCreateTime());
+                setUpdatedBy(other.getUpdatedBy());
+                setUpdateTime(other.getUpdateTime());
+            }
+        }
+
+        public Long getId() {
+            return id;
+        }
+
+        public void setId(Long id) {
+            this.id = id;
+        }
+
+        public String getCreatedBy() {
+            return createdBy;
+        }
+
+        public void setCreatedBy(String createdBy) {
+            this.createdBy = createdBy;
+        }
+
+        public String getUpdatedBy() {
+            return updatedBy;
+        }
+
+        public void setUpdatedBy(String updatedBy) {
+            this.updatedBy = updatedBy;
+        }
+
+        public Date getCreateTime() {
+            return createTime;
+        }
+
+        public void setCreateTime(Date createTime) {
+            this.createTime = createTime;
+        }
+
+        public Date getUpdateTime() {
+            return updateTime;
+        }
+
+        public void setUpdateTime(Date updateTime) {
+            this.updateTime = updateTime;
+        }
+
+        @Override
+        public String toString() {
+            return toString(new StringBuilder()).toString();
+        }
+
+        public StringBuilder toString(StringBuilder sb) {
+            if (sb == null) {
+                sb = new StringBuilder();
+            }
+
+            sb.append("{id=").append(id)
+              .append(", createdBy=").append(createdBy)
+              .append(", createTime=").append(createTime)
+              .append(", updatedBy=").append(updatedBy)
+              .append(", updateTime=").append(updateTime)
+              .append("}");
+
+            return sb;
+        }
+    }
+
+    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+    @JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+    @JsonIgnoreProperties(ignoreUnknown=true)
+    public static class RangerSecurityZoneResource extends 
RangerSecurityZoneResourceBase implements java.io.Serializable {
+        private static final long serialVersionUID = 1L;
+
+        private Map<String, List<String>> resource;
+
+        public RangerSecurityZoneResource() { this(null, null); }
+
+        public RangerSecurityZoneResource(Map<String, List<String>> resource) {
+            this(resource, null);
+        }
+
+        public RangerSecurityZoneResource(Map<String, List<String>> resource, 
RangerSecurityZoneResourceBase baseObj) {
+            super(baseObj);
+
+            setResource(resource);
+        }
+
+        public Map<String, List<String>> getResource() { return resource; }
+
+        public void setResource(Map<String, List<String>> resource) { 
this.resource = resource == null ? new HashMap<>() : resource; }
+
+        @Override
+        public String toString() {
+            return toString(new StringBuilder()).toString();
+        }
+
+        @Override
+        public StringBuilder toString(StringBuilder sb) {
+            if (sb == null) {
+                sb = new StringBuilder();
+            }
+
+            sb.append("{resource=");
+            super.toString(sb);
+            if (resource != null) {
+                for (Map.Entry<String, List<String>> entry : 
resource.entrySet()) {
+                    sb.append("{resource-def-name=").append(entry.getKey())
+                      .append(", values=").append(entry.getValue()).append("} 
");
+                }
+            }
+            sb.append("}");
+
+            return sb;
+        }
+    }
+
+    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
+    @JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
+    @JsonIgnoreProperties(ignoreUnknown=true)
+    public static class RangerSecurityZoneChangeRequest implements 
java.io.Serializable {
+        private static final long serialVersionUID = 1L;
+
+        private String                                   name;
+        private String                                   description;
+        private Map<String, RangerSecurityZoneServiceV2> resourcesToUpdate;
+        private Map<String, RangerSecurityZoneServiceV2> resourcesToRemove;
+        private List<String>                             tagServicesToAdd;
+        private List<String>                             tagServicesToRemove;
+        private List<RangerPrincipal>                    adminsToAdd;
+        private List<RangerPrincipal>                    adminsToRemove;
+        private List<RangerPrincipal>                    auditorsToAdd;
+        private List<RangerPrincipal>                    auditorsToRemove;
+
+        public RangerSecurityZoneChangeRequest() { }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        public Map<String, RangerSecurityZoneServiceV2> getResourcesToUpdate() 
{
+            return resourcesToUpdate;
+        }
+
+        public void setResourcesToUpdate(Map<String, 
RangerSecurityZoneServiceV2> resourcesToUpdate) {
+            this.resourcesToUpdate = resourcesToUpdate;
+        }
+
+        public Map<String, RangerSecurityZoneServiceV2> getResourcesToRemove() 
{
+            return resourcesToRemove;
+        }
+
+        public void setResourcesToRemove(Map<String, 
RangerSecurityZoneServiceV2> resourcesToRemove) {
+            this.resourcesToRemove = resourcesToRemove;
+        }
+
+        public List<String> getTagServicesToAdd() {
+            return tagServicesToAdd;
+        }
+
+        public void setTagServicesToAdd(List<String> tagServicesToAdd) {
+            this.tagServicesToAdd = tagServicesToAdd;
+        }
+
+        public List<String> getTagServicesToRemove() {
+            return tagServicesToRemove;
+        }
+
+        public void setTagServicesToRemove(List<String> tagServicesToRemove) {
+            this.tagServicesToRemove = tagServicesToRemove;
+        }
+
+        public List<RangerPrincipal> getAdminsToAdd() {
+            return adminsToAdd;
+        }
+
+        public void setAdminsToAdd(List<RangerPrincipal> adminsToAdd) {
+            this.adminsToAdd = adminsToAdd;
+        }
+
+        public List<RangerPrincipal> getAdminsToRemove() {
+            return adminsToRemove;
+        }
+
+        public void setAdminsToRemove(List<RangerPrincipal> adminsToRemove) {
+            this.adminsToRemove = adminsToRemove;
+        }
+
+        public List<RangerPrincipal> getAuditorsToAdd() {
+            return auditorsToAdd;
+        }
+
+        public void setAuditorsToAdd(List<RangerPrincipal> auditorsToAdd) {
+            this.auditorsToAdd = auditorsToAdd;
+        }
+
+        public List<RangerPrincipal> getAuditorsToRemove() {
+            return auditorsToRemove;
+        }
+
+        public void setAuditorsToRemove(List<RangerPrincipal> 
auditorsToRemove) {
+            this.auditorsToRemove = auditorsToRemove;
+        }
+
+
+    }
+
+    private void fromPrincipals(List<RangerPrincipal> principals, List<String> 
users, List<String> groups, List<String> roles) {
+        if (principals != null) {
+            for (RangerPrincipal principal : principals) {
+                if (principal.getType() == RangerPrincipal.PrincipalType.USER) 
{
+                    users.add(principal.getName());
+                } else if (principal.getType() == 
RangerPrincipal.PrincipalType.GROUP) {
+                    groups.add(principal.getName());
+                } else if (principal.getType() == 
RangerPrincipal.PrincipalType.ROLE) {
+                    roles.add(principal.getName());
+                }
+            }
+        }
+    }
+
+    private List<RangerPrincipal> toPrincipals(List<String> users, 
List<String> groups, List<String> roles) {
+        List<RangerPrincipal> ret = new ArrayList<>();
+
+        if (users != null) {
+            for (String name : users) {
+                ret.add(new 
RangerPrincipal(RangerPrincipal.PrincipalType.USER, name));
+            }
+        }
+
+        if (groups != null) {
+            for (String name : groups) {
+                ret.add(new 
RangerPrincipal(RangerPrincipal.PrincipalType.GROUP, name));
+            }
+        }
+
+        if (roles != null) {
+            for (String name : roles) {
+                ret.add(new 
RangerPrincipal(RangerPrincipal.PrincipalType.ROLE, name));
+            }
+        }
+
+        return ret;
+    }
+}
+
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerSecurityZoneHelper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerSecurityZoneHelper.java
new file mode 100644
index 000000000..460b55e1e
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerSecurityZoneHelper.java
@@ -0,0 +1,399 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+import org.apache.ranger.plugin.model.RangerPrincipal;
+import org.apache.ranger.plugin.model.RangerSecurityZone;
+import 
org.apache.ranger.plugin.model.RangerSecurityZone.RangerSecurityZoneService;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneChangeRequest;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResource;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResourceBase;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneServiceV2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class RangerSecurityZoneHelper {
+    private final RangerSecurityZone                           zone;
+    private final String                                       currentUser;
+    private final Map<String, RangerSecurityZoneServiceHelper> services;
+
+
+    public RangerSecurityZoneHelper(RangerSecurityZone zone, String 
currentUser) {
+        this.zone        = zone;
+        this.currentUser = currentUser;
+        this.services    = new HashMap<>();
+
+        for (Map.Entry<String, RangerSecurityZoneService> entry : 
zone.getServices().entrySet()) {
+            this.services.put(entry.getKey(), new 
RangerSecurityZoneServiceHelper(entry.getValue(), currentUser));
+        }
+    }
+
+    public RangerSecurityZone getZone() { return zone; }
+
+    public RangerSecurityZoneServiceHelper getZoneService(String serviceName) {
+        return services.get(serviceName);
+    }
+
+    public RangerSecurityZoneServiceHelper addZoneService(String serviceName) {
+        RangerSecurityZoneServiceHelper ret = services.get(serviceName);
+
+        if (ret == null) {
+            RangerSecurityZoneService zoneService = 
zone.getServices().get(serviceName);
+
+            if (zoneService == null) {
+                zoneService = new RangerSecurityZoneService();
+
+                zone.getServices().put(serviceName, zoneService);
+            }
+
+            ret = new RangerSecurityZoneServiceHelper(zoneService, 
currentUser);
+
+            services.put(serviceName, ret);
+        }
+
+        return ret;
+    }
+
+    public void removeService(String serviceName) {
+        services.remove(serviceName);
+        zone.getServices().remove(serviceName);
+    }
+
+    public RangerSecurityZone updateZone(RangerSecurityZoneChangeRequest 
changeData) {
+        if (changeData.getName() != null) {
+            zone.setName(changeData.getName());
+        }
+
+        if (changeData.getDescription() != null) {
+            zone.setDescription(changeData.getDescription());
+        }
+
+        if (changeData.getResourcesToUpdate() != null) {
+            for (Map.Entry<String, RangerSecurityZoneServiceV2> entry : 
changeData.getResourcesToUpdate().entrySet()) {
+                String                          serviceName       = 
entry.getKey();
+                RangerSecurityZoneServiceV2     zoneService       = 
entry.getValue();
+                RangerSecurityZoneServiceHelper zoneServiceHelper = 
addZoneService(serviceName);
+
+                if (zoneService != null && zoneService.getResources() != null) 
{
+                    for (RangerSecurityZoneResource resource : 
zoneService.getResources()) {
+                        if (resource != null) {
+                            zoneServiceHelper.updateResource(resource);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (changeData.getResourcesToRemove() != null) {
+            for (Map.Entry<String, RangerSecurityZoneServiceV2> entry : 
changeData.getResourcesToRemove().entrySet()) {
+                String                          serviceName       = 
entry.getKey();
+                RangerSecurityZoneServiceV2     zoneService       = 
entry.getValue();
+                RangerSecurityZoneServiceHelper zoneServiceHelper = 
getZoneService(serviceName);
+
+                if (zoneServiceHelper != null && zoneService != null && 
zoneService.getResources() != null) {
+                    for (RangerSecurityZoneResource resource : 
zoneService.getResources()) {
+                        if (resource != null) {
+                            if (resource.getId() != null) {
+                                
zoneServiceHelper.removeResource(resource.getId());
+                            } else if (resource.getResource() != null) {
+                                
zoneServiceHelper.removeResource(resource.getResource());
+                            }
+                        }
+                    }
+
+                    if (zoneServiceHelper.getResourceCount() == 0) {
+                        removeService(serviceName);
+                    }
+                }
+            }
+        }
+
+        if (changeData.getTagServicesToAdd() != null) {
+            zone.getTagServices().addAll(changeData.getTagServicesToAdd());
+        }
+
+        if (changeData.getTagServicesToRemove() != null) {
+            
zone.getTagServices().removeAll(changeData.getTagServicesToRemove());
+        }
+
+        if (changeData.getAdminsToAdd() != null) {
+            addPrincipals(changeData.getAdminsToAdd(), zone.getAdminUsers(), 
zone.getAdminUserGroups(), zone.getAdminRoles());
+        }
+
+        if (changeData.getAdminsToRemove() != null) {
+            removePrincipals(changeData.getAdminsToRemove(), 
zone.getAdminUsers(), zone.getAdminUserGroups(), zone.getAdminRoles());
+        }
+
+        if (changeData.getAuditorsToAdd() != null) {
+            addPrincipals(changeData.getAuditorsToAdd(), zone.getAuditUsers(), 
zone.getAuditUserGroups(), zone.getAuditRoles());
+        }
+
+        if (changeData.getAuditorsToRemove() != null) {
+            removePrincipals(changeData.getAuditorsToRemove(), 
zone.getAuditUsers(), zone.getAuditUserGroups(), zone.getAuditRoles());
+        }
+
+        return zone;
+    }
+
+    private void addPrincipals(List<RangerPrincipal> principals, List<String> 
users, List<String> groups, List<String> roles) {
+        for (RangerPrincipal principal : principals) {
+            if (principal.getType() == RangerPrincipal.PrincipalType.USER) {
+                users.add(principal.getName());
+            } else if (principal.getType() == 
RangerPrincipal.PrincipalType.GROUP) {
+                groups.add(principal.getName());
+            } else if (principal.getType() == 
RangerPrincipal.PrincipalType.ROLE) {
+                roles.add(principal.getName());
+            }
+        }
+    }
+
+    private void removePrincipals(List<RangerPrincipal> principals, 
List<String> users, List<String> groups, List<String> roles) {
+        for (RangerPrincipal principal : principals) {
+            if (principal.getType() == RangerPrincipal.PrincipalType.USER) {
+                users.remove(principal.getName());
+            } else if (principal.getType() == 
RangerPrincipal.PrincipalType.GROUP) {
+                groups.remove(principal.getName());
+            } else if (principal.getType() == 
RangerPrincipal.PrincipalType.ROLE) {
+                roles.remove(principal.getName());
+            }
+        }
+    }
+
+    public static class RangerSecurityZoneServiceHelper {
+        private final RangerSecurityZoneService            zoneService;
+        private final String                               currentUser;
+        private final List<HashMap<String, List<String>>>  resources;
+        private final List<RangerSecurityZoneResourceBase> resourcesBaseInfo;
+        private       long                                 nextResourceId = 0;
+
+        public RangerSecurityZoneServiceHelper(RangerSecurityZoneService 
zoneService, String currentUser) {
+            this.zoneService = zoneService;
+            this.currentUser = currentUser;
+
+            if (zoneService.getResources() != null) {
+                this.resources = zoneService.getResources();
+            } else {
+                this.resources = new ArrayList<>();
+
+                zoneService.setResources(this.resources);
+            }
+
+            if (zoneService.getResourcesBaseInfo() != null) {
+                this.resourcesBaseInfo = zoneService.getResourcesBaseInfo();
+            } else {
+                this.resourcesBaseInfo = new ArrayList<>();
+
+                zoneService.setResourcesBaseInfo(this.resourcesBaseInfo);
+            }
+
+            // make sure resourcesBaseInfo has as many entries as resources
+            for (int i = resourcesBaseInfo.size(); i < resources.size(); i++) {
+                RangerSecurityZoneResourceBase baseInfo = new 
RangerSecurityZoneResourceBase();
+
+                setCreated(baseInfo);
+
+                resourcesBaseInfo.add(baseInfo);
+            }
+
+            // remove any additional resourcesBaseInfo entries
+            for (int i = resources.size(); i < resourcesBaseInfo.size(); ) {
+                resourcesBaseInfo.remove(i);
+            }
+
+            // compute nextResourceId
+            for (RangerSecurityZoneResourceBase baseInfo : resourcesBaseInfo) {
+                if (baseInfo.getId() != null && nextResourceId <= 
baseInfo.getId()) {
+                    nextResourceId = baseInfo.getId() + 1;
+                }
+            }
+
+            // set missing IDs
+            for (RangerSecurityZoneResourceBase baseInfo : resourcesBaseInfo) {
+                if (baseInfo.getId() == null) {
+                    baseInfo.setId(nextResourceId++);
+                }
+            }
+        }
+
+        public RangerSecurityZoneService getZoneService() { return 
zoneService; }
+
+        public int getResourceCount() {
+            return resources != null ? resources.size() : 0;
+        }
+
+        public List<RangerSecurityZoneResource> getResources() {
+            List<RangerSecurityZoneResource> ret = new ArrayList<>();
+
+            if (resources != null) {
+                for (int i = 0; i < resources.size(); i++) {
+                    ret.add(getResourceAt(i));
+                }
+            }
+
+            return Collections.unmodifiableList(ret);
+        }
+
+        public List<RangerSecurityZoneResource> getResources(int startIdx, int 
count) {
+            List<RangerSecurityZoneResource> ret = new ArrayList<>();
+
+            if (resources != null) {
+                for (int i = 0; i < count; i++) {
+                    RangerSecurityZoneResource resource = 
getResourceAt(startIdx + i);
+
+                    if (resource == null) {
+                        break;
+                    }
+
+                    ret.add(resource);
+                }
+            }
+
+            return Collections.unmodifiableList(ret);
+        }
+
+        public RangerSecurityZoneResource getResource(long id) {
+            int idx = getResourceIdx(id);
+
+            return idx != -1 ? getResourceAt(idx) : null;
+        }
+
+        public RangerSecurityZoneResource getResource(Map<String, 
List<String>> resource) {
+            int idx = getResourceIdx(resource);
+
+            return idx != -1 ? getResourceAt(idx) : null;
+        }
+
+        public RangerSecurityZoneResource 
addResource(RangerSecurityZoneResource resource) {
+            setCreated(resource);
+
+            resources.add((HashMap<String, List<String>>) 
resource.getResource());
+            resourcesBaseInfo.add(new 
RangerSecurityZoneResourceBase(resource));
+
+            return resource;
+        }
+
+        public RangerSecurityZoneResource 
updateResource(RangerSecurityZoneResource resource) {
+            Long resourceId  = resource.getId();
+            int  resourceIdx = resourceId != null ? getResourceIdx(resourceId) 
: -1;
+
+            if (resourceIdx == -1) {
+                addResource(resource);
+            } else {
+                setUpdated(resource);
+
+                resources.set(resourceIdx, (HashMap<String, List<String>>) 
resource.getResource());
+                resourcesBaseInfo.set(resourceIdx, new 
RangerSecurityZoneResourceBase(resource));
+            }
+
+            return resource;
+       }
+
+        public RangerSecurityZoneResource removeResource(long id) {
+            int idx = getResourceIdx(id);
+
+            return idx != -1 ? removeResourceAt(idx) : null;
+        }
+
+        public RangerSecurityZoneResource removeResource(Map<String, 
List<String>> resource) {
+            int idx = getResourceIdx(resource);
+
+            return idx != -1 ? removeResourceAt(idx) : null;
+        }
+
+        private RangerSecurityZoneResource getResourceAt(int idx) {
+            RangerSecurityZoneResource     ret              = null;
+            HashMap<String, List<String>>  resource         = (resources != 
null && resources.size() > idx) ? resources.get(idx) : null;
+            RangerSecurityZoneResourceBase resourceBaseInfo = 
(resourcesBaseInfo != null && resourcesBaseInfo.size() > idx) ? 
resourcesBaseInfo.get(idx) : null;
+
+            if (resource != null) {
+                ret = new RangerSecurityZoneResource(resource, 
resourceBaseInfo);
+            }
+
+            return ret;
+        }
+
+        private RangerSecurityZoneResource removeResourceAt(int idx) {
+            RangerSecurityZoneResource     ret              = null;
+            HashMap<String, List<String>>  resource         = (resources != 
null && resources.size() > idx) ? resources.remove(idx) : null;
+            RangerSecurityZoneResourceBase resourceBaseInfo = 
(resourcesBaseInfo != null && resourcesBaseInfo.size() > idx) ? 
resourcesBaseInfo.remove(idx) : null;
+
+            if (resource != null) {
+                ret = new RangerSecurityZoneResource(resource, 
resourceBaseInfo);
+            }
+
+            return ret;
+        }
+
+        private int getResourceIdx(long id) {
+            int ret = -1;
+
+            if (resourcesBaseInfo != null) {
+                for (int i = 0; i < resourcesBaseInfo.size(); i++) {
+                    RangerSecurityZoneResourceBase baseInfo = 
resourcesBaseInfo.get(i);
+
+                    if (baseInfo != null && baseInfo.getId() != null && 
baseInfo.getId().equals(id)) {
+                        ret = i;
+
+                        break;
+                    }
+                }
+            }
+
+            return ret;
+        }
+
+        private int getResourceIdx(Map<String, List<String>> resource) {
+            int ret = -1;
+
+            if (resources != null) {
+                for (int i = 0; i < resources.size(); i++) {
+                    HashMap<String, List<String>> res = resources.get(i);
+
+                    if (Objects.equals(resource, res)) {
+                        ret = i;
+
+                        break;
+                    }
+                }
+            }
+
+            return ret;
+        }
+
+        private void setCreated(RangerSecurityZoneResourceBase baseInfo) {
+            baseInfo.setId(nextResourceId++);
+            baseInfo.setCreatedBy(currentUser);
+            baseInfo.setCreateTime(new Date());
+            baseInfo.setUpdatedBy(currentUser);
+            baseInfo.setUpdateTime(new Date());
+        }
+
+        private void setUpdated(RangerSecurityZoneResourceBase baseInfo) {
+            baseInfo.setUpdatedBy(currentUser);
+            baseInfo.setUpdateTime(new Date());
+        }
+    }
+}
diff --git a/intg/src/main/python/apache_ranger/client/ranger_client.py 
b/intg/src/main/python/apache_ranger/client/ranger_client.py
index 484a42128..f6e865107 100644
--- a/intg/src/main/python/apache_ranger/client/ranger_client.py
+++ b/intg/src/main/python/apache_ranger/client/ranger_client.py
@@ -20,10 +20,10 @@
 import json
 import logging
 from apache_ranger.exceptions                 import RangerServiceException
-from apache_ranger.model.ranger_base          import RangerBase
+from apache_ranger.model.ranger_base          import RangerBase, PList
 from apache_ranger.model.ranger_policy        import RangerPolicy
 from apache_ranger.model.ranger_role          import RangerRole
-from apache_ranger.model.ranger_security_zone import RangerSecurityZone, 
RangerSecurityZoneHeaderInfo
+from apache_ranger.model.ranger_security_zone import RangerSecurityZone, 
RangerSecurityZoneV2, RangerSecurityZoneHeaderInfo, RangerSecurityZoneResource
 from apache_ranger.model.ranger_service       import RangerService, 
RangerServiceHeaderInfo
 from apache_ranger.model.ranger_service_def   import RangerServiceDef
 from apache_ranger.model.ranger_service_tags  import RangerServiceTags
@@ -229,6 +229,59 @@ class RangerClient:
         return type_coerce_list(resp, RangerSecurityZone)
 
 
+    def create_security_zone_v2(self, securityZone):
+        resp = self.client_http.call_api(RangerClient.CREATE_ZONE_V2, 
request_data=securityZone)
+
+        return type_coerce(resp, RangerSecurityZoneV2)
+
+    def update_security_zone_v2(self, zoneId, securityZone):
+        resp = 
self.client_http.call_api(RangerClient.UPDATE_ZONE_V2_BY_ID.format_path({ 'id': 
zoneId }), request_data=securityZone)
+
+        return type_coerce(resp, RangerSecurityZoneV2)
+
+    def partial_update_security_zone_v2(self, zoneId, changeData):
+        resp = 
self.client_http.call_api(RangerClient.PARTIAL_UPDATE_ZONE_V2_BY_ID.format_path({
 'id': zoneId }), request_data=changeData)
+
+        return type_coerce(resp, RangerSecurityZoneV2)
+
+    def get_security_zone_v2(self, zoneName):
+        resp = 
self.client_http.call_api(RangerClient.GET_ZONE_V2_BY_NAME.format_path({ 
'name': zoneName }))
+
+        return type_coerce(resp, RangerSecurityZoneV2)
+
+    def get_security_zone_v2_by_id(self, zoneId):
+        resp = 
self.client_http.call_api(RangerClient.GET_ZONE_V2_BY_ID.format_path({ 'id': 
zoneId }))
+
+        return type_coerce(resp, RangerSecurityZoneV2)
+
+    def zone_v2_get_resources(self, zoneName, serviceName, filter=None):
+        resp = 
self.client_http.call_api(RangerClient.ZONE_V2_GET_RESOURCES.format_path({'name':
 zoneName, 'serviceName': serviceName}), filter)
+        ret  = type_coerce(resp, PList)
+
+        if ret is not None:
+          ret.type_coerce_list(RangerSecurityZoneResource)
+
+        return ret
+
+    def zone_v2_by_id_get_resources(self, zoneId, serviceName, filter=None):
+        resp = 
self.client_http.call_api(RangerClient.ZONE_V2_BY_ID_GET_RESOURCES.format_path({'id':
 zoneId, 'serviceName': serviceName}), filter)
+        ret  = type_coerce(resp, PList)
+
+        if ret is not None:
+          ret.type_coerce_list(RangerSecurityZoneResource)
+
+        return ret
+
+    def find_security_zones_v2(self, filter=None):
+        resp = self.client_http.call_api(RangerClient.FIND_ZONES_V2, filter)
+        ret  = type_coerce(resp, PList)
+
+        if ret is not None:
+          ret.type_coerce_list(RangerSecurityZoneV2)
+
+        return ret
+
+
     # Role APIs
     def create_role(self, serviceName, role, params=None):
         if params is None:
@@ -337,6 +390,12 @@ class RangerClient:
     URI_ZONE_HEADERS            = URI_BASE + "/zone-headers"
     URI_ZONE_SERVICE_HEADERS    = URI_ZONE + "/{id}/service-headers"
     URI_ZONE_NAMES_FOR_RESOURCE = URI_BASE + 
"/zone-names/{serviceName}/resource"
+    URI_ZONE_V2                   = URI_BASE + "/zones-v2"
+    URI_ZONE_V2_BY_ID             = URI_ZONE_V2 + "/{id}"
+    URI_ZONE_V2_BY_NAME           = URI_ZONE_V2 + "/name/{name}"
+    URL_ZONE_V2_BY_ID_RESOURCES   = URI_ZONE_V2_BY_ID + 
"/resources/{serviceName}"
+    URL_ZONE_V2_BY_NAME_RESOURCES = URI_ZONE_V2_BY_NAME+ 
"/resources/{serviceName}"
+    URI_ZONE_V2_PARTIAL_BY_ID     = URI_ZONE_V2_BY_ID + "/partial"
 
     URI_SERVICE_TAGS        = URI_SERVICE + "/{serviceName}/tags"
     URI_PLUGIN_INFO         = URI_BASE + "/plugins/info"
@@ -375,7 +434,6 @@ class RangerClient:
 
     CREATE_ZONE                 = API(URI_ZONE, HttpMethod.POST, HTTPStatus.OK)
     UPDATE_ZONE_BY_ID           = API(URI_ZONE_BY_ID, HttpMethod.PUT, 
HTTPStatus.OK)
-    UPDATE_ZONE_BY_NAME         = API(URI_ZONE_BY_NAME, HttpMethod.PUT, 
HTTPStatus.OK)
     DELETE_ZONE_BY_ID           = API(URI_ZONE_BY_ID, HttpMethod.DELETE, 
HTTPStatus.NO_CONTENT)
     DELETE_ZONE_BY_NAME         = API(URI_ZONE_BY_NAME, HttpMethod.DELETE, 
HTTPStatus.NO_CONTENT)
     GET_ZONE_BY_ID              = API(URI_ZONE_BY_ID, HttpMethod.GET, 
HTTPStatus.OK)
@@ -384,6 +442,14 @@ class RangerClient:
     GET_ZONE_HEADERS            = API(URI_ZONE_HEADERS, HttpMethod.GET, 
HTTPStatus.OK)
     GET_ZONE_SERVICE_HEADERS    = API(URI_ZONE_SERVICE_HEADERS, 
HttpMethod.GET, HTTPStatus.OK)
     GET_ZONE_NAMES_FOR_RESOURCE = API(URI_ZONE_NAMES_FOR_RESOURCE, 
HttpMethod.GET, HTTPStatus.OK)
+    CREATE_ZONE_V2                        = API(URI_ZONE_V2, HttpMethod.POST, 
HTTPStatus.OK)
+    UPDATE_ZONE_V2_BY_ID                  = API(URI_ZONE_V2_BY_ID, 
HttpMethod.PUT, HTTPStatus.OK)
+    PARTIAL_UPDATE_ZONE_V2_BY_ID          = API(URI_ZONE_V2_PARTIAL_BY_ID, 
HttpMethod.PUT, HTTPStatus.OK)
+    GET_ZONE_V2_BY_NAME                   = API(URI_ZONE_V2_BY_NAME, 
HttpMethod.GET, HTTPStatus.OK)
+    GET_ZONE_V2_BY_ID                     = API(URI_ZONE_V2_BY_ID, 
HttpMethod.GET, HTTPStatus.OK)
+    ZONE_V2_GET_RESOURCES                 = API(URL_ZONE_V2_BY_NAME_RESOURCES, 
HttpMethod.GET, HTTPStatus.OK)
+    ZONE_V2_BY_ID_GET_RESOURCES           = API(URL_ZONE_V2_BY_ID_RESOURCES, 
HttpMethod.GET, HTTPStatus.OK)
+    FIND_ZONES_V2                         = API(URI_ZONE_V2, HttpMethod.GET, 
HTTPStatus.OK)
 
     CREATE_ROLE               = API(URI_ROLE, HttpMethod.POST, HTTPStatus.OK)
     UPDATE_ROLE_BY_ID         = API(URI_ROLE_BY_ID, HttpMethod.PUT, 
HTTPStatus.OK)
diff --git a/intg/src/main/python/apache_ranger/model/ranger_base.py 
b/intg/src/main/python/apache_ranger/model/ranger_base.py
index 2111534d0..2cb06b8bd 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_base.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_base.py
@@ -71,3 +71,25 @@ class RangerBaseModelObject(RangerBase):
         self.createTime = attrs.get('createTime')
         self.updateTime = attrs.get('updateTime')
         self.version    = attrs.get('version')
+
+class PList(RangerBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBase.__init__(self, attrs)
+
+        self.startIndex  = attrs.get('startIndex')
+        self.pageSize    = attrs.get('pageSize')
+        self.totalCount  = attrs.get('totalCount')
+        self.resultSize  = attrs.get('resultSize')
+        self.sortType    = attrs.get('sortType')
+        self.sortBy      = attrs.get('sortBy')
+        self.queryTimeMS = attrs.get('queryTimeMS')
+        self.list        = attrs.get('list')
+
+    def type_coerce_attrs(self):
+        super(PList, self).type_coerce_attrs()
+
+    def type_coerce_list(self, elemType):
+        self.list = type_coerce_list(self.list, elemType)
diff --git a/intg/src/main/python/apache_ranger/model/ranger_principal.py 
b/intg/src/main/python/apache_ranger/model/ranger_principal.py
new file mode 100644
index 000000000..e592cf130
--- /dev/null
+++ b/intg/src/main/python/apache_ranger/model/ranger_principal.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from apache_ranger.model.ranger_base import RangerBase
+from apache_ranger.utils             import *
+from strenum                         import StrEnum
+
+class PrincipalType(StrEnum):
+  USER  = 'USER'
+  GROUP = 'GROUP'
+  ROLE  = 'ROLE'
+
+  @classmethod
+  def value_of(cls, val):
+    if isinstance(val, PrincipalType):
+      return val
+    else:
+      for key, member in cls.__members__.items():
+        if val == member.name or val == member.value:
+          return member
+      else:
+        raise ValueError(f"'{cls.__name__}' enum not found for '{val}'")
+
+
+class RangerPrincipal(RangerBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBase.__init__(self, attrs)
+
+        self.type = attrs.get('type')
+        self.name = attrs.get('name')
+
+    def __hash__(self):
+        return hash((self.type, self.name))
+
+    def __eq__(self, other):
+        return (self.type, self.name) == (other.type, other.name)
+
+    def type_coerce_attrs(self):
+        super(RangerPrincipal, self).type_coerce_attrs()
+
+        self.type = PrincipalType.value_of(self.type)
diff --git a/intg/src/main/python/apache_ranger/model/ranger_security_zone.py 
b/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
index 6faa15744..044848d34 100644
--- a/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
+++ b/intg/src/main/python/apache_ranger/model/ranger_security_zone.py
@@ -16,8 +16,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from apache_ranger.model.ranger_base import RangerBase, RangerBaseModelObject
-from apache_ranger.utils             import *
+from apache_ranger.model.ranger_base      import RangerBase, 
RangerBaseModelObject
+from apache_ranger.utils                  import *
+from apache_ranger.model.ranger_principal import RangerPrincipal
+
+
+class RangerSecurityZoneResourceBase(RangerBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBase.__init__(self, attrs)
+
+        self.id         = attrs.get('id')
+        self.createdBy  = attrs.get('createdBy')
+        self.updatedBy  = attrs.get('updatedBy')
+        self.createTime = attrs.get('createTime')
+        self.updateTime = attrs.get('updateTime')
 
 
 class RangerSecurityZoneService(RangerBase):
@@ -27,12 +42,14 @@ class RangerSecurityZoneService(RangerBase):
 
         RangerBase.__init__(self, attrs)
 
-        self.resources = attrs.get('resources')
+        self.resources         = attrs.get('resources')
+        self.resourcesBaseInfo = attrs.get('resourcesBaseInfo')
 
     def type_coerce_attrs(self):
         super(RangerSecurityZoneService, self).type_coerce_attrs()
 
-        self.resources = type_coerce_list_dict(self.resources, list)
+        self.resources         = type_coerce_list(self.resources, dict)
+        self.resourcesBaseInfo = type_coerce_list(self.resourcesBaseInfo, 
RangerSecurityZoneResourceBase)
 
 
 class RangerSecurityZone(RangerBaseModelObject):
@@ -58,6 +75,86 @@ class RangerSecurityZone(RangerBaseModelObject):
 
         self.services = type_coerce_dict(self.services, 
RangerSecurityZoneService)
 
+
+class RangerSecurityZoneResource(RangerSecurityZoneResourceBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerSecurityZoneResourceBase.__init__(self, attrs)
+
+        self.resource = attrs.get('resource')
+
+    def type_coerce_attrs(self):
+        super(RangerSecurityZoneResource, self).type_coerce_attrs()
+
+        self.resource = type_coerce_dict(self.resource, list)
+
+
+class RangerSecurityZoneServiceV2(RangerBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBase.__init__(self, attrs)
+
+        self.resources = attrs.get('resources')
+
+    def type_coerce_attrs(self):
+        super(RangerSecurityZoneServiceV2, self).type_coerce_attrs()
+
+        self.resources = type_coerce_list(self.resources, 
RangerSecurityZoneResource)
+
+
+class RangerSecurityZoneV2(RangerBaseModelObject):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBaseModelObject.__init__(self, attrs)
+
+        self.name        = attrs.get('name')
+        self.description = attrs.get('description')
+        self.services    = attrs.get('services')
+        self.tagServices = attrs.get('tagServices')
+        self.admins      = attrs.get('admins')
+        self.auditors    = attrs.get('auditors')
+
+    def type_coerce_attrs(self):
+        super(RangerSecurityZoneV2, self).type_coerce_attrs()
+
+        self.services = type_coerce_dict(self.services, 
RangerSecurityZoneServiceV2)
+        self.admins   = type_coerce_list(self.admins, RangerPrincipal)
+        self.auditors = type_coerce_list(self.auditors, RangerPrincipal)
+
+class RangerSecurityZoneChangeRequest(RangerBase):
+    def __init__(self, attrs=None):
+        if attrs is None:
+            attrs = {}
+
+        RangerBaseModelObject.__init__(self, attrs)
+
+        self.name                = attrs.get('name')
+        self.description         = attrs.get('description')
+        self.resourcesToUpdate   = attrs.get('resourcesToUpdate')
+        self.resourcesToRemove   = attrs.get('resourcesToRemove')
+        self.tagServicesToAdd    = attrs.get('tagServicesToAdd')
+        self.tagServicesToRemove = attrs.get('tagServicesToRemove')
+        self.adminsToAdd         = attrs.get('adminsToAdd')
+        self.adminsToRemove      = attrs.get('adminsToRemove')
+        self.auditorsToAdd       = attrs.get('auditorsToAdd')
+        self.auditorsToRemove    = attrs.get('auditorsToRemove')
+
+    def type_coerce_attrs(self):
+        super(RangerSecurityZoneChangeRequest, self).type_coerce_attrs()
+
+        self.resourcesToUpdate = type_coerce_dict(self.resourcesToUpdate, 
RangerSecurityZoneServiceV2)
+        self.resourcesToRemove = type_coerce_dict(self.resourcesToRemove, 
RangerSecurityZoneServiceV2)
+        self.adminsToAdd       = type_coerce_list(self.adminsToAdd, 
RangerPrincipal)
+        self.adminsToRemove    = type_coerce_list(self.adminsToRemove, 
RangerPrincipal)
+        self.auditorsToAdd     = type_coerce_list(self.auditorsToAdd, 
RangerPrincipal)
+        self.auditorsToRemove  = type_coerce_list(self.auditorsToRemove, 
RangerPrincipal)
+
 class RangerSecurityZoneHeaderInfo(RangerBaseModelObject):
     def __init__(self, attrs=None):
         if attrs is None:
diff --git a/intg/src/main/python/setup.py b/intg/src/main/python/setup.py
index 0a4b1c66e..c7dfaa0b4 100644
--- a/intg/src/main/python/setup.py
+++ b/intg/src/main/python/setup.py
@@ -19,7 +19,7 @@
 from setuptools import setup, find_packages
 
 # External dependencies
-requirements = ['requests>=2.24']
+requirements = ['requests>=2.24','strenum>=0.4.15']
 
 long_description = ''
 with open("README.md", "r") as fh:
diff --git a/ranger-examples/sample-client/src/main/python/security_zone_v2.py 
b/ranger-examples/sample-client/src/main/python/security_zone_v2.py
new file mode 100644
index 000000000..b7e15969a
--- /dev/null
+++ b/ranger-examples/sample-client/src/main/python/security_zone_v2.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from apache_ranger.client.ranger_client       import *
+from apache_ranger.model.ranger_security_zone import *
+from apache_ranger.model.ranger_principal     import *
+from datetime                                 import datetime
+
+
+
+## create a client to connect to Apache Ranger admin server
+ranger_url  = 'http://localhost:6080'
+ranger_auth = ('admin', 'rangerR0cks!')
+
+# For Kerberos authentication
+#
+# from requests_kerberos import HTTPKerberosAuth
+#
+# ranger_auth = HTTPKerberosAuth()
+
+
+print(f'\nUsing Ranger at {ranger_url}');
+
+ranger = RangerClient(ranger_url, ranger_auth)
+
+# to disable SSL certificate validation (not recommended for production use!)
+#
+# ranger.session.verify = False
+
+
+print('\nListing security-zones..')
+zones = ranger.find_security_zones_v2()
+
+print(f'    {len(zones.list)} security-zones found')
+for zone in zones.list:
+    print(f'        id: {zone.id}, name: {zone.name}')
+
+now = datetime.now()
+
+zone_name = 'zone1-' + now.strftime('%Y%m%d-%H%M%S-%f')
+
+zone             = RangerSecurityZoneV2()
+zone.name        = zone_name
+zone.description = 'zone created by example script'
+zone.admins      = [ RangerPrincipal({ 'type': PrincipalType.USER, 'name': 
'admin' }) ]
+zone.auditors    = [ RangerPrincipal({ 'type': PrincipalType.USER, 'name': 
'admin' }) ]
+
+print(f'\nCreating security-zone: name={zone_name}')
+
+created_zone = ranger.create_security_zone_v2(zone)
+
+print(f'    created zone: {created_zone}')
+
+zone_id = created_zone.id
+
+
+print(f'\nRetrieving zone by ID: id={zone_id}')
+
+retrieved_zone = ranger.get_security_zone_v2_by_id(zone_id)
+
+print(f'    retrieved zone: id: {retrieved_zone.id}, name: 
{retrieved_zone.name}')
+
+
+print(f'\nRetrieving zone by name: name={zone_name}')
+
+retrieved_zone = ranger.get_security_zone_v2(zone_name)
+
+print(f'    retrieved zone: id: {retrieved_zone.id}, name: 
{retrieved_zone.name}')
+
+
+print('\nListing security-zones..')
+zones = ranger.find_security_zones_v2()
+
+print(f'    {len(zones.list)} security-zones found')
+for zone in zones.list:
+    print(f'        id: {zone.id}, name: {zone.name}')
+
+
+change_req                   = RangerSecurityZoneChangeRequest()
+change_req.resourcesToUpdate = { 'dev_hive': RangerSecurityZoneServiceV2({ 
'resources': [ { 'resource': { 'database': [ 'db1' ] } } ] }), 'dev_hdfs': 
RangerSecurityZoneServiceV2({ 'resources': [ { 'resource': { 'path': [ '/path1' 
] } } ] }) }
+change_req.tagServicesToAdd  = [ 'dev_tag' ]
+change_req.adminsToAdd       = [ RangerPrincipal({ 'type': 'GROUP', 'name': 
'public' }) ]
+change_req.auditorsToAdd     = [ RangerPrincipal({ 'type': 'GROUP', 'name': 
'public' }) ]
+
+print(f'\nUpdating zone: add resources, add tag-services, add admins, add 
auditors..')
+print(f'    change-request: {change_req}')
+
+ranger.partial_update_security_zone_v2(created_zone.id, change_req)
+retrieved_zone = ranger.get_security_zone_v2(zone_name)
+
+print(f'    updated_zone: {retrieved_zone}')
+
+
+change_req                     = RangerSecurityZoneChangeRequest()
+change_req.resourcesToRemove   = { 'dev_hive': RangerSecurityZoneServiceV2({ 
'resources': [ { 'id': 0 } ] }) } # remove resource by ID
+change_req.tagServicesToRemove = [ 'dev_tag' ]
+change_req.adminsToRemove      = [ RangerPrincipal({ 'type': 'USER', 'name': 
'admin' }) ]
+change_req.auditorsToRemove    = [ RangerPrincipal({ 'type': 'USER', 'name': 
'admin' }) ]
+
+print(f'\nUpdating zone: remove resource-by-id, remove tag-services, remove 
admins, remove auditors..')
+print(f'    change-request: {change_req}')
+
+ranger.partial_update_security_zone_v2(created_zone.id, change_req)
+retrieved_zone = ranger.get_security_zone_v2(zone_name)
+
+print(f'    updated_zone: {retrieved_zone}')
+
+
+change_req                   = RangerSecurityZoneChangeRequest()
+change_req.resourcesToUpdate = { 'dev_hdfs': RangerSecurityZoneServiceV2({ 
'resources': [ { 'resource': { 'path': [ zone.name ] } } ] }) }
+change_req.resourcesToRemove = { 'dev_hdfs': RangerSecurityZoneServiceV2({ 
'resources': [ { 'resource': { 'path': [ '/path1' ] } } ] }) } # remove 
resource by value
+
+print(f'\nUpdating zone: remove resource-by-value, add resource..')
+print(f'    change-request: {change_req}')
+
+ranger.partial_update_security_zone_v2(created_zone.id, change_req)
+retrieved_zone = ranger.get_security_zone_v2(zone_name)
+
+print(f'    updated_zone: {retrieved_zone}')
+
+print(f'\nDeleting zone id={zone_id}')
+
+ranger.delete_security_zone_by_id(zone_id)
+
+print(f'    deleted zone: id: {zone_id}, name: {zone.name}')
+
+
+print('\nListing security-zones..')
+zones = ranger.find_security_zones_v2()
+
+print(f'    {len(zones.list)} security-zones found')
+for zone in zones.list:
+    print(f'        id: {zone.id}, name: {zone.name}')
diff --git 
a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java 
b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
index cd906ed22..92ade823b 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
@@ -34,6 +34,10 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceHeaderInfo;
 import org.apache.ranger.plugin.model.RangerServiceResource;
 import org.apache.ranger.plugin.model.RangerServiceTags;
+import org.apache.ranger.plugin.model.RangerSecurityZoneV2;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneChangeRequest;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResource;
+import org.apache.ranger.plugin.store.PList;
 import org.apache.ranger.plugin.util.GrantRevokeRoleRequest;
 import org.apache.ranger.plugin.util.RangerPurgeResult;
 import org.apache.ranger.plugin.util.ServiceTags;
@@ -216,6 +220,65 @@ public class PublicAPIsv2 {
                return securityZoneRest.getZoneNamesForResource(serviceName, 
request);
        }
 
+       @POST
+       @Path("/api/zones-v2")
+       @Consumes({ "application/json" })
+       @Produces({ "application/json" })
+       public RangerSecurityZoneV2 createSecurityZone(RangerSecurityZoneV2 
securityZone) {
+               return securityZoneRest.createSecurityZone(securityZone);
+       }
+
+       @PUT
+       @Path("/api/zones-v2/{id}")
+       @Consumes({ "application/json" })
+       @Produces({ "application/json" })
+       public RangerSecurityZoneV2 updateSecurityZone(@PathParam("id") Long 
zoneId, RangerSecurityZoneV2 securityZone) {
+               return securityZoneRest.updateSecurityZone(zoneId, 
securityZone);
+       }
+
+       @PUT
+       @Path("/api/zones-v2/{id}/partial")
+       @Consumes({ "application/json" })
+       @Produces({ "application/json" })
+       public Boolean updateSecurityZone(@PathParam("id") Long zoneId, 
RangerSecurityZoneChangeRequest changeRequest) {
+               return securityZoneRest.updateSecurityZone(zoneId, 
changeRequest);
+       }
+
+       @GET
+       @Path("/api/zones-v2/name/{name}")
+       @Produces({ "application/json" })
+       public RangerSecurityZoneV2 getSecurityZoneV2(@PathParam("name") String 
zoneName) {
+               return securityZoneRest.getSecurityZoneV2(zoneName);
+       }
+
+       @GET
+       @Path("/api/zones-v2/{id}")
+       @Produces({ "application/json" })
+       public RangerSecurityZoneV2 getSecurityZoneV2(@PathParam("id") Long 
zoneId) {
+               return securityZoneRest.getSecurityZoneV2(zoneId);
+       }
+
+       @GET
+       @Path("/api/zones-v2/{id}/resources/{serviceName}")
+       @Produces({ "application/json" })
+       public PList<RangerSecurityZoneResource> getResources(@PathParam("id") 
Long zoneId, @PathParam("serviceName") String serviceName, @Context 
HttpServletRequest request) {
+               return securityZoneRest.getResources(zoneId, serviceName, 
request);
+       }
+
+       @GET
+       @Path("/api/zones-v2/name/{name}/resources/{serviceName}")
+       @Produces({ "application/json" })
+       public PList<RangerSecurityZoneResource> 
getResources(@PathParam("name") String zoneName, @PathParam("serviceName") 
String serviceName, @Context HttpServletRequest request) {
+               return securityZoneRest.getResources(zoneName, serviceName, 
request);
+       }
+
+       @GET
+       @Path("/api/zones-v2")
+       @Produces({ "application/json"})
+       public PList<RangerSecurityZoneV2> getAllZonesV2(@Context 
HttpServletRequest request){
+               return securityZoneRest.getAllZonesV2(request);
+       }
+
        /*
        * ServiceDef Manipulation APIs
         */
diff --git 
a/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java 
b/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java
index 55d6aaac5..7c1e01053 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java
@@ -58,11 +58,17 @@ import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.plugin.model.RangerSecurityZone;
+import org.apache.ranger.plugin.model.RangerSecurityZoneV2;
 import org.apache.ranger.plugin.model.validation.RangerSecurityZoneValidator;
 import org.apache.ranger.plugin.model.validation.RangerValidator;
+import org.apache.ranger.plugin.store.PList;
+import org.apache.ranger.plugin.util.RangerSecurityZoneHelper;
+import 
org.apache.ranger.plugin.util.RangerSecurityZoneHelper.RangerSecurityZoneServiceHelper;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.service.RangerSecurityZoneServiceService;
 import 
org.apache.ranger.plugin.model.RangerSecurityZone.RangerSecurityZoneService;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneChangeRequest;
+import 
org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResource;
 import org.apache.ranger.view.RangerSecurityZoneList;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.slf4j.Logger;
@@ -114,7 +120,6 @@ public class SecurityZoneREST {
        @Autowired
        ServiceMgr serviceMgr;
 
-
     @POST
     @Path("/zones")
     @Consumes({ "application/json" })
@@ -126,6 +131,10 @@ public class SecurityZoneREST {
 
         RangerSecurityZone ret;
         try {
+            RangerSecurityZoneHelper zoneHelper = new 
RangerSecurityZoneHelper(securityZone, bizUtil.getCurrentUserLoginId()); // 
this populates resourcesBaseInfo
+
+            securityZone = zoneHelper.getZone();
+
             ensureAdminAccess(securityZone);
             removeEmptyEntries(securityZone);
             RangerSecurityZoneValidator validator = 
validatorFactory.getSecurityZoneValidator(svcStore, securityZoneStore);
@@ -162,6 +171,10 @@ public class SecurityZoneREST {
             throw restErrorUtil.createRESTException("Cannot update unzoned 
zone");
         }
 
+        RangerSecurityZoneHelper zoneHelper = new 
RangerSecurityZoneHelper(securityZone, bizUtil.getCurrentUserLoginId()); // 
this populates resourcesBaseInfo
+
+        securityZone = zoneHelper.getZone();
+
         ensureUserAllowOperationOnServiceForZone(securityZone);
         removeEmptyEntries(securityZone);
         if (securityZone.getId() != null && 
!zoneId.equals(securityZone.getId())) {
@@ -380,7 +393,113 @@ public class SecurityZoneREST {
         return ret;
     }
 
-       private void ensureAdminAccess(){
+    public RangerSecurityZoneV2 createSecurityZone(RangerSecurityZoneV2 
securityZone) {
+        LOG.debug("==> createSecurityZone({})", securityZone);
+
+        RangerSecurityZone   retV1 = createSecurityZone(securityZone.toV1());
+        RangerSecurityZoneV2 ret   = retV1 != null ? new 
RangerSecurityZoneV2(retV1) : null;
+
+        LOG.debug("<== createSecurityZone({}): ret={}", securityZone, ret);
+
+        return ret;
+    }
+
+    public RangerSecurityZoneV2 updateSecurityZone(Long zoneId, 
RangerSecurityZoneV2 securityZone) {
+        LOG.debug("==> updateSecurityZone({}, {})", zoneId, securityZone);
+
+        RangerSecurityZone   retV1 = updateSecurityZone(zoneId, 
securityZone.toV1());
+        RangerSecurityZoneV2 ret   = retV1 != null ? new 
RangerSecurityZoneV2(retV1) : null;
+
+        LOG.debug("<== updateSecurityZone({}, {}): ret={}", zoneId, 
securityZone, ret);
+
+        return ret;
+    }
+
+    public Boolean updateSecurityZone(Long zoneId, 
RangerSecurityZoneChangeRequest changeData) {
+        LOG.debug("==> updateSecurityZone({}, {})", zoneId, changeData);
+
+        RangerSecurityZone       zone        = getSecurityZone(zoneId);
+        RangerSecurityZoneHelper zoneHelper  = new 
RangerSecurityZoneHelper(zone, bizUtil.getCurrentUserLoginId());
+        RangerSecurityZone       updatedZone = 
zoneHelper.updateZone(changeData);
+
+        RangerSecurityZone retV1 = updateSecurityZone(zoneId, updatedZone);
+        Boolean            ret   = retV1 != null;
+
+        LOG.debug("<== updateSecurityZone({}, {}): ret={}", zoneId, 
changeData, ret);
+
+        return ret;
+    }
+
+    public RangerSecurityZoneV2 getSecurityZoneV2(String zoneName) {
+        LOG.debug("==> getSecurityZoneV2({})", zoneName);
+
+        RangerSecurityZone   retV1 = getSecurityZone(zoneName);
+        RangerSecurityZoneV2 ret   = retV1 != null ? new 
RangerSecurityZoneV2(retV1) : null;
+
+        LOG.debug("<== getSecurityZoneV2({}): ret={}", zoneName, ret);
+
+        return ret;
+    }
+
+    public RangerSecurityZoneV2 getSecurityZoneV2(Long zoneId) {
+        LOG.debug("==> getSecurityZoneV2({})", zoneId);
+
+        RangerSecurityZone   retV1 = getSecurityZone(zoneId);
+        RangerSecurityZoneV2 ret   = retV1 != null ? new 
RangerSecurityZoneV2(retV1) : null;
+
+        LOG.debug("<== getSecurityZoneV2({}): ret={}", zoneId, ret);
+
+        return ret;
+    }
+
+    public PList<RangerSecurityZoneResource> getResources(Long zoneId, String 
serviceName, HttpServletRequest request) {
+        LOG.debug("==> getResources(zoneId={}, serviceName={})", zoneId, 
serviceName);
+
+        PList<RangerSecurityZoneResource> ret = 
getResources(getSecurityZone(zoneId), serviceName, request);
+
+        LOG.debug("<== getResources(zoneId={}, serviceName={}): ret={}", 
zoneId, serviceName, ret);
+
+        return ret;
+    }
+
+    public PList<RangerSecurityZoneResource> getResources(String zoneName, 
String serviceName, HttpServletRequest request) {
+        LOG.debug("==> getResources(zoneName={}, serviceName={})", zoneName, 
serviceName);
+
+        PList<RangerSecurityZoneResource> ret = 
getResources(getSecurityZone(zoneName), serviceName, request);
+
+        LOG.debug("<== getResources(zoneName={}, serviceName={}): ret={}", 
zoneName, serviceName, ret);
+
+        return ret;
+    }
+
+    public PList<RangerSecurityZoneV2> getAllZonesV2(HttpServletRequest 
request) {
+        LOG.debug("==> getAllZonesV2()");
+
+        PList<RangerSecurityZoneV2> ret     = new PList<>();
+        RangerSecurityZoneList      retList = getAllZones(request);
+
+        if (retList != null) {
+            ret.setList(new ArrayList<>(retList.getListSize()));
+            ret.setPageSize(retList.getPageSize());
+            ret.setStartIndex(retList.getStartIndex());
+            ret.setResultSize(retList.getResultSize());
+            ret.setTotalCount(retList.getTotalCount());
+            ret.setSortBy(retList.getSortBy());
+            ret.setSortType(retList.getSortType());
+
+            if (retList.getSecurityZones() != null) {
+                for (RangerSecurityZone zone : retList.getSecurityZones()) {
+                    ret.getList().add(new RangerSecurityZoneV2(zone));
+                }
+            }
+        }
+
+        LOG.debug("<== getAllZonesV2(): ret={}", ret);
+
+        return ret;
+    }
+
+    private void ensureAdminAccess(){
                if(!bizUtil.isAdmin()){
                        String userName = bizUtil.getCurrentUserLoginId();
                        throw 
restErrorUtil.createRESTException(HttpServletResponse.SC_FORBIDDEN, "Ranger 
Security Zone is not accessible for user '" + userName + "'.", true);
@@ -529,7 +648,7 @@ public class SecurityZoneREST {
 
                }
        }
-       
+
        private void throwRestError(String message){
                throw 
restErrorUtil.createRESTException(HttpServletResponse.SC_FORBIDDEN, message, 
true);
        }
@@ -595,4 +714,19 @@ public class SecurityZoneREST {
                        }
                }
        }
+
+    private PList<RangerSecurityZoneResource> getResources(RangerSecurityZone 
zone, String serviceName, @Context HttpServletRequest request) {
+        RangerSecurityZoneHelper          zoneHelper        = new 
RangerSecurityZoneHelper(zone, bizUtil.getCurrentUserLoginId());
+        RangerSecurityZoneServiceHelper   zoneServiceHelper = 
zoneHelper.getZoneService(serviceName);
+        PList<RangerSecurityZoneResource> ret               = null;
+
+        if (zoneServiceHelper != null) {
+            SearchFilter                     filter = 
searchUtil.getSearchFilter(request, Collections.emptyList());
+            List<RangerSecurityZoneResource> result = 
zoneServiceHelper.getResources(filter.getStartIndex(), filter.getMaxRows());
+
+            ret = new PList<>(result, filter.getStartIndex(), 
filter.getMaxRows(), zoneServiceHelper.getResourceCount(), result.size(), null, 
null);
+        }
+
+        return ret;
+    }
 }

Reply via email to