You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2023/06/09 12:59:53 UTC

[ranger] branch master updated: RANGER-4274: updated security-zones to support admin-roles and audit-roles

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 04cb1dc5b RANGER-4274: updated security-zones to support admin-roles and audit-roles
04cb1dc5b is described below

commit 04cb1dc5bd01d1772b4fc42e01a164333c43a1d7
Author: Madhan Neethiraj <ma...@apache.org>
AuthorDate: Tue Jun 6 07:14:36 2023 -0700

    RANGER-4274: updated security-zones to support admin-roles and audit-roles
---
 .../ranger/plugin/errors/ValidationErrorCode.java  |   2 +-
 .../ranger/plugin/model/RangerSecurityZone.java    |  24 ++-
 .../validation/RangerSecurityZoneValidator.java    |  16 +-
 .../apache_ranger/model/ranger_security_zone.py    |   2 +
 .../optimized/current/ranger_core_db_mysql.sql     |  18 ++
 .../mysql/patches/075-create-sz-role-ref-table.sql |  32 ++++
 .../optimized/current/ranger_core_db_oracle.sql    |  19 +++
 .../patches/075-create-sz-ref-role-table.sql       |  33 ++++
 .../optimized/current/ranger_core_db_postgres.sql  |  21 +++
 .../patches/075-create-sz-ref-role-table.sql       |  37 +++++
 .../current/ranger_core_db_sqlanywhere.sql         |  24 +++
 .../patches/075-create-sz-ref-role-table.sql       |  40 +++++
 .../optimized/current/ranger_core_db_sqlserver.sql |  49 ++++++
 .../patches/075-create-sz-ref-role-table.sql       |  66 ++++++++
 .../java/org/apache/ranger/biz/RoleDBStore.java    |  18 ++
 .../apache/ranger/biz/SecurityZoneRefUpdater.java  | 144 +++++++---------
 .../java/org/apache/ranger/biz/ServiceMgr.java     |  65 +++++++-
 .../org/apache/ranger/db/RangerDaoManagerBase.java |   2 +
 .../apache/ranger/db/XXSecurityZoneRefRoleDao.java | 105 ++++++++++++
 .../ranger/entity/XXSecurityZoneRefRole.java       | 185 +++++++++++++++++++++
 .../org/apache/ranger/rest/SecurityZoneREST.java   |   9 +
 .../service/RangerSecurityZoneServiceService.java  |   2 +
 .../main/resources/META-INF/jpa_named_queries.xml  |  18 ++
 23 files changed, 835 insertions(+), 96 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
index f44b9d9a1..85c42bcc8 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
@@ -111,7 +111,7 @@ public enum ValidationErrorCode {
     SECURITY_ZONE_VALIDATION_ERR_MISSING_FIELD(3035, "Internal error: missing field[{0}]"),
     SECURITY_ZONE_VALIDATION_ERR_ZONE_NAME_CONFLICT(3036, "Another security zone already exists for this name: zone-id=[{0}]]"),
     SECURITY_ZONE_VALIDATION_ERR_INVALID_ZONE_ID(3037, "No security zone found for [{0}]"),
-    SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS(3038, "both users and user-groups collections for the security zone were null/empty"),
+    SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS_AND_ROLES(3038, "users, user-groups and roles collections for the security zone were null/empty"),
     SECURITY_ZONE_VALIDATION_ERR_MISSING_RESOURCES(3039, "No resources specified for service [{0}]"),
     SECURITY_ZONE_VALIDATION_ERR_INVALID_SERVICE_NAME(3040, "Invalid service [{0}]"),
     SECURITY_ZONE_VALIDATION_ERR_INVALID_SERVICE_TYPE(3041, "Invalid service-type [{0}]"),
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 7327f3fe2..ea79b69e8 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
@@ -44,21 +44,29 @@ public class RangerSecurityZone extends RangerBaseModelObject implements java.io
     private List<String>  							tagServices;
     private List<String>                            adminUsers;
     private List<String>                            adminUserGroups;
+    private List<String>                            adminRoles;
     private List<String>                            auditUsers;
     private List<String>                            auditUserGroups;
+    private List<String>                            auditRoles;
     private String                                  description;
 
     public RangerSecurityZone() {
-        this(null, null, null, null, null, null, null,null);
+        this(null, null, null, null, null, null, null,null, null, null);
     }
 
     public RangerSecurityZone(String name, Map<String, RangerSecurityZoneService> services,List<String> tagServices, List<String> adminUsers, List<String> adminUserGroups, List<String> auditUsers, List<String> auditUserGroups, String description) {
+        this(name, services, tagServices, adminUsers, adminUserGroups, null, adminUsers, adminUserGroups, null, description);
+    }
+
+    public RangerSecurityZone(String name, Map<String, RangerSecurityZoneService> services,List<String> tagServices, List<String> adminUsers, List<String> adminUserGroups, List<String> adminRoles, List<String> auditUsers, List<String> auditUserGroups, List<String> auditRoles, String description) {
         setName(name);
         setServices(services);
         setAdminUsers(adminUsers);
         setAdminUserGroups(adminUserGroups);
+        setAdminRoles(adminRoles);
         setAuditUsers(auditUsers);
         setAuditUserGroups(auditUserGroups);
+        setAuditRoles(auditRoles);
         setDescription(description);
         setTagServices(tagServices);
     }
@@ -92,6 +100,12 @@ public class RangerSecurityZone extends RangerBaseModelObject implements java.io
         this.adminUserGroups = adminUserGroups == null ? new ArrayList<>() : adminUserGroups;
     }
 
+    public List<String> getAdminRoles() { return adminRoles; }
+
+    public void setAdminRoles(List<String> adminRoles) {
+        this.adminRoles = adminRoles == null ? new ArrayList<>() : adminRoles;
+    }
+
     public List<String> getAuditUsers() { return auditUsers; }
 
     public void setAuditUsers(List<String> auditUsers) {
@@ -104,6 +118,12 @@ public class RangerSecurityZone extends RangerBaseModelObject implements java.io
         this.auditUserGroups = auditUserGroups == null ? new ArrayList<>() : auditUserGroups;
     }
 
+    public List<String> getAuditRoles() { return auditRoles; }
+
+    public void setAuditRoles(List<String> auditRoles) {
+        this.auditRoles = auditRoles == null ? new ArrayList<>() : auditRoles;
+    }
+
     public List<String> getTagServices() {
                 return tagServices;
         }
@@ -119,8 +139,10 @@ public class RangerSecurityZone extends RangerBaseModelObject implements java.io
                 + ", tagServices=" + tagServices
                 + ", adminUsers=" + adminUsers
                 + ", adminUserGroups=" + adminUserGroups
+                + ", adminRoles=" + adminRoles
                 + ", auditUsers=" + auditUsers
                 + ", auditUserGroups=" + auditUserGroups
+                + ", auditRoles=" + auditRoles
                 + ", description="+ description
                 +"}";
     }
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
index ca899979a..cb4f37cc0 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
@@ -233,18 +233,18 @@ public class RangerSecurityZoneValidator extends RangerValidator {
             failures.add(new ValidationFailureDetailsBuilder().becauseOf("security zone services").isMissing().field("services").errorCode(error.getErrorCode()).becauseOf(error.getMessage(securityZone.getName())).build());
             ret = false;
         }
-        // both admin users and user-groups collections can't be empty
-        if (CollectionUtils.isEmpty(securityZone.getAdminUsers()) && CollectionUtils.isEmpty(securityZone.getAdminUserGroups())) {
-            ValidationErrorCode error = ValidationErrorCode.SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS;
+        // admin users, user-groups and roles collections can't be empty
+        if (CollectionUtils.isEmpty(securityZone.getAdminUsers()) && CollectionUtils.isEmpty(securityZone.getAdminUserGroups()) && CollectionUtils.isEmpty(securityZone.getAdminRoles())) {
+            ValidationErrorCode error = ValidationErrorCode.SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS_AND_ROLES;
 
-            failures.add(new ValidationFailureDetailsBuilder().field("security zone admin users/user-groups").isMissing().becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build());
+            failures.add(new ValidationFailureDetailsBuilder().field("security zone admin users/user-groups/roles").isMissing().becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build());
             ret = false;
         }
-        // both audit users and user-groups collections can't be empty
-        if (CollectionUtils.isEmpty(securityZone.getAuditUsers()) && CollectionUtils.isEmpty(securityZone.getAuditUserGroups())) {
-            ValidationErrorCode error = ValidationErrorCode.SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS;
+        // audit users, user-groups and roles collections can't be empty
+        if (CollectionUtils.isEmpty(securityZone.getAuditUsers()) && CollectionUtils.isEmpty(securityZone.getAuditUserGroups()) && CollectionUtils.isEmpty(securityZone.getAuditRoles())) {
+            ValidationErrorCode error = ValidationErrorCode.SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS_AND_ROLES;
 
-            failures.add(new ValidationFailureDetailsBuilder().field("security zone audit users/user-groups").isMissing().becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build());
+            failures.add(new ValidationFailureDetailsBuilder().field("security zone audit users/user-groups/roles").isMissing().becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build());
             ret = false;
         }
 
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 9b3eec623..6faa15744 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
@@ -47,8 +47,10 @@ class RangerSecurityZone(RangerBaseModelObject):
         self.tagServices     = attrs.get('tagServices')
         self.adminUsers      = attrs.get('adminUsers')
         self.adminUserGroups = attrs.get('adminUserGroups')
+        self.adminRoles      = attrs.get('adminRoles')
         self.auditUsers      = attrs.get('auditUsers')
         self.auditUserGroups = attrs.get('auditUserGroups')
+        self.auditRoles      = attrs.get('auditRoles')
         self.description     = attrs.get('description')
 
     def type_coerce_attrs(self):
diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
index 66ae5060a..ac1fa1509 100644
--- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
+++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
@@ -67,6 +67,7 @@ DROP TABLE IF EXISTS `x_service_config_def`;
 DROP TABLE IF EXISTS `x_policy`;
 DROP TABLE IF EXISTS `x_security_zone_ref_group`;
 DROP TABLE IF EXISTS `x_security_zone_ref_user`;
+DROP TABLE IF EXISTS `x_security_zone_ref_role`;
 DROP TABLE IF EXISTS `x_security_zone_ref_tag_srvc`;
 DROP TABLE IF EXISTS `x_security_zone_ref_service`;
 DROP TABLE IF EXISTS `x_ranger_global_state`;
@@ -1542,6 +1543,22 @@ CREATE TABLE IF NOT EXISTS `x_role_ref_role`(
  CONSTRAINT `x_role_ref_role_FK_role_ref_id` FOREIGN KEY (`role_ref_id`) REFERENCES `x_role` (`id`)
 )ROW_FORMAT=DYNAMIC;
 
+CREATE TABLE IF NOT EXISTS `x_security_zone_ref_role`(
+`id` bigint(20) NOT NULL AUTO_INCREMENT,
+`create_time` datetime NULL DEFAULT NULL,
+`update_time` datetime NULL DEFAULT NULL,
+`added_by_id` bigint(20) NULL DEFAULT NULL,
+`upd_by_id` bigint(20) NULL DEFAULT NULL,
+`zone_id` bigint(20) NULL DEFAULT NULL,
+`role_id` bigint(20) NULL DEFAULT NULL,
+`role_name` varchar(255) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_added_by_id` FOREIGN KEY (`added_by_id`) REFERENCES `x_portal_user` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_upd_by_id` FOREIGN KEY (`upd_by_id`) REFERENCES `x_portal_user` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_zone_id` FOREIGN KEY (`zone_id`) REFERENCES `x_security_zone` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_role_id` FOREIGN KEY (`role_id`) REFERENCES `x_role` (`id`)
+ )ROW_FORMAT=DYNAMIC;
+
 CREATE TABLE IF NOT EXISTS `x_tag_change_log` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `create_time` datetime NULL DEFAULT NULL,
@@ -1814,6 +1831,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('060',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('065',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('075',UTC_TIMESTAMP(),'Ranger 3.0.0',UTC_TIMESTAMP(),'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
 
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10001',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y');
diff --git a/security-admin/db/mysql/patches/075-create-sz-role-ref-table.sql b/security-admin/db/mysql/patches/075-create-sz-role-ref-table.sql
new file mode 100644
index 000000000..d09bf6422
--- /dev/null
+++ b/security-admin/db/mysql/patches/075-create-sz-role-ref-table.sql
@@ -0,0 +1,32 @@
+-- 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.
+
+DROP TABLE IF EXISTS `x_security_zone_ref_role`;
+
+CREATE TABLE IF NOT EXISTS `x_security_zone_ref_role`(
+`id` bigint(20) NOT NULL AUTO_INCREMENT,
+`create_time` datetime NULL DEFAULT NULL,
+`update_time` datetime NULL DEFAULT NULL,
+`added_by_id` bigint(20) NULL DEFAULT NULL,
+`upd_by_id` bigint(20) NULL DEFAULT NULL,
+`zone_id` bigint(20) NULL DEFAULT NULL,
+`role_id` bigint(20) NULL DEFAULT NULL,
+`role_name` varchar(255) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_added_by_id` FOREIGN KEY (`added_by_id`) REFERENCES `x_portal_user` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_upd_by_id` FOREIGN KEY (`upd_by_id`) REFERENCES `x_portal_user` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_zone_id` FOREIGN KEY (`zone_id`) REFERENCES `x_security_zone` (`id`),
+ CONSTRAINT `x_sz_ref_role_FK_role_id` FOREIGN KEY (`role_id`) REFERENCES `x_role` (`id`)
+ )ROW_FORMAT=DYNAMIC;
diff --git a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
index bfa6dd572..a4d145de0 100644
--- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
+++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
@@ -257,6 +257,7 @@ call spdroptable('x_service_config_def');
 call spdroptable('x_policy');
 call spdroptable('x_security_zone_ref_group');
 call spdroptable('x_security_zone_ref_user');
+call spdroptable('x_security_zone_ref_role');
 call spdroptable('x_security_zone_ref_tag_srvc');
 call spdroptable('x_security_zone_ref_service');
 call spdroptable('x_ranger_global_state');
@@ -1641,6 +1642,23 @@ CONSTRAINT x_sz_ref_res_FK_res_def_id FOREIGN KEY (resource_def_id) REFERENCES x
 );
 commit;
 
+CREATE TABLE x_security_zone_ref_role (
+id NUMBER(20) NOT NULL,
+create_time DATE DEFAULT NULL NULL,
+update_time DATE DEFAULT NULL NULL,
+added_by_id NUMBER(20) DEFAULT NULL NULL,
+upd_by_id NUMBER(20) DEFAULT NULL NULL,
+zone_id NUMBER(20)  DEFAULT NULL NULL,
+role_id NUMBER(20)  DEFAULT NULL NULL,
+role_name varchar(255) DEFAULT NULL NULL,
+primary key (id),
+CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY (zone_id) REFERENCES x_security_zone (id),
+CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY (role_id) REFERENCES x_role (id)
+);
+commit;
+
 CREATE VIEW vx_trx_log AS select x_trx_log.id AS id,x_trx_log.create_time AS create_time,x_trx_log.update_time AS update_time,x_trx_log.added_by_id AS added_by_id,x_trx_log.upd_by_id AS upd_by_id,x_trx_log.class_type AS class_type,x_trx_log.object_id AS object_id,x_trx_log.parent_object_id AS parent_object_id,x_trx_log.parent_object_class_type AS parent_object_class_type,x_trx_log.attr_name AS attr_name,x_trx_log.parent_object_name AS parent_object_name,x_trx_log.object_name AS object_na [...]
 commit;
 
@@ -1974,6 +1992,7 @@ INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,act
 INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '059',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
 INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '060',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
 INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '065',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
+INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, '075',sys_extract_utc(systimestamp),'Ranger 3.0.0',sys_extract_utc(systimestamp),'localhost','Y');
 INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval, 'DB_PATCHES',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y');
 
 INSERT INTO x_user_module_perm (id,user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (X_USER_MODULE_PERM_SEQ.nextval,getXportalUIdByLoginId('admin'),getModulesIdByName('Reports'),sys_extract_utc(systimestamp),sys_extract_utc(systimestamp),getXportalUIdByLoginId('admin'),getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/oracle/patches/075-create-sz-ref-role-table.sql b/security-admin/db/oracle/patches/075-create-sz-ref-role-table.sql
new file mode 100644
index 000000000..990c8fd29
--- /dev/null
+++ b/security-admin/db/oracle/patches/075-create-sz-ref-role-table.sql
@@ -0,0 +1,33 @@
+-- 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.
+
+call spdroptable('x_security_zone_ref_role');
+
+CREATE TABLE x_security_zone_ref_role (
+id NUMBER(20) NOT NULL,
+create_time DATE DEFAULT NULL NULL,
+update_time DATE DEFAULT NULL NULL,
+added_by_id NUMBER(20) DEFAULT NULL NULL,
+upd_by_id NUMBER(20) DEFAULT NULL NULL,
+zone_id NUMBER(20)  DEFAULT NULL NULL,
+role_id NUMBER(20)  DEFAULT NULL NULL,
+role_name varchar(255) DEFAULT NULL NULL,
+primary key (id),
+CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY (zone_id) REFERENCES x_security_zone (id),
+CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY (role_id) REFERENCES x_role (id)
+);
+commit;
diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
index 8dd90c1b8..e3273497e 100644
--- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
+++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
@@ -66,6 +66,7 @@ DROP TABLE IF EXISTS x_service_config_def CASCADE;
 DROP TABLE IF EXISTS x_policy CASCADE;
 DROP TABLE IF EXISTS x_security_zone_ref_group CASCADE;
 DROP TABLE IF EXISTS x_security_zone_ref_user CASCADE;
+DROP TABLE IF EXISTS x_security_zone_ref_role CASCADE;
 DROP TABLE IF EXISTS x_security_zone_ref_tag_srvc CASCADE;
 DROP TABLE IF EXISTS x_security_zone_ref_service CASCADE;
 DROP TABLE IF EXISTS x_ranger_global_state CASCADE;
@@ -92,6 +93,7 @@ DROP TABLE IF EXISTS x_db_version_h CASCADE;
 
 DROP SEQUENCE IF EXISTS x_sec_zone_ref_group_seq;
 DROP SEQUENCE IF EXISTS x_sec_zone_ref_user_seq;
+DROP SEQUENCE IF EXISTS x_sec_zone_ref_role_seq;
 DROP SEQUENCE IF EXISTS x_sec_zone_ref_resource_seq;
 DROP SEQUENCE IF EXISTS x_sec_zone_ref_service_seq;
 DROP SEQUENCE IF EXISTS x_sec_zone_ref_tag_srvc_SEQ;
@@ -1573,6 +1575,24 @@ priv_type INT DEFAULT NULL NULL,
 );
 commit;
 
+CREATE SEQUENCE x_sec_zone_ref_role_seq;
+CREATE TABLE x_security_zone_ref_role (
+id BIGINT DEFAULT nextval('x_sec_zone_ref_role_seq'::regclass),
+create_time TIMESTAMP DEFAULT NULL NULL,
+update_time TIMESTAMP DEFAULT NULL NULL,
+added_by_id BIGINT DEFAULT NULL NULL,
+upd_by_id BIGINT DEFAULT NULL NULL,
+zone_id BIGINT DEFAULT NULL NULL,
+role_id BIGINT DEFAULT NULL NULL,
+role_name varchar(255) NULL DEFAULT NULL::character varying,
+primary key (id),
+CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY (zone_id) REFERENCES x_security_zone (id),
+CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY (role_id) REFERENCES x_role (id)
+);
+commit;
+
 CREATE SEQUENCE x_tag_change_log_seq;
 
 CREATE TABLE x_tag_change_log (
@@ -1897,6 +1917,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('060',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('065',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('075',current_timestamp,'Ranger 3.0.0',current_timestamp,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y');
 
 INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES
diff --git a/security-admin/db/postgres/patches/075-create-sz-ref-role-table.sql b/security-admin/db/postgres/patches/075-create-sz-ref-role-table.sql
new file mode 100644
index 000000000..ab4e5748c
--- /dev/null
+++ b/security-admin/db/postgres/patches/075-create-sz-ref-role-table.sql
@@ -0,0 +1,37 @@
+-- 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.
+
+DROP TABLE IF EXISTS x_security_zone_ref_role CASCADE;
+
+DROP SEQUENCE IF EXISTS x_sec_zone_ref_role_seq;
+
+CREATE SEQUENCE x_sec_zone_ref_role_seq;
+CREATE TABLE x_security_zone_ref_role (
+id BIGINT DEFAULT nextval('x_sec_zone_ref_role_seq'::regclass),
+create_time TIMESTAMP DEFAULT NULL NULL,
+update_time TIMESTAMP DEFAULT NULL NULL,
+added_by_id BIGINT DEFAULT NULL NULL,
+upd_by_id BIGINT DEFAULT NULL NULL,
+zone_id BIGINT DEFAULT NULL NULL,
+role_id BIGINT DEFAULT NULL NULL,
+role_name varchar(255) NULL DEFAULT NULL::character varying,
+primary key (id),
+CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id),
+CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY (zone_id) REFERENCES x_security_zone (id),
+CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY (role_id) REFERENCES x_role (id)
+);
+commit;
+
diff --git a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
index 3a614e44e..8fe9dbf5f 100644
--- a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
+++ b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
@@ -144,6 +144,8 @@ call dbo.removeForeignKeysAndTable('x_security_zone_ref_group')
 GO
 call dbo.removeForeignKeysAndTable('x_security_zone_ref_user')
 GO
+call dbo.removeForeignKeysAndTable('x_security_zone_ref_role')
+GO
 call dbo.removeForeignKeysAndTable('x_security_zone_ref_tag_srvc')
 GO
 call dbo.removeForeignKeysAndTable('x_security_zone_ref_service')
@@ -1224,6 +1226,18 @@ CREATE TABLE dbo.x_security_zone_ref_group(
         CONSTRAINT x_sz_ref_agroup_PK_id PRIMARY KEY CLUSTERED(id)
 )
 GO
+CREATE TABLE dbo.x_security_zone_ref_role(
+        id bigint IDENTITY NOT NULL,
+        create_time datetime DEFAULT NULL NULL,
+        update_time datetime DEFAULT NULL NULL,
+        added_by_id bigint DEFAULT NULL NULL,
+        upd_by_id bigint DEFAULT NULL NULL,
+        zone_id bigint DEFAULT NULL NULL,
+        role_id bigint DEFAULT NULL NULL,
+        role_name varchar(767) DEFAULT NULL NULL
+        CONSTRAINT x_sz_ref_arole_PK_id PRIMARY KEY CLUSTERED(id)
+)
+GO
 CREATE TABLE dbo.x_policy_change_log(
         id bigint IDENTITY NOT NULL,
         create_time datetime DEFAULT NULL NULL,
@@ -1709,6 +1723,14 @@ ALTER TABLE dbo.x_security_zone_ref_group ADD CONSTRAINT x_sz_ref_grp_FK_zone_id
 GO
 ALTER TABLE dbo.x_security_zone_ref_group ADD CONSTRAINT x_sz_ref_grp_FK_group_id FOREIGN KEY(group_id) REFERENCES dbo.x_group (id)
 GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES dbo.x_portal_user (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES dbo.x_portal_user (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY(zone_id) REFERENCES dbo.x_security_zone (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY(role_id) REFERENCES dbo.x_role (id)
+GO
 
 ALTER TABLE dbo.x_role_ref_role ADD CONSTRAINT x_role_ref_role_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES dbo.x_portal_user (id)
 GO
@@ -2269,6 +2291,8 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
 GO
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('065',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 GO
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('075',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+GO
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 GO
 INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Reports'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/sqlanywhere/patches/075-create-sz-ref-role-table.sql b/security-admin/db/sqlanywhere/patches/075-create-sz-ref-role-table.sql
new file mode 100644
index 000000000..dce6fe6a3
--- /dev/null
+++ b/security-admin/db/sqlanywhere/patches/075-create-sz-ref-role-table.sql
@@ -0,0 +1,40 @@
+-- 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.
+
+call dbo.removeForeignKeysAndTable('x_security_zone_ref_role')
+GO
+
+CREATE TABLE dbo.x_security_zone_ref_role(
+        id bigint IDENTITY NOT NULL,
+        create_time datetime DEFAULT NULL NULL,
+        update_time datetime DEFAULT NULL NULL,
+        added_by_id bigint DEFAULT NULL NULL,
+        upd_by_id bigint DEFAULT NULL NULL,
+        zone_id bigint DEFAULT NULL NULL,
+        role_id bigint DEFAULT NULL NULL,
+        role_name varchar(767) DEFAULT NULL NULL
+        CONSTRAINT x_sz_ref_arole_PK_id PRIMARY KEY CLUSTERED(id)
+)
+GO
+
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES dbo.x_portal_user (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES dbo.x_portal_user (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_zone_id FOREIGN KEY(zone_id) REFERENCES dbo.x_security_zone (id)
+GO
+ALTER TABLE dbo.x_security_zone_ref_role ADD CONSTRAINT x_sz_ref_role_FK_role_id FOREIGN KEY(role_id) REFERENCES dbo.x_role (id)
+GO
+EXIT
\ No newline at end of file
diff --git a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
index bbef08859..465500814 100644
--- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
+++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
@@ -545,6 +545,23 @@ IF (OBJECT_ID('x_sz_ref_user_FK_user_name') IS NOT NULL)
 BEGIN
     ALTER TABLE [dbo].[x_security_zone_ref_user] DROP CONSTRAINT x_sz_ref_user_FK_user_name
 END
+IF (OBJECT_ID('x_sz_ref_admin_role_FK_added_by_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_added_by_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_upd_by_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_upd_by_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_zone_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_zone_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_role_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_role_id
+END
+
 IF (OBJECT_ID('x_sz_ref_resource_FK_added_by_id') IS NOT NULL)
 BEGIN
     ALTER TABLE [dbo].[x_security_zone_ref_resource] DROP CONSTRAINT x_sz_ref_resource_FK_added_by_id
@@ -837,6 +854,10 @@ IF (OBJECT_ID('x_security_zone_ref_user') IS NOT NULL)
 BEGIN
     DROP TABLE [dbo].[x_security_zone_ref_user]
 END
+IF (OBJECT_ID('x_security_zone_ref_role') IS NOT NULL)
+BEGIN
+    DROP TABLE [dbo].[x_security_zone_ref_role]
+END
 IF (OBJECT_ID('x_security_zone_ref_tag_srvc') IS NOT NULL)
 BEGIN
     DROP TABLE [dbo].[x_security_zone_ref_tag_srvc]
@@ -2597,6 +2618,33 @@ GO
 ALTER TABLE [dbo].[x_role_ref_role] WITH CHECK ADD CONSTRAINT [x_role_ref_role_FK_role_ref_id] FOREIGN KEY([role_ref_id]) REFERENCES [dbo].[x_role] ([id])
 GO
 
+SET ANSI_NULLS ON
+SET QUOTED_IDENTIFIER ON
+SET ANSI_PADDING ON
+CREATE TABLE [dbo].[x_security_zone_ref_role](
+        [id] [bigint] IDENTITY(1,1) NOT NULL,
+        [create_time] [datetime2] DEFAULT NULL NULL,
+        [update_time] [datetime2] DEFAULT NULL NULL,
+        [added_by_id] [bigint] DEFAULT NULL NULL,
+        [upd_by_id] [bigint] DEFAULT NULL NULL,
+        [zone_id] [bigint] DEFAULT NULL NULL,
+        [role_id] [bigint] DEFAULT NULL NULL,
+        [role_name] [nvarchar](767) DEFAULT NULL NULL
+        PRIMARY KEY CLUSTERED
+(
+        [id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
+) ON [PRIMARY]
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_added_by_id] FOREIGN KEY([added_by_id]) REFERENCES [dbo].[x_portal_user] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_upd_by_id] FOREIGN KEY([upd_by_id]) REFERENCES [dbo].[x_portal_user] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_zone_id] FOREIGN KEY([zone_id]) REFERENCES [dbo].[x_security_zone] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_role_id] FOREIGN KEY([role_id]) REFERENCES [dbo].[x_role] ([id])
+GO
+
 SET ANSI_NULLS ON
 SET QUOTED_IDENTIFIER ON
 SET ANSI_PADDING ON
@@ -4113,6 +4161,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('059',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('060',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('065',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
+INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('075',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('DB_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y');
 INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Reports'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
 INSERT INTO x_user_module_perm (user_id,module_id,create_time,update_time,added_by_id,upd_by_id,is_allowed) VALUES (dbo.getXportalUIdByLoginId('admin'),dbo.getModulesIdByName('Resource Based Policies'),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,dbo.getXportalUIdByLoginId('admin'),dbo.getXportalUIdByLoginId('admin'),1);
diff --git a/security-admin/db/sqlserver/patches/075-create-sz-ref-role-table.sql b/security-admin/db/sqlserver/patches/075-create-sz-ref-role-table.sql
new file mode 100644
index 000000000..6b4071865
--- /dev/null
+++ b/security-admin/db/sqlserver/patches/075-create-sz-ref-role-table.sql
@@ -0,0 +1,66 @@
+-- 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.
+
+IF (OBJECT_ID('x_sz_ref_admin_role_FK_added_by_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_added_by_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_upd_by_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_upd_by_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_zone_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_zone_id
+END
+IF (OBJECT_ID('x_sz_ref_role_FK_role_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_security_zone_ref_role] DROP CONSTRAINT x_sz_ref_role_FK_role_id
+END
+
+IF (OBJECT_ID('x_security_zone_ref_role') IS NOT NULL)
+BEGIN
+    DROP TABLE [dbo].[x_security_zone_ref_role]
+END
+
+CREATE TABLE [dbo].[x_security_zone_ref_role](
+        [id] [bigint] IDENTITY(1,1) NOT NULL,
+        [create_time] [datetime2] DEFAULT NULL NULL,
+        [update_time] [datetime2] DEFAULT NULL NULL,
+        [added_by_id] [bigint] DEFAULT NULL NULL,
+        [upd_by_id] [bigint] DEFAULT NULL NULL,
+        [zone_id] [bigint] DEFAULT NULL NULL,
+        [role_id] [bigint] DEFAULT NULL NULL,
+        [role_name] [nvarchar](767) DEFAULT NULL NULL
+        PRIMARY KEY CLUSTERED
+(
+        [id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
+) ON [PRIMARY]
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_added_by_id] FOREIGN KEY([added_by_id]) REFERENCES [dbo].[x_portal_user] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_upd_by_id] FOREIGN KEY([upd_by_id]) REFERENCES [dbo].[x_portal_user] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_zone_id] FOREIGN KEY([zone_id]) REFERENCES [dbo].[x_security_zone] ([id])
+GO
+ALTER TABLE [dbo].[x_security_zone_ref_role] WITH CHECK ADD CONSTRAINT [x_sz_ref_role_FK_role_id] FOREIGN KEY([role_id]) REFERENCES [dbo].[x_role] ([id])
+GO
+
+SET ANSI_NULLS ON
+SET QUOTED_IDENTIFIER ON
+SET ANSI_PADDING ON
+
+exit
\ No newline at end of file
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
index c19e3e1a1..12983688b 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
@@ -185,6 +185,12 @@ public class RoleDBStore implements RoleStore {
 			throw new Exception("Rolename for '" + roleName
 					+ "' can not be updated as it is referenced in one or more other roles");
 		}
+
+		boolean rleNotInZone = ensureRoleNotInZone(roleName);
+
+		if(!rleNotInZone) {
+			throw new Exception("Rolename for '"+ roleName + "' can not be updated as it is referenced in one or more security zones");
+		}
 	}
 
 	@Override
@@ -236,6 +242,12 @@ public class RoleDBStore implements RoleStore {
         if(!roleNotInOtherRole) {
             throw new Exception("Role '"+ roleName + "' can not be deleted as it is referenced in one or more other roles");
         }
+
+        boolean rleNotInZone = ensureRoleNotInZone(roleName);
+
+        if(!rleNotInZone) {
+            throw new Exception("Role '"+ roleName + "' can not be deleted as it is referenced in one or more security zones");
+        }
     }
 
 	private boolean ensureRoleNotInPolicy(String roleName) {
@@ -250,6 +262,12 @@ public class RoleDBStore implements RoleStore {
 		return roleRefRoleCount < 1;
 	}
 
+    private boolean ensureRoleNotInZone(String roleName) {
+        Long roleRefZoneCount = daoMgr.getXXSecurityZoneRefRole().findRoleRefZoneCount(roleName);
+
+        return roleRefZoneCount < 1;
+    }
+
     @Override
     public RangerRole getRole(Long id) throws Exception {
         return roleService.read(id);
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneRefUpdater.java b/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneRefUpdater.java
index ebc26528c..10bbfcd32 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneRefUpdater.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneRefUpdater.java
@@ -31,14 +31,17 @@ import org.apache.ranger.common.RangerConstants;
 import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.db.XXSecurityZoneRefGroupDao;
 import org.apache.ranger.db.XXSecurityZoneRefResourceDao;
+import org.apache.ranger.db.XXSecurityZoneRefRoleDao;
 import org.apache.ranger.db.XXSecurityZoneRefServiceDao;
 import org.apache.ranger.db.XXSecurityZoneRefTagServiceDao;
 import org.apache.ranger.db.XXSecurityZoneRefUserDao;
 import org.apache.ranger.entity.XXGroup;
 import org.apache.ranger.entity.XXPolicy;
 import org.apache.ranger.entity.XXResourceDef;
+import org.apache.ranger.entity.XXRole;
 import org.apache.ranger.entity.XXSecurityZoneRefGroup;
 import org.apache.ranger.entity.XXSecurityZoneRefResource;
+import org.apache.ranger.entity.XXSecurityZoneRefRole;
 import org.apache.ranger.entity.XXSecurityZoneRefService;
 import org.apache.ranger.entity.XXSecurityZoneRefTagService;
 import org.apache.ranger.entity.XXSecurityZoneRefUser;
@@ -94,18 +97,19 @@ public class SecurityZoneRefUpdater {
 		final Long zoneId = rangerSecurityZone == null ? null : rangerSecurityZone.getId();
 		final Map<String, RangerSecurityZoneService> zoneServices = rangerSecurityZone.getServices();
 
-		final Set<String> adminUsers = new HashSet<>();
-		final Set<String> adminUserGroups = new HashSet<>();
-		final Set<String> auditUsers = new HashSet<>();
-		final Set<String> auditUserGroups = new HashSet<>();
-                final Set<String> tagServices = new HashSet<>();
-		XXServiceDef xServiceDef = new XXServiceDef();
-
-		adminUsers.addAll(rangerSecurityZone.getAdminUsers());
-		adminUserGroups.addAll(rangerSecurityZone.getAdminUserGroups());
-		auditUsers.addAll(rangerSecurityZone.getAuditUsers());
-		auditUserGroups.addAll(rangerSecurityZone.getAuditUserGroups());
-                tagServices.addAll(rangerSecurityZone.getTagServices());
+		final Set<String> users = new HashSet<>();
+		final Set<String> userGroups = new HashSet<>();
+		final Set<String> roles = new HashSet<>();
+		final Set<String> tagServices = new HashSet<>();
+
+		users.addAll(rangerSecurityZone.getAdminUsers());
+		userGroups.addAll(rangerSecurityZone.getAdminUserGroups());
+		roles.addAll(rangerSecurityZone.getAdminRoles());
+		users.addAll(rangerSecurityZone.getAuditUsers());
+		userGroups.addAll(rangerSecurityZone.getAuditUserGroups());
+		roles.addAll(rangerSecurityZone.getAuditRoles());
+		tagServices.addAll(rangerSecurityZone.getTagServices());
+
 		for(Map.Entry<String, RangerSecurityZoneService> service : zoneServices.entrySet()) {
 			String serviceName = service.getKey();
 
@@ -115,8 +119,7 @@ public class SecurityZoneRefUpdater {
 
 			XXService xService = daoMgr.getXXService().findByName(serviceName);
 			RangerService rService = svcService.getPopulatedViewObject(xService);
-			xServiceDef = daoMgr.getXXServiceDef().findByName(rService.getType());
-
+			XXServiceDef xServiceDef = daoMgr.getXXServiceDef().findByName(rService.getType());
 			XXSecurityZoneRefService xZoneService = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefService());
 
 			xZoneService.setZoneId(zoneId);
@@ -174,102 +177,76 @@ public class SecurityZoneRefUpdater {
                         }
                 }
 
-		if(CollectionUtils.isNotEmpty(adminUsers)) {
-			for(String adminUser : adminUsers) {
+		if(CollectionUtils.isNotEmpty(users)) {
+			for(String user : users) {
 
-				if (StringUtils.isBlank(adminUser)) {
+				if (StringUtils.isBlank(user)) {
 					continue;
 				}
 
-				XXUser xUser = daoMgr.getXXUser().findByUserName(adminUser);
+				XXUser xUser = daoMgr.getXXUser().findByUserName(user);
 
 				if (xUser == null) {
-					throw restErrorUtil.createRESTException("user with name: " + adminUser + " does not exist ",
+					throw restErrorUtil.createRESTException("user with name: " + user + " does not exist ",
 							MessageEnums.INVALID_INPUT_DATA);
 				}
 
-				XXSecurityZoneRefUser xZoneAdminUser = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefUser());
+				XXSecurityZoneRefUser xZoneUser = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefUser());
 
-				xZoneAdminUser.setZoneId(zoneId);
-				xZoneAdminUser.setUserId(xUser.getId());
-				xZoneAdminUser.setUserName(adminUser);
-				xZoneAdminUser.setUserType(1);
+				xZoneUser.setZoneId(zoneId);
+				xZoneUser.setUserId(xUser.getId());
+				xZoneUser.setUserName(user);
+				xZoneUser.setUserType(1);
 
-				daoMgr.getXXSecurityZoneRefUser().create(xZoneAdminUser);
+				daoMgr.getXXSecurityZoneRefUser().create(xZoneUser);
 			}
 		}
 
-		if(CollectionUtils.isNotEmpty(adminUserGroups)) {
-			for(String adminUserGroup : adminUserGroups) {
+		if(CollectionUtils.isNotEmpty(userGroups)) {
+			for(String userGroup : userGroups) {
 
-				if (StringUtils.isBlank(adminUserGroup)) {
+				if (StringUtils.isBlank(userGroup)) {
 					continue;
 				}
 
-				XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(adminUserGroup);
+				XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(userGroup);
 
 				if (xGroup == null) {
-					throw restErrorUtil.createRESTException("group with name: " + adminUserGroup + " does not exist ",
-							MessageEnums.INVALID_INPUT_DATA);
-				}
-
-				XXSecurityZoneRefGroup xZoneAdminGroup = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefGroup());
-
-				xZoneAdminGroup.setZoneId(zoneId);
-				xZoneAdminGroup.setGroupId(xGroup.getId());
-				xZoneAdminGroup.setGroupName(adminUserGroup);
-				xZoneAdminGroup.setGroupType(1);
-
-				daoMgr.getXXSecurityZoneRefGroup().create(xZoneAdminGroup);
-			}
-		}
-
-		if(CollectionUtils.isNotEmpty(auditUsers)) {
-			for(String auditUser : auditUsers) {
-
-				if (StringUtils.isBlank(auditUser)) {
-					continue;
-				}
-
-				XXUser xUser = daoMgr.getXXUser().findByUserName(auditUser);
-
-				if (xUser == null) {
-					throw restErrorUtil.createRESTException("user with name: " + auditUser + " does not exist ",
+					throw restErrorUtil.createRESTException("group with name: " + userGroup + " does not exist ",
 							MessageEnums.INVALID_INPUT_DATA);
 				}
 
-				XXSecurityZoneRefUser xZoneAuditUser = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefUser());
+				XXSecurityZoneRefGroup xZoneGroup = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefGroup());
 
-				xZoneAuditUser.setZoneId(zoneId);
-				xZoneAuditUser.setUserId(xUser.getId());
-				xZoneAuditUser.setUserName(auditUser);
-				xZoneAuditUser.setUserType(0);
+				xZoneGroup.setZoneId(zoneId);
+				xZoneGroup.setGroupId(xGroup.getId());
+				xZoneGroup.setGroupName(userGroup);
+				xZoneGroup.setGroupType(1);
 
-				daoMgr.getXXSecurityZoneRefUser().create(xZoneAuditUser);
+				daoMgr.getXXSecurityZoneRefGroup().create(xZoneGroup);
 			}
 		}
 
-		if(CollectionUtils.isNotEmpty(auditUserGroups)) {
-			for(String auditUserGroup : auditUserGroups) {
-				if (StringUtils.isBlank(auditUserGroup)) {
+		if(CollectionUtils.isNotEmpty(roles)) {
+			for(String role : roles) {
+				if (StringUtils.isBlank(role)) {
 					continue;
 				}
 
-				XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(auditUserGroup);
+				XXRole xRole = daoMgr.getXXRole().findByRoleName(role);
 
-				if (xGroup == null) {
-					throw restErrorUtil.createRESTException("group with name: " + auditUserGroup + " does not exist ",
+				if (xRole == null) {
+					throw restErrorUtil.createRESTException("role with name: " + role + " does not exist ",
 							MessageEnums.INVALID_INPUT_DATA);
 				}
 
-				XXSecurityZoneRefGroup xZoneAuditGroup = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefGroup());
+				XXSecurityZoneRefRole xZoneRole = rangerAuditFields.populateAuditFieldsForCreate(new XXSecurityZoneRefRole());
 
-				xZoneAuditGroup.setZoneId(zoneId);
-				xZoneAuditGroup.setGroupId(xGroup.getId());
-				xZoneAuditGroup.setGroupName(auditUserGroup);
-				xZoneAuditGroup.setGroupType(0);
+				xZoneRole.setZoneId(zoneId);
+				xZoneRole.setRoleId(xRole.getId());
+				xZoneRole.setRoleName(role);
 
-				daoMgr.getXXSecurityZoneRefGroup().create(xZoneAuditGroup);
+				daoMgr.getXXSecurityZoneRefRole().create(xZoneRole);
 			}
 		}
 	}
@@ -282,19 +259,20 @@ public class SecurityZoneRefUpdater {
 			return false;
 		}
 
-		XXSecurityZoneRefServiceDao     xZoneServiceDao      = daoMgr.getXXSecurityZoneRefService();
-                XXSecurityZoneRefTagServiceDao     xZoneTagServiceDao      = daoMgr.getXXSecurityZoneRefTagService();
-		XXSecurityZoneRefResourceDao        xZoneResourceDao    = daoMgr.getXXSecurityZoneRefResource();
-		XXSecurityZoneRefUserDao         xZoneUserDao     = daoMgr.getXXSecurityZoneRefUser();
-		XXSecurityZoneRefGroupDao   xZoneGroupDao   = daoMgr.getXXSecurityZoneRefGroup();
+		XXSecurityZoneRefServiceDao    xZoneServiceDao    = daoMgr.getXXSecurityZoneRefService();
+		XXSecurityZoneRefTagServiceDao xZoneTagServiceDao = daoMgr.getXXSecurityZoneRefTagService();
+		XXSecurityZoneRefResourceDao   xZoneResourceDao   = daoMgr.getXXSecurityZoneRefResource();
+		XXSecurityZoneRefUserDao       xZoneUserDao       = daoMgr.getXXSecurityZoneRefUser();
+		XXSecurityZoneRefGroupDao      xZoneGroupDao      = daoMgr.getXXSecurityZoneRefGroup();
+		XXSecurityZoneRefRoleDao       xZoneRoleDao      = daoMgr.getXXSecurityZoneRefRole();
 
 		for (XXSecurityZoneRefService service : xZoneServiceDao.findByZoneId(zoneId)) {
 			xZoneServiceDao.remove(service);
 		}
 
-                for (XXSecurityZoneRefTagService service : xZoneTagServiceDao.findByZoneId(zoneId)) {
-                        xZoneTagServiceDao.remove(service);
-                }
+		for (XXSecurityZoneRefTagService service : xZoneTagServiceDao.findByZoneId(zoneId)) {
+			xZoneTagServiceDao.remove(service);
+		}
 
 		for(XXSecurityZoneRefResource resource : xZoneResourceDao.findByZoneId(zoneId)) {
 			xZoneResourceDao.remove(resource);
@@ -308,6 +286,10 @@ public class SecurityZoneRefUpdater {
 			xZoneGroupDao.remove(group);
 		}
 
+		for(XXSecurityZoneRefRole role : xZoneRoleDao.findByZoneId(zoneId)) {
+			xZoneRoleDao.remove(role);
+		}
+
 		return true;
 	}
 
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
index 77f86a0ad..be360a66e 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceMgr.java
@@ -23,10 +23,13 @@ import java.io.File;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
@@ -46,6 +49,8 @@ import org.apache.ranger.plugin.service.RangerBaseService;
 import org.apache.ranger.plugin.service.ResourceLookupContext;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.RangerRoles;
+import org.apache.ranger.plugin.util.RangerRolesUtil;
 import org.apache.ranger.service.RangerServiceService;
 import org.apache.ranger.services.tag.RangerServiceTag;
 import org.apache.ranger.view.VXMessage;
@@ -81,6 +86,9 @@ public class ServiceMgr {
 	@Autowired
 	TagDBStore tagStore;
 
+	@Autowired
+	RoleDBStore rolesStore;
+
 	@Autowired
 	TimedExecutor timedExecutor;
 
@@ -224,9 +232,14 @@ public class ServiceMgr {
 
 			if (securityZone.getAdminUsers() != null && securityZone.getAdminUsers().contains(userId)) {
 				isZoneAdmin = true;
-			} else if (securityZone.getAdminUserGroups() != null) {
+			}
+
+			Set<String> loggedInUsersGroups = Collections.emptySet();
+
+			if (!isZoneAdmin && securityZone.getAdminUserGroups() != null) {
 				List<XXGroupUser> groupUsers          = groupUserDao.findByUserId(rangerBizUtil.getXUserId());
-				List<String>      loggedInUsersGroups = new ArrayList<>();
+
+				loggedInUsersGroups = new HashSet<>();
 
 				loggedInUsersGroups.add(GROUP_PUBLIC);
 
@@ -238,6 +251,10 @@ public class ServiceMgr {
 
 				isZoneAdmin = CollectionUtils.containsAny(securityZone.getAdminUserGroups(), loggedInUsersGroups);
 			}
+
+			if (!isZoneAdmin && securityZone.getAdminRoles() != null) {
+				isZoneAdmin = isUserOrUserGroupsInRole(userId, loggedInUsersGroups, securityZone.getAdminRoles());
+			}
 		}
 
 		return isZoneAdmin;
@@ -258,9 +275,14 @@ public class ServiceMgr {
 
 			if (securityZone.getAuditUsers() != null && securityZone.getAuditUsers().contains(userId)) {
 				isZoneAuditor = true;
-			} else if (securityZone.getAuditUserGroups() != null) {
+			}
+
+			Set<String> loggedInUsersGroups = Collections.emptySet();
+
+			if (!isZoneAuditor && securityZone.getAuditUserGroups() != null) {
 				List<XXGroupUser> groupUsers          = groupUserDao.findByUserId(rangerBizUtil.getXUserId());
-				List<String>      loggedInUsersGroups = new ArrayList<>();
+
+				loggedInUsersGroups = new HashSet<>();
 
 				loggedInUsersGroups.add(GROUP_PUBLIC);
 
@@ -272,6 +294,10 @@ public class ServiceMgr {
 
 				isZoneAuditor = CollectionUtils.containsAny(securityZone.getAuditUserGroups(), loggedInUsersGroups);
 			}
+
+			if (!isZoneAuditor && securityZone.getAuditRoles() != null) {
+				isZoneAuditor = isUserOrUserGroupsInRole(userId, loggedInUsersGroups, securityZone.getAuditRoles());
+			}
 		}
 
 		return isZoneAuditor;
@@ -511,7 +537,36 @@ public class ServiceMgr {
 		vXResponse.setStatusCode(statusCode);
 		return vXResponse;
 	}
-	
+
+	private boolean isUserOrUserGroupsInRole(String userId, Set<String> userGroups, List<String> roles) {
+		boolean      ret         = false;
+		RangerRoles  rangerRoles = null;
+
+		try {
+			rangerRoles = rolesStore.getRoles("", -1L);
+		} catch (Exception excp) {
+			LOG.error("Unexpected error when fetching roles from database", excp);
+		}
+
+		if (rangerRoles != null) {
+			RangerRolesUtil rolesUtil = new RangerRolesUtil(rangerRoles);
+
+			ret = CollectionUtils.containsAny(roles, rolesUtil.getUserRoleMapping().get(userId));
+
+			if (!ret && userGroups != null) {
+				for (String userGroup : userGroups) {
+					ret = CollectionUtils.containsAny(roles, rolesUtil.getGroupRoleMapping().get(userGroup));
+
+					if (ret) {
+						break;
+					}
+				}
+			}
+		}
+
+		return ret;
+	}
+
 	static final long _DefaultTimeoutValue_Lookp = 1000; // 1 s
 	static final long _DefaultTimeoutValue_ValidateConfig = 10000; // 10 s
 
diff --git a/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java b/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
index 10d73a76c..300c8b4bb 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
@@ -301,6 +301,8 @@ public abstract class RangerDaoManagerBase {
 
 	public XXSecurityZoneRefGroupDao getXXSecurityZoneRefGroup() { return new XXSecurityZoneRefGroupDao(this); }
 
+	public XXSecurityZoneRefRoleDao getXXSecurityZoneRefRole() { return new XXSecurityZoneRefRoleDao(this); }
+
 	public XXGlobalStateDao getXXGlobalState() { return new XXGlobalStateDao(this); }
 
 	public XXPolicyChangeLogDao getXXPolicyChangeLog() { return new XXPolicyChangeLogDao(this); }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneRefRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneRefRoleDao.java
new file mode 100644
index 000000000..65c602dea
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneRefRoleDao.java
@@ -0,0 +1,105 @@
+/*
+ * 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.db;
+
+import org.apache.ranger.common.db.BaseDao;
+import org.apache.ranger.entity.XXSecurityZoneRefRole;
+
+import javax.persistence.NoResultException;
+import java.util.Collections;
+import java.util.List;
+
+public class XXSecurityZoneRefRoleDao extends BaseDao<XXSecurityZoneRefRole>{
+
+	public XXSecurityZoneRefRoleDao(RangerDaoManagerBase daoManager) {
+		super(daoManager);
+	}
+
+	public List<XXSecurityZoneRefRole> findByZoneId(Long zoneId) {
+        if (zoneId == null) {
+            return null;
+        }
+        try {
+            List<XXSecurityZoneRefRole> xxZoneRefService = getEntityManager()
+                    .createNamedQuery("XXSecurityZoneRefRole.findByZoneId", tClass)
+                    .setParameter("zoneId", zoneId)
+                    .getResultList();
+            return xxZoneRefService;
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+
+	public List<XXSecurityZoneRefRole> findByRoleId(Long roleId) {
+		if (roleId == null) {
+			return Collections.emptyList();
+		}
+		try {
+			return getEntityManager().createNamedQuery("XXSecurityZoneRefRole.findByRoleId", tClass)
+					.setParameter("roleId", roleId).getResultList();
+		} catch (NoResultException e) {
+			return Collections.emptyList();
+		}
+	}
+
+    public Long findRoleRefZoneCount(String roleName) {
+        Long ret = -1L;
+
+        try {
+            ret = getEntityManager().createNamedQuery("XXSecurityZoneRefRole.findRoleRefZoneCount", Long.class)
+                    .setParameter("roleName", roleName).getSingleResult();
+        } catch (Exception e) {
+        }
+
+        return ret;
+    }
+
+	public List<XXSecurityZoneRefRole> findAdminRoleByZoneId(Long zoneId) {
+        if (zoneId == null) {
+            return null;
+        }
+        try {
+            List<XXSecurityZoneRefRole> xxZoneRefRole = getEntityManager()
+                    .createNamedQuery("XXSecurityZoneRefRole.findRoleTypeByZoneId", tClass)
+                    .setParameter("zoneId", zoneId)
+                    .setParameter("roleType", "1")
+                    .getResultList();
+            return xxZoneRefRole;
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+
+	public List<XXSecurityZoneRefRole> findAuditRoleByZoneId(Long zoneId) {
+        if (zoneId == null) {
+            return null;
+        }
+        try {
+            List<XXSecurityZoneRefRole> xxZoneRefRole = getEntityManager()
+                    .createNamedQuery("XXSecurityZoneRefRole.findRoleTypeByZoneId", tClass)
+                    .setParameter("zoneId", zoneId)
+                    .setParameter("roleType", "0")
+                    .getResultList();
+            return xxZoneRefRole;
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+}
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXSecurityZoneRefRole.java b/security-admin/src/main/java/org/apache/ranger/entity/XXSecurityZoneRefRole.java
new file mode 100644
index 000000000..aaf5b8929
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXSecurityZoneRefRole.java
@@ -0,0 +1,185 @@
+/*
+ * 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.entity;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.Objects;
+
+@Entity
+@Cacheable
+@XmlRootElement
+@Table(name = "x_security_zone_ref_role")
+public class XXSecurityZoneRefRole extends XXDBBase implements java.io.Serializable{
+	private static final long serialVersionUID = 1L;
+  	@Id
+    @SequenceGenerator(name = "x_sec_zone_ref_role_SEQ", sequenceName = "x_sec_zone_ref_role_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.AUTO, generator = "x_sec_zone_ref_role_SEQ")
+    @Column(name = "id")
+    protected Long id;
+
+  	/**
+	 * zoneId of the XXSecurityZoneRefRole
+	 * <ul>
+	 * </ul>
+	 *
+	 */
+	@Column(name = "zone_id")
+	protected Long zoneId;
+
+  	/**
+	 * roleId of the XXSecurityZoneRefRole
+	 * <ul>
+	 * </ul>
+	 *
+	 */
+	@Column(name = "role_id")
+	protected Long roleId;
+
+	/**
+	 * roleName of the XXSecurityZoneRefRole
+	 * <ul>
+	 * </ul>
+	 *
+	 */
+	@Column(name = "role_name")
+	protected String roleName;
+
+	/**
+	 * roleType of the XXSecurityZoneRefRole , 1 for admin,0 for audit user.
+	 * <ul>
+	 * </ul>
+	 *
+	 */
+    @Override
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    @Override
+    public Long getId() {
+        return id;
+    }
+
+    /**
+	 * This method sets the value to the member attribute <b> zoneId</b> .
+	 * You cannot set null to the attribute.
+	 *
+	 * @param zoneId
+	 *            Value to set member attribute <b> zoneId</b>
+	 */
+	public void setZoneId(Long zoneId) {
+		this.zoneId = zoneId;
+	}
+
+	/**
+	 * Returns the value for the member attribute <b>zoneId</b>
+	 *
+	 * @return Date - value of member attribute <b>zoneId</b> .
+	 */
+	public Long getZoneId() {
+		return this.zoneId;
+	}
+
+	/**
+	 * This method sets the value to the member attribute <b> roleId</b> .
+	 * You cannot set null to the attribute.
+	 *
+	 * @param roleId
+	 *            Value to set member attribute <b> roleId</b>
+	 */
+	public void setRoleId(Long roleId) {
+		this.roleId = roleId;
+	}
+
+	/**
+	 * Returns the value for the member attribute <b>roleId</b>
+	 *
+	 * @return Date - value of member attribute <b>roleId</b> .
+	 */
+	public Long getRoleId() {
+		return roleId;
+	}
+
+	/**
+	 * This method sets the value to the member attribute <b> roleName</b> .
+	 * You cannot set null to the attribute.
+	 *
+	 * @param roleName
+	 *            Value to set member attribute <b> roleName</b>
+	 */
+	public void setRoleName(String roleName) {
+		this.roleName = roleName;
+	}
+
+	/**
+	 * Returns the value for the member attribute <b>roleName</b>
+	 *
+	 * @return Date - value of member attribute <b>roleName</b> .
+	 */
+	public String getRoleName() {
+		return roleName;
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(super.hashCode(), id, zoneId, roleId, roleName);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+
+		if (getClass() != obj.getClass()) {
+			return false;
+		}
+
+		XXSecurityZoneRefRole other = (XXSecurityZoneRefRole) obj;
+
+		return super.equals(obj) &&
+			   Objects.equals(id, other.id) &&
+			   Objects.equals(zoneId, other.zoneId) &&
+			   Objects.equals(roleId, other.roleId) &&
+			   Objects.equals(roleName, other.roleName);
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return "XXSecurityZoneRefRole [" + super.toString() + " id=" + id + ", zoneId=" + zoneId + ", roleId="
+				+ roleId + ", roleName=" + roleName + "]";
+	}
+}
\ No newline at end of file
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 53aafae94..66fa22163 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
@@ -415,6 +415,9 @@ public class SecurityZoneREST {
 					} else if (!Objects.equals(securityZone.getAdminUsers(), existingSecurityZone.getAdminUsers())) {
 						throwRestError("User : " + userName
 								+ " is not allowed to edit zone Admin User of zone : " + existingSecurityZone.getName());
+                    } else if (!Objects.equals(securityZone.getAdminRoles(), existingSecurityZone.getAdminRoles())) {
+                        throwRestError("User : " + userName
+                                + " is not allowed to edit zone Admin Roles of zone : " + existingSecurityZone.getName());
 					} else if (!Objects.equals(securityZone.getAuditUsers(), existingSecurityZone.getAuditUsers())) {
 						throwRestError("User : " + userName
 								+ " is not allowed to edit zone Audit User of zone : " + existingSecurityZone.getName());
@@ -422,6 +425,10 @@ public class SecurityZoneREST {
 						throwRestError("User : "
 								+ userName
 								+ " is not allowed to edit zone Audit User Group of zone : " + existingSecurityZone.getName());
+                    } else if (!Objects.equals(securityZone.getAuditRoles(), existingSecurityZone.getAuditRoles())) {
+                        throwRestError("User : "
+                                + userName
+                                + " is not allowed to edit zone Audit Roles of zone : " + existingSecurityZone.getName());
 					}
 				}
 				
@@ -560,8 +567,10 @@ public class SecurityZoneREST {
                 bizUtil.removeEmptyStrings(securityZone.getTagServices());
 		bizUtil.removeEmptyStrings(securityZone.getAdminUsers());
 		bizUtil.removeEmptyStrings(securityZone.getAdminUserGroups());
+        bizUtil.removeEmptyStrings(securityZone.getAdminRoles());
 		bizUtil.removeEmptyStrings(securityZone.getAuditUsers());
 		bizUtil.removeEmptyStrings(securityZone.getAuditUserGroups());
+        bizUtil.removeEmptyStrings(securityZone.getAdminRoles());
 		Map<String, RangerSecurityZoneService> serviceResouceMap=securityZone.getServices();
 		if(serviceResouceMap!=null) {
 			Set<Map.Entry<String, RangerSecurityZoneService>> serviceResouceMapEntries = serviceResouceMap.entrySet();
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerSecurityZoneServiceService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerSecurityZoneServiceService.java
index dfa9fbb69..476d1511b 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerSecurityZoneServiceService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerSecurityZoneServiceService.java
@@ -117,8 +117,10 @@ public class RangerSecurityZoneServiceService extends RangerSecurityZoneServiceB
                 ret.setServices(zoneFromJsonData.getServices());
                 ret.setAdminUsers(zoneFromJsonData.getAdminUsers());
                 ret.setAdminUserGroups(zoneFromJsonData.getAdminUserGroups());
+                ret.setAdminRoles(zoneFromJsonData.getAdminRoles());
                 ret.setAuditUsers(zoneFromJsonData.getAuditUsers());
                 ret.setAuditUserGroups(zoneFromJsonData.getAuditUserGroups());
+                ret.setAuditRoles(zoneFromJsonData.getAuditRoles());
                 ret.setTagServices(zoneFromJsonData.getTagServices());
             }
         } else {
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index d3cdecdca..14eca878f 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -1646,6 +1646,24 @@
         </query>
     </named-query>
 
+	<named-query name="XXSecurityZoneRefRole.findByZoneId">
+		<query>
+			select obj from XXSecurityZoneRefRole obj where obj.zoneId = :zoneId
+		</query>
+	</named-query>
+
+	<named-query name="XXSecurityZoneRefRole.findByRoleId">
+		<query>
+			select obj from XXSecurityZoneRefRole obj where obj.roleId = :roleId
+		</query>
+	</named-query>
+
+	<named-query name="XXSecurityZoneRefRole.findRoleRefZoneCount">
+		<query>
+			select count(obj.zoneId) from XXSecurityZoneRefRole obj where obj.roleName = :roleName
+		</query>
+	</named-query>
+
 	<named-query name="XXSecurityZoneRefResource.findByZoneId">
         <query>
             select obj from XXSecurityZoneRefResource obj where obj.zoneId = :zoneId