ranger-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mad...@apache.org
Subject [4/4] incubator-ranger git commit: RANGER-230 Hbase plugin implementation using new pluggable service model
Date Sat, 31 Jan 2015 08:43:18 GMT
RANGER-230 Hbase plugin implementation using new pluggable service model


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

Branch: refs/heads/stack
Commit: 46633a9ed2ed3499e95ad87409ce5b0460929da7
Parents: 1d6a259
Author: Alok Lal <alal@hortonworks.com>
Authored: Sat Jan 31 00:42:21 2015 -0800
Committer: Madhan Neethiraj <madhan@apache.org>
Committed: Sat Jan 31 00:42:21 2015 -0800

----------------------------------------------------------------------
 .../hbase/AuthorizationSession.java             | 342 +++++++++++++++++++
 .../authorization/hbase/ColumnIterator.java     |  94 +++++
 .../authorization/hbase/HbaseAuditHandler.java  |  48 +++
 .../hbase/HbaseAuditHandlerImpl.java            |  69 ++++
 .../authorization/hbase/HbaseAuthUtils.java     |  33 ++
 .../authorization/hbase/HbaseAuthUtilsImpl.java |  66 ++++
 .../authorization/hbase/HbaseFactory.java       |  58 ++++
 .../authorization/hbase/HbaseUserUtils.java     |  52 +++
 .../authorization/hbase/HbaseUserUtilsImpl.java |  91 +++++
 .../hbase/RangerAuthorizationFilter.java        |  69 ++++
 .../hbase/AuthorizationSessionTest.java         | 218 ++++++++++++
 .../hbase/HbaseAuthUtilsImplTest.java           |  33 ++
 .../hbase/RangerCoprocessorTest.java            |  33 ++
 .../authorization/hbase/TestPolicyEngine.java   | 178 ++++++++++
 hbase-agent/src/test/resources/log4j.properties |  16 +
 .../policyengine/test_policyengine_hbase.json   | 159 +++++++++
 16 files changed, 1559 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..e6067ce
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/AuthorizationSession.java
@@ -0,0 +1,342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.security.AccessDeniedException;
+import org.apache.hadoop.hbase.security.User;
+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.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerResourceImpl;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+public class AuthorizationSession {
+
+	private static final Log LOG = LogFactory.getLog(AuthorizationSession.class.getName());
+	// collaborator objects
+	final HbaseFactory _factory = HbaseFactory.getInstance();
+	final HbaseUserUtils _userUtils = _factory.getUserUtils();
+	final HbaseAuthUtils _authUtils = _factory.getAuthUtils();
+	// immutable state
+	final RangerPolicyEngine _authorizer;
+	// Mutable state: Use supplied state information
+	String _operation;
+	String _otherInformation;
+	String _access;
+	String _table;
+	String _column;
+	String _columnFamily;
+	String _remoteAddress;
+	User _user;
+	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;
+	
+	// internal state per-authorization
+	RangerAccessRequest _request;
+	RangerAccessResult _result;
+	
+	public AuthorizationSession(RangerPolicyEngine authorizer) {
+		_authorizer = authorizer;
+	}
+
+	AuthorizationSession operation(String anOperation) {
+		_operation = anOperation;
+		return this;
+	}
+
+	AuthorizationSession otherInformation(String information) {
+		_otherInformation = information;
+		return this;
+	}
+	
+	AuthorizationSession remoteAddress(String ipAddress) {
+		_remoteAddress = ipAddress;
+		return this;
+	}
+	
+	AuthorizationSession access(String anAccess) {
+		_access = anAccess; 
+		return this;
+	}
+
+	AuthorizationSession user(User aUser) {
+		_user = aUser;
+		if (_user == null) {
+			LOG.debug("AuthorizationSession.user: user is null!");
+			_groups = null;
+		} else {
+			_groups = _userUtils.getUserGroups(_user);
+		}
+		return this;
+	}
+	AuthorizationSession table(String aTable) {
+		_table = aTable;
+		return this;
+	}
+
+	AuthorizationSession columnFamily(String aColumnFamily) {
+		_columnFamily = aColumnFamily;
+		return this;
+	}
+
+	AuthorizationSession column(String aColumn) {
+		_column = aColumn;
+		return this;
+	}
+
+	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");
+			LOG.error(message);
+			throw new IllegalStateException(message);
+		}
+		if (_access == null || _access.isEmpty()) {
+			String message = String.format(template, "access is null");
+			LOG.error(message);
+			throw new IllegalStateException(message);
+		}
+		if (_user == null) {
+			String message = String.format(template, "user is null");
+			LOG.error(message);
+			throw new IllegalStateException(message);
+		}
+		if (isProvided(_columnFamily) && !isProvided(_table)) {
+			String message = String.format(template, "Table must be provided if column-family is provided");
+			LOG.error(message);
+			throw new IllegalStateException(message);
+		}
+		if (isProvided(_column) && !isProvided(_columnFamily)) {
+			String message = String.format(template, "Column family must be provided if column is provided");
+			LOG.error(message);
+			throw new IllegalStateException(message);
+		}
+	}
+
+	void zapAuthorizationState() {
+		_request = null;
+		_result = null;
+	}
+
+	boolean isProvided(String aString) {
+		return aString != null && !aString.isEmpty();
+	}
+	
+	AuthorizationSession buildRequest() {
+
+		verifyBuildable();
+		// session can be reused so reset its state
+		zapAuthorizationState();
+		// TODO get this via a factory instead
+		RangerResourceImpl resource = new RangerResourceImpl();
+		// policy engine should deal sensibly with null/empty values, if any
+		resource.setValue("table", _table);
+		resource.setValue("column-family", _columnFamily);
+		resource.setValue("column", _column);
+		
+		String user = _userUtils.getUserAsString(_user);
+		LOG.debug("AuthorizationSession buildRequest: user[" + user + "], groups[" + _groups + "]");
+
+		RangerAccessRequestImpl request = new RangerAccessRequestImpl(resource, _access, user, _groups);
+		request.setAction(_operation);
+		request.setRequestData(_otherInformation);
+		request.setClientIPAddress(_remoteAddress);
+		
+		_request = request;
+		return this;
+	}
+	
+	AuthorizationSession authorize() {
+		if (LOG.isDebugEnabled()) {
+			String message = "authorize: " + getRequestMessage();
+			LOG.debug(message);
+		}
+		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);
+		} else {
+			// ok to pass potentially null handler to policy engine.  Null handler effectively suppresses the audit.
+			_result = _authorizer.isAccessAllowed(_request, _auditHandler);
+		}
+		if (LOG.isDebugEnabled()) {
+			boolean allowed = isAuthorized();
+			String reason = getDenialReason();
+			String message = "AuthorizationSession.authorize: " + getLogMessage(allowed, reason);
+			LOG.debug(message);
+		}
+		return this;
+	}
+	
+	void publishResults() throws AccessDeniedException {
+
+		boolean authorized = isAuthorized();
+		if (_auditHandler != null) {
+			List<AuthzAuditEvent> events = null;
+			/*
+			 * What we log to audit depends on authorization status.  For success we log all accumulated events.  In case of failure 
+			 * we log just the last set of audit messages as we only need to record the cause of overall denial.
+			 */
+			if (authorized) {
+				List<AuthzAuditEvent> theseEvents = _auditHandler.getCapturedEvents();
+				if (theseEvents != null && !theseEvents.isEmpty()) {
+					events = theseEvents;
+				}
+			} else {
+				AuthzAuditEvent event = _auditHandler.discardMostRecentEvent();
+				if (event != null) {
+					events = Lists.newArrayList(event);
+				}
+			}
+			if (LOG.isDebugEnabled()) {
+				int size = events == null ? 0 : events.size();
+				String auditMessage = events == null ? "" : events.toString();
+				String message = String.format("Writing %d messages to audit: [%s]", size, auditMessage);
+				LOG.debug(message);
+			}
+			_auditHandler.logAuthzAudits(events);
+		}
+		if (!authorized) {
+			// and throw and exception... callers expect this behavior
+			String reason = getDenialReason();
+			String message = getLogMessage(false, reason);
+			if (LOG.isDebugEnabled()) {
+				LOG.debug("AuthorizationSession.publishResults: throwing exception: " + message);
+			}
+			throw new AccessDeniedException("Insufficient permissions for user '" + _user.getName() + "' (action=" + _access + ")");
+		}
+	}
+	
+	boolean isAudited() {
+
+		boolean audited = false;
+		if (_result == null) {
+			String message = String.format("Internal error: _result was null!  Assuming no audit. Request[%s]", _request.toString());
+			LOG.error(message);
+		} else {
+			audited = _result.getIsAudited();
+		}
+		return audited;
+	}
+
+	boolean isAuthorized() {
+		boolean allowed = false;
+		if (_result == null) {
+			String message = String.format("Internal error: _result was null! Returning false.");
+			LOG.error(message);
+		} else {
+			allowed = _result.getIsAllowed();
+		}
+		return allowed;
+	}
+	
+	String getDenialReason() {
+		String reason = "";
+		if (_result == null) {
+			String message = String.format("Internal error: _result was null!  Returning empty reason.");
+			LOG.error(message);
+		} else {
+			boolean allowed = _result.getIsAllowed();
+			if (!allowed) {
+				reason = _result.getReason();
+			}
+		}
+		return reason;
+	}
+	
+	String requestToString() {
+		return Objects.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("table", _table)
+			.add("column", _column)
+			.add("column-family", _columnFamily)
+			.toString();
+	}
+
+	String getPrintableValue(String value) {
+		if (isProvided(value)) {
+			return value;
+		} else {
+			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();
+		String message = String.format(format, getPrintableValue(_access), getPrintableValue(user), _groups, getPrintableValue(_table),
+				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);
+		return message;
+	}
+
+	/**
+	 * Hand creates a result object and set it on the request for cases where we need not go to policy manager.
+	 * @return
+	 */
+	AuthorizationSession knownPatternAllowedNotAudited(String reason) {
+		_result = buildResult(true, false, reason);
+		return this;
+	}
+
+	AuthorizationSession knownPatternDisallowedNotAudited(String reason) {
+		_result = buildResult(false, false, reason);
+		
+		return this;
+	}
+	
+	/**
+	 * This method could potentially null out an earlier audit handler -- which effectively would suppress audits. 
+	 * @param anAuditHandler
+	 * @return
+	 */
+	AuthorizationSession auditHandler(HbaseAuditHandler anAuditHandler) {
+		_auditHandler = anAuditHandler;
+		return this;
+	}
+
+	RangerAccessResult buildResult(boolean allowed, boolean audited, String reason) {
+		RangerAccessResult result = _authorizer.createAccessResult(_request);
+		result.setIsAllowed(allowed);
+		result.setReason(reason);
+		result.setIsAudited(audited);
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
new file mode 100644
index 0000000..2c6f805
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class ColumnIterator implements Iterator<String> {
+	// TODO write tests for this class
+	
+	private static final Log LOG = LogFactory.getLog(ColumnIterator.class.getName());
+	Iterator<byte[]> _setIterator;
+	Iterator<KeyValue> _listIterator;
+	
+	@SuppressWarnings("unchecked")
+	public ColumnIterator(Collection<?> columnCollection) {
+		if (columnCollection != null) {
+			if (columnCollection instanceof Set) {
+				_setIterator = ((Set<byte[]>)columnCollection).iterator();
+			} else if (columnCollection instanceof List) {
+				_listIterator = ((List<KeyValue>)columnCollection).iterator();
+			} else { // unexpected
+				// TODO make message better
+				LOG.error("Unexpected type " + columnCollection.getClass().getName() + " passed as value in column family collection");
+			}
+		}
+	}
+
+	@Override
+	public boolean hasNext() {
+		if (_setIterator != null) {
+			return _setIterator.hasNext();
+		}
+		if (_listIterator != null) {
+			_listIterator.hasNext();
+		}
+		return false;
+	}
+
+	/**
+	 * Never returns a null value.  Will return empty string in case of null value.
+	 */
+	@Override
+	public String next() {
+		String value = "";
+		if (_setIterator != null) {
+			byte[] valueBytes = _setIterator.next();
+			if (valueBytes != null) {
+				value = Bytes.toString(valueBytes);
+			}
+		} else if (_listIterator != null) {
+			KeyValue kv = _listIterator.next();
+			byte[] v = kv.getQualifier();
+			if (v != null) {
+				value = Bytes.toString(v);
+			}
+		} else {
+			// TODO make the error message better
+			throw new NoSuchElementException("Empty values passed in!");
+		}
+		return value;
+	}
+
+	@Override
+	public void remove() {
+		// TODO make the error message better
+		throw new UnsupportedOperationException("Remove not supported from iterator!");
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..28d41aa
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.ranger.audit.model.AuthzAuditEvent;
+import org.apache.ranger.plugin.audit.RangerAuditHandler;
+
+public interface HbaseAuditHandler extends RangerAuditHandler {
+
+	List<AuthzAuditEvent> getCapturedEvents();
+	
+	void logAuthzAudits(Collection<AuthzAuditEvent> auditEvents);
+	
+	/**
+	 * Discards and returns the last audit events captured by the audit handler.  Last audit event should be the ones generated during the most recent authorization request.
+	 * However, it won't be all of the audit events called during an authorize call since implementation class may not override the method which takes a list of responses -- in 
+	 * which case there would be several audit messages generated by one call but this only allows you to get last of those messages created during single auth request.
+	 * After this call the last set of audit events won't be returned by <code>getCapturedEvents</code>. 
+	 * @return
+	 */
+	AuthzAuditEvent discardMostRecentEvent();
+	
+	/**
+	 * This is a complement to <code>discardMostRecentEvent</code> to set the most recent events.  Often useful to un-pop audit messages that were take out.
+	 * @param capturedEvents
+	 */
+	void setMostRecentEvent(AuthzAuditEvent capturedEvents);
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..a5d3f16
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuditHandlerImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ranger.audit.model.AuthzAuditEvent;
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+
+public class HbaseAuditHandlerImpl extends RangerDefaultAuditHandler implements HbaseAuditHandler {
+
+	static final List<AuthzAuditEvent> _EmptyList = new ArrayList<AuthzAuditEvent>();
+	final List<AuthzAuditEvent> _allEvents = new ArrayList<AuthzAuditEvent>();
+	// we replace its contents anytime new audit events are generated.
+	AuthzAuditEvent _mostRecentEvent = null;
+	
+	@Override
+	public AuthzAuditEvent getAuthzEvents(RangerAccessResult result) {
+		
+		AuthzAuditEvent event = super.getAuthzEvents(result);
+		// first accumulate last set of events and then capture these as the most recent ones
+		if (_mostRecentEvent != null) {
+			_allEvents.add(_mostRecentEvent);
+		}
+		_mostRecentEvent = event;
+		return event;
+	}
+	
+	@Override
+	public List<AuthzAuditEvent> getCapturedEvents() {
+		// construct a new collection since we don't want to lose track of which were the most recent events;
+		List<AuthzAuditEvent> result = new ArrayList<AuthzAuditEvent>(_allEvents);
+		if (_mostRecentEvent != null) {
+			result.add(_mostRecentEvent);
+		}
+		
+		return result;
+	}
+
+	@Override
+	public AuthzAuditEvent  discardMostRecentEvent() {
+		AuthzAuditEvent result = _mostRecentEvent;
+		_mostRecentEvent = null;
+		return result;
+	}
+
+	@Override
+	public void setMostRecentEvent(AuthzAuditEvent event) {
+		_mostRecentEvent = event;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtils.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtils.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtils.java
new file mode 100644
index 0000000..45d4cb4
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtils.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+
+public interface HbaseAuthUtils {
+
+	String getAccess(Action action);
+
+	boolean isReadAccess(String access);
+	
+	boolean isWriteAccess(String access);
+
+	String getTable(RegionCoprocessorEnvironment regionServerEnv);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..955a85c
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+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;
+
+public class HbaseAuthUtilsImpl implements HbaseAuthUtils {
+
+	private static final Log LOG = LogFactory.getLog(HbaseAuthUtilsImpl.class.getName());
+
+	public String getNameSpace(NamespaceDescriptor ns) {
+		if (ns == null) {
+			// TODO log an error and Throw an error so the operation is denied?
+		}
+		return ns.getName();
+	}
+
+	@Override
+	public String getAccess(Action action) {
+		return action.toString().toLowerCase();
+	}
+
+	@Override
+	public boolean isReadAccess(String access) {
+		return getAccess(Action.READ).equals(access);
+	}
+
+	@Override
+	public boolean isWriteAccess(String access) {
+		return getAccess(Action.WRITE).equals(access);
+	}
+
+	@Override
+	public String getTable(RegionCoprocessorEnvironment regionServerEnv) {
+		HRegionInfo hri = regionServerEnv.getRegion().getRegionInfo();
+		byte[] tableName = hri.getTable().getName() ;
+		String tableNameStr = Bytes.toString(tableName);
+		if (LOG.isDebugEnabled()) {
+			String message = String.format("getTable: Returning tablename[%s]", tableNameStr);
+			LOG.debug(message);
+		}
+		return tableNameStr;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..97e70ec
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+
+
+// TODO remove this in favor of Guice DI
+public class HbaseFactory {
+	
+	static final HbaseUserUtils _UserUtils = new HbaseUserUtilsImpl();
+	static final HbaseAuthUtils _AuthUtils = new HbaseAuthUtilsImpl();
+	static final RangerPolicyEngine _PolicyEngine = new RangerPolicyEngineImpl();
+	static final HbaseFactory _Factory = new HbaseFactory();
+	/**
+	 * This is a singleton 
+	 */
+	private HbaseFactory() {
+		// TODO remove this clutch to enforce singleton by moving to a DI framework
+	}
+	
+	static HbaseFactory getInstance() {
+		return _Factory;
+	}
+	
+	HbaseAuthUtils getAuthUtils() {
+		return _AuthUtils;
+	}
+	
+	HbaseUserUtils getUserUtils() {
+		return _UserUtils;
+	}
+	
+	RangerPolicyEngine getPolicyEngine() {
+		return _PolicyEngine;
+	}
+	
+	HbaseAuditHandler getAuditHandler() {
+		return new HbaseAuditHandlerImpl();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..aa85994
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import java.util.Set;
+
+import org.apache.hadoop.hbase.security.User;
+
+public interface HbaseUserUtils {
+	/**
+	 * Returns user's short name or empty string if null is passed in.
+	 * @param user
+	 * @return
+	 */
+	String getUserAsString(User user);
+
+	/**
+	 * Returns the groups to which user belongs to as known to User object.  For null values it returns an empty set.
+	 * @param user
+	 * @return
+	 */
+	Set<String> getUserGroups(User user);
+
+	/**
+	 * May return null in case of an error 
+	 * @return
+	 */
+	User getUser();
+	
+	/**
+	 * Returns the user short name.  Returns an empty string if Hbase User of context can't be found.
+	 * @param request
+	 * @return
+	 */
+	String getUserAsString();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/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
new file mode 100644
index 0000000..6b32e54
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/HbaseUserUtilsImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.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 org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.ipc.RequestContext;
+import org.apache.hadoop.hbase.security.User;
+
+public class HbaseUserUtilsImpl implements HbaseUserUtils {
+
+	private static final Log LOG = LogFactory.getLog(HbaseUserUtilsImpl.class.getName());
+
+	static Set<String> _SuperUsers = Collections.synchronizedSet(new HashSet<String>());
+	static AtomicBoolean initialized = new AtomicBoolean(false);
+	
+	@Override
+	public String getUserAsString(User user) {
+		if (user == null) {
+			throw new IllegalArgumentException("User is null!");
+		}
+		else {
+			return user.getShortName();
+		}
+	}
+
+	@Override
+	public Set<String> getUserGroups(User user) {
+		if (user == null) {
+			throw new IllegalArgumentException("User is null!");
+		}
+		else {
+			String[] groupsArray = user.getGroupNames();
+			return new HashSet<String>(Arrays.asList(groupsArray));
+		}
+	}
+
+	@Override
+	public User getUser() {
+		// current implementation does not use the request object!
+		User user;
+		if (RequestContext.isInRequestContext()) {
+			// this is the more common case
+			user = RequestContext.getRequestUser();
+		}
+		else {
+			try {
+				user = User.getCurrent();
+			} catch (IOException e) {
+				LOG.error("Unable to get current user: User.getCurrent() threw IOException");
+				user = null;
+			}
+		}
+		return user;
+	}
+
+
+	@Override
+	public String getUserAsString() {
+		User user = getUser();
+		if (user == null) {
+			return "";
+		}
+		else {
+			return getUserAsString(user);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..5a66eb2
--- /dev/null
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationFilter.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hbase;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.filter.FilterBase;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class RangerAuthorizationFilter extends FilterBase {
+
+	final Map<String, Set<String>> _cache;
+
+	public RangerAuthorizationFilter(Map<String, Set<String>> cache) {
+		_cache = cache;
+	}
+	
+	@SuppressWarnings("deprecation")
+	@Override
+	public ReturnCode filterKeyValue(Cell kv) throws IOException {
+		// if our cache is null or empty then there is no hope for any access
+		if (_cache == null || _cache.isEmpty()) {
+			return ReturnCode.NEXT_COL;
+		}
+		// null/empty families are denied
+		byte[] familyBytes = kv.getFamily();
+		if (familyBytes == null || familyBytes.length == 0) {
+			return ReturnCode.NEXT_COL;
+		}
+		String family = Bytes.toString(familyBytes);
+		// null/empty columns are also denied
+		byte[] columnBytes = kv.getQualifier();
+		if (columnBytes == null || columnBytes.length == 0) {
+			return ReturnCode.NEXT_COL;
+		}
+		String column = Bytes.toString(columnBytes);
+		// allow if cache contains the family/column in it
+		Set<String> columns = _cache.get(family);
+		if (columns == null || columns.isEmpty()) {
+			// column family with a null/empty set of columns means all columns within that family are allowed
+			return ReturnCode.INCLUDE;
+		}
+		else if (columns.contains(column)) {
+			return ReturnCode.INCLUDE;
+		} else {
+			return ReturnCode.NEXT_COL;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..1cd0d92
--- /dev/null
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/AuthorizationSessionTest.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import org.apache.hadoop.hbase.security.User;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AuthorizationSessionTest {
+
+	@Test
+	public void testAuthorizationSession() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testOperation() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testOtherInformation() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testAccess() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testUser() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testTable() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testColumnFamily() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testColumn() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testIsBuildable() {
+		RangerPolicyEngine engine = new RangerPolicyEngineImpl();
+		AuthorizationSession session = new AuthorizationSession(engine);
+		try {
+			session.verifyBuildable();
+			Assert.fail("Should have thrown exception");
+		} catch (IllegalStateException e) { }
+		// user and access are the only required ones.
+		User user = mock(User.class);
+		when(user.getGroupNames()).thenReturn(new String[] { "groups", "group2" });
+		session.access(" ");
+		session.user(user);
+		try {
+			session.verifyBuildable();
+		} catch (IllegalStateException e) {
+			fail("Shouldn't have thrown an exception!");
+		}
+		// setting column-family without table is a problem
+		session.columnFamily("family");
+		try {
+			session.verifyBuildable();
+			fail("Should have thrown an exception");
+		} catch (IllegalStateException e) { }
+		
+		session.table("table");
+		try {
+			session.verifyBuildable();
+		} catch (IllegalStateException e) {
+			fail("Shouldn't have thrown an exception!");
+		}
+		// setting column without column-family is a problem
+		session.columnFamily(null);
+		session.column("col");
+		try {
+			session.verifyBuildable();
+			fail("Should have thrown an exception");
+		} catch (IllegalStateException e) { }
+		session.columnFamily("family");
+		try {
+			session.verifyBuildable();
+		} catch (IllegalStateException e) { 
+			fail("Should have thrown an exception");
+		}
+	}
+
+	@Test
+	public void testZapAuthorizationState() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testIsProvided() {
+		AuthorizationSession session = new AuthorizationSession(null);
+		assertFalse(session.isProvided(null));
+		assertFalse(session.isProvided(""));
+		assertTrue(session.isProvided(" "));
+		assertTrue(session.isProvided("xtq"));
+	}
+
+	@Test
+	public void testBuildRequest() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testAuthorize() {
+		RangerPolicyEngine engine = new RangerPolicyEngineImpl();
+		
+		User user = mock(User.class);
+		when(user.getShortName()).thenReturn("user1");
+		when(user.getGroupNames()).thenReturn(new String[] { "users" } );
+		AuthorizationSession session = new AuthorizationSession(engine);
+		session.access("read")
+			.user(user)
+			.table(":meta:")
+			.buildRequest()
+			.authorize();
+	}
+
+	@Test
+	public void testPublishResults() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testIsAuthorized() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testGetDenialReason() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testGetResourceType() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testRequestToString() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testAudit() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testGetPrintableValue() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testBuildAccessDeniedMessage() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testBuildAccessDeniedMessageString() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testKnownPatternAllowedNotAudited() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testKnownPatternDisallowedNotAudited() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testAuditHandler() {
+//		fail("Not yet implemented");
+	}
+
+	@Test
+	public void testBuildResult() {
+//		fail("Not yet implemented");
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImplTest.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImplTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImplTest.java
new file mode 100644
index 0000000..e40f31a
--- /dev/null
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/HbaseAuthUtilsImplTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class HbaseAuthUtilsImplTest {
+
+	@Test
+	public void testIsReadAccess() {
+		HbaseAuthUtilsImpl authUtils = new HbaseAuthUtilsImpl();
+		assertTrue(authUtils.isReadAccess("read"));
+		assertTrue(authUtils.isWriteAccess("write"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerCoprocessorTest.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerCoprocessorTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerCoprocessorTest.java
new file mode 100644
index 0000000..15d4f93
--- /dev/null
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerCoprocessorTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.hbase;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+public class RangerCoprocessorTest {
+
+	@Test
+	public void test_canBeNewed() {
+		RangerAuthorizationCoprocessor _coprocessor = new RangerAuthorizationCoprocessor();
+		assertNotNull(_coprocessor);
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/TestPolicyEngine.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/TestPolicyEngine.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/TestPolicyEngine.java
new file mode 100644
index 0000000..ed6bcf0
--- /dev/null
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/TestPolicyEngine.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hbase;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.hadoop.hbase.security.AccessDeniedException;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.ranger.authorization.hbase.TestPolicyEngine.PolicyEngineTestCase.TestData;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+import org.apache.ranger.plugin.policyengine.RangerResource;
+import org.apache.ranger.plugin.policyengine.RangerResourceImpl;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+
+public class TestPolicyEngine {
+	static RangerPolicyEngineImpl policyEngine = null;
+	static Gson                   gsonBuilder  = null;
+
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws Exception {
+		policyEngine = new RangerPolicyEngineImpl();
+		gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z")
+									   .setPrettyPrinting()
+									   .registerTypeAdapter(RangerAccessRequest.class, new RangerAccessRequestDeserializer())
+									   .registerTypeAdapter(RangerResource.class,  new RangerResourceDeserializer())
+									   .create();
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Test
+	public void testPolicyEngine_hbase() {
+		String[] hbaseTestResourceFiles = { "/policyengine/test_policyengine_hbase.json" };
+
+		runTestsFromResourceFiles(hbaseTestResourceFiles);
+		
+		// lets use that policy engine now
+		AuthorizationSession session = new AuthorizationSession(policyEngine);
+		User user = mock(User.class);
+		when(user.getShortName()).thenReturn("user1");
+		when(user.getGroupNames()).thenReturn(new String[] { "users" });
+		session.access("read")
+			.user(user)
+			.table("finance")
+			.buildRequest()
+			.authorize();
+		assertTrue(session.isAuthorized());
+		try {
+			session.publishResults();
+		} catch (AccessDeniedException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		
+		when(user.getShortName()).thenReturn("user1");
+		when(user.getGroupNames()).thenReturn(new String[] { "users" });
+		session.access("write")
+			.buildRequest()
+			.authorize();
+		assertFalse(session.isAuthorized());
+		try {
+			session.publishResults();
+			fail("Should have throw exception on denied request!");
+		} catch (AccessDeniedException e) {
+		}
+		
+	}
+
+	private void runTestsFromResourceFiles(String[] resourceNames) {
+		for(String resourceName : resourceNames) {
+			InputStream       inStream = this.getClass().getResourceAsStream(resourceName);
+			InputStreamReader reader   = new InputStreamReader(inStream);
+
+			runTests(reader, resourceName);
+		}
+	}
+
+	private void runTests(InputStreamReader reader, String testName) {
+		try {
+			PolicyEngineTestCase testCase = gsonBuilder.fromJson(reader, PolicyEngineTestCase.class);
+
+			assertTrue("invalid input: " + testName, testCase != null && testCase.serviceDef != null && testCase.policies != null && testCase.tests != null);
+
+			policyEngine.setPolicies(testCase.serviceName, testCase.serviceDef, testCase.policies);
+			boolean justBuildingPolicyEngine = true;
+			if (justBuildingPolicyEngine) {
+				return;
+			} else {
+				for(TestData test : testCase.tests) {
+					RangerAccessResult expected = test.result;
+					RangerAccessResult result   = policyEngine.isAccessAllowed(test.request, null);
+	
+					assertNotNull(test.name, result);
+					assertEquals(test.name, expected.getIsAllowed(), result.getIsAllowed());
+				}
+			}
+		} catch(Throwable excp) {
+			excp.printStackTrace();
+		}
+		
+	}
+
+	static class PolicyEngineTestCase {
+		public String             serviceName;
+		public RangerServiceDef   serviceDef;
+		public List<RangerPolicy> policies;
+		public List<TestData>     tests;
+		
+		class TestData {
+			public String              name;
+			public RangerAccessRequest request;
+			public RangerAccessResult  result;
+		}
+	}
+	
+	static class RangerAccessRequestDeserializer implements JsonDeserializer<RangerAccessRequest> {
+		@Override
+		public RangerAccessRequest deserialize(JsonElement jsonObj, Type type,
+				JsonDeserializationContext context) throws JsonParseException {
+			return gsonBuilder.fromJson(jsonObj, RangerAccessRequestImpl.class);
+		}
+	}
+	
+	static class RangerResourceDeserializer implements JsonDeserializer<RangerResource> {
+		@Override
+		public RangerResource deserialize(JsonElement jsonObj, Type type,
+				JsonDeserializationContext context) throws JsonParseException {
+			return gsonBuilder.fromJson(jsonObj, RangerResourceImpl.class);
+		}
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/hbase-agent/src/test/resources/log4j.properties b/hbase-agent/src/test/resources/log4j.properties
new file mode 100644
index 0000000..71a8957
--- /dev/null
+++ b/hbase-agent/src/test/resources/log4j.properties
@@ -0,0 +1,16 @@
+# Define some default values that can be overridden by system properties
+ranger.root.logger=DEBUG,console
+# Define the root logger to the system property "hbase.root.logger".
+log4j.rootLogger=${ranger.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/46633a9e/hbase-agent/src/test/resources/policyengine/test_policyengine_hbase.json
----------------------------------------------------------------------
diff --git a/hbase-agent/src/test/resources/policyengine/test_policyengine_hbase.json b/hbase-agent/src/test/resources/policyengine/test_policyengine_hbase.json
new file mode 100644
index 0000000..f563c28
--- /dev/null
+++ b/hbase-agent/src/test/resources/policyengine/test_policyengine_hbase.json
@@ -0,0 +1,159 @@
+{
+  "serviceName":"hbasedev",
+
+  "serviceDef":{
+    "name":"hbase",
+    "id":2,
+    "resources":[
+      {"name":"table","level":1,"parent":"","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":"wildCard=true;ignoreCase=true","label":"HBase Table","description":"HBase Table"},
+      {"name":"column-family","level":2,"table":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":"wildCard=true;ignoreCase=true","label":"HBase Column-Family","description":"HBase Column-Family"},
+      {"name":"column","level":3,"parent":"column-family","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":"wildCard=true;ignoreCase=true","label":"HBase Column","description":"HBase Column"}
+    ],
+    "accessTypes":[
+      {"name":"read","label":"Read"},
+      {"name":"write","label":"Write"},
+      {"name":"create","label":"Create"},
+      {"name":"admin","label":"Admin","impliedGrants":["read","write","create"]}
+    ]
+  },
+
+  "policies":[
+    {"id":1,"name":"table=finance; column-family=restricted*: audit-all-access","isEnabled":true,"isAuditEnabled":true,
+     "resources":{"table":{"values":["finance"]},"column-family":{"values":["restricted*"]}},
+     "policyItems":[
+       {"accesses":[],"users":[],"groups":["public"],"delegateAdmin":false}
+     ]
+    }
+    ,
+    {"id":2,"name":"table=finance; column-family=restricted*","isEnabled":true,"isAuditEnabled":true,
+     "resources":{"table":{"values":["finance"]},"column-family":{"values":["restricted*"]}},
+     "policyItems":[
+       {"accesses":[{"type":"read","isAllowed":true},{"type":"write","isAllowed":true}],"users":[],"groups":["finance"],"delegateAdmin":false}
+       ,
+       {"accesses":[{"type":"admin","isAllowed":true}],"users":[],"groups":["finance-admin"],"delegateAdmin":true}
+     ]
+    }
+    ,
+    {"id":3,"name":"table=*; column-family=<excluding>restricted*","isEnabled":true,"isAuditEnabled":false,
+     "resources":{"table":{"values":["*"]},"column-family":{"values":["restricted*"],"isExcludes":true}},
+     "policyItems":[
+       {"accesses":[{"type":"read","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false}
+     ]
+    }
+  ],
+
+  "tests":[
+    {"name":"ALLOW 'scan finance restricted-cf;' for finance",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["read"],"user":"user1","userGroups":["users","finance"],"requestData":"scan finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"read":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"ALLOW 'put finance restricted-cf;' for finance",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["write"],"user":"user1","userGroups":["users","finance"],"requestData":"put finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"write":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"DENY 'create finance restricted-cf;' for finance",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["create"],"user":"user1","userGroups":["users","finance"],"requestData":"create finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"create":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"DENY 'grant finance restricted-cf;' for finance",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["admin"],"user":"user1","userGroups":["users","finance"],"requestData":"grant finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"admin":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"DENY 'scan finance restricted-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["read"],"user":"user1","userGroups":["users"],"requestData":"scan finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"read":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"DENY 'put finance restricted-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["write"],"user":"user1","userGroups":["users"],"requestData":"put finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"write":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"DENY 'create finance restricted-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["create"],"user":"user1","userGroups":["users"],"requestData":"create finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"create":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"DENY 'grant finance restricted-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["admin"],"user":"user1","userGroups":["users"],"requestData":"grant finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"admin":{"isAllowed":false,"isAudited":true,"policyId":-1}}}
+    }
+    ,
+    {"name":"ALLOW 'scan finance restricted-cf;' for finance-admin",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["read"],"user":"user1","userGroups":["users","finance-admin"],"requestData":"scan finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"read":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"ALLOW 'put finance restricted-cf;' for finance-admin",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["write"],"user":"user1","userGroups":["users","finance-admin"],"requestData":"put finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"write":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"ALLOW 'create finance restricted-cf;' for finance-admin",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["create"],"user":"user1","userGroups":["users","finance-admin"],"requestData":"create finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"create":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"ALLOW 'grant finance restricted-cf;' for finance-admin",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}},
+      "accessTypes":["admin"],"user":"user1","userGroups":["users","finance-admin"],"requestData":"grant finance restricted-cf"
+     },
+     "result":{"accessTypeResults":{"admin":{"isAllowed":true,"isAudited":true,"policyId":2}}}
+    }
+    ,
+    {"name":"ALLOW 'scan finance regular-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"regular-cf"}},
+      "accessTypes":["read"],"user":"user1","userGroups":["users"],"requestData":"scan finance regular-cf"
+     },
+     "result":{"accessTypeResults":{"read":{"isAllowed":true,"isAudited":false,"policyId":3}}}
+    }
+    ,
+    {"name":"DENY 'put finance regular-cf;' for user1",
+     "request":{
+      "resource":{"elements":{"table":"finance","column-family":"regular-cf"}},
+      "accessTypes":["write"],"user":"user1","userGroups":["users"],"requestData":"put finance regular-cf"
+     },
+     "result":{"accessTypeResults":{"write":{"isAllowed":false,"isAudited":false,"policyId":-1}}}
+    }
+  ]
+}
+


Mime
View raw message