You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ni...@apache.org on 2021/03/16 05:30:41 UTC

[ranger] branch ranger-2.2 updated: RANGER-3191 : Ranger UI for configuring Audit filters.

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

ni3galave pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.2 by this push:
     new 74f5a5e  RANGER-3191 : Ranger UI for configuring Audit filters.
74f5a5e is described below

commit 74f5a5e237639c8e542a6336bfe2ce7e1690aa27
Author: Nitin Galave <ni...@apache.org>
AuthorDate: Mon Mar 15 20:53:24 2021 +0530

    RANGER-3191 : Ranger UI for configuring Audit filters.
---
 .../webapp/scripts/models/BackboneFormDataType.js  |  26 +-
 .../src/main/webapp/scripts/utils/XAUtils.js       |  25 +-
 .../scripts/views/service/AuditFilterConfig.js     | 438 ++++++++++++++++++
 .../views/service/ServiceAuditFilterResources.js   | 488 +++++++++++++++++++++
 .../webapp/scripts/views/service/ServiceForm.js    |  35 +-
 .../scripts/views/users/AddUsersOrGroupsList.js    |   2 +-
 security-admin/src/main/webapp/styles/xa.css       |  97 ++++
 .../templates/service/AuditFilterItem_tmpl.html    |  70 +++
 .../templates/service/AuditFilterList_tmpl.html    |  50 +++
 .../ServiceAuditFilterResourcesForm_tmpl.html      |  17 +
 .../webapp/templates/service/ServiceForm_tmpl.html |  14 +
 11 files changed, 1239 insertions(+), 23 deletions(-)

diff --git a/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js b/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
index bf048e8..18c760b 100644
--- a/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
+++ b/security-admin/src/main/webapp/scripts/models/BackboneFormDataType.js
@@ -124,7 +124,11 @@ define(function(require) {
                                     }
                                     opts['type'] = v.name;
                                     if(v.lookupSupported){
-                                        opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+                                        if (form.serviceName) {
+											opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.serviceName;
+										} else {
+											opts['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+										}
                                         resourceOpts['select2Opts'] = form.getPlugginAttr(true, opts);
                                     }else{
                                         resourceOpts['select2Opts'] = XAUtils.select2OptionForUserCreateChoice();
@@ -207,15 +211,19 @@ define(function(require) {
 							formObj['recursiveSupport'] = v.recursiveSupported;
 							formObj['name'] = v.name;
 							formObj['editorAttrs'] = {'data-placeholder': v.label };
-                                                        formObj.fieldAttrs = { 'data-name' : 'field-'+v.name, 'parent' : v.parent };
-                                                        formObj.fieldAttrs.fieldClass = "resorces-with-label-css"
-                                                        if(!_.isUndefined(v.lookupSupported)){
+							formObj.fieldAttrs = { 'data-name' : 'field-'+v.name, 'parent' : v.parent };
+							formObj.fieldAttrs.fieldClass = "resorces-with-label-css"
+							if(!_.isUndefined(v.lookupSupported)){
 								var options = {
-										'containerCssClass' : v.name,
-                                                                };
-                                                                if(v.lookupSupported){
-                                                                    options['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
-                                                                }
+									'containerCssClass' : v.name,
+								};
+							if(v.lookupSupported){
+								if (form.serviceName) {
+									options['lookupURL'] = "service/plugins/services/lookupResource/"+form.serviceName;
+								} else {
+									options['lookupURL'] = "service/plugins/services/lookupResource/"+form.rangerService.get('name');
+								}
+							}
 								//to support regexp level validation
 								if(_.has(v, 'validationRegEx') && !_.isEmpty(v.validationRegEx)){
 									options['regExpValidation'] = {'type': 'regexp', 'regexp':new RegExp(v.validationRegEx), 'message' : v.validationMessage};
diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
index 600a0fe..b90f885 100644
--- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
@@ -1640,27 +1640,26 @@ define(function(require) {
         });
     }
 
-    XAUtils.getUsersGroupsList = function($select, domElement){
+    XAUtils.getUsersGroupsList = function($select, domElement, width, auditFilter){
         var that = domElement,
             tags = [],
             placeholder = $select === 'users' ? "Select User" : $select === 'groups' ? "Select Group" : "Select Role",
             searchUrl = $select === 'users' ? "service/xusers/lookup/users" : $select === 'groups' ? "service/xusers/lookup/groups"
                 : "service/roles/roles";
-            // if(that.model && !_.isEmpty(that.model.get('name'))){
-            //     tags.push({
-            //         'id': _.escape(that.model.get('name')),
-            //         'text': _.escape(that.model.get('name'))
-            //     });
-            //     domElement.ui['selectUsersOrGroups'].val(tags.map(function(val) {
-            //         return val.text
-            //     }));
-            // }
+            if(that.model && !_.isEmpty(that.model.get($select))){
+                _.map (that.model.get($select) , function(name){
+                    tags.push({
+	                    'id': _.escape(name),
+	                    'text': _.escape(name)
+	                });
+                })
+            }
 
         return {
             closeOnSelect : true,
             placeholder   : placeholder,
             tags : true,
-            width : '300px',
+            width : width,
             initSelection: function(element, callback) {
                 callback(tags);
             },
@@ -1686,7 +1685,9 @@ define(function(require) {
                     if (data.totalCount != "0") {
                         //remove users {USER} and {OWNER}
                         if ($select == 'users' || $select == 'groups') {
-                            data.vXStrings = _.reject(data.vXStrings, function(m){return (m.value == '{USER}' || m.value == '{OWNER}')})
+                            if (_.isUndefined(auditFilter)) {
+                                data.vXStrings = _.reject(data.vXStrings, function(m){return (m.value == '{USER}' || m.value == '{OWNER}')})
+                            }
                             results = data.vXStrings.map(function(m) {
                                 return {
                                     id: _.escape(m.value),
diff --git a/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js b/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js
new file mode 100644
index 0000000..79dcd07
--- /dev/null
+++ b/security-admin/src/main/webapp/scripts/views/service/AuditFilterConfig.js
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+ /*
+ *
+ */
+define(function(require) {
+    'use strict';
+    
+    var Backbone        = require('backbone');
+    var App             = require('App');
+    var XAEnums         = require('utils/XAEnums');
+    var XAUtil          = require('utils/XAUtils');
+    var localization    = require('utils/XALangSupport');
+    var ServiceAuditFilterResourcesForm = require('views/service/ServiceAuditFilterResources');
+    var RangerPolicyResource = require('models/RangerPolicyResource');
+    require('bootstrap-editable');
+            
+    var AuditConfigItem = Backbone.Marionette.ItemView.extend({
+        _msvName : 'FormInputItem',
+
+        template : require('hbs!tmpl/service/AuditFilterItem_tmpl'),
+
+        tagName : 'tr',
+
+        templateHelpers : function(){},
+
+        ui : {
+            selectUsers     : '[data-js="selectUsers"]',
+            selectGroups    : '[data-js="selectGroups"]',
+            selectRoles    : '[data-js="selectRoles"]',
+            addPerms        : 'a[data-js="permissions"]',
+            addPermissionsSpan : '.add-permissions',
+            addResources : '[data-js="serviceResource"]',
+            removeResources : '[data-action="deleteResources"]',
+            oparations       : '[data-js="oparations"]',
+            accessResult : '[data-js="accessResult"]',
+        },
+        events : {
+            'click [data-action="delete"]'  : 'evDelete',
+            'change [data-js="isAudited"]': 'evIsAudited',
+            'change [data-js="accessResult"]': 'evAccessResult',
+            'click [data-js="serviceResource"]'  : 'eGetResources',
+            'click [data-action="deleteResources"]' : 'eRemoveResources',
+            'change [data-js="selectUsers"]': 'evSelectUsers',
+            'change [data-js="selectGroups"]': 'evSelectGroup',
+            'change [data-js="selectRoles"]': 'evSelectRoles',
+            'change [data-js="oparations"]': 'evOparations',
+        },
+
+        initialize : function(options) {
+            _.extend(this, _.pick(options,'rangerServiceDefModel', 'accessTypes', 'serviceName'));
+        },
+ 
+        onRender : function() {
+            var accessResultVal = _.map(XAEnums.AccessResult, function(m){
+                return {'id' : m.label ,'text': m.label}
+            })
+            if (this.model && !_.isUndefined(this.model.get('accessResult'))) {
+                this.ui.accessResult.val(this.model.get('accessResult'));
+            }
+            this.ui.accessResult.select2({
+                placeholder: "Select Value",
+                allowClear: true,
+                maximumSelectionSize : 1,
+                data: accessResultVal,
+                theme: 'bootstrap4',
+            });
+            this.setupFormForEditMode();
+            this.evIsAudited();
+            this.renderPermissions();
+            this.ui.selectUsers.select2(XAUtil.getUsersGroupsList("users", this, '250px', "auditFilter"));
+            this.ui.selectGroups.select2(XAUtil.getUsersGroupsList("groups", this, '250px', "auditFilter"));
+            this.ui.selectRoles.select2(XAUtil.getUsersGroupsList("roles", this, '250px', "auditFilter"));
+            this.selectOparations();
+        },
+
+        setupFormForEditMode : function () {
+            var that = this;
+            if(!this.model.isEmpty()) {
+                if (this.model.get('isAudited')) {
+                    this.$el.find('[data-js="isAudited"]').val(this.model.get('isAudited'));
+                }
+                if (this.model.get('users')) {
+                    this.ui.selectUsers.val(_.map(this.model.get('users'), function(name){ return _.escape(name)}));
+                }
+                if (this.model.get('groups')) {
+                    this.ui.selectGroups.val(_.map(this.model.get('groups'), function(name){ return _.escape(name); }));
+                }
+                if (this.model.get('roles')) {
+                    this.ui.selectRoles.val(_.map(this.model.get('roles'), function(name){ return _.escape(name); }));
+                }
+                if (this.model.get('accessTypes')) {
+                    _.each(this.model.get('accessTypes'), function(val) {
+                        that.$el.find('input[data-name="' + val + '"]').prop('checked', true);
+                    })
+                }
+                if (this.model.get('resources')) {
+                    this.displayResources(this.model.get('resources'));
+                }
+            }
+        },
+
+        evIsAudited : function (e) {
+            if(_.isUndefined(e)) {
+                this.model.set('isAudited',this.$el.find('[data-js="isAudited"]').val());
+            }else {
+                this.model.set('isAudited', e.currentTarget.value);
+            }
+        },
+
+        evAccessResult : function (e){
+            if($(e.currentTarget).val() != "") {
+                this.model.set('accessResult', e.currentTarget.value);
+            } else {
+                this.model.unset('accessResult');
+            }
+        },
+
+        evSelectUsers : function (e) {
+            this.model.set('users', e.val)
+        },
+
+        evSelectGroup : function (e) {
+            this.model.set('groups', e.val)
+        },
+
+        evSelectRoles : function (e) {
+            this.model.set('roles', e.val)
+        },
+
+        evOparations : function (e) {
+            this.model.set('actions', e.val)
+        },
+
+        renderPermissions : function() {
+            this.permsIds = [];
+            var that = this;
+            this.perms =  _.map(this.accessTypes , function(m){return {text : m.label, value : m.name};});
+            if(this.perms.length > 1){
+                this.perms.push({'value' : -1, 'text' : 'Select/Deselect All'});
+            }
+            if (this.model && this.model.get('accessTypes')) {
+                this.permsIds = this.model.get('accessTypes');
+            }
+            this.ui.addPerms.editable({
+                emptytext : 'Add Permissions',
+                source: this.perms,
+                value : this.permsIds,
+                display: function(values,srcData) {
+                    if(_.isNull(values) || _.isEmpty(values) || (_.contains(values,"-1")  &&  values.length == 1)){
+                        $(this).empty();
+                        that.model.unset('accessTypes');
+                        that.ui.addPermissionsSpan.find('i').attr('class', 'fa-fw fa fa-plus');
+                        that.ui.addPermissionsSpan.attr('title','add');
+                        return;
+                    }
+                    if(_.contains(values,"-1")){
+                        values = _.without(values,"-1")
+                    }
+                    //that.checkDirtyFieldForGroup(values);
+                    var permTypeArr = [];
+                    var valArr = _.map(values, function(id){
+                        if(!_.isUndefined(id)){
+                            var obj = _.findWhere(that.rangerServiceDefModel.attributes.accessTypes,{'name' : id});
+                            permTypeArr.push({permType : obj.value});
+                            return "<span class='badge badge-info'>" + obj.label + "</span>";
+                        }
+                    });
+                    that.model.set('accessTypes', values);
+                    $(this).html(valArr.join(" "));
+                    that.ui.addPermissionsSpan.find('i').attr('class', 'fa-fw fa fa-pencil');
+                    that.ui.addPermissionsSpan.attr('title','edit');
+                }}).on('shown', function(e, editable) {
+                    that.clickOnPermissions(that);
+                });
+                that.ui.addPermissionsSpan.click(function(e) {
+                e.stopImmediatePropagation();
+                that.$('a[data-js="permissions"]').editable('toggle');
+                that.clickOnPermissions(that);
+                });
+
+        },
+
+        clickOnPermissions : function(that) {
+            var selectAll = true;
+            var checklist = $('.editable-checklist').find('input[type="checkbox"]')
+            _.each(checklist,function(checkbox){
+                if($(checkbox).val() != -1 && !$(checkbox).is(':checked'))
+                    selectAll = false;
+            })
+            if(selectAll){
+                $('.editable-checklist').find('input[type="checkbox"][value="-1"]').prop('checked',true)
+            } else {
+                $('.editable-checklist').find('input[type="checkbox"][value="-1"]').prop('checked',false)
+            }
+            //for selectAll functionality
+                        $('input[type="checkbox"][value="-1"]').click(function(e){
+                var checkboxlist =$(this).closest('.editable-checklist').find('input[type="checkbox"][value!=-1]')
+                $(this).is(':checked') ? checkboxlist.prop('checked',true) : checkboxlist.prop('checked',false);
+            });
+            $('.editable-checklist input[type="checkbox"]').click(function(e){
+                if(this.value!="-1"){
+                    var selectAll = true;
+                    $('.editable-checklist input[type="checkbox"]').each(function(index,item){
+                        if(item.value!="-1" && !item.checked){
+                            selectAll = false;
+                        }
+                    });
+                    $('input[type="checkbox"][value="-1"]').prop('checked',selectAll);
+                }
+            });
+        },
+
+        eGetResources :function () {
+            var model = null;
+            if (!_.isUndefined(this.model.get('resources'))) {
+                this.model.set('policyType', 0);
+                this.model.set('id', 'resource' + this.model.collection.length);
+                model = $.extend(true, {}, this.model);
+                // model = _.clone(resourceModel)
+                // _.each(model.get('resources'), function(val, key, obj) {
+                //     obj[key] = {
+                //         'values': val
+                //     };
+                // });
+            }
+            // this.rangerServiceDefModel.get('resources')[0].lookupSupported = false
+            if (_.isEmpty(this.serviceName)) {
+                this.rangerServiceDefModel.get('resources').map( function(m){
+                    m.lookupSupported = false;
+                    m.validationRegEx = '';
+                    m.validationMessage = '';
+                })
+            }
+            this.form = new ServiceAuditFilterResourcesForm({
+                template: require('hbs!tmpl/service/ServiceAuditFilterResourcesForm_tmpl'),
+                model: model ? model : new RangerPolicyResource({
+                    policyType: 0
+                }),
+                rangerServiceDefModel: this.rangerServiceDefModel,
+                serviceName : this.serviceName,
+            });
+            this.modal = new Backbone.BootstrapModal({
+                animate: true,
+                content: this.form,
+                title: 'Add/Edit Resources',
+                okText: 'Save',
+                allowCancel: true,
+                escape: true
+            }).open();
+            this.modal.on("ok", this.onSave.bind(this, this.model));
+        },
+
+        onSave: function(resourceModel) {
+            var that = this,
+                tmpResource = {}, resource = {};
+            var errors = this.form.commit({
+                validate: false
+            });
+            if (!_.isEmpty(errors)) {
+                that.modal.preventClose();
+                return;
+            }
+            _.each(this.form.model.attributes, function(val, key) {
+                if (key.indexOf("sameLevel") >= 0 && !_.isNull(val)) {
+                    this.form.model.set(val.resourceType, val);
+                    this.form.model.unset(key);
+                }
+            }, this);
+            _.each(that.rangerServiceDefModel.get('resources'), function(obj) {
+                var tmpObj = that.form.model.get(obj.name);
+                if (!_.isUndefined(tmpObj) && _.isObject(tmpObj) && !_.isEmpty(tmpObj.resource)) {
+                    tmpResource[obj.name] ={}, resource[obj.name] ={};
+                    tmpResource[obj.name].values = tmpObj.resource.split(',');
+                    resource[obj.name].values = tmpObj.resource.split(',');
+                    if (obj.excludesSupported) {
+                        resource[obj.name]['isExcludes'] = tmpObj.isExcludes;
+                    }
+                    if (obj.recursiveSupported) {
+                        resource[obj.name]['isRecursive'] = tmpObj.isRecursive;
+                    }
+                    that.form.model.unset(obj.name);
+                }
+            });
+            this.displayResources(resource);
+            this.model.set('resources', resource)   ;
+        },
+
+        displayResources : function(tmpResource) {
+            var $dataResources; 
+            $dataResources = '<div class="resourceGrp"><div>'
+                _.filter(tmpResource, function(key, value) {
+                    var $toggleBtn =''
+                    if(!_.isUndefined(key.isExcludes)) {
+                        var isExcludes = key.isExcludes ? XAEnums.ExcludeStatus.STATUS_EXCLUDE.label : XAEnums.ExcludeStatus.STATUS_INCLUDE.label;
+                        $toggleBtn += '<span class="badge badge-dark pull-right">'+isExcludes+'</span>'
+                    }
+                    if (!_.isUndefined(key.isRecursive)) {
+                        var isRecursive = key.isRecursive ? XAEnums.RecursiveStatus.STATUS_RECURSIVE.label : XAEnums.RecursiveStatus.STATUS_NONRECURSIVE.label;
+                        $toggleBtn += '<span class="badge badge-dark pull-right">'+isRecursive+'</span>'
+                    }
+                    $dataResources += '<div class="resourcesFilter"><div><b>' + value + '</b>:' + key.values.join(', ') +'</div>' + $toggleBtn +'</div>'
+                })
+            $dataResources += '</div>'
+            this.$el.find('.js-formInput').html($dataResources);
+            this.ui.addResources.find('i').attr('class', 'fa-fw fa fa-pencil');
+        },
+
+        eRemoveResources : function (argument) {
+            var $dataResources = '<div class="resourceGrp text-center">--</div>'
+            this.$el.find('.js-formInput').html($dataResources);
+            if(this.model && !_.isUndefined(this.model.get('resources')))  {
+                this.model.unset('resources');
+            }
+        },
+
+        evSelectUserGroupRole : function (e) {
+            e.currentTarget.select2(XAUtil.getUsersGroupsList(e.currentTarget.dataset.type, this))
+        },
+        evDelete : function(){
+            var that = this;
+            this.collection.remove(this.model);
+        },
+        selectOparations : function() {
+            var that = this;
+            var tags = [];
+            this.ui.oparations.select2({
+                multiple: true,
+                closeOnSelect : true,
+                placeholder : 'Select Action',
+                allowClear: true,
+                width : '200px',
+                tokenSeparators: ["," , " "],
+                tags : [],
+                dropdownCssClass: 'select2-text-hidden',
+                initSelection : function (element, callback) {
+                    callback(tags);
+                },
+                createSearchChoice : function(term, data) {
+                    if ($(data).filter(function() {
+                        return this.text.localeCompare(term)===0; 
+                    }).length===0)
+                        {return {id:term, text:term};}
+                },
+            })
+            if (this.model.get('actions')) {
+                _.each(this.model.get('actions') , function(name){
+                    tags.push( { 'id' : _.escape( name ), 'text' : _.escape( name ) } );
+                });
+                this.ui.oparations.select2('val',tags)
+            }
+        },
+
+    });
+
+    var AuditFilterList =  Backbone.Marionette.CompositeView.extend({
+        _msvName : 'AuditFilterList',
+
+        template : require('hbs!tmpl/service/AuditFilterList_tmpl'),
+
+        templateHelpers :function(){
+            return {
+                emptyAuditFilterCol : this.collection.length == 0 ? true : false,
+            }
+        },
+        
+        getItemView : function(item){
+            if(!item){
+                return;
+            }
+            return AuditConfigItem;
+        },
+        itemViewContainer : ".js-formInput",
+
+        itemViewOptions : function() {
+            return {
+                'collection' : this.collection,
+                'accessTypes' : this.rangerServiceDefModel.get('accessTypes').filter(function(val) { return val !== null; }),
+                'rangerServiceDefModel' : this.rangerServiceDefModel,
+                'serviceName' : this.serviceName,
+            };
+        },
+        events : {
+            'click [data-action="addGroup"]' : 'addNew'
+        },
+        initialize : function(options) {
+            _.extend(this, _.pick(options, 'rangerServiceDefModel', 'serviceName'));
+            if(this.collection.length == 0){
+                this.collection.add();
+            }
+        },
+        onRender : function(){
+            this.makePolicyItemSortable();
+        },
+        addNew : function(){
+            var that =this;
+            this.$el.find('.emptySet').remove();
+            this.$('table').show();
+            this.collection.add(new Backbone.Model());
+        },
+        makePolicyItemSortable : function(){
+            var that = this, draggedModel;
+            this.$el.find(".js-formInput" ).sortable({
+                placeholder: "ui-state-highlight",
+                start : function(event, ui){
+                    var row = ui.item[0].rowIndex - 1;
+                    draggedModel = that.collection.at(row);
+                },
+                stop : function(event, ui){
+                    var row = ui.item[0].rowIndex -1;
+                    that.collection.remove(draggedModel, { silent : true});
+                    that.collection.add(draggedModel ,{ at: row, silent : true });
+                    that.$el.find(ui.item[0]).addClass("dirtyField");
+                },
+            });
+        }
+    });
+    
+    return AuditFilterList;
+
+});
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js b/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js
new file mode 100644
index 0000000..c08f745
--- /dev/null
+++ b/security-admin/src/main/webapp/scripts/views/service/ServiceAuditFilterResources.js
@@ -0,0 +1,488 @@
+/*
+ * 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.
+ */
+define(function(require) {
+    'use strict';
+
+    var Backbone = require('backbone');
+    var XAEnums = require('utils/XAEnums');
+    var localization = require('utils/XALangSupport');
+    var XAUtil = require('utils/XAUtils');
+    var RangerPolicyResource = require('models/RangerPolicyResource');
+    var BackboneFormDataType = require('models/BackboneFormDataType');
+    require('backbone-forms.list');
+    require('backbone-forms.templates');
+    require('backbone-forms');
+    require('backbone-forms.XAOverrides');
+    require('jquery-ui');
+    require('tag-it');
+
+    var ServiceAuditFilterResources = Backbone.Form.extend(
+        /** @lends ServiceAuditFilterResources */
+        {
+            _viewName: 'ServiceAuditFilterResources',
+
+            /**
+             * intialize a new ServiceAuditFilterResources Form View
+             * @constructs
+             */
+
+            templateData: function() {
+                var policyType = XAUtil.enumElementByValue(XAEnums.RangerPolicyType, this.model.get('policyType'));
+                return {
+                    'id': this.model.id,
+                    'policyType': policyType.label
+                };
+            },
+
+            initialize: function(options) {
+                console.log("initialized a ServiceAuditFilterResources Form View");
+                _.extend(this, _.pick(options, 'rangerServiceDefModel', 'serviceName'));
+                this.setupForm();
+                Backbone.Form.prototype.initialize.call(this, options);
+                this.bindEvents();
+                this.defaultValidator = {}
+            },
+
+            /** all events binding here */
+            bindEvents: function() {
+                this.on('policyForm:parentChildHideShow', this.renderParentChildHideShow);
+            },
+
+            ui: {},
+
+            /** fields for the form
+             */
+            fields: [],
+
+            schema: function() {
+                return this.getSchema();
+            },
+
+            getSchema: function() {
+                var attrs = {},
+                    that = this;
+                var formDataType = new BackboneFormDataType();
+                attrs = formDataType.getFormElements(this.rangerServiceDefModel.get('resources'), this.rangerServiceDefModel.get('enums'), attrs, this, true);
+                return attrs;
+            },
+
+            /** on render callback */
+            render: function(options) {
+                var that = this;
+                Backbone.Form.prototype.render.call(this, options);
+                //initialize path plugin for hdfs component : resourcePath
+                if (!_.isUndefined(this.initilializePathPlugin) && this.initilializePathPlugin) {
+                    this.initializePathPlugins(this.pathPluginOpts);
+                }
+                //checkParent
+                this.renderParentChildHideShow();
+            },
+
+            setupForm: function() {
+                if (!this.model.isNew()) {
+                    this.selectedResourceTypes = {};
+                    var resourceDefList = this.rangerServiceDefModel.get('resources');
+                    _.each(this.model.get('resources'), function(obj, key) {
+                        var resourceDef = _.findWhere(resourceDefList, {
+                                'name': key
+                        }),
+                        sameLevelResourceDef = [],
+                        parentResource;
+                        sameLevelResourceDef = _.filter(resourceDefList, function(objRsc){
+                            if (objRsc.level === resourceDef.level && objRsc.parent === resourceDef.parent) {
+                                return objRsc
+                            }
+                        });
+                        //for parent leftnode status
+                        if (resourceDef.parent) {
+                            parentResource = _.findWhere(resourceDefList, {
+                                'name': resourceDef.parent
+                            });
+                        }
+                        if (sameLevelResourceDef.length == 1 && !_.isUndefined(sameLevelResourceDef[0].parent) &&
+                            !_.isEmpty(sameLevelResourceDef[0].parent) &&
+                            parentResource.isValidLeaf) {
+                            sameLevelResourceDef.push({
+                                'level': sameLevelResourceDef[0].level,
+                                name: 'none',
+                                label: 'none'
+                            });
+                        }
+                        if (sameLevelResourceDef.length > 1) {
+                            obj['resourceType'] = key;
+                            if (_.isUndefined(resourceDef.parent)) {
+                                this.model.set('sameLevel' + resourceDef.level, obj);
+                                //parentShowHide
+                                this.selectedResourceTypes['sameLevel' + resourceDef.level] = key;
+                            } else {
+                                this.model.set('sameLevel' + resourceDef.level + resourceDef.parent, obj);
+                                this.selectedResourceTypes['sameLevel' + resourceDef.level + resourceDef.parent] = key;
+                            }
+
+                        } else {
+                            this.model.set(resourceDef.name, obj)
+                        }
+                    }, this);
+                }
+            },
+
+            /** all custom field rendering */
+            renderParentChildHideShow: function(onChangeOfSameLevelType, val, e) {
+                var formDiv = this.$el.find('.zoneResources-form');
+                if (!this.model.isNew() && !onChangeOfSameLevelType) {
+                    _.each(this.selectedResourceTypes, function(val, sameLevelName) {
+                        if (formDiv.find('.field-' + sameLevelName).length > 0) {
+                            formDiv.find('.field-' + sameLevelName).attr('data-name', 'field-' + val)
+                        }
+                    });
+                }
+                //hide form fields if it's parent is hidden
+                var resources = formDiv.find('.form-group');
+                _.each(resources, function(rsrc, key) {
+                    var parent = $(rsrc).attr('parent');
+                    var label = $(rsrc).find('label').html();
+                    $(rsrc).removeClass('error');
+                    //remove validation and Required msg
+                    $(rsrc).find('.help-inline').empty();
+                    $(rsrc).find('.help-block').empty();
+                    if (!_.isUndefined(parent) && !_.isEmpty(parent)) {
+                        var selector = "div[data-name='field-" + parent + "']";
+                        var kclass = formDiv.find(selector).attr('class');
+                        var label = $(rsrc).find('label').html();
+                        if (_.isUndefined(kclass) || (kclass.indexOf("field-sameLevel") >= 0 &&
+                                formDiv.find(selector).find('select').val() != parent) ||
+                            formDiv.find(selector).hasClass('hideResource')) {
+                            $(rsrc).addClass('hideResource');
+                            $(rsrc).removeClass('error');
+                            //reset input field to "none" if it is hide
+                            var resorceFieldName = _.pick(this.schema, this.selectedFields[key]);
+                            if (resorceFieldName[this.selectedFields[key]].sameLevelOpts && _.contains(resorceFieldName[this.selectedFields[key]].sameLevelOpts, 'none') &&
+                                formDiv.find(selector).find('select').val() != 'none' && onChangeOfSameLevelType) {
+                                //change trigger and set value to none
+                                $(rsrc).find('select').val("none").trigger('change', "onChangeResources");
+                            }
+                        } else {
+                            if ($(rsrc).find('select').val() == 'none') {
+                                $(rsrc).find('input[data-js="resource"]').select2('disable');
+                                $(rsrc).removeClass('error');
+                                $(rsrc).find('label').html(label.split('*').join(''));
+                            } else {
+                                $(rsrc).find('input[data-js="resource"]').select2('enable');
+                                if (label.slice(-2) == '**') {
+                                    $(rsrc).find('label').html(label.slice(-1) == '*' ? label : label + "*");
+                                }
+                            }
+                            $(rsrc).removeClass('hideResource');
+                        }
+                    }
+                }, this);
+                //remove validation of fields if it's hidden
+                //remove validation if fields is not empty
+                _.each(this.fields, function(field, key) {
+                    if ((key.substring(0, key.length - 2) === "sameLevel") && field.$el.find('[data-js="resource"]').val() != "" && field.$el.hasClass('error')) {
+                        field.$el.removeClass('error');
+                        field.$el.find('.help-inline').empty();
+                    }
+                    if (field.$el.hasClass('hideResource')) {
+                        if ($.inArray('required', field.editor.validators) >= 0) {
+                            this.defaultValidator[key] = field.editor.validators;
+                            field.editor.validators = [];
+                            var label = field.$el.find('label').html();
+                            field.$el.find('label').html(label.replace('*', ''));
+                            field.$el.removeClass('error');
+                            field.$el.find('.help-inline').empty();
+                        }
+                    } else {
+                        if (field.$el.find('select').val() == 'none') {
+                            field.editor.validators = [];
+                            this.defaultValidator[key] = field.editor.validators;
+                            field.$el.removeClass('error');
+                            field.$el.find('.help-inline').empty();
+                        } else {
+                            if (!_.isUndefined(this.defaultValidator[key])) {
+                                field.editor.validators.push('required');
+                                if ($.inArray('required', field.editor.validators) >= 0) {
+                                    var label = field.$el.find('label').html();
+                                    field.$el.find('label').html(label.slice(-1) == '*' ? label : label + "*");
+                                }
+                            }
+                        }
+                    }
+                }, this);
+            },
+
+            /** all post render plugin initialization */
+            initializePathPlugins: function(options) {
+                var that = this,
+                    defaultValue = [];
+                if (!this.model.isNew() && !_.isUndefined(this.model.get('path'))) {
+                    defaultValue = this.model.get('path').values;
+                }
+
+                function split(val) {
+                    return val.split(/,\s*/);
+                }
+
+                function extractLast(term) {
+                    return split(term).pop();
+                }
+                var tagitOpts = {}
+                if (!_.isUndefined(options.lookupURL) && options.lookupURL) {
+                    tagitOpts["autocomplete"] = {
+                        cache: false,
+                        source: function(request, response) {
+                            var url = "service/plugins/services/lookupResource/" + that.serviceName;
+                            var context = {
+                                'userInput': extractLast(request.term),
+                                'resourceName': that.pathFieldName,
+                                'resources': {}
+                            };
+                            var val = that.fields[that.pathFieldName].editor.getValue();
+                            context.resources[that.pathFieldName] = _.isNull(val) || _.isEmpty(val) ? [] : val.resource.split(",");
+                            var p = $.ajax({
+                                url: url,
+                                type: "POST",
+                                data: JSON.stringify(context),
+                                dataType: 'json',
+                                contentType: "application/json; charset=utf-8",
+                            }).done(function(data) {
+                                if (data) {
+                                    response(data);
+                                } else {
+                                    response();
+                                }
+                            }).fail(function() {
+                                response();
+                            });
+                            setTimeout(function() {
+                                p.abort();
+                                console.log('connection timeout for resource path request...!!');
+                            }, 10000);
+                        },
+                        open: function() {
+                            $(this).removeClass('working');
+                        },
+                        search: function() {
+                            $('.tagit-autocomplete').addClass('tagit-position');
+                            if (!_.isUndefined(this.value) && (/[ ,]+/).test(this.value)) {
+                                var values = this.value.trim().split(/[ ,]+/);
+                                if (values.length > 1) {
+                                    for (var i = 0; i < values.length; i++) {
+                                        that.fields[that.pathFieldName].editor.$el.find('[data-js="resource"]').tagit("createTag", values[i]);
+                                    }
+                                    return ''
+                                } else {
+                                    return val
+                                }
+                            }
+                            var term = extractLast(_.escape(this.value));
+                            $(this).addClass('working');
+                            if (term.length < 1) {
+                                return false;
+                            }
+                        },
+                    }
+                }
+                tagitOpts['beforeTagAdded'] = function(event, ui) {
+                    // do something special
+                    that.fields[that.pathFieldName].$el.removeClass('error');
+                    that.fields[that.pathFieldName].$el.find('.help-inline').html('');
+                    var tags = [];
+                    console.log(ui.tag);
+                    if (!_.isUndefined(options.regExpValidation) && !options.regExpValidation.regexp.test(ui.tagLabel)) {
+                        that.fields[that.pathFieldName].$el.addClass('error');
+                        that.fields[that.pathFieldName].$el.find('.help-inline').html(options.regExpValidation.message);
+                        return false;
+                    }
+                }
+                this.fields[that.pathFieldName].editor.$el.find('[data-js="resource"]').tagit(tagitOpts).on('change', function(e) {
+                    //check dirty field for tagit input type : `path`
+                    XAUtil.checkDirtyField($(e.currentTarget).val(), defaultValue.toString(), $(e.currentTarget));
+                });
+            },
+
+            getPlugginAttr: function(autocomplete, options) {
+                var that = this,
+                    type = options.containerCssClass,
+                    validRegExpString = true,
+                    select2Opts = [];
+                if (!autocomplete)
+                    return {
+                        tags: true,
+                        width: '220px',
+                        multiple: true,
+                        minimumInputLength: 1,
+                        'containerCssClass': type
+                    };
+                else {
+                    select2Opts = {
+                        containerCssClass: options.type,
+                        closeOnSelect: true,
+                        tags: true,
+                        multiple: true,
+                        minimumInputLength: 1,
+                        width: '220px',
+                        tokenSeparators: [",", " "],
+                        initSelection: function(element, callback) {
+                            var data = [];
+                            //to set single select value
+                            if (!_.isUndefined(options.singleValueInput) && options.singleValueInput) {
+                                callback({
+                                    id: element.val(),
+                                    text: element.val()
+                                });
+                                return;
+                            }
+                            //this is form multi-select value
+                            $(element.val().split(",")).each(function() {
+                                data.push({
+                                    id: this,
+                                    text: this
+                                });
+                            });
+                            callback(data);
+                        },
+                        createSearchChoice: function(term, data) {
+                            term = _.escape(term);
+                            if ($(data).filter(function() {
+                                    return this.text.localeCompare(term) === 0;
+                                }).length === 0) {
+                                if (!_.isUndefined(options.regExpValidation) && !options.regExpValidation.regexp.test(term)) {
+                                    validRegExpString = false;
+                                } else if ($.inArray(term, this.val()) >= 0) {
+                                    return null;
+                                } else {
+                                    return {
+                                        id: term,
+                                        text: term
+                                    };
+                                }
+                            }
+                        },
+                        ajax: {
+                            url: options.lookupURL,
+                            type: 'POST',
+                            params: {
+                                timeout: 10000,
+                                contentType: "application/json; charset=utf-8",
+                            },
+                            cache: false,
+                            data: function(term, page) {
+                                return that.getDataParams(term, options);
+                            },
+                            results: function(data, page) {
+                                var results = [];
+                                if (!_.isUndefined(data)) {
+                                    if (_.isArray(data) && data.length > 0) {
+                                        results = data.map(function(m, i) {
+                                            return {
+                                                id: m,
+                                                text: m
+                                            };
+                                        });
+                                    }
+                                    if (!_.isUndefined(data.resultSize) && data.resultSize != "0") {
+                                        results = data.vXStrings.map(function(m, i) {
+                                            return {
+                                                id: m.value,
+                                                text: m.value
+                                            };
+                                        });
+                                    }
+                                }
+                                return {
+                                    results: results
+                                };
+                            },
+                            transport: function(options) {
+                                $.ajax(options).fail(function() {
+                                    console.log("ajax failed");
+                                    this.success({
+                                        resultSize: 0
+                                    });
+                                });
+                            }
+
+                        },
+                        formatResult: function(result) {
+                            return result.text;
+                        },
+                        formatSelection: function(result) {
+                            return result.text;
+                        },
+                        formatNoMatches: function(term) {
+                            if (!validRegExpString && !_.isUndefined(options.regExpValidation)) {
+                                return options.regExpValidation.message;
+                            }
+                            return "No Matches found";
+                        }
+                    };
+                    //To support single value input
+                    if (!_.isUndefined(options.singleValueInput) && options.singleValueInput) {
+                        select2Opts['maximumSelectionSize'] = 1;
+                    }
+                    return select2Opts;
+                }
+            },
+
+            getDataParams: function(term, options) {
+                var resources = {},
+                    resourceName = options.type;
+                var isParent = true,
+                    name = options.type,
+                    val = null,
+                    isCurrentSameLevelField = true;
+                while (isParent) {
+                    var currentResource = _.findWhere(this.rangerServiceDefModel.get('resources'), {
+                        'name': name
+                    });
+                    //same level type
+                    if (_.isUndefined(this.fields[currentResource.name])) {
+                        if (!_.isUndefined(currentResource.parent)) {
+                            var sameLevelName = 'sameLevel' + currentResource.level + currentResource.parent;
+                        } else {
+                            var sameLevelName = 'sameLevel' + currentResource.level;
+                        }
+
+                        name = this.fields[sameLevelName].editor.$resourceType.val()
+                        val = this.fields[sameLevelName].getValue();
+                        if (isCurrentSameLevelField) {
+                            resourceName = name;
+                        }
+                    } else {
+                        val = this.fields[name].getValue();
+                    }
+                    resources[name] = _.isNull(val) ? [] : val.resource.split(',');
+                    if (!_.isEmpty(currentResource.parent)) {
+                        name = currentResource.parent;
+                    } else {
+                        isParent = false;
+                    }
+                    isCurrentSameLevelField = false;
+                }
+                var context = {
+                    'userInput': term,
+                    'resourceName': resourceName,
+                    'resources': resources
+                };
+                return JSON.stringify(context);
+            },
+        });
+    return ServiceAuditFilterResources;
+});
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js b/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
index 653d3d5..e7d5b79 100644
--- a/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
+++ b/security-admin/src/main/webapp/scripts/views/service/ServiceForm.js
@@ -27,7 +27,8 @@ define(function(require){
 
 	var localization	= require('utils/XALangSupport');
 	var BackboneFormDataType	= require('models/BackboneFormDataType');
-	var ConfigurationList		= require('views/service/ConfigurationList')
+	var ConfigurationList		= require('views/service/ConfigurationList');
+	var AuditFilterConfig		= require('views/service/AuditFilterConfig')
 
 	require('backbone-forms');
 	require('backbone-forms.list');
@@ -62,6 +63,7 @@ define(function(require){
 			console.log("initialized a ServiceForm Form View");
 			_.extend(this, _.pick(options, 'rangerServiceDefModel'));
 			this.extraConfigColl = new Backbone.Collection();
+			this.auditFilterColl = new Backbone.Collection();
 			this.setupFormForEditMode();
     		Backbone.Form.prototype.initialize.call(this, options);
 
@@ -98,9 +100,16 @@ define(function(require){
 			this.setupForm();
 			this.initializePlugins();
 			this.renderCustomFields();
+			this.renderAuditFilterFields();
 		},
 		setupFormForEditMode : function() {
+			var that = this;
 			if(!this.model.isNew()){
+
+				if(this.model.get('configs')['ranger.plugin.audit.filters']) {
+					var auditFilterCollValue = this.model.get('configs')['ranger.plugin.audit.filters'];
+					delete this.model.get('configs')['ranger.plugin.audit.filters']
+				}
 				_.each(this.model.get('configs'),function(value, name){
 					var configObj = _.findWhere(this.rangerServiceDefModel.get('configs'),{'name' : name });
 					if(!_.isUndefined(configObj) && configObj.type == 'bool'){
@@ -112,6 +121,14 @@ define(function(require){
 						}
 					}
 				},this);
+
+				if(auditFilterCollValue) {
+					auditFilterCollValue = JSON.parse(auditFilterCollValue);
+					console.log(auditFilterCollValue);
+					auditFilterCollValue.forEach(function(model) {
+						that.auditFilterColl.add(new Backbone.Model(model));
+					})
+				}
 			}
 		},
 		setupForm : function() {
@@ -138,6 +155,15 @@ define(function(require){
 			}).render().el);
 		},
 
+		/**Audit filters rendering**/
+		renderAuditFilterFields: function(){
+			this.$('[data-customfields="aduitFilterConfig"]').html(new AuditFilterConfig({
+				collection : this.auditFilterColl,
+				rangerServiceDefModel : this.rangerServiceDefModel,
+				serviceName : (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('name')) ? this.model.get('name') : ''),
+			}).render().el);
+		},
+
 		/** all post render plugin initialization */
 		initializePlugins: function(){
 		},
@@ -185,6 +211,13 @@ define(function(require){
 			this.extraConfigColl.each(function(obj){
 				if(!_.isEmpty(obj.attributes)) config[obj.get('name')] = obj.get('value');
 			});
+			if (this.auditFilterColl.length > 0) {
+				var auditFiltter = [];
+				this.auditFilterColl.each(function (e) {
+					auditFiltter.push(e.attributes);
+				})
+				config['ranger.plugin.audit.filters'] = JSON.stringify(auditFiltter);
+			}
 			this.model.set('configs',config);
 
 			//Set service type
diff --git a/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js b/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
index 3a24690..26a62e6 100644
--- a/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
+++ b/security-admin/src/main/webapp/scripts/views/users/AddUsersOrGroupsList.js
@@ -128,7 +128,7 @@ define(function(require) {
                 this.$el.find('[data-id="userGroupsTable"]').html('<tr data-name="'+this.fieldName+'"><td colspan="3"> No '
                     +this.fieldName+' found</td></tr>');
             }
-            this.ui.selectUsersOrGroups.select2(XAUtil.getUsersGroupsList(this.fieldName, this));
+            this.ui.selectUsersOrGroups.select2(XAUtil.getUsersGroupsList(this.fieldName, this, '300px'));
             this.ui.selectUsersOrGroups.attr("data-name", this.fieldName+"Select");
             this.ui.addUserGroupRoleBtn.attr("data-name", this.fieldName+"AddBtn")
         },
diff --git a/security-admin/src/main/webapp/styles/xa.css b/security-admin/src/main/webapp/styles/xa.css
index 80ece70..5c11e14 100644
--- a/security-admin/src/main/webapp/styles/xa.css
+++ b/security-admin/src/main/webapp/styles/xa.css
@@ -4566,4 +4566,101 @@ input.textFiledInputPadding:disabled {
 
 .report-table .backgrid-subgrid-custom-row th:not(.renderable), .report-table .backgrid-subgrid-custom-row td:not(.renderable){
   display: table-cell!important;
+}
+
+.zoneResources-form .select2-container {
+  float: left;
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .include-toggle {
+  left: -7vw;
+  top: 7vh;
+}
+
+.zoneResources-form .form-horizontal .form-group{
+  float:none;
+}
+
+.zoneResources-form .control-label{
+  padding-top: 1px;
+}
+
+.zoneResources-form .recursive-toggle-2 {
+  left: -7vw;
+  position: relative;
+}
+
+.width-75 {
+  width: 75px
+}
+
+.width-170 {
+  width: 170px
+}
+
+.min-width-150 {
+  min-width: 150px
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .recursive-toggle-hdfs-1 {
+  margin-left: 14vw;
+  margin-top: 0px;
+}
+
+.zoneResources-form .include-toggle {
+  left: -7vw;
+}
+
+.zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .include-toggle {
+  left: -7vw;
+  top: 2vw;
+}
+
+.select2-text-hidden {
+  display:none !important;
+}
+
+.resourcesFilter {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  margin-bottom: 8px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] > .control-label{
+  top:10px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] .include-toggle{
+  margin-top: 0px;
+}
+
+.zoneResources-form [fieldclass="resorces-css"] .include-toggle{
+  top: 0px;
+}
+
+.zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-1{
+  margin-left: 16vw;
+}
+
+@media  screen and (max-width: 1366px) {
+  .zoneResources-form [fieldclass="resorces-css"] .include-toggle{
+    margin-left: 28vw;
+  }
+
+  .zoneResources-form [fieldclass="resorces-with-label-css"] .include-toggle{
+    margin-left: 28vw;
+  }
+  .zoneResources-form .form-group.field-path[fieldclass="resorces-with-label-css"] .recursive-toggle-hdfs-1{
+    margin-left: 21vw;
+  }
+  .zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-1 {
+    margin-left: 21vw;
+  }
+  .zoneResources-form [fieldclass="resorces-with-label-css"] .recursive-toggle-2 {
+    left:0px;
+  }
+  .zoneResources-form [fieldclass="resorces-css"] .recursive-toggle-2 {
+    left:0px;
+  }
 }
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html b/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html
new file mode 100644
index 0000000..0fc2ce7
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/AuditFilterItem_tmpl.html
@@ -0,0 +1,70 @@
+{{!-- 
+  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.
+--}}
+
+<!-- Is Audited -->
+<td class="">
+    <div class="width-75">
+        <select class="form-control custom-select-sm w-100" data-js="isAudited">
+            <option selected value="true">Yes</option>
+            <option value="false">No</option>
+        </select>
+    </div>
+</td>
+<!-- Access Result -->
+<td class="">
+    <div class="width-170">
+        <input type="text" class="form-control custom-select-sm" data-js="accessResult">
+    </div>
+</td>
+<!-- Resources -->
+<td> 
+    <div class="resource-list min-width-150">
+        <div class="js-formInput"><div class="resourceGrp text-center">--</div></div>
+        <button type="button" class="btn btn-mini btn-primary" title="Add Resources" data-js="serviceResource" style="display: inline-block;">
+            <i class="fa-fw fa fa-plus"></i>
+        </button>
+        <a class="btn btn-danger btn-mini" data-action="deleteResources"><i class="fa-fw fa fa-remove"></i></a></div>
+    </div>   
+</td>
+
+<!-- Oparations -->
+<td>    
+    <input  type="text" data-js="oparations" data-type="roles"/>
+</td>
+<!-- Actions -->
+<td>    
+    <a href="javascript:;" data-js="permissions" data-type="checklist" data-title="Select permissions" title="add/edit permissions" ></a>
+    <button type="button" class="btn btn-sm add-permissions" title="Add" style="display: inline-block;">
+        <i class="fa-fw fa fa-plus"></i>
+    </button>
+</td>
+<!--  -->
+<td class="">
+    <input  type="text" data-js="selectUsers" data-type="users" />
+</td>
+<td class="">
+    <input  type="text" data-js="selectGroups" data-type="groups" />
+</td>
+<td class="">
+    <input  type="text" data-js="selectRoles" data-type="roles"/>
+</td>
+<!-- Cross Button -->
+<td>
+    <button type="button" class="btn btn-sm btn-danger " data-action="delete">
+        <i class="fa-fw fa fa-remove"></i>
+    </button>
+</td>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html b/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html
new file mode 100644
index 0000000..268917a
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/AuditFilterList_tmpl.html
@@ -0,0 +1,50 @@
+{{!-- 
+  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.
+--}}
+<div class="form-group">
+    <!--label class="control-label">{{headerTitle}}</label-->
+    <div class="col-md-12 m-t-sm">
+        <div class="table-responsive">
+            <table class="table-permission table-condensed">
+                <thead>
+                    <tr>
+                        <th>Is Audited</th>
+                        <th>Access Result</th>
+                        <th>Resources</th>
+                        <th>Operations</th>
+                        <th>Permissions</th>
+                        <th>Users</th>
+                        <th>Groups</th>
+                        <th>Roles</th>
+                        <th></th>
+                    </tr>
+                </thead>
+                <tbody class="js-formInput permissionItemSortable">
+                    {{#if emptyAuditFilterCol}}
+                        <td class="emptySet text-muted" colspan="9">No Audit Filter Data Found !!</td>
+                    {{/if}}
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+<div class="form-group">
+    <div class="col-md-12 m-t-sm">
+        <button type="button" class="btn btn-sm" data-action="addGroup" title="Add">
+            <i class="fa-fw fa fa-plus"></i>
+        </button>
+    </div>
+</div>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html b/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html
new file mode 100644
index 0000000..d3ed5ab
--- /dev/null
+++ b/security-admin/src/main/webapp/templates/service/ServiceAuditFilterResourcesForm_tmpl.html
@@ -0,0 +1,17 @@
+{{!-- 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. --}}
+<form class="form-horizontal">
+    <fieldset>
+        <b data-fieldsets class="zoneResources-form"></b>
+    </fieldset>
+</form>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html b/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
index 90ee2a5..2b2e9c0 100644
--- a/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
+++ b/security-admin/src/main/webapp/templates/service/ServiceForm_tmpl.html
@@ -30,6 +30,20 @@
         {{/compare}}
         <div class="extraServiceConfigs"></div>
     </fieldset>
+    <fieldset class="configProp">
+        <p class="formHeader">
+            Audit Filter :
+        </p>
+        <div data-customfields="aduitFilterConfig">
+            <div class="form-group">
+                <div class="controls">
+                    <img src="images/loading.gif"
+                        style="margin-left: 4%; margin-top: 1%;">
+                    </img>  
+                </div>
+            </div>
+        </div>
+    </fieldset>
     <div>
         <div class="form-group field-username hdfs hive knox storm">
             <label class="control-label" for="c12_username"></label>