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 2015/04/18 07:58:36 UTC

incubator-ranger git commit: RANGER-405 Hbase plugin: Don't skipt auditing access requests by "superusers"

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 80c289370 -> f8b4d4a9a


RANGER-405 Hbase plugin: Don't skipt auditing access requests by "superusers"

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/f8b4d4a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/f8b4d4a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/f8b4d4a9

Branch: refs/heads/master
Commit: f8b4d4a9a28e097abe21565a0af9c21ee700c699
Parents: 80c2893
Author: Alok Lal <al...@hortonworks.com>
Authored: Fri Apr 17 01:07:27 2015 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Fri Apr 17 22:52:19 2015 -0700

----------------------------------------------------------------------
 .../hbase/AuthorizationSession.java             | 16 ++++++-
 .../authorization/hbase/HbaseAuditHandler.java  |  5 ++
 .../hbase/HbaseAuditHandlerImpl.java            | 21 +++++++-
 .../authorization/hbase/HbaseAuthUtilsImpl.java |  1 -
 .../authorization/hbase/HbaseFactory.java       |  6 +++
 .../authorization/hbase/HbaseUserUtils.java     |  7 +++
 .../authorization/hbase/HbaseUserUtilsImpl.java | 50 ++++++++++++++++++--
 .../hbase/RangerAuthorizationCoprocessor.java   | 44 ++++-------------
 .../java/org/apache/ranger/biz/AssetMgr.java    |  2 +-
 9 files changed, 110 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java
----------------------------------------------------------------------
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 1c712a4..46ed758 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
@@ -57,6 +57,7 @@ public class AuthorizationSession {
 	Set<String> _groups; // this exits to avoid having to get group for a user repeatedly.  It is kept in sync with _user;
 	// Passing a null handler to policy engine would suppress audit logging.
 	HbaseAuditHandler _auditHandler = null;
+	boolean _superUser = false; // is this session for a super user?
 	
 	// internal state per-authorization
 	RangerAccessRequest _request;
@@ -89,10 +90,11 @@ public class AuthorizationSession {
 	AuthorizationSession user(User aUser) {
 		_user = aUser;
 		if (_user == null) {
-			LOG.debug("AuthorizationSession.user: user is null!");
+			LOG.warn("AuthorizationSession.user: user is null!");
 			_groups = null;
 		} else {
 			_groups = _userUtils.getUserGroups(_user);
+			_superUser = _userUtils.isSuperUser(_user);
 		}
 		return this;
 	}
@@ -185,6 +187,12 @@ public class AuthorizationSession {
 			throw new IllegalStateException(message);
 		} else {
 			// ok to pass potentially null handler to policy engine.  Null handler effectively suppresses the audit.
+			if (_auditHandler != null && _superUser) {
+				if (LOG.isDebugEnabled()) {
+	                LOG.debug("Setting super-user override on audit handler");
+				}
+				_auditHandler.setSuperUserOverride(_superUser);
+			}
 			_result = _authorizer.isAccessAllowed(_request, _auditHandler);
 		}
 		if (LOG.isDebugEnabled()) {
@@ -255,6 +263,12 @@ public class AuthorizationSession {
 		} else {
 			allowed = _result.getIsAllowed();
 		}
+		if (!allowed && _superUser) {
+			if (LOG.isDebugEnabled()) {
+				LOG.debug("User [" + _user + "] is a superUser!  Overriding policy engine's decision.  Request is deemed authorized!");
+			}
+			allowed = true;
+		}
 		return allowed;
 	}
 	

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java
index 28d41aa..f94cef4 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java
@@ -45,4 +45,9 @@ public interface HbaseAuditHandler extends RangerAuditHandler {
 	 */
 	void setMostRecentEvent(AuthzAuditEvent capturedEvents);
 	
+	/**
+	 * Is audit handler being used in context of a access authorization of a superuser?
+	 * @param override
+	 */
+	void setSuperUserOverride(boolean override);
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java
index fb4f8a0..e383614 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java
@@ -31,6 +31,7 @@ public class HbaseAuditHandlerImpl extends RangerDefaultAuditHandler implements
 	final List<AuthzAuditEvent> _allEvents = new ArrayList<AuthzAuditEvent>();
 	// we replace its contents anytime new audit events are generated.
 	AuthzAuditEvent _mostRecentEvent = null;
+	boolean _superUserOverride = false;
 	
 	@Override
 	public AuthzAuditEvent getAuthzEvents(RangerAccessResult result) {
@@ -52,13 +53,14 @@ public class HbaseAuditHandlerImpl extends RangerDefaultAuditHandler implements
 		if (_mostRecentEvent != null) {
 			result.add(_mostRecentEvent);
 		}
-		
+		applySuperUserOverride(result);
 		return result;
 	}
 
 	@Override
 	public AuthzAuditEvent  discardMostRecentEvent() {
 		AuthzAuditEvent result = _mostRecentEvent;
+		applySuperUserOverride(result);
 		_mostRecentEvent = null;
 		return result;
 	}
@@ -67,4 +69,21 @@ public class HbaseAuditHandlerImpl extends RangerDefaultAuditHandler implements
 	public void setMostRecentEvent(AuthzAuditEvent event) {
 		_mostRecentEvent = event;
 	}
+
+	@Override
+	public void setSuperUserOverride(boolean override) {
+		_superUserOverride = override;
+	}
+	
+	void applySuperUserOverride(List<AuthzAuditEvent> events) {
+		for (AuthzAuditEvent event : events) {
+			applySuperUserOverride(event);
+		}
+	}
+	
+	void applySuperUserOverride(AuthzAuditEvent event) {
+		if (event != null && _superUserOverride) {
+			event.setAccessResult((short)1);
+		}
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java
index a94bf1e..d80a04a 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java
@@ -21,7 +21,6 @@ package org.apache.ranger.authorization.hbase;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.HRegionInfo;
-import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
 import org.apache.hadoop.hbase.security.access.Permission.Action;
 import org.apache.hadoop.hbase.util.Bytes;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java
index 5b5690f..3488d70 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java
@@ -18,6 +18,8 @@
  */
 package org.apache.ranger.authorization.hbase;
 
+import org.apache.hadoop.conf.Configuration;
+
 
 
 // TODO remove this in favor of Guice DI
@@ -48,4 +50,8 @@ public class HbaseFactory {
 	HbaseAuditHandler getAuditHandler() {
 		return new HbaseAuditHandlerImpl();
 	}
+
+	static void initialize(Configuration conf) {
+		HbaseUserUtilsImpl.initiailize(conf);
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java
index aa85994..05d67d6 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java
@@ -49,4 +49,11 @@ public interface HbaseUserUtils {
 	 * @return
 	 */
 	String getUserAsString();
+
+	/**
+	 * Returns true of specified user is configured to be a super user
+	 * @param user
+	 * @return
+	 */
+	boolean isSuperUser(User user);
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java
index fd15aaa..ddc84d8 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java
@@ -20,22 +20,49 @@ package org.apache.ranger.authorization.hbase;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.ipc.RpcServer;
 import org.apache.hadoop.hbase.security.User;
 
 public class HbaseUserUtilsImpl implements HbaseUserUtils {
 
 	private static final Log LOG = LogFactory.getLog(HbaseUserUtilsImpl.class.getName());
+	private static final String SUPERUSER_CONFIG_PROP = "hbase.superuser";
 
-	static Set<String> _SuperUsers = Collections.synchronizedSet(new HashSet<String>());
-	static AtomicBoolean initialized = new AtomicBoolean(false);
+	// only to detect problems with initialization order, not for thread-safety. 
+	static final AtomicBoolean _Initialized = new AtomicBoolean(false);
+	// should never be null
+	static final AtomicReference<Set<String>> _SuperUsers = new AtomicReference<Set<String>>(new HashSet<String>());
+	
+	public static void initiailize(Configuration conf) {
+		
+		if (_Initialized.get()) {
+			LOG.warn("HbaseUserUtilsImpl.initialize: Unexpected: initialization called more than once!");
+		} else {
+			if (conf == null) {
+				LOG.error("HbaseUserUtilsImpl.initialize: Internal error: called with null conf value!");
+			} else {
+				String[] users = conf.getStrings(SUPERUSER_CONFIG_PROP);
+				if (users != null && users.length > 0) {
+					Set<String> superUsers = new HashSet<String>(users.length);
+					for (String user : users) {
+						user = user.trim();
+						LOG.info("HbaseUserUtilsImpl.initialize: Adding Super User(" + user + ")");
+						superUsers.add(user);
+					}
+					_SuperUsers.set(superUsers);
+				}
+			}
+			_Initialized.set(true);
+		}
+	}
 	
 	@Override
 	public String getUserAsString(User user) {
@@ -84,4 +111,21 @@ public class HbaseUserUtilsImpl implements HbaseUserUtils {
 			return getUserAsString(user);
 		}
 	}
+
+	/**
+	 * No user can be a superuser till the class is properly initialized.  Once class is properly initialized, users specified in
+	 * configuration would be reported as super users.
+	 */
+	@Override
+	public boolean isSuperUser(User user) {
+		if (!_Initialized.get()) {
+			LOG.error("HbaseUserUtilsImpl.isSuperUser: Internal error: called before initialization was complete!");
+		}
+		Set<String> superUsers = _SuperUsers.get(); // can never be null
+		boolean isSuper = superUsers.contains(user.getShortName());
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("IsSuperCheck on [" + user.getShortName() + "] returns [" + isSuper + "]");
+		}
+		return isSuper;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
----------------------------------------------------------------------
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 edc769b..2926bec 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
@@ -72,11 +72,11 @@ import org.apache.hadoop.hbase.protobuf.ResponseConverter;
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
+import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
 import org.apache.hadoop.hbase.protobuf.generated.SecureBulkLoadProtos.CleanupBulkLoadRequest;
 import org.apache.hadoop.hbase.protobuf.generated.SecureBulkLoadProtos.PrepareBulkLoadRequest;
-import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
-import org.apache.hadoop.hbase.regionserver.Region;
 import org.apache.hadoop.hbase.regionserver.InternalScanner;
+import org.apache.hadoop.hbase.regionserver.Region;
 import org.apache.hadoop.hbase.regionserver.RegionScanner;
 import org.apache.hadoop.hbase.regionserver.ScanType;
 import org.apache.hadoop.hbase.regionserver.Store;
@@ -115,7 +115,6 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 	private static boolean UpdateRangerPoliciesOnGrantRevoke = RangerHadoopConstants.HBASE_UPDATE_RANGER_POLICIES_ON_GRANT_REVOKE_DEFAULT_VALUE;
 	private static final String GROUP_PREFIX = "@";
 		
-	private static final String SUPERUSER_CONFIG_PROP = "hbase.superuser";
 	private static final String WILDCARD = "*";
 	
     private static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT+0");
@@ -123,8 +122,6 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
     private RegionCoprocessorEnvironment regionEnv;
 	private Map<InternalScanner, String> scannerOwners = new MapMaker().weakKeys().makeMap();
 	
-	private List<String> superUserList = null;
-
 	/*
 	 * These are package level only for testability and aren't meant to be exposed outside via getters/setters or made available to derived classes.
 	 */
@@ -150,21 +147,12 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 		if (user == null) {
 			throw new IOException("Unable to obtain the current user, authorization checks for internal operations will not work correctly!");
 		}
-		String currentUser = user.getShortName();
-		List<String> superusers = Lists.asList(currentUser, conf.getStrings(SUPERUSER_CONFIG_PROP, new String[0]));
+		String systemUser = user.getShortName();
 		User activeUser = getActiveUser();
-		if (!(superusers.contains(activeUser.getShortName()))) {
+		if (!Objects.equal(systemUser, activeUser.getShortName()) && !_userUtils.isSuperUser(activeUser)) {
 			throw new AccessDeniedException("User '" + user.getShortName() + "is not system or super user.");
 		}
 	}
-	private boolean isSuperUser(User user) {
-		boolean isSuper = false;
-		isSuper = (superUserList != null && superUserList.contains(user.getShortName()));
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("IsSuperCheck on [" + user.getShortName() + "] returns [" + isSuper + "]");
-		}
-		return isSuper;
-	}
 	protected boolean isSpecialTable(HRegionInfo regionInfo) {
 		return isSpecialTable(regionInfo.getTable().getName());
 	}
@@ -213,7 +201,6 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
        throw new AccessDeniedException("User '"+ requestUserName +"' is not the scanner owner!");
      }	
 	}
-
 	/**
 	 * @param families
 	 * @return empty map if families is null, would never have empty or null keys, would never have null values, values could be empty (non-null) set
@@ -344,7 +331,7 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 			// if authorized then pass captured events as access allowed set else as access denied set.
 			result = new ColumnFamilyAccessResult(authorized, authorized, 
 						authorized ? Collections.singletonList(event) : null,
-						authorized ? null : event, null, reason); 
+						authorized ? null : event, null, reason);
 			if (LOG.isDebugEnabled()) {
 				String message = String.format(messageTemplate, operation, access, families.toString(), result.toString());
 				LOG.debug(message);
@@ -534,9 +521,6 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 			String message = "Unexpeceted: User is null: access denied, not audited!"; 
 			LOG.warn("canSkipAccessCheck: exiting" + message);
 			throw new AccessDeniedException("No user associated with request (" + operation + ") for action: " + access + "on table:" + table);
-		} else if (isSuperUser(user)) {
-			LOG.debug("canSkipAccessCheck: true: superuser access allowed, not audited");
-			result = true;
 		} else if (isAccessForMetadataRead(access, table)) {
 			LOG.debug("canSkipAccessCheck: true: metadata read access always allowed, not audited");
 			result = true;
@@ -913,19 +897,9 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 			coprocessorType = REGIONAL_COPROCESSOR_TYPE;
 			appType = "hbaseRegional";
 		}
-
-		if (superUserList == null) {
-			superUserList = new ArrayList<String>();
-			Configuration conf = env.getConfiguration();
-			String[] users = conf.getStrings(SUPERUSER_CONFIG_PROP);
-			if (users != null) {
-				for (String user : users) {
-					user = user.trim();
-					LOG.info("Start() - Adding Super User(" + user + ")");
-					superUserList.add(user);
-				}
-			}
-		}
+		
+		Configuration conf = env.getConfiguration();
+		HbaseFactory.initialize(conf);
 
 		// create and initialize the plugin class
 		RangerHBasePlugin plugin = hbasePlugin;
@@ -947,7 +921,7 @@ public class RangerAuthorizationCoprocessor extends RangerAuthorizationCoprocess
 		}
 		
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("Start of Coprocessor: [" + coprocessorType + "] with superUserList [" + superUserList + "]");
+			LOG.debug("Start of Coprocessor: [" + coprocessorType + "]");
 		}
 	}
 	@Override

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f8b4d4a9/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
index 1c076c5..a838d8e 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
@@ -1694,7 +1694,7 @@ public class AssetMgr extends AssetMgrBase {
 									.getBooleanProperty(
 											"xa.log.SC_NOT_MODIFIED", false);
 							if (!logNotModified) {
-								logger.info("Not logging HttpServletResponse."
+								logger.debug("Not logging HttpServletResponse."
 										+ "SC_NOT_MODIFIED, to enable, update "
 										+ ": xa.log.SC_NOT_MODIFIED");
 								return null;