blob: 6cd8634a5d6c4e0658952586151c1cb7842db61c [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 org.apache.ranger.biz;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.log4j.Logger;
import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
import org.apache.ranger.common.AppConstants;
import org.apache.ranger.common.ContextUtil;
import org.apache.ranger.common.GUIDUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerConstants;
import org.apache.ranger.common.StringUtil;
import org.apache.ranger.common.UserSessionBase;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.db.XXDBBaseDao;
import org.apache.ranger.entity.XXAsset;
import org.apache.ranger.entity.XXDBBase;
import org.apache.ranger.entity.XXGroup;
import org.apache.ranger.entity.XXPermMap;
import org.apache.ranger.entity.XXPortalUser;
import org.apache.ranger.entity.XXResource;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.entity.XXUser;
import org.apache.ranger.plugin.model.RangerBaseModelObject;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.view.VXPortalUser;
import org.apache.ranger.view.VXResource;
import org.apache.ranger.view.VXResponse;
import org.apache.ranger.view.VXString;
import org.apache.ranger.view.VXStringList;
import org.apache.ranger.view.VXUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RangerBizUtil {
private static final Logger logger = Logger.getLogger(RangerBizUtil.class);
@Autowired
RESTErrorUtil restErrorUtil;
@Autowired
RangerDaoManager daoManager;
@Autowired
StringUtil stringUtil;
@Autowired
UserMgr userMgr;
@Autowired
GUIDUtil guidUtil;
Set<Class<?>> groupEditableClasses;
private Class<?>[] groupEditableClassesList = {};
private int maxFirstNameLength;
int maxDisplayNameLength = 150;
public final String EMPTY_CONTENT_DISPLAY_NAME = "...";
boolean enableResourceAccessControl;
private SecureRandom random;
private static final String PATH_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst0123456789-_.";
private static char[] PATH_CHAR_SET = PATH_CHARS.toCharArray();
private static int PATH_CHAR_SET_LEN = PATH_CHAR_SET.length;
public static final String AUDIT_STORE_RDBMS = "DB";
public static final String AUDIT_STORE_SOLR = "solr";
public static final boolean batchClearEnabled = PropertiesUtil.getBooleanProperty("ranger.jpa.jdbc.batch-clear.enable", true);
public static final int batchSize = PropertiesUtil.getIntProperty("ranger.jpa.jdbc.batch-clear.size", 10);
String auditDBType = AUDIT_STORE_RDBMS;
private final boolean allowUnauthenticatedAccessInSecureEnvironment;
static String fileSeparator = PropertiesUtil.getProperty("ranger.file.separator", "/");
public RangerBizUtil() {
RangerAdminConfig config = new RangerAdminConfig();
allowUnauthenticatedAccessInSecureEnvironment = config.getBoolean("ranger.admin.allow.unauthenticated.access", false);
maxFirstNameLength = Integer.parseInt(PropertiesUtil.getProperty("ranger.user.firstname.maxlength", "16"));
maxDisplayNameLength = PropertiesUtil.getIntProperty("ranger.bookmark.name.maxlen", maxDisplayNameLength);
groupEditableClasses = new HashSet<Class<?>>(
Arrays.asList(groupEditableClassesList));
enableResourceAccessControl = PropertiesUtil.getBooleanProperty("ranger.resource.accessControl.enabled", true);
auditDBType = PropertiesUtil.getProperty("ranger.audit.source.type",
auditDBType).toLowerCase();
logger.info("java.library.path is " + System.getProperty("java.library.path"));
logger.info("Audit datasource is " + auditDBType);
random = new SecureRandom();
}
// Access control methods
public void checkSystemAdminAccess() {
UserSessionBase currentUserSession = ContextUtil
.getCurrentUserSession();
if (currentUserSession != null && currentUserSession.isUserAdmin()) {
return;
}
throw restErrorUtil
.create403RESTException("Only System Administrators can add accounts");
}
/**
* @param userProfile
* @return
*/
public String generatePublicName(VXPortalUser userProfile,
XXPortalUser gjUser) {
return generatePublicName(userProfile.getFirstName(),
userProfile.getLastName());
}
public String generatePublicName(String firstName, String lastName) {
String publicName = null;
String fName = firstName;
if (firstName.length() > maxFirstNameLength) {
fName = firstName.substring(0, maxFirstNameLength - (1 + 3))
+ "...";
}
if (lastName != null && lastName.length() > 0) {
publicName = fName + " " + lastName.substring(0, 1) + ".";
}
return publicName;
}
public VXStringList mapStringListToVStringList(List<String> stringList) {
if (stringList == null) {
return null;
}
List<VXString> vStringList = new ArrayList<VXString>();
for (String str : stringList) {
VXString vXString = new VXString();
vXString.setValue(str);
vStringList.add(vXString);
}
return new VXStringList(vStringList);
}
/**
* return response object if users is having permission on given resource
*
* @param vXResource
* @param permission
* @return
*/
public VXResponse hasPermission(VXResource vXResource, int permission) {
VXResponse vXResponse = new VXResponse();
if (!enableResourceAccessControl) {
logger.debug("Resource Access Control is disabled !!!");
return vXResponse;
}
if (vXResource == null) {
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
vXResponse.setMsgDesc("Please provide valid policy.");
return vXResponse;
}
String resourceNames = vXResource.getName();
if (stringUtil.isEmpty(resourceNames)) {
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
vXResponse.setMsgDesc("Please provide valid policy.");
return vXResponse;
}
if (isAdmin()) {
return vXResponse;
}
Long xUserId = getXUserId();
Long assetId = vXResource.getAssetId();
List<XXResource> xResourceList = daoManager.getXXResource()
.findByAssetIdAndResourceStatus(assetId,
AppConstants.STATUS_ENABLED);
XXAsset xAsset = daoManager.getXXAsset().getById(assetId);
int assetType = xAsset.getAssetType();
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
vXResponse.setMsgDesc("Permission Denied !");
if (assetType == AppConstants.ASSET_HIVE) {
String[] requestResNameList = resourceNames.split(",");
if (stringUtil.isEmpty(vXResource.getUdfs())) {
int reqTableType = vXResource.getTableType();
int reqColumnType = vXResource.getColumnType();
for (String resourceName : requestResNameList) {
boolean matchFound = matchHivePolicy(resourceName,
xResourceList, xUserId, permission, reqTableType,
reqColumnType, false);
if (!matchFound) {
vXResponse
.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : "
+ resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
} else {
for (String resourceName : requestResNameList) {
boolean matchFound = matchHivePolicy(resourceName,
xResourceList, xUserId, permission);
if (!matchFound) {
vXResponse
.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : "
+ resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
}
vXResponse.setStatusCode(VXResponse.STATUS_SUCCESS);
return vXResponse;
} else if (assetType == AppConstants.ASSET_HBASE) {
String[] requestResNameList = resourceNames.split(",");
for (String resourceName : requestResNameList) {
boolean matchFound = matchHbasePolicy(resourceName,
xResourceList, vXResponse, xUserId, permission);
if (!matchFound) {
vXResponse.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : " + resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
vXResponse.setStatusCode(VXResponse.STATUS_SUCCESS);
return vXResponse;
} else if (assetType == AppConstants.ASSET_HDFS) {
String[] requestResNameList = resourceNames.split(",");
for (String resourceName : requestResNameList) {
boolean matchFound = matchHdfsPolicy(resourceName,
xResourceList, xUserId, permission);
if (!matchFound) {
vXResponse.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : " + resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
vXResponse.setStatusCode(VXResponse.STATUS_SUCCESS);
return vXResponse;
} else if (assetType == AppConstants.ASSET_KNOX) {
String[] requestResNameList = resourceNames.split(",");
for (String resourceName : requestResNameList) {
boolean matchFound = matchKnoxPolicy(resourceName,
xResourceList, xUserId, permission);
if (!matchFound) {
vXResponse.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : " + resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
vXResponse.setStatusCode(VXResponse.STATUS_SUCCESS);
return vXResponse;
} else if (assetType == AppConstants.ASSET_STORM) {
String[] requestResNameList = resourceNames.split(",");
for (String resourceName : requestResNameList) {
boolean matchFound = matchStormPolicy(resourceName,
xResourceList, xUserId, permission);
if (!matchFound) {
vXResponse.setMsgDesc("You're not permitted to perform "
+ "the action for resource path : " + resourceName);
vXResponse.setStatusCode(VXResponse.STATUS_ERROR);
return vXResponse;
}
}
vXResponse.setStatusCode(VXResponse.STATUS_SUCCESS);
return vXResponse;
}
return vXResponse;
}
/**
* return true id current logged in session is owned by admin
*
* @return
*/
public boolean isAdmin() {
UserSessionBase currentUserSession = ContextUtil
.getCurrentUserSession();
if (currentUserSession == null) {
logger.debug("Unable to find session.");
return false;
}
if (currentUserSession.isUserAdmin()) {
return true;
}
return false;
}
public boolean isAuditAdmin() {
UserSessionBase currentUserSession = ContextUtil
.getCurrentUserSession();
if (currentUserSession == null) {
logger.debug("Unable to find session.");
return false;
}
if (currentUserSession.isAuditUserAdmin()) {
return true;
}
return false;
}
/**
* return username of currently logged in user
*
* @return
*/
public String getCurrentUserLoginId() {
String ret = null;
UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
if (currentUserSession != null) {
ret = currentUserSession.getLoginId();
}
return ret;
}
/**
* returns current user's userID from active user sessions
*
* @return
*/
public Long getXUserId() {
UserSessionBase currentUserSession = ContextUtil
.getCurrentUserSession();
if (currentUserSession == null) {
logger.debug("Unable to find session.");
return null;
}
XXPortalUser user = daoManager.getXXPortalUser().getById(
currentUserSession.getUserId());
if (user == null) {
logger.debug("XXPortalUser not found with logged in user id : "
+ currentUserSession.getUserId());
return null;
}
XXUser xUser = daoManager.getXXUser().findByUserName(user.getLoginId());
if (xUser == null) {
logger.debug("XXPortalUser not found for user id :" + user.getId()
+ " with name " + user.getFirstName());
return null;
}
return xUser.getId();
}
/**
* returns true if user is having required permission on given Hdfs resource
*
* @param resourceName
* @param xResourceList
* @param xUserId
* @param permission
* @return
*/
private boolean matchHdfsPolicy(String resourceName,
List<XXResource> xResourceList, Long xUserId, int permission) {
boolean matchFound = false;
resourceName = replaceMetaChars(resourceName);
for (XXResource xResource : xResourceList) {
if (xResource.getResourceStatus() != AppConstants.STATUS_ENABLED) {
continue;
}
Long resourceId = xResource.getId();
matchFound = checkUsrPermForPolicy(xUserId, permission, resourceId);
if (matchFound) {
matchFound = false;
String resource = xResource.getName();
String[] dbResourceNameList = resource.split(",");
for (String dbResourceName : dbResourceNameList) {
if (comparePathsForExactMatch(resourceName, dbResourceName)) {
matchFound = true;
} else {
if (xResource.getIsRecursive() == AppConstants.BOOL_TRUE) {
matchFound = isRecursiveWildCardMatch(resourceName,
dbResourceName);
} else {
matchFound = nonRecursiveWildCardMatch(
resourceName, dbResourceName);
}
}
if (matchFound) {
break;
}
}
if (matchFound) {
break;
}
}
}
return matchFound;
}
public void failUnauthenticatedIfNotAllowed() throws Exception {
if (UserGroupInformation.isSecurityEnabled()) {
UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
if (currentUserSession == null) {
if (!allowUnauthenticatedAccessInSecureEnvironment) {
throw new Exception("Unauthenticated access not allowed");
}
}
}
}
/**
* returns true if user is having required permission on given Hbase
* resource
*
* @param resourceName
* @param xResourceList
* @param vXResponse
* @param xUserId
* @param permission
* @return
*/
public boolean matchHbasePolicy(String resourceName,
List<XXResource> xResourceList, VXResponse vXResponse,
Long xUserId, int permission) {
if (stringUtil.isEmpty(resourceName) || xResourceList == null
|| xUserId == null) {
return false;
}
String[] splittedResources = stringUtil.split(resourceName,
fileSeparator);
if (splittedResources.length < 1 || splittedResources.length > 3) {
logger.debug("Invalid resourceName name : " + resourceName);
return false;
}
String tblName = splittedResources.length > 0 ? splittedResources[0]
: StringUtil.WILDCARD_ASTERISK;
String colFamName = splittedResources.length > 1 ? splittedResources[1]
: StringUtil.WILDCARD_ASTERISK;
String colName = splittedResources.length > 2 ? splittedResources[2]
: StringUtil.WILDCARD_ASTERISK;
boolean policyMatched = false;
// check all resources whether Hbase policy is enabled in any resource
// of provided resource list
for (XXResource xResource : xResourceList) {
if (xResource.getResourceStatus() != AppConstants.STATUS_ENABLED) {
continue;
}
Long resourceId = xResource.getId();
boolean hasPermission = checkUsrPermForPolicy(xUserId, permission,
resourceId);
// if permission is enabled then load Tables,column family and
// columns list from resource
if (!hasPermission) {
continue;
}
// 1. does the policy match the table?
String[] xTables = stringUtil.isEmpty(xResource.getTables()) ? null
: stringUtil.split(xResource.getTables(), ",");
boolean matchFound = (xTables == null || xTables.length == 0) || matchPath(tblName, xTables);
if (matchFound) {
// 2. does the policy match the column?
String[] xColumnFamilies = stringUtil.isEmpty(xResource
.getColumnFamilies()) ? null : stringUtil.split(
xResource.getColumnFamilies(), ",");
matchFound = (xColumnFamilies == null || xColumnFamilies.length == 0)
|| matchPath(colFamName, xColumnFamilies);
if (matchFound) {
// 3. does the policy match the columnFamily?
String[] xColumns = stringUtil.isEmpty(xResource
.getColumns()) ? null : stringUtil.split(
xResource.getColumns(), ",");
matchFound = (xColumns == null || xColumns.length == 0)
|| matchPath(colName, xColumns);
}
}
if (matchFound) {
policyMatched = true;
break;
}
}
return policyMatched;
}
public boolean matchHivePolicy(String resourceName,
List<XXResource> xResourceList, Long xUserId, int permission) {
return matchHivePolicy(resourceName, xResourceList, xUserId,
permission, 0, 0, true);
}
/**
* returns true if user is having required permission on given Hive resource
*
* @param resourceName
* @param xResourceList
* @param xUserId
* @param permission
* @param reqTableType
* @param reqColumnType
* @param isUdfPolicy
* @return
*/
public boolean matchHivePolicy(String resourceName,
List<XXResource> xResourceList, Long xUserId, int permission,
int reqTableType, int reqColumnType, boolean isUdfPolicy) {
if (stringUtil.isEmpty(resourceName) || xResourceList == null
|| xUserId == null) {
return false;
}
String[] splittedResources = stringUtil.split(resourceName,
fileSeparator);// get list of resources
if (splittedResources.length < 1 || splittedResources.length > 3) {
logger.debug("Invalid resource name : " + resourceName);
return false;
}
String dbName = splittedResources.length > 0 ? splittedResources[0]
: StringUtil.WILDCARD_ASTERISK;
String tblName = splittedResources.length > 1 ? splittedResources[1]
: StringUtil.WILDCARD_ASTERISK;
String colName = splittedResources.length > 2 ? splittedResources[2]
: StringUtil.WILDCARD_ASTERISK;
boolean policyMatched = false;
for (XXResource xResource : xResourceList) {
if (xResource.getResourceStatus() != AppConstants.STATUS_ENABLED) {
continue;
}
Long resourceId = xResource.getId();
boolean hasPermission = checkUsrPermForPolicy(xUserId, permission,
resourceId);
if (!hasPermission) {
continue;
}
// 1. does the policy match the database?
String[] xDatabases = stringUtil.isEmpty(xResource.getDatabases()) ? null
: stringUtil.split(xResource.getDatabases(), ",");
boolean matchFound = (xDatabases == null || xDatabases.length == 0)
|| matchPath(dbName, xDatabases);
if (!matchFound) {
continue;
}
// Type(either UDFs policy or non-UDFs policy) of current policy
// should be of same as type of policy being iterated
if (!stringUtil.isEmpty(xResource.getUdfs()) && !isUdfPolicy) {
continue;
}
if (isUdfPolicy) {
// 2. does the policy match the UDF?
String[] xUdfs = stringUtil.isEmpty(xResource.getUdfs()) ? null
: stringUtil.split(xResource.getUdfs(), ",");
if (!matchPath(tblName, xUdfs)) {
continue;
} else {
policyMatched = true;
break;
}
} else {
// 2. does the policy match the table?
String[] xTables = stringUtil.isEmpty(xResource.getTables()) ? null
: stringUtil.split(xResource.getTables(), ",");
matchFound = (xTables == null || xTables.length == 0)
|| matchPath(tblName, xTables);
if (xResource.getTableType() == AppConstants.POLICY_EXCLUSION) {
matchFound = !matchFound;
}
if (!matchFound) {
continue;
}
// 3. does current policy match the column?
String[] xColumns = stringUtil.isEmpty(xResource.getColumns()) ? null
: stringUtil.split(xResource.getColumns(), ",");
matchFound = (xColumns == null || xColumns.length == 0)
|| matchPath(colName, xColumns);
if (xResource.getColumnType() == AppConstants.POLICY_EXCLUSION) {
matchFound = !matchFound;
}
if (!matchFound) {
continue;
} else {
policyMatched = true;
break;
}
}
}
return policyMatched;
}
/**
* returns true if user is having required permission on given Hbase
* resource
*
* @param resourceName
* @param xResourceList
* @param xUserId
* @param permission
* @return
*/
private boolean matchKnoxPolicy(String resourceName,
List<XXResource> xResourceList,
Long xUserId, int permission) {
String[] splittedResources = stringUtil.split(resourceName,
fileSeparator);
int numberOfResources = splittedResources.length;
if (numberOfResources < 1 || numberOfResources > 3) {
logger.debug("Invalid policy name : " + resourceName);
return false;
}
boolean policyMatched = false;
// check all resources whether Knox policy is enabled in any resource
// of provided resource list
for (XXResource xResource : xResourceList) {
if (xResource.getResourceStatus() != AppConstants.STATUS_ENABLED) {
continue;
}
Long resourceId = xResource.getId();
boolean hasPermission = checkUsrPermForPolicy(xUserId, permission,
resourceId);
// if permission is enabled then load Topologies,services list from
// resource
if (hasPermission) {
String[] xTopologies = (xResource.getTopologies() == null || "".equalsIgnoreCase(xResource
.getTopologies())) ? null
: stringUtil.split(xResource.getTopologies(), ",");
String[] xServices = (xResource.getServices() == null || "".equalsIgnoreCase(xResource
.getServices())) ? null
: stringUtil.split(xResource.getServices(), ",");
boolean matchFound = false;
for (int index = 0; index < numberOfResources; index++) {
matchFound = false;
// check whether given table resource matches with any
// existing topology resource
if (index == 0) {
if (xTopologies != null) {
for (String xTopology : xTopologies) {
if (matchPath(splittedResources[index],
xTopology)) {
matchFound = true;
continue;
}
}
}
if (!matchFound) {
break;
}
} // check whether given service resource matches with
// any existing service resource
else if (index == 1) {
if (xServices != null) {
for (String xService : xServices) {
if (matchPath(splittedResources[index],
xService)) {
matchFound = true;
continue;
}
}
}
if (!matchFound) {
break;
}
}
}
if (matchFound) {
policyMatched = true;
break;
}
}
}
return policyMatched;
}
/**
* returns true if user is having required permission on given STORM
* resource
*
* @param resourceName
* @param xResourceList
* @param xUserId
* @param permission
* @return
*/
private boolean matchStormPolicy(String resourceName,
List<XXResource> xResourceList,
Long xUserId, int permission) {
String[] splittedResources = stringUtil.split(resourceName,
fileSeparator);
int numberOfResources = splittedResources.length;
if (numberOfResources < 1 || numberOfResources > 3) {
logger.debug("Invalid policy name : " + resourceName);
return false;
}
boolean policyMatched = false;
// check all resources whether Knox policy is enabled in any resource
// of provided resource list
for (XXResource xResource : xResourceList) {
if (xResource.getResourceStatus() != AppConstants.STATUS_ENABLED) {
continue;
}
Long resourceId = xResource.getId();
boolean hasPermission = checkUsrPermForPolicy(xUserId, permission,
resourceId);
// if permission is enabled then load Topologies,services list from
// resource
if (hasPermission) {
String[] xTopologies = (xResource.getTopologies() == null || "".equalsIgnoreCase(xResource
.getTopologies())) ? null
: stringUtil.split(xResource.getTopologies(), ",");
/*
* String[] xServices = (xResource.getServices() == null ||
* xResource .getServices().equalsIgnoreCase("")) ? null :
* stringUtil.split(xResource.getServices(), ",");
*/
boolean matchFound = false;
for (int index = 0; index < numberOfResources; index++) {
matchFound = false;
// check whether given table resource matches with any
// existing topology resource
if (index == 0) {
if (xTopologies != null) {
for (String xTopology : xTopologies) {
if (matchPath(splittedResources[index],
xTopology)) {
matchFound = true;
continue;
}
}
}
} // check whether given service resource matches with
// any existing service resource
/*
* else if (index == 1) { if(xServices!=null){ for (String
* xService : xServices) { if
* (matchPath(splittedResources[index], xService)) {
* matchFound = true; continue; } } } }
*/
}
if (matchFound) {
policyMatched = true;
break;
}
}
}
return policyMatched;
}
/**
* returns path without meta characters
*
* @param path
* @return
*/
public String replaceMetaChars(String path) {
if (path == null || path.isEmpty()) {
return path;
}
if (path.contains("*")) {
String replacement = getRandomString(5, 60);
path = path.replaceAll("\\*", replacement);
}
if (path.contains("?")) {
String replacement = getRandomString(1, 1);
path = path.replaceAll("\\?", replacement);
}
return path;
}
/**
* returns random String of given length range
*
* @param minLen
* @param maxLen
* @return
*/
private String getRandomString(int minLen, int maxLen) {
StringBuilder sb = new StringBuilder();
int len = getRandomInt(minLen, maxLen);
for (int i = 0; i < len; i++) {
int charIdx = random.nextInt(PATH_CHAR_SET_LEN);
sb.append(PATH_CHAR_SET[charIdx]);
}
return sb.toString();
}
/**
* return random integer number for given range
*
* @param min
* @param max
* @return
*/
private int getRandomInt(int min, int max) {
if (min == max) {
return min;
} else {
int interval = max - min;
int randomNum = random.nextInt();
if(randomNum<0){
randomNum=Math.abs(randomNum);
}
return ((randomNum % interval) + min);
}
}
/**
* returns true if given userID is having specified permission on specified
* resource
*
* @param xUserId
* @param permission
* @param resourceId
* @return
*/
private boolean checkUsrPermForPolicy(Long xUserId, int permission,
Long resourceId) {
// this snippet load user groups and permission map list from DB
List<XXGroup> userGroups = new ArrayList<XXGroup>();
List<XXPermMap> permMapList = new ArrayList<XXPermMap>();
userGroups = daoManager.getXXGroup().findByUserId(xUserId);
permMapList = daoManager.getXXPermMap().findByResourceId(resourceId);
Long publicGroupId = getPublicGroupId();
boolean matchFound = false;
for (XXPermMap permMap : permMapList) {
if (permMap.getPermType() == permission) {
if (permMap.getPermFor() == AppConstants.XA_PERM_FOR_GROUP) {
// check whether permission is enabled for public group or a
// group to which user belongs
matchFound = (publicGroupId != null && publicGroupId == permMap
.getGroupId())
|| isGroupInList(permMap.getGroupId(), userGroups);
} else if (permMap.getPermFor() == AppConstants.XA_PERM_FOR_USER) {
// check whether permission is enabled to user
matchFound = permMap.getUserId().equals(xUserId);
}
}
if (matchFound) {
break;
}
}
return matchFound;
}
public Long getPublicGroupId() {
XXGroup xXGroupPublic = daoManager.getXXGroup().findByGroupName(
RangerConstants.GROUP_PUBLIC);
return xXGroupPublic != null ? xXGroupPublic.getId() : null;
}
/**
* returns true is given group id is in given group list
*
* @param groupId
* @param xGroupList
* @return
*/
public boolean isGroupInList(Long groupId, List<XXGroup> xGroupList) {
for (XXGroup xGroup : xGroupList) {
if (xGroup.getId().equals(groupId)) {
return true;
}
}
return false;
}
/**
* returns true if given path matches in same level or sub directories with
* given wild card pattern
*
* @param pathToCheck
* @param wildcardPath
* @return
*/
public boolean isRecursiveWildCardMatch(String pathToCheck,
String wildcardPath) {
if (pathToCheck != null) {
if (wildcardPath != null && wildcardPath.equals(fileSeparator)) {
return true;
}
StringBuilder sb = new StringBuilder();
for (String p : pathToCheck.split(fileSeparator)) {
sb.append(p);
boolean matchFound = FilenameUtils.wildcardMatch(sb.toString(),
wildcardPath);
if (matchFound) {
return true;
}
sb.append(fileSeparator);
}
sb = null;
}
return false;
}
/**
* return List<Integer>
*
* List of all possible parent return type for some specific resourceType
*
* @param resourceType
* , assetType
*
*/
public List<Integer> getResorceTypeParentHirearchy(int resourceType,
int assetType) {
List<Integer> resourceTypeList = new ArrayList<Integer>();
if (assetType == AppConstants.ASSET_HDFS) {
resourceTypeList.add(AppConstants.RESOURCE_PATH);
} else if (assetType == AppConstants.ASSET_HIVE) {
resourceTypeList.add(AppConstants.RESOURCE_DB);
if (resourceType == AppConstants.RESOURCE_TABLE) {
resourceTypeList.add(AppConstants.RESOURCE_TABLE);
} else if (resourceType == AppConstants.RESOURCE_UDF) {
resourceTypeList.add(AppConstants.RESOURCE_UDF);
} else if (resourceType == AppConstants.RESOURCE_COLUMN) {
resourceTypeList.add(AppConstants.RESOURCE_TABLE);
resourceTypeList.add(AppConstants.RESOURCE_COLUMN);
}
} else if (assetType == AppConstants.ASSET_HBASE) {
resourceTypeList.add(AppConstants.RESOURCE_TABLE);
if (resourceType == AppConstants.RESOURCE_COL_FAM) {
resourceTypeList.add(AppConstants.RESOURCE_COL_FAM);
} else if (resourceType == AppConstants.RESOURCE_COLUMN) {
resourceTypeList.add(AppConstants.RESOURCE_COL_FAM);
resourceTypeList.add(AppConstants.RESOURCE_COLUMN);
}
}
return resourceTypeList;
}
/**
* return true if both path matches exactly, wild card matching is not
* checked
*
* @param path1
* @param path2
* @return
*/
public boolean comparePathsForExactMatch(String path1, String path2) {
String pathSeparator = fileSeparator;
if (!path1.endsWith(pathSeparator)) {
path1 = path1.concat(pathSeparator);
}
if (!path2.endsWith(pathSeparator)) {
path2 = path2.concat(pathSeparator);
}
return path1.equalsIgnoreCase(path2);
}
/**
* return true if both path matches at same level path, this function does
* not match sub directories
*
* @param pathToCheck
* @param wildcardPath
* @return
*/
public boolean nonRecursiveWildCardMatch(String pathToCheck,
String wildcardPath) {
if (pathToCheck != null && wildcardPath != null) {
List<String> pathToCheckArray = new ArrayList<String>();
List<String> wildcardPathArray = new ArrayList<String>();
Collections.addAll(pathToCheckArray, pathToCheck.split(fileSeparator));
Collections.addAll(wildcardPathArray, wildcardPath.split(fileSeparator));
if (pathToCheckArray.size() == wildcardPathArray.size()) {
boolean match = false;
for (int index = 0; index < pathToCheckArray.size(); index++) {
match = matchPath(pathToCheckArray.get(index),
wildcardPathArray.get(index));
if (!match)
return match;
}
return match;
}
}
return false;
}
/**
* returns true if first and second path are same
*
* @param pathToCheckFragment
* @param wildCardPathFragment
* @return
*/
private boolean matchPath(String pathToCheckFragment,
String wildCardPathFragment) {
if (pathToCheckFragment == null || wildCardPathFragment == null) {
return false;
}
if (pathToCheckFragment.contains("*")
|| pathToCheckFragment.contains("?")) {
pathToCheckFragment = replaceMetaChars(pathToCheckFragment);
if (wildCardPathFragment.contains("*")
|| wildCardPathFragment.contains("?")) {
return FilenameUtils.wildcardMatch(pathToCheckFragment,
wildCardPathFragment, IOCase.SENSITIVE);
} else {
return false;
}
} else {
if (wildCardPathFragment.contains("*")
|| wildCardPathFragment.contains("?")) {
return FilenameUtils.wildcardMatch(pathToCheckFragment,
wildCardPathFragment, IOCase.SENSITIVE);
} else {
return pathToCheckFragment.trim().equals(
wildCardPathFragment.trim());
}
}
}
private boolean matchPath(String pathToCheck, String[] wildCardPaths) {
if (pathToCheck != null && wildCardPaths != null) {
for (String wildCardPath : wildCardPaths) {
if (matchPath(pathToCheck, wildCardPath)) {
return true;
}
}
}
return false;
}
/**
* This method returns true if first parameter value is equal to others
* argument value passed
*
* @param checkValue
* @param otherValues
* @return
*/
public static boolean areAllEqual(int checkValue, int... otherValues) {
for (int value : otherValues) {
if (value != checkValue) {
return false;
}
}
return true;
}
public void createTrxLog(List<XXTrxLog> trxLogList) {
if (trxLogList == null) {
return;
}
UserSessionBase usb = ContextUtil.getCurrentUserSession();
Long authSessionId = null;
if (usb != null) {
authSessionId = ContextUtil.getCurrentUserSession().getSessionId();
}
if(guidUtil != null){
Long trxId = guidUtil.genLong();
for (XXTrxLog xTrxLog : trxLogList) {
if (xTrxLog != null) {
if ("Password".equalsIgnoreCase(StringUtil.trim(xTrxLog.getAttributeName()))) {
if (xTrxLog.getPreviousValue() != null
&& !xTrxLog.getPreviousValue().trim().isEmpty()
&& !"null".equalsIgnoreCase(xTrxLog
.getPreviousValue().trim())) {
xTrxLog.setPreviousValue(AppConstants.Masked_String);
}
if (xTrxLog.getNewValue() != null
&& !xTrxLog.getNewValue().trim().isEmpty()
&& !"null".equalsIgnoreCase(xTrxLog.getNewValue()
.trim())) {
xTrxLog.setNewValue(AppConstants.Masked_String);
}
}
xTrxLog.setTransactionId(trxId.toString());
if (authSessionId != null) {
xTrxLog.setSessionId("" + authSessionId);
}
xTrxLog.setSessionType("Spring Authenticated Session");
xTrxLog.setRequestId(trxId.toString());
daoManager.getXXTrxLog().create(xTrxLog);
}
}
}
}
public static int getDBFlavor() {
String[] propertyNames = { "xa.db.flavor",
"ranger.jpa.jdbc.dialect",
"ranger.jpa.jdbc.url",
"ranger.jpa.jdbc.driver"
};
for(String propertyName : propertyNames) {
String propertyValue = PropertiesUtil.getProperty(propertyName);
if(StringUtils.isBlank(propertyValue)) {
continue;
}
if (StringUtils.containsIgnoreCase(propertyValue, "mysql")) {
return AppConstants.DB_FLAVOR_MYSQL;
} else if (StringUtils.containsIgnoreCase(propertyValue, "oracle")) {
return AppConstants.DB_FLAVOR_ORACLE;
} else if (StringUtils.containsIgnoreCase(propertyValue, "postgresql")) {
return AppConstants.DB_FLAVOR_POSTGRES;
} else if (StringUtils.containsIgnoreCase(propertyValue, "sqlserver")) {
return AppConstants.DB_FLAVOR_SQLSERVER;
} else if (StringUtils.containsIgnoreCase(propertyValue, "mssql")) {
return AppConstants.DB_FLAVOR_SQLSERVER;
} else if (StringUtils.containsIgnoreCase(propertyValue, "sqlanywhere")) {
return AppConstants.DB_FLAVOR_SQLANYWHERE;
} else if (StringUtils.containsIgnoreCase(propertyValue, "sqla")) {
return AppConstants.DB_FLAVOR_SQLANYWHERE;
}else {
if(logger.isDebugEnabled()) {
logger.debug("DB Flavor could not be determined from property - " + propertyName + "=" + propertyValue);
}
}
}
logger.error("DB Flavor could not be determined");
return AppConstants.DB_FLAVOR_UNKNOWN;
}
public String getDBVersion(){
return daoManager.getXXUser().getDBVersion();
}
public String getAuditDBType() {
return auditDBType;
}
public void setAuditDBType(String auditDBType) {
this.auditDBType = auditDBType;
}
/**
* return true id current logged in session is owned by keyadmin
*
* @return
*/
public boolean isKeyAdmin() {
UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
if (currentUserSession == null) {
logger.debug("Unable to find session.");
return false;
}
if (currentUserSession.isKeyAdmin()) {
return true;
}
return false;
}
public boolean isAuditKeyAdmin() {
UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
if (currentUserSession == null) {
logger.debug("Unable to find session.");
return false;
}
if (currentUserSession.isAuditKeyAdmin()) {
return true;
}
return false;
}
/**
* @param xxDbBase
* @param baseModel
* @return Boolean
*
* @NOTE: Kindly check all the references of this function before making any changes
*/
public Boolean hasAccess(XXDBBase xxDbBase, RangerBaseModelObject baseModel) {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session == null) {
logger.info("User session not found, granting access.");
return true;
}
boolean isKeyAdmin = session.isKeyAdmin();
boolean isSysAdmin = session.isUserAdmin();
boolean isAuditor = session.isAuditUserAdmin();
boolean isAuditorKeyAdmin = session.isAuditKeyAdmin();
boolean isUser = false;
List<String> roleList = session.getUserRoleList();
if (roleList.contains(RangerConstants.ROLE_USER) ) {
isUser = true;
}
if (xxDbBase != null && xxDbBase instanceof XXServiceDef) {
XXServiceDef xServiceDef = (XXServiceDef) xxDbBase;
final String implClass = xServiceDef.getImplclassname();
if (EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME.equals(implClass)) {
// KMS case
return isKeyAdmin || isAuditorKeyAdmin;
} else {
// Other cases - implClass can be null!
return isSysAdmin || isUser || isAuditor;
}
}
if (xxDbBase != null && xxDbBase instanceof XXService) {
// TODO: As of now we are allowing SYS_ADMIN to create/update/read/delete all the
// services including KMS
if (isSysAdmin || isAuditor) {
return true;
}
XXService xService = (XXService) xxDbBase;
XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());
String implClass = xServiceDef.getImplclassname();
if (EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME.equals(implClass)) {
// KMS case
return isKeyAdmin || isAuditorKeyAdmin;
} else {
// Other cases - implClass can be null!
return isUser;
}
}
return false;
}
public void hasAdminPermissions(String objType) {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session == null) {
throw restErrorUtil.createRESTException("UserSession cannot be null, only Admin can create/update/delete "
+ objType, MessageEnums.OPER_NO_PERMISSION);
}
if (!session.isKeyAdmin() && !session.isUserAdmin()) {
throw restErrorUtil.createRESTException(
"This user is not allowed this operation. Only users with Admin permission have access to this operation " + objType,
MessageEnums.OPER_NO_PERMISSION);
}
}
public void hasKMSPermissions(String objType, String implClassName) {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session == null) {
throw restErrorUtil.createRESTException("UserSession cannot be null, only KeyAdmin can create/update/delete "
+ objType, MessageEnums.OPER_NO_PERMISSION);
}
if (session.isKeyAdmin() && !EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME.equals(implClassName)) {
throw restErrorUtil.createRESTException("KeyAdmin can create/update/delete only KMS " + objType,
MessageEnums.OPER_NO_PERMISSION);
}
// TODO: As of now we are allowing SYS_ADMIN to create/update/read/delete all the
// services including KMS
if ("Service-Def".equalsIgnoreCase(objType) && session.isUserAdmin() && EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME.equals(implClassName)) {
throw restErrorUtil.createRESTException("System Admin cannot create/update/delete KMS " + objType,
MessageEnums.OPER_NO_PERMISSION);
}
}
public boolean checkUserAccessible(VXUser vXUser) {
boolean isAccessible = true;
Collection<String> roleList = userMgr.getRolesByLoginId(vXUser
.getName());
if (isKeyAdmin()) {
if (vXUser.getUserRoleList().contains(RangerConstants.ROLE_SYS_ADMIN)
|| vXUser.getUserRoleList().contains(RangerConstants.ROLE_ADMIN_AUDITOR)
|| roleList.contains(RangerConstants.ROLE_SYS_ADMIN)
|| roleList.contains(RangerConstants.ROLE_ADMIN_AUDITOR)) {
isAccessible = false;
}
}
if (isAdmin()) {
if (vXUser.getUserRoleList().contains(RangerConstants.ROLE_KEY_ADMIN)
|| vXUser.getUserRoleList().contains(RangerConstants.ROLE_KEY_ADMIN_AUDITOR)
|| roleList.contains(RangerConstants.ROLE_KEY_ADMIN)
|| roleList.contains(RangerConstants.ROLE_KEY_ADMIN_AUDITOR)) {
isAccessible = false;
}
}
if (!isAccessible) {
throw restErrorUtil.createRESTException(
"Logged in user is not allowed to create/update user",
MessageEnums.OPER_NO_PERMISSION);
}
return isAccessible;
}
public boolean isSSOEnabled() {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session != null) {
return session.isSSOEnabled() == null ? PropertiesUtil.getBooleanProperty("ranger.sso.enabled", false) : session.isSSOEnabled();
} else {
throw restErrorUtil.createRESTException(
"User session is not created",
MessageEnums.OPER_NOT_ALLOWED_FOR_STATE);
}
}
public boolean isUserAllowed(RangerService rangerService, String cfgNameAllowedUsers) {
Map<String, String> map = rangerService.getConfigs();
String user = null;
UserSessionBase userSession = ContextUtil.getCurrentUserSession();
if(userSession != null){
user = userSession.getLoginId();
}
if (map != null && map.containsKey(cfgNameAllowedUsers)) {
String userNames = map.get(cfgNameAllowedUsers);
String[] userList = userNames.split(",");
if(userList != null){
for (String u : userList) {
if ("*".equals(u) || (user != null && u.equalsIgnoreCase(user))) {
return true;
}
}
}
}
return false;
}
public boolean isUserAllowedForGrantRevoke(RangerService rangerService,
String cfgNameAllowedUsers, String userName) {
Map<String, String> map = rangerService.getConfigs();
if (map != null && map.containsKey(cfgNameAllowedUsers)) {
String userNames = map.get(cfgNameAllowedUsers);
String[] userList = userNames.split(",");
if (userList != null) {
for (String u : userList) {
if ("*".equals(u) || (userName != null && u.equalsIgnoreCase(userName))) {
return true;
}
}
}
}
return false;
}
public void blockAuditorRoleUser() {
UserSessionBase session = ContextUtil.getCurrentUserSession();
if (session != null) {
if (session.isAuditKeyAdmin() || session.isAuditUserAdmin()) {
VXResponse vXResponse = new VXResponse();
vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
vXResponse.setMsgDesc("Operation"
+ " denied. LoggedInUser="
+ session.getXXPortalUser().getId()
+ " ,isn't permitted to perform the action.");
throw restErrorUtil.generateRESTException(vXResponse);
}
} else {
VXResponse vXResponse = new VXResponse();
vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
vXResponse.setMsgDesc("Bad Credentials");
throw restErrorUtil.generateRESTException(vXResponse);
}
}
public boolean hasModuleAccess(String moduleName) {
UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
if(currentUserSession == null) {
return false;
}
if(!currentUserSession.isUserAdmin() && !currentUserSession.isAuditUserAdmin()) {
if(!currentUserSession.getRangerUserPermission().getUserPermissions().contains(moduleName)) {
return false;
}
}
return true;
}
public void removeEmptyStrings(List<String> list) {
if(!CollectionUtils.isEmpty(list)) {
Iterator<String> i = list.iterator();
while (i.hasNext()){
String item = i.next();
if (item == null || StringUtils.isEmpty(StringUtils.trim(item))){
i.remove();
}
}
trimAll(list);
}
}
public void trimAll(List<String> list) {
if(!CollectionUtils.isEmpty(list)) {
for (int i = 0; i < list.size(); i++) {
String item=list.get(i);
if(item.startsWith(" ") || item.endsWith(" ")) {
list.set(i, StringUtils.trim(item));
}
}
}
}
public static boolean isBulkMode() {
return ContextUtil.isBulkModeContext();
}
//should be used only in bulk operation like importPolicies, policies delete.
public void bulkModeOnlyFlushAndClear() {
if (batchClearEnabled) {
XXDBBaseDao xXDBBaseDao = daoManager.getXXDBBase();
if (xXDBBaseDao != null) {
xXDBBaseDao.flush();
xXDBBaseDao.clear();
}
}
}
}