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 <[email protected]>


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 <[email protected]>
Authored: Fri Apr 17 01:07:27 2015 -0700
Committer: Madhan Neethiraj <[email protected]>
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;

Reply via email to