blob: 1a039cb90b85562220dc05f45d74935853b08df7 [file] [log] [blame]
/*
* 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 com.xasecure.pdp.hbase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.access.Permission.Action;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.util.StringUtils;
import com.xasecure.authorization.hbase.HBaseAccessController;
import com.xasecure.pdp.constants.XaSecureConstants;
public class HBaseAuthDB implements HBaseAccessController {
private static final long MAX_CACHE_AUDIT_ENTRIES = 1000L ;
private static final long MAX_CACHE_ENCRYPT_ENTRIES = 1000L ;
private static final Log LOG = LogFactory.getLog(HBaseAuthDB.class) ;
private ArrayList<HBaseAuthRules> ruleList = null;
private ArrayList<HBaseAuthRules> globalList = null;
private ArrayList<HBaseAuthRules> tableList = null;
private ArrayList<String> auditList = null ;
private HashMap<byte[],Boolean> cachedAuditTable = new HashMap<byte[],Boolean>() ;
private ArrayList<String> encryptList = null ;
private HashSet<String> encryptTableList = null ;
private HashMap<byte[],Boolean> cachedEncryptedTable = new HashMap<byte[],Boolean>() ;
public HBaseAuthDB(ArrayList<HBaseAuthRules> ruleList, ArrayList<String> auditList, ArrayList<String> encryptList) {
if (LOG.isDebugEnabled()) {
LOG.debug("+Creating HBaseAuthDB is creating with ruleList [" + (ruleList == null ? 0 : ruleList.size()) + "]" );
}
this.auditList = auditList;
this.encryptList = encryptList;
this.ruleList = new ArrayList<HBaseAuthRules>() ;
this.globalList = new ArrayList<HBaseAuthRules>() ;
this.tableList = new ArrayList<HBaseAuthRules>() ;
for(HBaseAuthRules rule : ruleList ) {
if (rule.isGlobalRule()) {
this.globalList.add(rule) ;
if (LOG.isDebugEnabled()) {
LOG.debug("RULE:[" + rule + "] is being added as GLOBAL Policy");
}
}
else if (rule.isTableRule()) {
this.tableList.add(rule) ;
if (LOG.isDebugEnabled()) {
LOG.debug("RULE:[" + rule + "] is being added as Table Policy");
}
}
else {
this.ruleList.add(rule) ;
if (LOG.isDebugEnabled()) {
LOG.debug("RULE:[" + rule + "] is being added as non-global, non-table Policy");
}
}
}
this.encryptTableList = new HashSet<String>() ;
if (encryptList != null && encryptList.size() > 0) {
for(String encryptKey : encryptList) {
String[] objKeys = encryptKey.split("/") ;
String tableName = objKeys[0] ;
if (! encryptTableList.contains(tableName)) {
encryptTableList.add(tableName) ;
if (LOG.isDebugEnabled()) {
LOG.debug("EncryptionList:[" + tableName + "] is being added encrypted table.");
}
}
}
}
}
public boolean isAccessAllowed(User user, Action accessAction) {
String access = accessAction.toString().toLowerCase() ;
if (user == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(GLOBAL," + access + ") => [FALSE] as user passed for check was null.");
}
return false ;
}
String username = user.getShortName() ;
String[] groups = user.getGroupNames() ;
if (LOG.isDebugEnabled()) {
LOG.debug("Init of Global access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "]");
}
for (HBaseAuthRules rule : globalList) {
if (rule.getAccessType().equals(access)) {
String authorizedUser = rule.getUser() ;
String authorizedGroup = rule.getGroup();
if (authorizedGroup != null) {
if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true ;
}
for (String group : groups) {
if (group.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
if (authorizedUser != null) {
if (username.equals(authorizedUser)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
}
return false;
}
public boolean isAccessAllowed(User user, byte[] tableName, Action accessAction) {
if ( isAccessAllowed(user,accessAction)) { // Check Global Action
return true ;
}
String tableNameStr = Bytes.toString(tableName) ;
String access = accessAction.toString().toLowerCase() ;
if (user == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + tableNameStr + "," + access + ") => [FALSE] as user passed for check was null.");
}
return false ;
}
String username = user.getShortName() ;
String[] groups = user.getGroupNames() ;
if (LOG.isDebugEnabled()) {
LOG.debug("Init of Table access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "], tableName: [" + tableNameStr + "]");
}
for (HBaseAuthRules rule : tableList) {
if (rule.isTableNameMatched(tableNameStr)) {
if (rule.getAccessType().equals(access)) {
String authorizedUser = rule.getUser() ;
String authorizedGroup = rule.getGroup();
if (authorizedGroup != null) {
if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true ;
}
for (String group : groups) {
if (group.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
if (authorizedUser != null && username.equals(authorizedUser)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
}
return false;
}
public boolean isAccessAllowed(User user, byte[] tableName, byte[] columnFamily, byte[] qualifier, Action accessAction) {
String FQColName = getFullyQualifiedColumnName(tableName, columnFamily, qualifier) ;
String access = accessAction.toString().toLowerCase() ;
if (LOG.isDebugEnabled()) {
LOG.debug("isAccessAllowed on HBaseAuthDB: for FQColName [" + FQColName + "]");
}
if (user == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + FQColName + "," + access + ") => [FALSE] as as user passed for check was null.");
}
return false ;
}
if (isAccessAllowed(user, accessAction)) { // Check Global Action
return true ;
}
if (isAccessAllowed(user,tableName, accessAction)) { // Check Table Action
return true;
}
String username = user.getShortName() ;
String[] groups = user.getGroupNames() ;
if (LOG.isDebugEnabled()) {
LOG.debug("Init of Table access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "], FQColumnFamily: [" + FQColName + "]");
}
for (HBaseAuthRules rule : ruleList) {
if (rule.isMatched(FQColName)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Rule [" + rule + "] matched [" + FQColName + "]");
}
if (rule.getAccessType().equals(access)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Access [" + rule.getAccessType() + "] matched [" + access + "]");
}
String authorizedUser = rule.getUser() ;
String authorizedGroup = rule.getGroup();
if (authorizedGroup != null) {
if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true ;
}
for (String group : groups) {
if (group.equals(authorizedGroup)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
if (authorizedUser != null) {
if (username.equals(authorizedUser)) {
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
}
return true;
}
}
}
else {
if (LOG.isDebugEnabled()) {
LOG.debug("Access [" + rule.getAccessType() + "] DID NOT match [" + access + "]");
}
}
}
else {
if (LOG.isDebugEnabled()) {
LOG.debug("Rule [" + rule + "] not matched [" + FQColName + "]");
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
}
return false;
}
public boolean isEncrypted(byte[] tableName, byte[] columnFamily, byte[] qualifier) {
String colName = getFullyQualifiedColumnName(tableName, columnFamily, qualifier) ;
for(String encryptable : encryptList) {
if (FilenameUtils.wildcardMatch(colName,encryptable)) {
return true ;
}
}
return false;
}
public boolean isAudited(byte[] tableName) {
Boolean ret = cachedAuditTable.get(tableName) ;
if (ret == null) {
ret = isAuditedFromTableList(tableName) ;
synchronized(cachedAuditTable) {
if (cachedAuditTable.size() > MAX_CACHE_AUDIT_ENTRIES) {
cachedAuditTable.clear();
}
cachedAuditTable.put(tableName,ret) ;
}
}
return ret.booleanValue();
}
private boolean isAuditedFromTableList(byte[] tableName) {
boolean ret = false ;
String tableNameStr = Bytes.toString(tableName) ;
for(String auditable : auditList) {
if (FilenameUtils.wildcardMatch(tableNameStr,auditable)) {
ret = true ;
break ;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("isAudited(" + tableNameStr + "):" + ret) ;
}
return ret;
}
public boolean isTableHasEncryptedColumn(byte[] tableName) {
Boolean ret = cachedEncryptedTable.get(tableName) ;
if (ret == null) {
ret = isTableHasEncryptedColumnFromTableList(tableName) ;
synchronized(cachedEncryptedTable) {
if (cachedEncryptedTable.size() > MAX_CACHE_ENCRYPT_ENTRIES) {
cachedEncryptedTable.clear();
}
cachedEncryptedTable.put(tableName, ret) ;
}
}
return ret.booleanValue() ;
}
private boolean isTableHasEncryptedColumnFromTableList(byte[] tableName)
{
boolean ret = false ;
String tableNameStr = Bytes.toString(tableName) ;
for(String encryptTable : encryptTableList) {
ret = FilenameUtils.wildcardMatch(tableNameStr, encryptTable) ;
if (ret) {
break ;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("isTableHasEncryptedColumn(" + tableNameStr + "):" + ret);
}
return ret ;
}
public static String getFullyQualifiedColumnName(byte[] tableName, byte[] columnFamily, byte[] qualifier) {
StringBuilder sb = new StringBuilder() ;
sb.append(((tableName != null && tableName.length > 0) ? Bytes.toString(tableName) : "*"))
.append("/")
.append(((columnFamily != null && columnFamily.length > 0) ? Bytes.toString(columnFamily) : "*"))
.append("/")
.append(((qualifier != null && qualifier.length > 0) ? Bytes.toString(qualifier) : "*")) ;
return sb.toString() ;
}
public List<UserPermission> getUserPermissions(User user) {
List<UserPermission> ret = new ArrayList<UserPermission>() ;
if (user != null) {
ArrayList<ArrayList<HBaseAuthRules>> allList = new ArrayList<ArrayList<HBaseAuthRules>>();
allList.add(globalList) ;
allList.add(tableList) ;
allList.add(ruleList) ;
for(ArrayList<HBaseAuthRules> rList : allList) {
for(HBaseAuthRules rule : rList) {
UserPermission perm = rule.getUserPermission(user) ;
if (perm != null) {
ret.add(perm) ;
}
}
}
}
return ret ;
}
public List<UserPermission> getUserPermissions(User user, byte[] tableName) {
String tableNameStr = Bytes.toString(tableName) ;
List<UserPermission> ret = new ArrayList<UserPermission>() ;
if (user != null) {
ArrayList<ArrayList<HBaseAuthRules>> allList = new ArrayList<ArrayList<HBaseAuthRules>>();
allList.add(globalList) ;
allList.add(tableList) ;
allList.add(ruleList) ;
for(ArrayList<HBaseAuthRules> rList : allList) {
for(HBaseAuthRules rule : rList) {
if (rule.isTableNameMatched(tableNameStr)) {
UserPermission perm = rule.getUserPermission(user) ;
if (perm != null) {
ret.add(perm) ;
}
}
}
}
}
return ret ;
}
}