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 2024/12/18 08:03:52 UTC

(ranger) 05/16: RANGER-4670: (hbase plugin) Config to support disabling column authorization for fully authorized column families (#417)

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

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

commit 4d20197adf71749031a6f0c3d447058364cec525
Author: Fateh Singh <fa...@gmail.com>
AuthorDate: Wed Dec 4 18:09:21 2024 -0800

    RANGER-4670: (hbase plugin) Config to support disabling column authorization for fully authorized column families (#417)
    
    (cherry picked from commit cf736a5493eba485adfcba74cd0664efbdd321a0)
---
 .../hadoop/constants/RangerHadoopConstants.java    |   1 +
 .../authorization/hbase/AuthorizationSession.java  |  93 +--
 .../hbase/RangerAuthorizationCoprocessor.java      | 153 +++-
 .../hbase/RangerAuthorizationFilter.java           |   7 +-
 .../hbase/AuthorizationSessionTest.java            |   5 +-
 .../hbase/HBaseRangerAuthorizationTest.java        | 773 ++++++++++++++++-----
 .../hbase/RangerAuthorizationFilterTest.java       |   3 +-
 hbase-agent/src/test/resources/hbase-policies.json |  97 ++-
 8 files changed, 863 insertions(+), 269 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/authorization/hadoop/constants/RangerHadoopConstants.java b/agents-common/src/main/java/org/apache/ranger/authorization/hadoop/constants/RangerHadoopConstants.java
index fcd9ebd4d..86827e655 100644
--- a/agents-common/src/main/java/org/apache/ranger/authorization/hadoop/constants/RangerHadoopConstants.java
+++ b/agents-common/src/main/java/org/apache/ranger/authorization/hadoop/constants/RangerHadoopConstants.java
@@ -51,6 +51,7 @@ public class RangerHadoopConstants {
 
 	public static final String  HBASE_UPDATE_RANGER_POLICIES_ON_GRANT_REVOKE_PROP 	     = "xasecure.hbase.update.xapolicies.on.grant.revoke";
 	public static final boolean HBASE_UPDATE_RANGER_POLICIES_ON_GRANT_REVOKE_DEFAULT_VALUE = true;
+	public static final String HBASE_COLUMN_AUTH_OPTIMIZATION = "ranger.plugin.hbase.column.auth.optimized";
 	
 	public static final String KNOX_ACCESS_VERIFIER_CLASS_NAME_PROP 	= "knox.authorization.verifier.classname";
 	public static final String KNOX_ACCESS_VERIFIER_CLASS_NAME_DEFAULT_VALUE = "org.apache.ranger.pdp.knox.RangerAuthorizer";
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java
index 6e999ba51..df68f571c 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java
@@ -30,11 +30,7 @@ import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
 import org.apache.hadoop.thirdparty.com.google.common.collect.Sets;
 import org.apache.hadoop.thirdparty.com.google.common.base.MoreObjects;
 import org.apache.ranger.audit.model.AuthzAuditEvent;
-import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
-import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
-import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
-import org.apache.ranger.plugin.policyengine.RangerAccessResult;
-import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.apache.ranger.plugin.policyengine.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,7 +43,7 @@ public class AuthorizationSession {
 	final HbaseUserUtils _userUtils = _factory.getUserUtils();
 	final HbaseAuthUtils _authUtils = _factory.getAuthUtils();
 	// immutable state
-	final RangerBasePlugin _authorizer;
+	final RangerHBasePlugin _authorizer;
 	// Mutable state: Use supplied state information
 	String _operation;
 	String _otherInformation;
@@ -69,8 +65,8 @@ public class AuthorizationSession {
 	// internal state per-authorization
 	RangerAccessRequest _request;
 	RangerAccessResult _result;
-	
-	public AuthorizationSession(RangerBasePlugin authorizer) {
+
+	public AuthorizationSession(RangerHBasePlugin authorizer) {
 		_authorizer = authorizer;
 	}
 
@@ -83,12 +79,12 @@ public class AuthorizationSession {
 		_otherInformation = information;
 		return this;
 	}
-	
+
 	AuthorizationSession remoteAddress(String ipAddress) {
 		_remoteAddress = ipAddress;
 		return this;
 	}
-	
+
 	AuthorizationSession access(String anAccess) {
 		_access = anAccess;
 		return this;
@@ -127,7 +123,7 @@ public class AuthorizationSession {
 	}
 
 	void verifyBuildable() {
-		
+
 		String template = "Internal error: Incomplete/inconsisten state: [%s]. Can't build auth request!";
 		if (_factory == null) {
 			String message = String.format(template, "factory is null");
@@ -174,11 +170,7 @@ public class AuthorizationSession {
 				StringUtils.equals(_operation, "getUserPermissionForNamespace");
 	}
 
-	AuthorizationSession buildRequest() {
-
-		verifyBuildable();
-		// session can be reused so reset its state
-		zapAuthorizationState();
+	private RangerAccessResource createHBaseResource() {
 		// TODO get this via a factory instead
 		RangerAccessResourceImpl resource = new RangerHBaseResource();
 		// policy engine should deal sensibly with null/empty values, if any
@@ -189,7 +181,11 @@ public class AuthorizationSession {
 		}
 		resource.setValue(RangerHBaseResource.KEY_COLUMN_FAMILY, _columnFamily);
 		resource.setValue(RangerHBaseResource.KEY_COLUMN, _column);
-		
+		return resource;
+	}
+
+	private RangerAccessRequest createRangerRequest() {
+		RangerAccessResource resource = createHBaseResource();
 		String user = _userUtils.getUserAsString(_user);
 		RangerAccessRequestImpl request = new RangerAccessRequestImpl(resource, _access, user, _groups, null);
 		request.setAction(_operation);
@@ -198,18 +194,25 @@ public class AuthorizationSession {
 		request.setResourceMatchingScope(_resourceMatchingScope);
 		request.setAccessTime(new Date());
 		request.setIgnoreDescendantDeny(_ignoreDescendantDeny);
-		_request = request;
+		return request;
+	}
+
+	AuthorizationSession buildRequest() {
+		verifyBuildable();
+		// session can be reused so reset its state
+		zapAuthorizationState();
+		_request = createRangerRequest();
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("Built request: " + request.toString());
+			LOG.debug("Built request: " + _request.toString());
 		}
 		return this;
 	}
-	
+
 	AuthorizationSession authorize() {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("==> AuthorizationSession.authorize: " + getRequestMessage());
 		}
-		
+
 		if (_request == null) {
 			String message = String.format("Invalid state transition: buildRequest() must be called before authorize().  This request would ultimately get denied.!");
 			throw new IllegalStateException(message);
@@ -223,7 +226,7 @@ public class AuthorizationSession {
 			}
 			_result = _authorizer.isAccessAllowed(_request, _auditHandler);
 		}
-		
+
 		if (LOG.isDebugEnabled()) {
 			boolean allowed = isAuthorized();
 			String reason = getDenialReason();
@@ -231,19 +234,19 @@ public class AuthorizationSession {
 		}
 		return this;
 	}
-	
+
 	void logCapturedEvents() {
 		if (_auditHandler != null) {
 			List<AuthzAuditEvent> events = _auditHandler.getCapturedEvents();
 			_auditHandler.logAuthzAudits(events);
 		}
 	}
-	
+
 	void publishResults() throws AccessDeniedException {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("==> AuthorizationSession.publishResults()");
 		}
-		
+
 		boolean authorized = isAuthorized();
 		if (_auditHandler != null && isAudited()) {
 			List<AuthzAuditEvent> events = null;
@@ -284,7 +287,7 @@ public class AuthorizationSession {
 			LOG.debug("<== AuthorizationSession.publishResults()");
 		}
 	}
-	
+
 	boolean isAudited() {
 
 		boolean audited = false;
@@ -313,7 +316,7 @@ public class AuthorizationSession {
 		}
 		return allowed;
 	}
-	
+
 	String getDenialReason() {
 		String reason = "";
 		if (_result == null) {
@@ -327,20 +330,21 @@ public class AuthorizationSession {
 		}
 		return reason;
 	}
-	
+
 	String requestToString() {
 		return MoreObjects.toStringHelper(_request.getClass())
-			.add("operation", _operation)
-			.add("otherInformation", _otherInformation)
-			.add("access", _access)
-			.add("user", _user == null ? null : _user.getName())
-			.add("groups", _groups)
-			.add("auditHandler", _auditHandler == null ? null : _auditHandler.getClass().getSimpleName())
-			.add(RangerHBaseResource.KEY_TABLE, _table)
-			.add(RangerHBaseResource.KEY_COLUMN, _column)
-			.add(RangerHBaseResource.KEY_COLUMN_FAMILY, _columnFamily)
-			.add("resource-matching-scope", _resourceMatchingScope)
-			.toString();
+				.add("operation", _operation)
+				.add("otherInformation", _otherInformation)
+				.add("access", _access)
+				.add("user", _user == null ? null : _user.getName())
+				.add("groups", _groups)
+				.add("auditHandler", _auditHandler == null ? null : _auditHandler.getClass().getSimpleName())
+				.add(RangerHBaseResource.KEY_TABLE, _table)
+				.add(RangerHBaseResource.KEY_COLUMN, _column)
+				.add(RangerHBaseResource.KEY_COLUMN_FAMILY, _columnFamily)
+				.add("resource-matching-scope", _resourceMatchingScope)
+				.add("ignoreDescendantDeny", _ignoreDescendantDeny)
+				.toString();
 	}
 
 	String getPrintableValue(String value) {
@@ -350,7 +354,7 @@ public class AuthorizationSession {
 			return "";
 		}
 	}
-	
+
 	String getRequestMessage() {
 		String format = "Access[%s] by user[%s] belonging to groups[%s] to table[%s] for column-family[%s], column[%s] triggered by operation[%s], otherInformation[%s]";
 		String user = _userUtils.getUserAsString();
@@ -358,7 +362,7 @@ public class AuthorizationSession {
 				getPrintableValue(_columnFamily), getPrintableValue(_column), getPrintableValue(_operation), getPrintableValue(_otherInformation));
 		return message;
 	}
-	
+
 	String getLogMessage(boolean allowed, String reason) {
 		String format = " %s: status[%s], reason[%s]";
 		String message = String.format(format, getRequestMessage(), allowed ? "allowed" : "denied", reason);
@@ -379,8 +383,13 @@ public class AuthorizationSession {
 		_resourceMatchingScope = scope;
 		return this;
 	}
+
 	AuthorizationSession ignoreDescendantDeny(boolean ignoreDescendantDeny) {
 		_ignoreDescendantDeny = ignoreDescendantDeny;
 		return this;
 	}
-}
+
+	public boolean getPropertyIsColumnAuthOptimizationEnabled() {
+		return _authorizer.getPropertyIsColumnAuthOptimizationEnabled();
+	}
+}
\ No newline at end of file
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
index 2c9b6b80b..213e15d49 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
@@ -76,6 +76,7 @@ import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 import org.apache.ranger.plugin.service.RangerBasePlugin;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
+import org.apache.ranger.plugin.util.ServicePolicies;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -90,11 +91,11 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 	private static final String GROUP_PREFIX = "@";
 
 	private UserProvider userProvider;
-    private RegionCoprocessorEnvironment regionEnv;
+	private RegionCoprocessorEnvironment regionEnv;
 	private Map<InternalScanner, String> scannerOwners = new MapMaker().weakKeys().makeMap();
 	/** if we should check EXEC permissions */
 	private boolean shouldCheckExecPermission;
-	
+
 	/*
 	 * These are package level only for testability and aren't meant to be exposed outside via getters/setters or made available to derived classes.
 	 */
@@ -102,7 +103,17 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 	final HbaseUserUtils _userUtils = _factory.getUserUtils();
 	final HbaseAuthUtils _authUtils = _factory.getAuthUtils();
 	private static volatile RangerHBasePlugin hbasePlugin = null;
-	
+
+	public void setColumnAuthOptimizationEnabled(boolean enable) throws Exception {
+		RangerHBasePlugin plugin = hbasePlugin;
+		if (plugin!=null) {
+			plugin.setColumnAuthOptimizationEnabled(enable);
+		}
+		else {
+			throw new Exception("Error while enabling column auth optimization");
+		}
+	}
+
 	// Utilities Methods
 	protected byte[] getTableName(RegionCoprocessorEnvironment e) {
 		Region region = e.getRegion();
@@ -139,7 +150,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				return true;
 			}
 		}
-			
+
 		return false;
 	}
 	protected boolean isAccessForMetaTables(RegionCoprocessorEnvironment env) {
@@ -205,7 +216,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		return user;
 	}
 
-	
+
 	private String getRemoteAddress() {
 		InetAddress remoteAddr = null;
 		try {
@@ -237,7 +248,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
      String owner = scannerOwners.get(s);
      if (owner != null && !owner.equals(requestUserName)) {
        throw new AccessDeniedException("User '"+ requestUserName +"' is not the scanner owner!");
-     }	
+     }
 	}
 	/**
 	 * @param families
@@ -258,8 +269,16 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				Collection<?> columnCollection = anEntry.getValue();
 				if (CollectionUtils.isEmpty(columnCollection)) {
 					// family points to null map, OK.
+					// if column auth disabled, then also empty set is fine
+					if (LOG.isDebugEnabled()) {
+						LOG.debug("RangerAuthorizationCoprocessor getColumnFamilies: columns are empty. " +
+								"Setting columns to emptySet in familyMap");
+					}
 					result.put(family, Collections.<String> emptySet());
 				} else {
+					if (LOG.isDebugEnabled()) {
+						LOG.debug("RangerAuthorizationCoprocessor getColumnFamilies: columns exist");
+					}
 					Iterator<String> columnIterator = new ColumnIterator(columnCollection);
 					Set<String> columns = new HashSet<String>();
 					try {
@@ -278,7 +297,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		}
 		return result;
 	}
-	
+
 	static class ColumnFamilyAccessResult {
 		final boolean _everythingIsAccessible;
 		final boolean _somethingIsAccessible;
@@ -301,7 +320,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			// cached values of access results
 			_filter = filter;
 		}
-		
+
 		@Override
 		public String toString() {
 			return MoreObjects.toStringHelper(getClass())
@@ -313,12 +332,15 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 					.add("denialReason", _denialReason)
 					.add("filter", _filter)
 					.toString();
-			
+
 		}
 	}
-	
+
 	ColumnFamilyAccessResult evaluateAccess(ObserverContext<?> ctx, String operation, Action action, final RegionCoprocessorEnvironment env,
-											final Map<byte[], ? extends Collection<?>> familyMap, String commandStr) throws AccessDeniedException {
+			final Map<byte[], ? extends Collection<?>> familyMap, String commandStr) throws AccessDeniedException {
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("evaluateAccess: isColumnAuthOptimizationEnabled="+hbasePlugin.getPropertyIsColumnAuthOptimizationEnabled());
+		}
 
 		String access = _authUtils.getAccess(action);
 		User user = getActiveUser(ctx);
@@ -393,7 +415,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		} else {
 			LOG.debug("evaluateAccess: Families collection not null.  Skipping table-level check, will do finer level check");
 		}
-		
+
 		boolean everythingIsAccessible = true;
 		boolean somethingIsAccessible = false;
 		/*
@@ -409,6 +431,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		Set<String> familesAccessAllowed = new HashSet<String>();
 		Set<String> familesAccessDenied = new HashSet<String>();
 		Set<String> familesAccessIndeterminate = new HashSet<String>();
+		Set<String> familiesFullyAuthorized = new HashSet<>();
 
 		for (Map.Entry<byte[], ? extends Collection<?>> anEntry : familyMap.entrySet()) {
 			String family = Bytes.toString(anEntry.getKey());
@@ -440,6 +463,8 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				if (LOG.isDebugEnabled()) {
 					LOG.debug("evaluateAccess: family level access for [" + family + "] is evaluated to " + isColumnFamilyAuthorized + ". Checking if [" + family + "] descendants have access.");
 				}
+				// buildRequest again since resourceMatchingScope changed
+				// reset ResourceMatchingScope to SELF, ignoreDescendantDeny to true
 				session.resourceMatchingScope(RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS)
 						.ignoreDescendantDeny(false)
 						.buildRequest()
@@ -491,7 +516,51 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				session.resourceMatchingScope(RangerAccessRequest.ResourceMatchingScope.SELF);
 				session.ignoreDescendantDeny(true);
 			} else {
-				LOG.debug("evaluateAccess: columns collection not empty.  Skipping Family level check, will do finer level access check.");
+				boolean isColumnAuthOptimizationEnabled = hbasePlugin.getPropertyIsColumnAuthOptimizationEnabled();
+				if(LOG.isDebugEnabled()) {
+					LOG.debug("evaluateAccess: columns collection not empty." +
+							" Skipping Family level check, will do finer level access check for columns.");
+				}
+				if (isColumnAuthOptimizationEnabled) {
+					session.column(null)
+							.buildRequest()
+							.authorize();
+					if (LOG.isDebugEnabled()) {
+						LOG.debug(
+								"evaluateAccess: isColumnAuthOptimizationEnabled={}, isColumnFamilyAuthorized={}",
+								isColumnAuthOptimizationEnabled, session.isAuthorized());
+					}
+					if(session.isAuthorized()) {
+
+						//check if column family fully authorized i.e. no deny for columns
+						session.column(null)
+								.resourceMatchingScope(RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS)
+								.ignoreDescendantDeny(false)
+								.buildRequest()
+								.authorize();
+
+						boolean isColumnFamilyAndDescendantsAuthorized = session.isAuthorized();
+						AuthzAuditEvent auditEvent = auditHandler.getAndDiscardMostRecentEvent();
+						// reset ResourceMatchingScope to SELF, ignoreDescendantDeny to true
+						session.resourceMatchingScope(RangerAccessRequest.ResourceMatchingScope.SELF)
+								.ignoreDescendantDeny(true);
+						if (LOG.isDebugEnabled()) {
+							LOG.debug(
+									"evaluateAccess: isColumnAuthOptimizationEnabled={}, isColumnFamilyAndDescendantsAuthorized={}",
+									isColumnAuthOptimizationEnabled, isColumnFamilyAndDescendantsAuthorized);
+						}
+						if (isColumnFamilyAndDescendantsAuthorized) {
+							familiesFullyAuthorized.add(family);
+							if (auditEvent != null) {
+								if (LOG.isDebugEnabled()) {
+									LOG.debug("evaluateAccess: isColumnAuthOptimizationEnabled ={}, adding family {} to familiesFullyAuthorized", isColumnAuthOptimizationEnabled, family);
+								}
+								familyLevelAccessEvents.add(auditEvent);
+							}
+							continue;
+						}
+					}
+				}
 				Set<String> accessibleColumns = new HashSet<String>(); // will be used in to populate our results cache for the filter
 				Iterator<String> columnIterator = new ColumnIterator(columns);
 				while (columnIterator.hasNext()) {
@@ -499,6 +568,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 					 if (LOG.isDebugEnabled()) {
  						LOG.debug("evaluateAccess: Processing column: " + column);
  					}
+					//buildRequest required again since now column is being set
  					session.column(column)
  						.buildRequest()
  						.authorize();
@@ -533,7 +603,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			}
 		}
 		// Cache of auth results are encapsulated the in the filter. Not every caller of the function uses it - only preGet and preOpt will.
-		RangerAuthorizationFilter filter = new RangerAuthorizationFilter(session, familesAccessAllowed, familesAccessDenied, familesAccessIndeterminate, columnsAccessAllowed);
+		RangerAuthorizationFilter filter = new RangerAuthorizationFilter(session, familesAccessAllowed, familesAccessDenied, familesAccessIndeterminate, columnsAccessAllowed, familiesFullyAuthorized);
 		result = new ColumnFamilyAccessResult(everythingIsAccessible, somethingIsAccessible, authorizedEvents, familyLevelAccessEvents, deniedEvent, denialReason, filter);
 		if (LOG.isDebugEnabled()) {
 			String message = String.format(messageTemplate, userName, operation, access, colFamiliesForDebugLoggingOnly, result.toString());
@@ -577,7 +647,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			}
 		}
 	}
-	
+
 	Filter combineFilters(Filter filter, Filter existingFilter) {
 		Filter combinedFilter = filter;
 		if (existingFilter != null) {
@@ -611,7 +681,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			RangerPerfTracer.log(perf);
 		}
 	}
-	
+
 	/**
 	 * This could run s
 	 * @param operation
@@ -630,7 +700,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			String message = String.format(format, "Entering", operation, otherInformation, access, table, columnFamily, column);
 			LOG.debug(message);
 		}
-		
+
 		final String format =  "authorizeAccess: %s: Operation[%s], Info[%s], access[%s], table[%s], columnFamily[%s], column[%s], allowed[%s], reason[%s]";
 		if (canSkipAccessCheck(user, operation, access, table)) {
 			if (LOG.isDebugEnabled()) {
@@ -640,7 +710,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			return;
 		}
 
-		
+
 		HbaseAuditHandler auditHandler = _factory.getAuditHandler();
 		AuthorizationSession session = new AuthorizationSession(hbasePlugin)
 			.operation(operation)
@@ -654,20 +724,20 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 			.column(column)
 			.buildRequest()
 			.authorize();
-		
+
 		if (LOG.isDebugEnabled()) {
 			boolean allowed = session.isAuthorized();
 			String reason = session.getDenialReason();
 			String message = String.format(format, "Exiting", operation, otherInformation, access, table, columnFamily, column, allowed, reason);
 			LOG.debug(message);
 		}
-		
+
 		session.publishResults();
 	}
-	
+
 	boolean canSkipAccessCheck(User user, final String operation, String access, final String table)
 			throws AccessDeniedException {
-		
+
 		boolean result = false;
 		if (user == null) {
 			String message = "Unexpeceted: User is null: access denied, not audited!";
@@ -679,10 +749,10 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		} else {
 			LOG.debug("Can't skip access checks");
 		}
-		
+
 		return result;
 	}
-	
+
 	boolean canSkipAccessCheck(User user, final String operation, String access, final RegionCoprocessorEnvironment regionServerEnv) throws AccessDeniedException {
 
 		// read access to metadata tables is always allowed and isn't audited.
@@ -708,7 +778,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		}
 		return false;
 	}
-	
+
 	boolean isAccessForMetadataRead(String access, String table) {
 		if (_authUtils.isReadAccess(access) && isSpecialTable(table)) {
 			LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed!");
@@ -731,7 +801,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 
 		authorizeAccess(ctx, request, null, action, table, null, null);
 	}
-	
+
 	protected void requirePermission(ObserverContext<?> ctx, String request, byte[] aTableName, byte[] aColumnFamily, byte[] aQualifier, Permission.Action action) throws AccessDeniedException {
 
 		String table = Bytes.toString(aTableName);
@@ -740,7 +810,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 
 		authorizeAccess(ctx, request, null, action, table, columnFamily, column);
 	}
-	
+
 	protected void requirePermission(ObserverContext<?> ctx, String request, Permission.Action perm, RegionCoprocessorEnvironment env, Collection<byte[]> families) throws IOException {
 		HashMap<byte[], Set<byte[]>> familyMap = new HashMap<byte[], Set<byte[]>>();
 
@@ -929,7 +999,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 	@Override
 	public Result preIncrement(ObserverContext<RegionCoprocessorEnvironment> c, Increment increment) throws IOException {
 		requirePermission(c, "increment", TablePermission.Action.WRITE, c.getEnvironment(), increment.getFamilyCellMap().keySet());
-		
+
 		return null;
 	}
 
@@ -1123,7 +1193,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		if(plugin == null) {
 			synchronized(RangerAuthorizationCoprocessor.class) {
 				plugin = hbasePlugin;
-				
+
 				if(plugin == null) {
 					plugin = new RangerHBasePlugin(appType);
 
@@ -1135,7 +1205,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				}
 			}
 		}
-		
+
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("Start of Coprocessor: [" + coprocessorType + "]");
 		}
@@ -1145,7 +1215,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 	public void prePut(ObserverContext<RegionCoprocessorEnvironment> c, Put put, WALEdit edit, Durability durability) throws IOException {
 		requirePermission(c, "put", TablePermission.Action.WRITE, c.getEnvironment(), put.getFamilyCellMap());
 	}
-	
+
 	@Override
 	public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> rEnv, final Get get, final List<Cell> result) throws IOException {
 		if (LOG.isDebugEnabled()) {
@@ -1216,7 +1286,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		}
 
 		checkGetTableInfoAccess(ctx, "getTableDescriptors", descriptors, regex, _authUtils.getAccess(Action.CREATE));
-		
+
 		if (LOG.isDebugEnabled()) {
 			LOG.debug(String.format("<== postGetTableDescriptors(count(tableNamesList)=%s, count(descriptors)=%s, regex=%s)", tableNamesList == null ? 0 : tableNamesList.size(),
 					descriptors == null ? 0 : descriptors.size(), regex));
@@ -1271,7 +1341,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 
 		if(UpdateRangerPoliciesOnGrantRevoke) {
 			GrantRevokeRequest grData = null;
-	
+
 			try {
 				grData = createGrantData(request);
 
@@ -1507,7 +1577,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 				nameSpace = namepsacePermission.getNamespace();
 			break;
 		}
-		
+
 		if(StringUtil.isEmpty(nameSpace) && StringUtil.isEmpty(tableName) && StringUtil.isEmpty(colFamily) && StringUtil.isEmpty(qualifier)) {
 			throw new Exception("grant(): namespace/table/columnFamily/columnQualifier not specified");
 		}
@@ -1659,7 +1729,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 		ret.setForwardedAddresses(null);//TODO: Need to check with Knox proxy how they handle forwarded add.
 		ret.setRemoteIPAddress(getRemoteAddress());
 		ret.setRequestData(up.toString());
-		
+
 		if(userName.startsWith(GROUP_PREFIX)) {
 			ret.getGroups().add(userName.substring(GROUP_PREFIX.length()));
 		} else {
@@ -1872,6 +1942,7 @@ public class RangerAuthorizationCoprocessor implements AccessControlService.Inte
 class RangerHBasePlugin extends RangerBasePlugin {
 	private static final Logger LOG = LoggerFactory.getLogger(RangerHBasePlugin.class);
 	boolean isHBaseShuttingDown  = false;
+	private boolean isColumnAuthOptimizationEnabled = false;
 
 	public RangerHBasePlugin(String appType) {
 		super("hbase", appType);
@@ -1894,6 +1965,18 @@ class RangerHBasePlugin extends RangerBasePlugin {
 		}
 		return ret;
 	}
+	@Override
+	public void setPolicies(ServicePolicies policies) {
+		super.setPolicies(policies);
+		this.isColumnAuthOptimizationEnabled = Boolean.parseBoolean(this.getServiceConfigs().get(RangerHadoopConstants.HBASE_COLUMN_AUTH_OPTIMIZATION));
+		LOG.info("isColumnAuthOptimizationEnabled="+this.isColumnAuthOptimizationEnabled);
+	}
+	public boolean getPropertyIsColumnAuthOptimizationEnabled(){
+		return this.isColumnAuthOptimizationEnabled;
+	}
+	public void setColumnAuthOptimizationEnabled(boolean enable){
+		this.isColumnAuthOptimizationEnabled = enable;
+	}
 }
 
 
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java
index 3cccd0169..7ddd0910b 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java
@@ -40,16 +40,18 @@ public class RangerAuthorizationFilter extends FilterBase {
 	final Set<String> _familiesAccessDenied;
 	final Set<String> _familiesAccessIndeterminate;
 	final Map<String, Set<String>> _columnsAccessAllowed;
+	final Set<String> _familiesFullyAuthorized;
 	final AuthorizationSession _session;
 	final HbaseAuditHandler _auditHandler = HbaseFactory.getInstance().getAuditHandler();
 
 	public RangerAuthorizationFilter(AuthorizationSession session, Set<String> familiesAccessAllowed, Set<String> familiesAccessDenied, Set<String> familiesAccessIndeterminate,
-									 Map<String, Set<String>> columnsAccessAllowed) {
+									 Map<String, Set<String>> columnsAccessAllowed, Set<String> familiesFullyAuthorized) {
 		// the class assumes that all of these can be empty but none of these can be null
 		_familiesAccessAllowed = familiesAccessAllowed;
 		_familiesAccessDenied = familiesAccessDenied;
 		_familiesAccessIndeterminate = familiesAccessIndeterminate;
 		_columnsAccessAllowed = columnsAccessAllowed;
+		_familiesFullyAuthorized = familiesFullyAuthorized;
 		// this session should have everything set on it except family and column which would be altered based on need
 		_session = session;
 		// we don't want to audit denial, so we need to make sure the hander is what we need it to be.
@@ -88,6 +90,9 @@ public class RangerAuthorizationFilter extends FilterBase {
 			LOG.warn("filterKeyValue: Unexpected - null/empty family! Access denied!");
 		} else if (_familiesAccessDenied.contains(family)) {
 			LOG.debug("filterKeyValue: family found in access denied families cache.  Access denied.");
+		} else if (_session.getPropertyIsColumnAuthOptimizationEnabled() && _familiesFullyAuthorized.contains(family)){
+			LOG.debug("filterKeyValue: ColumnAuthOptimizationEnabled and family found in fully authorized families cache.  Column authorization is not required");
+			result = ReturnCode.INCLUDE;
 		} else if (_columnsAccessAllowed.containsKey(family)) {
 			LOG.debug("filterKeyValue: family found in column level access results cache.");
 			if (_columnsAccessAllowed.get(family).contains(column)) {
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java
index 2c8f9af52..2be256ffd 100644
--- a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java
@@ -23,7 +23,6 @@ package org.apache.ranger.authorization.hbase;
 import static org.mockito.Mockito.*;
 
 import org.apache.hadoop.hbase.security.User;
-import org.apache.ranger.plugin.service.RangerBasePlugin;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -71,7 +70,7 @@ public class AuthorizationSessionTest {
 
 	@Test
 	public void testIsBuildable() {
-		RangerBasePlugin plugin = new RangerBasePlugin("hbase", "hbase");
+		RangerHBasePlugin plugin = new RangerHBasePlugin( "hbase");
 		AuthorizationSession session = new AuthorizationSession(plugin);
 		try {
 			session.verifyBuildable();
@@ -136,7 +135,7 @@ public class AuthorizationSessionTest {
 
 	@Test
 	public void testAuthorize() {
-		RangerBasePlugin plugin = new RangerBasePlugin("hbase", "hbase");
+		RangerHBasePlugin plugin = new RangerHBasePlugin( "hbase");
 		
 		User user = mock(User.class);
 		when(user.getShortName()).thenReturn("user1");
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HBaseRangerAuthorizationTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HBaseRangerAuthorizationTest.java
index b559c338a..d973079c7 100644
--- a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HBaseRangerAuthorizationTest.java
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HBaseRangerAuthorizationTest.java
@@ -20,31 +20,23 @@ package org.apache.ranger.authorization.hbase;
 import java.io.IOException;
 import java.net.ServerSocket;
 import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import com.google.protobuf.ByteString;
+import com.google.protobuf.RpcCallback;
+import com.google.protobuf.RpcController;
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseConfiguration;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.Admin;
-import org.apache.hadoop.hbase.client.Connection;
-import org.apache.hadoop.hbase.client.ConnectionFactory;
-import org.apache.hadoop.hbase.client.Delete;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.SnapshotDescription;
-import org.apache.hadoop.hbase.client.Table;
-import org.apache.hadoop.hbase.security.access.AccessControlClient;
-import org.apache.hadoop.hbase.security.access.NamespacePermission;
-import org.apache.hadoop.hbase.security.access.Permission;
-import org.apache.hadoop.hbase.security.access.UserPermission;
+import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
+import org.apache.hadoop.hbase.security.access.*;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.junit.Assert;
@@ -53,12 +45,15 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A custom RangerAdminClient is plugged into Ranger in turn, which loads security policies from a local file. These policies were 
+ * A custom RangerAdminClient is plugged into Ranger in turn, which loads security policies from a local file. These policies were
  * generated in the Ranger Admin UI for a service called "HBaseTest":
- * 
+ *
  * a) The "logged in" user can do anything
  * b) The IT group can read and write to the "temp" table, but only the "colfam1" column family.
  * c) The QA group can read and write to tables in "test_namespace" namespace.
+ * d) The IT group can read and write to the "temp6" table's "colfam1" column family and "col1" column only.
+ * e) The IT group for "temp7" table and "temp8" table can read "colfam1" column family but has denied for "col1" column in that column family
+ * f) The IT2 group for "temp7" table can read "colfam1" column family and does not have any denied columns in the column family
  *
  * In addition we have some TAG based policies created in Atlas and synced into Ranger:
  *
@@ -68,7 +63,7 @@ import org.slf4j.LoggerFactory;
  * the "temp3" table.
  *
  * Policies available from admin via:
- * 
+ *
  * http://localhost:6080/service/plugins/policies/download/cl1_hbase
  */
 @org.junit.Ignore
@@ -79,23 +74,26 @@ public class HBaseRangerAuthorizationTest {
     private static int port;
     private static HBaseTestingUtility utility;
 
+
     @org.junit.BeforeClass
     public static void setup() throws Exception {
         port = getFreePort();
-        
+
         utility = new HBaseTestingUtility();
         utility.getConfiguration().set("test.hbase.zookeeper.property.clientPort", "" + port);
+        utility.getConfiguration().set("hbase.master.hostname", "localhost");
         utility.getConfiguration().set("hbase.master.port", "" + getFreePort());
         utility.getConfiguration().set("hbase.master.info.port", "" + getFreePort());
+        utility.getConfiguration().set("hbase.unsafe.regionserver.hostname", "localhost");
         utility.getConfiguration().set("hbase.regionserver.port", "" + getFreePort());
         utility.getConfiguration().set("hbase.regionserver.info.port", "" + getFreePort());
         utility.getConfiguration().set("zookeeper.znode.parent", "/hbase-unsecure");
 
         // Enable authorization
         utility.getConfiguration().set("hbase.security.authorization", "true");
-        utility.getConfiguration().set("hbase.coprocessor.master.classes", 
+        utility.getConfiguration().set("hbase.coprocessor.master.classes",
             "org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor");
-        utility.getConfiguration().set("hbase.coprocessor.region.classes", 
+        utility.getConfiguration().set("hbase.coprocessor.region.classes",
             "org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor");
 
         utility.startMiniCluster();
@@ -112,30 +110,21 @@ public class HBaseRangerAuthorizationTest {
 
         // Create a table
         if (!admin.tableExists(TableName.valueOf("default:temp"))) {
-            HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("default:temp"));
+            TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("default:temp"));
 
             // Adding column families to table descriptor
-            tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-            tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
-            admin.createTable(tableDescriptor);
+            admin.createTable(tableDescriptor.build());
         }
 
-		if (!admin.tableExists(TableName.valueOf("default:temp5"))) {
-			HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("default:temp5"));
-
-			// Adding column families to table descriptor
-			tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-
-			admin.createTable(tableDescriptor);
-		}
-
         // Add a new row
         Put put = new Put(Bytes.toBytes("row1"));
         put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val1"));
         Table table = conn.getTable(TableName.valueOf("temp"));
         table.put(put);
-        
+
         put = new Put(Bytes.toBytes("row1"));
         put.addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
         table.put(put);
@@ -146,15 +135,40 @@ public class HBaseRangerAuthorizationTest {
 
         // Create a table
         if (!admin.tableExists(TableName.valueOf("test_namespace", "temp"))) {
-            HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("test_namespace", "temp"));
+            TableDescriptorBuilder tableDescriptor =  TableDescriptorBuilder.newBuilder(TableName.valueOf("test_namespace", "temp"));
 
             // Adding column families to table descriptor
-            tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-            tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
-            admin.createTable(tableDescriptor);
+            admin.createTable(tableDescriptor.build());
         }
 
+        if (!admin.tableExists(TableName.valueOf("default:temp5"))) {
+            TableDescriptorBuilder tableDescriptor =  TableDescriptorBuilder.newBuilder(TableName.valueOf("default:temp5"));
+            // Adding column families to table descriptor
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            admin.createTable(tableDescriptor.build());
+        }
+        if (!admin.tableExists(TableName.valueOf("default:temp6"))) {
+            TableDescriptorBuilder tableDescriptor =  TableDescriptorBuilder.newBuilder(TableName.valueOf("default:temp6"));
+            // Adding column families to table descriptor
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            admin.createTable(tableDescriptor.build());
+        }
+        if (!admin.tableExists(TableName.valueOf("default:temp7"))) {
+            TableDescriptorBuilder tableDescriptor =  TableDescriptorBuilder.newBuilder(TableName.valueOf("default:temp7"));
+            // Adding column families to table descriptor
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            admin.createTable(tableDescriptor.build());
+        }
+        table = conn.getTable(TableName.valueOf("default", "temp7"));
+
+        // Add a new row
+        put = new Put(Bytes.toBytes("row1"));
+        put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val1"));
+        table.put(put);
+
         table = conn.getTable(TableName.valueOf("test_namespace", "temp"));
 
         // Add a new row
@@ -166,33 +180,51 @@ public class HBaseRangerAuthorizationTest {
         put.addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
         table.put(put);
 
+        if (!admin.tableExists(TableName.valueOf("default:temp8"))) {
+            TableDescriptorBuilder tableDescriptor =  TableDescriptorBuilder.newBuilder(TableName.valueOf("default:temp8"));
+            // Adding column families to table descriptor
+            tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+            admin.createTable(tableDescriptor.build());
+        }
+        table = conn.getTable(TableName.valueOf("default", "temp8"));
+
+        // Add a new row
+        put = new Put(Bytes.toBytes("row1"));
+        put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val1"));
+        table.put(put);
+
+        // Add a new row
+        put = new Put(Bytes.toBytes("row2"));
+        put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col2"), Bytes.toBytes("val2"));
+        table.put(put);
+
         conn.close();
     }
-    
+
     @org.junit.AfterClass
     public static void cleanup() throws Exception {
         utility.shutdownMiniCluster();
     }
-    
+
     @Test
     public void testReadTablesAsProcessOwner() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Admin admin = conn.getAdmin();
 
-        HTableDescriptor[] tableDescriptors = admin.listTables();
-        for (HTableDescriptor desc : tableDescriptors) {
+        List<TableDescriptor> tableDescriptors = admin.listTableDescriptors();
+        for (TableDescriptor desc : tableDescriptors) {
             LOG.info("Found table:[" + desc.getTableName().getNameAsString() + "]");
         }
-        Assert.assertEquals(3, tableDescriptors.length);
+        Assert.assertEquals(6, tableDescriptors.size());
 
         conn.close();
     }
-    
+
     // This should fail as the "IT" group only has read privileges, not admin privileges, on the table "temp"
     @Test
     public void testReadTablesAsGroupIT() throws Exception {
@@ -200,7 +232,7 @@ public class HBaseRangerAuthorizationTest {
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         String user = "IT";
 
         UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
@@ -208,40 +240,40 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Admin admin = conn.getAdmin();
-                
-                HTableDescriptor[] tableDescriptors = admin.listTables();
-                for (HTableDescriptor desc : tableDescriptors) {
+
+                List <TableDescriptor> tableDescriptors = admin.listTableDescriptors();
+                for (TableDescriptor desc : tableDescriptors) {
                     LOG.info("Found table:[" + desc.getTableName().getNameAsString() + "]");
                 }
-                Assert.assertEquals(0, tableDescriptors.length);
-        
+                Assert.assertEquals(0, tableDescriptors.size());
+
                 conn.close();
                 return null;
             }
         });
     }
-    
+
     @Test
     public void testCreateAndDropTables() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Admin admin = conn.getAdmin();
 
         // Create a new table as process owner
-        HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("temp2"));
+        TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp2"));
 
         // Adding column families to table descriptor
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
-        admin.createTable(tableDescriptor);
+        admin.createTable(tableDescriptor.build());
 
         conn.close();
-        
+
         // Try to disable + delete the table as the "IT" group
         String user = "IT";
 
@@ -250,7 +282,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Admin admin = conn.getAdmin();
-                
+
                 try {
                     admin.disableTable(TableName.valueOf("temp2"));
                     admin.deleteTable(TableName.valueOf("temp2"));
@@ -258,40 +290,40 @@ public class HBaseRangerAuthorizationTest {
                 } catch (IOException ex) {
                     // expected
                 }
-                
+
                 conn.close();
                 return null;
             }
         });
-        
+
         // Now disable and delete as process owner
         conn = ConnectionFactory.createConnection(conf);
         admin = conn.getAdmin();
         admin.disableTable(TableName.valueOf("temp2"));
         admin.deleteTable(TableName.valueOf("temp2"));
-        
+
         conn.close();
     }
-    
+
     @Test
     public void testReadRowAsProcessOwner() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Table table = conn.getTable(TableName.valueOf("temp"));
-        
+
         // Read a row
         Get get = new Get(Bytes.toBytes("row1"));
         Result result = table.get(get);
         byte[] valResult = result.getValue(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"));
         Assert.assertTrue(Arrays.equals(valResult, Bytes.toBytes("val1")));
-        
+
         conn.close();
     }
-    
+
     @Test
     public void testReadRowAsGroupIT() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
@@ -306,7 +338,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Read a row
                 Get get = new Get(Bytes.toBytes("row1"));
                 Result result = table.get(get);
@@ -318,7 +350,7 @@ public class HBaseRangerAuthorizationTest {
             }
         });
     }
-    
+
     // This should fail as "public" doesn't have the right to read the table
     @Test
     public void testReadRowAsGroupPublic() throws Exception {
@@ -334,7 +366,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Read a row
                 try {
                     Get get = new Get(Bytes.toBytes("row1"));
@@ -350,14 +382,14 @@ public class HBaseRangerAuthorizationTest {
             }
         });
     }
-    
+
     @Test
     public void testReadRowFromColFam2AsProcessOwner() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Table table = conn.getTable(TableName.valueOf("temp"));
 
@@ -369,7 +401,7 @@ public class HBaseRangerAuthorizationTest {
 
         conn.close();
     }
-    
+
     @Test
     public void testReadRowFromColFam2AsGroupIT() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
@@ -384,7 +416,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Read a row
                 Get get = new Get(Bytes.toBytes("row1"));
                 Result result = table.get(get);
@@ -396,25 +428,25 @@ public class HBaseRangerAuthorizationTest {
             }
         });
     }
-    
+
     @Test
     public void testWriteRowAsProcessOwner() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Table table = conn.getTable(TableName.valueOf("temp"));
-        
+
         // Add a new row
         Put put = new Put(Bytes.toBytes("row2"));
         put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
         table.put(put);
-        
+
         conn.close();
     }
-    
+
     @Test
     public void testWriteRowAsGroupIT() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
@@ -429,18 +461,18 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Add a new row
                 Put put = new Put(Bytes.toBytes("row3"));
                 put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
                 table.put(put);
-                
+
                 conn.close();
                 return null;
             }
         });
     }
-    
+
     @Test
     public void testWriteRowAsGroupPublic() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
@@ -455,7 +487,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Add a new row
                 try {
                     Put put = new Put(Bytes.toBytes("row3"));
@@ -465,13 +497,13 @@ public class HBaseRangerAuthorizationTest {
                 } catch (IOException ex) {
                     // expected
                 }
-                
+
                 conn.close();
                 return null;
             }
         });
     }
-    
+
     @Test
     public void testWriteRowInColFam2AsGroupIT() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
@@ -486,7 +518,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 // Add a new row
                 try {
                     Put put = new Put(Bytes.toBytes("row3"));
@@ -496,46 +528,46 @@ public class HBaseRangerAuthorizationTest {
                 } catch (IOException ex) {
                     // expected
                 }
-                
+
                 conn.close();
                 return null;
             }
         });
     }
-    
+
     @Test
     public void testReadRowInAnotherTable() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Admin admin = conn.getAdmin();
 
         // Create a new table as process owner
-        HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("temp4"));
+        TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp4"));
 
         // Adding column families to table descriptor
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
-        admin.createTable(tableDescriptor);
+        admin.createTable(tableDescriptor.build());
 
         // Write a value
         Put put = new Put(Bytes.toBytes("row1"));
         put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val1"));
         Table table = conn.getTable(TableName.valueOf("temp4"));
         table.put(put);
-        
+
         // Read a row
         Get get = new Get(Bytes.toBytes("row1"));
         Result result = table.get(get);
         byte[] valResult = result.getValue(Bytes.toBytes("colfam2"), Bytes.toBytes("col1"));
         Assert.assertNull(valResult);
-        
+
         conn.close();
-        
+
         // Now try to read the row as group "IT" - it should fail as "IT" can only read from table "temp"
         String user = "IT";
 
@@ -544,7 +576,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp4"));
-                
+
                 // Read a row
                 try {
                     Get get = new Get(Bytes.toBytes("row1"));
@@ -559,48 +591,48 @@ public class HBaseRangerAuthorizationTest {
                 return null;
             }
         });
-        
+
         // Now disable and delete as process owner
         conn = ConnectionFactory.createConnection(conf);
         admin = conn.getAdmin();
         admin.disableTable(TableName.valueOf("temp4"));
         admin.deleteTable(TableName.valueOf("temp4"));
-        
+
         conn.close();
     }
-    
+
     @Test
     public void testDeleteRowAsProcessOwner() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Table table = conn.getTable(TableName.valueOf("temp"));
-        
+
         // Add a new row
         Put put = new Put(Bytes.toBytes("row4"));
         put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
         table.put(put);
-        
+
         // Delete the new row
         Delete delete = new Delete(Bytes.toBytes("row4"));
         table.delete(delete);
-        
+
         conn.close();
     }
-    
+
     @Test
     public void testDeleteRowAsGroupIT() throws Exception {
         final Configuration conf = HBaseConfiguration.create();
         conf.set("hbase.zookeeper.quorum", "localhost");
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-        
+
         Connection conn = ConnectionFactory.createConnection(conf);
         Table table = conn.getTable(TableName.valueOf("temp"));
-        
+
         // Add a new row (as process owner)
         Put put = new Put(Bytes.toBytes("row5"));
         put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
@@ -613,7 +645,7 @@ public class HBaseRangerAuthorizationTest {
             public Void run() throws Exception {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Table table = conn.getTable(TableName.valueOf("temp"));
-                
+
                 try {
                     // Delete the new row
                     Delete delete = new Delete(Bytes.toBytes("row5"));
@@ -622,16 +654,16 @@ public class HBaseRangerAuthorizationTest {
                 } catch (IOException ex) {
                     // expected
                 }
-                
+
                 conn.close();
                 return null;
             }
         });
-        
+
         // Delete the new row (as process owner)
         Delete delete = new Delete(Bytes.toBytes("row5"));
         table.delete(delete);
-        
+
         conn.close();
     }
 
@@ -666,7 +698,8 @@ public class HBaseRangerAuthorizationTest {
                 admin.snapshot("test_snapshot", tableName);
 
                 // Clone snapshot
-                HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("test_namespace", "temp_cloned"));
+                TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("test_namespace", "temp_cloned")).build();
+
                 TableName newTableName = tableDescriptor.getTableName();
                 admin.cloneSnapshot("test_snapshot", newTableName);
                 admin.disableTable(newTableName);
@@ -746,11 +779,11 @@ public class HBaseRangerAuthorizationTest {
         conf.set("hbase.zookeeper.property.clientPort", "" + port);
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
 
-        final HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("temp3"));
+        final TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp3"));
 
         // Adding column families to table descriptor
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
         // Try to create a "temp3" table as the "IT" group - this should fail
         String user = "IT";
@@ -763,7 +796,7 @@ public class HBaseRangerAuthorizationTest {
                 Admin admin = conn.getAdmin();
 
                 try {
-                    admin.createTable(tableDescriptor);
+                    admin.createTable(tableDescriptor.build());
                     Assert.fail("Failure expected on an unauthorized user");
                 } catch (IOException ex) {
                     // expected
@@ -781,7 +814,7 @@ public class HBaseRangerAuthorizationTest {
                 Connection conn = ConnectionFactory.createConnection(conf);
                 Admin admin = conn.getAdmin();
 
-                admin.createTable(tableDescriptor);
+                admin.createTable(tableDescriptor.build());
 
                 conn.close();
                 return null;
@@ -806,16 +839,16 @@ public class HBaseRangerAuthorizationTest {
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
 
         // Create a new table as process owner
-        final HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("temp3"));
+        final TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp3"));
 
         // Adding column families to table descriptor
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
         Connection conn = ConnectionFactory.createConnection(conf);
         Admin admin = conn.getAdmin();
 
-        admin.createTable(tableDescriptor);
+        admin.createTable(tableDescriptor.build());
 
         // Add a new row
         Put put = new Put(Bytes.toBytes("row1"));
@@ -891,16 +924,16 @@ public class HBaseRangerAuthorizationTest {
         conf.set("zookeeper.znode.parent", "/hbase-unsecure");
 
         // Create a new table as process owner
-        final HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("temp3"));
+        final TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp3"));
 
         // Adding column families to table descriptor
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam1"));
-        tableDescriptor.addFamily(new HColumnDescriptor("colfam2"));
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
 
         Connection conn = ConnectionFactory.createConnection(conf);
         Admin admin = conn.getAdmin();
 
-        admin.createTable(tableDescriptor);
+        admin.createTable(tableDescriptor.build());
 
         // Add a new row
         Put put = new Put(Bytes.toBytes("row1"));
@@ -975,64 +1008,431 @@ public class HBaseRangerAuthorizationTest {
         conn.close();
     }
 
-	@Test
-	public void testGetUserPermission() throws Throwable {
-		final Configuration conf = HBaseConfiguration.create();
-		conf.set("hbase.zookeeper.quorum", "localhost");
-		conf.set("hbase.zookeeper.property.clientPort", "" + port);
-		conf.set("zookeeper.znode.parent", "/hbase-unsecure");
-		String user = "IT";
-		UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] { "IT" });
-		ugi.doAs(new PrivilegedExceptionAction<Void>() {
-			public Void run() throws Exception {
-				try (Connection conn = ConnectionFactory.createConnection(conf)) {
-					AccessControlClient.getUserPermissions(conn, "temp");
-					Assert.fail();
-				} catch (Throwable e) {
-					// expected
-				}
-				return null;
-			}
-
-		});
-
-		user = "QA";
-		ugi = UserGroupInformation.createUserForTesting(user, new String[] { "QA" });
-		ugi.doAs(new PrivilegedExceptionAction<Void>() {
-			public Void run() throws Exception {
-				List<UserPermission> userPermissions;
-				try (Connection conn = ConnectionFactory.createConnection(conf)) {
-					userPermissions = AccessControlClient.getUserPermissions(conn, "@test_namespace");
-				} catch (Throwable e) {
-					throw new Exception(e);
-				}
-				boolean found = false;
-				for (UserPermission namespacePermission : userPermissions) {
-					if (namespacePermission.getPermission() instanceof NamespacePermission) {
-						found = StringUtils.equals(namespacePermission.getUser(), "@QA");
-						if (found) {
-							break;
-						}
-					}
-				}
-				Assert.assertTrue("QA is not found", found);
-				return null;
-			}
-		});
-
-		List<UserPermission> userPermissions;
-		try (Connection conn = ConnectionFactory.createConnection(conf)) {
-			userPermissions = AccessControlClient.getUserPermissions(conn, "temp5");
-		} catch (Throwable e) {
-			throw new Exception(e);
-		}
-
-		UserPermission userPermission = new UserPermission("@IT",
-				Permission.newBuilder(TableName.valueOf("temp5")).withActions(Permission.Action.READ, Permission.Action.WRITE, Permission.Action.EXEC).build());
-
-		Assert.assertTrue("@IT permission should be there", userPermissions.contains(userPermission));
-
-	}
+    @Test
+    public void testGetUserPermission() throws Throwable {
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] { "IT" });
+        if(!utility.getHBaseCluster().isDistributedCluster()) {
+            RangerAuthorizationCoprocessor authorizationCoprocessor =
+                utility.getHBaseCluster().getMaster().getMasterCoprocessorHost().
+                    findCoprocessor(RangerAuthorizationCoprocessor.class);
+            RpcController rpcController = new RpcController() {
+                @Override
+                public void reset() {
+
+                }
+
+                @Override
+                public boolean failed() {
+                    return false;
+                }
+
+                @Override
+                public String errorText() {
+                    return null;
+                }
+
+                @Override
+                public void startCancel() {
+
+                }
+
+                @Override
+                public void setFailed(String reason) {
+
+                }
+
+                @Override
+                public boolean isCanceled() {
+                    return false;
+                }
+
+                @Override
+                public void notifyOnCancel(RpcCallback<Object> callback) {
+
+                }
+            };
+            ugi.doAs(new PrivilegedExceptionAction<Void>() {
+                public Void run() throws Exception {
+                    AccessControlProtos.GetUserPermissionsRequest requestTablePerms = getTableUserPermissions("temp");
+                    authorizationCoprocessor.getUserPermissions(rpcController, requestTablePerms,
+                        new RpcCallback<AccessControlProtos.GetUserPermissionsResponse>() {
+                            @Override
+                            public void run(AccessControlProtos.GetUserPermissionsResponse message) {
+                                if (message != null) {
+                                    for (AccessControlProtos.UserPermission perm : message
+                                        .getUserPermissionList()) {
+                                        AccessControlUtil.toUserPermission(perm);
+                                        Assert.fail();
+                                    }
+                                }
+                            }
+                        });
+                    return null;
+                }
+
+            });
+
+            user = "QA";
+            ugi = UserGroupInformation.createUserForTesting(user, new String[] { "QA" });
+            ugi.doAs(new PrivilegedExceptionAction<Void>() {
+                public Void run() throws Exception {
+                    final List<UserPermission> userPermissions = new ArrayList<UserPermission>();
+                    AccessControlProtos.GetUserPermissionsRequest requestTablePerms = getNamespaceUserPermissions("test_namespace");
+                    getUserPermissions(userPermissions, requestTablePerms, authorizationCoprocessor, rpcController);
+                    boolean found = false;
+                    for (UserPermission namespacePermission : userPermissions) {
+                        if (namespacePermission.getPermission() instanceof NamespacePermission  ) {
+                            found = Bytes.equals(namespacePermission.getUser().getBytes(), Bytes.toBytes("@QA"));
+                            if (found) {
+                                break;
+                            }
+                        }
+                    }
+                    Assert.assertTrue("QA is not found", found);
+                    return null;
+                }
+            });
+
+            final List<UserPermission> userPermissions = new ArrayList<>();
+            AccessControlProtos.GetUserPermissionsRequest requestTablePerms = getTableUserPermissions("temp5");
+            getUserPermissions(userPermissions, requestTablePerms, authorizationCoprocessor, rpcController);
+            Permission p = Permission.newBuilder(TableName.valueOf("temp5")).
+                withActions(Permission.Action.READ, Permission.Action.WRITE, Permission.Action.EXEC).build();
+            UserPermission userPermission = new UserPermission("@IT", p);
+            Assert.assertTrue("@IT permission should be there", userPermissions.contains(userPermission));
+        }
+    }
+    @Test
+    public void testWriteRowAsGroupIT2() throws Exception {
+        //check access to table temp6 to test the policy TempPolicyForOptimizedColAuth with non * column
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp6"));
+                // Add a new row
+                Put put = new Put(Bytes.toBytes("row3"));
+                put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                table.put(put);
+                conn.close();
+                return null;
+            }
+        });
+    }
+    @Test
+    public void testWriteRowAsGroupIT2Optimized() throws Exception {
+        // No behavior change from testWriteRowAsGroupIT2()
+        enableColumnAuthOptimization(true);
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp6"));
+                // Add a new row
+                Put put = new Put(Bytes.toBytes("row3"));
+                put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                table.put(put);
+                conn.close();
+                return null;
+            }
+        });
+        enableColumnAuthOptimization(false);
+    }
+    @Test
+    public void testWriteRowDeniedAsGroupIT2() throws Exception {
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp7"));
+                try {
+                    // Add a new row
+                    Put put = new Put(Bytes.toBytes("row3"));
+                    put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                    table.put(put);
+                    Assert.fail("Failure expected on an unauthorized user");
+                }
+                catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+    }
+    @Test
+    public void testWriteRowDeniedAsGroupIT2Optimized() throws Exception {
+        // no behavior change from testWriteRowDeniedAsGroupIT2
+        enableColumnAuthOptimization(true);
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp7"));
+                try {
+                    // Add a new row
+                    Put put = new Put(Bytes.toBytes("row3"));
+                    put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                    table.put(put);
+                    Assert.fail("Failure expected on an unauthorized user");
+                }
+                catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+        enableColumnAuthOptimization(false);
+    }
+    @Test
+    public void testScanTableAsGroupIT() throws Exception {
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "IT";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp8"));
+                try {
+                    Scan scan = new Scan();
+                    ResultScanner scanner = table.getScanner(scan);
+                    int numRowsInResult = 0;
+                    for (Result result = scanner.next(); result != null; result = scanner.next()){
+                        System.out.println("Found row : " + result);
+                        numRowsInResult += 1;
+                    }
+                    //while there are 2 rows in this table, one of the columns is explicitly denied so only one column should be in the result
+                    Assert.assertEquals(1,numRowsInResult);
+                }
+                catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+
+        user = "IT2";
+        ugi = UserGroupInformation.createUserForTesting(user, new String[] {"IT2"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp8"));
+                try {
+                    Scan scan = new Scan();
+                    ResultScanner scanner = table.getScanner(scan);
+                    int numRowsInResult = 0;
+                    for (Result result = scanner.next(); result != null; result = scanner.next()){
+                        System.out.println("Found row : " + result);
+                        numRowsInResult += 1;
+                    }
+                    //there are 2 rows in this table, group IT2 does not have any denied columns
+                    Assert.assertEquals(2,numRowsInResult);
+                }
+                catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+    }
+
+
+    @Test
+    public void testWriteRowAsGroupPublicOptimized() throws Exception {
+        enableColumnAuthOptimization(true); // enable optimization
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+        String user = "public";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"public"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp"));
+                // Add a new row
+                try {
+                    Put put = new Put(Bytes.toBytes("row3"));
+                    put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                    table.put(put);
+                    Assert.fail("Failure expected on an unauthorized user");
+                } catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+        enableColumnAuthOptimization(false); // disable optimization after test case complete
+    }
+    @Test
+    public void testTagBasedColumnPolicyOptimized() throws Exception {
+        // There should not be any behavior change from testTagBasedColumnPolicy() even after
+        // column optimization enabled as tags will exist for the accessed resource and should
+        // fall back to default behavior
+        enableColumnAuthOptimization(true);
+        final Configuration conf = HBaseConfiguration.create();
+        conf.set("hbase.zookeeper.quorum", "localhost");
+        conf.set("hbase.zookeeper.property.clientPort", "" + port);
+        conf.set("zookeeper.znode.parent", "/hbase-unsecure");
+
+        // Create a new table as process owner
+        final TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf("temp3"));
+
+        // Adding column families to table descriptor
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam1".getBytes()).build());
+        tableDescriptor.addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder("colfam2".getBytes()).build());
+
+        Connection conn = ConnectionFactory.createConnection(conf);
+        Admin admin = conn.getAdmin();
+
+        admin.createTable(tableDescriptor.build());
+
+        // Add a new row
+        Put put = new Put(Bytes.toBytes("row1"));
+        put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val1"));
+        Table table = conn.getTable(TableName.valueOf("temp3"));
+        table.put(put);
+
+        put = new Put(Bytes.toBytes("row1"));
+        put.addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+        table.put(put);
+
+        conn.close();
+
+        String user = "dev";
+        UserGroupInformation ugi = UserGroupInformation.createUserForTesting(user, new String[] {"dev"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp3"));
+
+                // Try to write something to the "col1" column of the "colfam1" of the "temp3" table as the "dev" group
+                // - this should work
+                Put put = new Put(Bytes.toBytes("row3"));
+                put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                table.put(put);
+
+                // Try to write something to the "col2" column of the "colfam1" of the "temp3" table as the "dev" group
+                // - this should fail
+                put = new Put(Bytes.toBytes("row3"));
+                put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col2"), Bytes.toBytes("val2"));
+                try {
+                    table.put(put);
+                    Assert.fail("Failure expected on an unauthorized user");
+                } catch (IOException ex) {
+                    // expected
+                }
+
+                conn.close();
+                return null;
+            }
+        });
+
+        ugi = UserGroupInformation.createUserForTesting("IT", new String[] {"IT"});
+        ugi.doAs(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws Exception {
+                Connection conn = ConnectionFactory.createConnection(conf);
+                Table table = conn.getTable(TableName.valueOf("temp3"));
+
+                // Try to write something to the "col1" column of the "colfam1" of the "temp3" table as the "IT" group
+                // - this should fail
+                Put put = new Put(Bytes.toBytes("row3"));
+                put.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col1"), Bytes.toBytes("val2"));
+                try {
+                    table.put(put);
+                    Assert.fail("Failure expected on an unauthorized user");
+                } catch (IOException ex) {
+                    // expected
+                }
+                conn.close();
+                return null;
+            }
+        });
+
+        // Drop the table
+        conn = ConnectionFactory.createConnection(conf);
+        admin = conn.getAdmin();
+
+        admin.disableTable(TableName.valueOf("temp3"));
+        admin.deleteTable(TableName.valueOf("temp3"));
+
+        conn.close();
+        enableColumnAuthOptimization(false);
+    }
+
+    private static void enableColumnAuthOptimization(boolean enable){
+        RangerAuthorizationCoprocessor authorizationCoprocessor =
+            utility.getHBaseCluster().getMaster().getMasterCoprocessorHost().
+                findCoprocessor(RangerAuthorizationCoprocessor.class);
+        try {
+            authorizationCoprocessor.setColumnAuthOptimizationEnabled(enable);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private AccessControlProtos.GetUserPermissionsRequest getNamespaceUserPermissions(String namespace) {
+        AccessControlProtos.GetUserPermissionsRequest.Builder builderTablePerms = AccessControlProtos.GetUserPermissionsRequest
+            .newBuilder();
+        builderTablePerms.setNamespaceName(ByteString.copyFromUtf8(namespace));
+        builderTablePerms.setType(AccessControlProtos.Permission.Type.Namespace);
+        return builderTablePerms.build();
+    }
+
+    private AccessControlProtos.GetUserPermissionsRequest getTableUserPermissions(String tableName) {
+        AccessControlProtos.GetUserPermissionsRequest.Builder builderTablePerms = AccessControlProtos.GetUserPermissionsRequest
+            .newBuilder();
+        builderTablePerms.setTableName(ProtobufUtil.toProtoTableName(TableName.valueOf(tableName)));
+        builderTablePerms.setType(AccessControlProtos.Permission.Type.Table);
+        return builderTablePerms.build();
+    }
+
+    private void getUserPermissions(List<UserPermission> userPermissions, AccessControlProtos.GetUserPermissionsRequest requestTablePerms, RangerAuthorizationCoprocessor authorizationCoprocessor, RpcController rpcController) {
+        authorizationCoprocessor.getUserPermissions(rpcController, requestTablePerms,
+            new RpcCallback<AccessControlProtos.GetUserPermissionsResponse>() {
+                @Override
+                public void run(AccessControlProtos.GetUserPermissionsResponse message) {
+                    if (message != null) {
+                        for (AccessControlProtos.UserPermission perm : message
+                            .getUserPermissionList()) {
+                            userPermissions.add(AccessControlUtil.toUserPermission(perm));
+                        }
+                    }
+                }
+            });
+    }
 
     private static int getFreePort() throws IOException {
         ServerSocket serverSocket = new ServerSocket(0);
@@ -1040,4 +1440,5 @@ public class HBaseRangerAuthorizationTest {
         serverSocket.close();
         return port;
     }
-}
+
+}
\ No newline at end of file
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilterTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilterTest.java
index 6b97c3064..fffc7943d 100644
--- a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilterTest.java
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilterTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
 
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -54,7 +55,7 @@ public class RangerAuthorizationFilterTest {
 
 		// auth session
 		AuthorizationSession session = createSessionMock();
-		RangerAuthorizationFilter filter = new RangerAuthorizationFilter(session, familiesAccessAllowed, familiesAccessDenied, familiesAccessIndeterminate, columnsAccessAllowed);
+		RangerAuthorizationFilter filter = new RangerAuthorizationFilter(session, familiesAccessAllowed, familiesAccessDenied, familiesAccessIndeterminate, columnsAccessAllowed, new HashSet<>());
 
 		// evaluate access for various types of cases
 		Cell aCell = mock(Cell.class);
diff --git a/hbase-agent/src/test/resources/hbase-policies.json b/hbase-agent/src/test/resources/hbase-policies.json
index 61960c0af..8ee73b1e0 100644
--- a/hbase-agent/src/test/resources/hbase-policies.json
+++ b/hbase-agent/src/test/resources/hbase-policies.json
@@ -245,6 +245,101 @@
       "id": 38,
       "isEnabled": true,
       "version": 1
+    },
+    {
+      "service": "cl1_hbase", "name": "TempPolicyForOptimizedColAuth", "policyType": 0, "description": "", "isAuditEnabled": true,
+      "resources": {
+        "column-family": {"values": ["colfam1"], "isExcludes": false, "isRecursive": false },
+        "column": {"values": ["col1"], "isExcludes": false, "isRecursive": false},
+        "table": {"values": ["temp6"], "isExcludes": false, "isRecursive": false}
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {"type": "read", "isAllowed": true},
+            {"type": "write", "isAllowed": true},
+            {"type": "execute", "isAllowed": true}
+          ],
+          "users": [], "groups": ["IT"], "conditions": [], "delegateAdmin": false
+        }
+      ],
+      "id": 101, "isEnabled": true, "version": 1
+    },
+    {
+      "service": "cl1_hbase", "name": "AllowColFamWhenColDeniedForOptimized", "policyType": 0, "description": "", "isAuditEnabled": true,
+      "resources": {
+        "column-family": {"values": ["colfam1"], "isExcludes": false, "isRecursive": false},
+        "column": {"values": ["*"], "isExcludes": false, "isRecursive": false},
+        "table": {"values": ["temp7"], "isExcludes": false, "isRecursive": false}
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {"type": "read", "isAllowed": true},
+            {"type": "write", "isAllowed": true},
+            {"type": "execute", "isAllowed": true}
+          ],
+          "users": [], "groups": ["IT"], "conditions": [], "delegateAdmin": false
+        }
+      ],
+      "id": 102, "isEnabled": true, "version": 1
+    },
+    {
+      "service": "cl1_hbase", "name": "DenyColWhenColFamAllowedForOptimizedCheck", "policyType": 0, "description": "", "isAuditEnabled": true,
+      "resources": {
+        "column-family": {"values": ["colfam1"], "isExcludes": false, "isRecursive": false},
+        "column": {"values": ["col1"], "isExcludes": false, "isRecursive": false},
+        "table": {"values": ["temp7"], "isExcludes": false, "isRecursive": false}
+      },
+      "denyPolicyItems": [
+        {
+          "accesses": [
+            {"type": "read", "isAllowed": true},
+            {"type": "write", "isAllowed": true},
+            {"type": "execute", "isAllowed": true}
+          ],
+          "users": [], "groups": ["IT"], "conditions": [], "delegateAdmin": false
+        }
+      ],
+      "id": 103, "isEnabled": true, "version": 1
+    },
+    {
+      "service": "cl1_hbase", "name": "PolicyForAllowColumnFamilyForScan", "policyType": 0, "description": "", "isAuditEnabled": true,
+      "resources": {
+        "column-family": {"values": ["colfam1"], "isExcludes": false, "isRecursive": false},
+        "column": {"values": ["*"], "isExcludes": false, "isRecursive": false},
+        "table": {"values": ["temp8"], "isExcludes": false, "isRecursive": false}
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {"type": "read", "isAllowed": true},
+            {"type": "write", "isAllowed": true},
+            {"type": "execute", "isAllowed": true}
+          ],
+          "users": [], "groups": ["IT","IT2"], "conditions": [], "delegateAdmin": false
+        }
+      ],
+      "id": 104, "isEnabled": true, "version": 1
+    },
+    {
+      "service": "cl1_hbase", "name": "PolicyForDenyColumnForScan", "policyType": 0, "description": "", "isAuditEnabled": true,
+      "resources": {
+        "column-family": {"values": ["colfam1"], "isExcludes": false, "isRecursive": false},
+        "column": {"values": ["col1"], "isExcludes": false, "isRecursive": false},
+        "table": {"values": ["temp8"], "isExcludes": false, "isRecursive": false}
+      },
+      "denyPolicyItems": [
+        {
+          "accesses": [
+            {"type": "read", "isAllowed": true},
+            {"type": "write", "isAllowed": true},
+            {"type": "execute", "isAllowed": true}
+          ],
+          "users": [], "groups": ["IT"], "conditions": [], "delegateAdmin": false
+        }
+      ],
+      "id": 105, "isEnabled": true, "version": 1
     }
   ],
   "serviceDef": {
@@ -1317,4 +1412,4 @@
     },
     "auditMode": "audit-default"
   }
-}
+}
\ No newline at end of file