| /* |
| * 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 org.apache.commons.collections.CollectionUtils; |
| import org.apache.commons.io.FilenameUtils; |
| import org.apache.commons.io.IOCase; |
| import org.apache.commons.lang3.StringUtils; |
| 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.RangerCommonEnums; |
| import org.apache.ranger.common.RangerConstants; |
| import org.apache.ranger.common.RangerSuperUserConfig; |
| 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.db.XXTrxLogV2Dao; |
| 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.XXTrxLogV2; |
| 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.model.RangerServiceHeaderInfo; |
| import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; |
| import org.apache.ranger.rest.ServiceREST; |
| import org.apache.ranger.security.context.RangerAdminOpContext; |
| import org.apache.ranger.security.context.RangerContextHolder; |
| import org.apache.ranger.service.XUserService; |
| 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.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.stereotype.Component; |
| |
| import javax.servlet.http.HttpServletResponse; |
| |
| 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.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| @Component |
| public class RangerBizUtil { |
| private static final Logger logger = LoggerFactory.getLogger(RangerBizUtil.class); |
| |
| public static final String AUDIT_STORE_RDBMS = "DB"; |
| public static final String AUDIT_STORE_SOLR = "solr"; |
| public static final String AUDIT_STORE_ELASTIC_SEARCH = "elasticSearch"; |
| public static final String AUDIT_STORE_OPENSEARCH = "opensearch"; |
| public static final String AUDIT_STORE_CLOUD_WATCH = "cloudwatch"; |
| // login id used by the Ranger Admin health readiness endpoint |
| public static final String HEALTHCHECK_USERNAME = RangerAdminConfig.getInstance().get("ranger.admin.healthcheck.username", "healthcheck"); |
| public static final boolean BATCH_CLEAR_ENABLED = PropertiesUtil.getBooleanProperty("ranger.jpa.jdbc.batch-clear.enable", true); |
| public static final int POLICY_BATCH_SIZE = PropertiesUtil.getIntProperty("ranger.jpa.jdbc.batch-clear.size", 10); |
| public static final int BATCH_PERSIST_SIZE = PropertiesUtil.getIntProperty("ranger.jpa.jdbc.batch-persist.size", 500); |
| |
| private static final String PATH_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst0123456789-_."; |
| |
| static String fileSeparator = PropertiesUtil.getProperty("ranger.file.separator", "/"); |
| |
| private static final char[] PATH_CHAR_SET = PATH_CHARS.toCharArray(); |
| private static final int PATH_CHAR_SET_LEN = PATH_CHAR_SET.length; |
| |
| @Autowired |
| RESTErrorUtil restErrorUtil; |
| |
| @Autowired |
| RangerDaoManager daoManager; |
| |
| @Autowired |
| StringUtil stringUtil; |
| |
| @Autowired |
| UserMgr userMgr; |
| |
| /** Used for config super-user group lookup in {@link #isUserRangerAdmin(String)}. */ |
| @Autowired |
| XUserMgr xUserMgr; |
| |
| @Autowired |
| XUserService xUserService; |
| |
| @Autowired |
| GUIDUtil guidUtil; |
| |
| private final boolean allowUnauthenticatedAccessInSecureEnvironment; |
| private final boolean allowUnauthenticatedDownloadAccessInSecureEnvironment; |
| private final Class<?>[] groupEditableClassesList = {}; |
| private final int maxFirstNameLength; |
| private final SecureRandom random; |
| |
| Set<Class<?>> groupEditableClasses; |
| int maxDisplayNameLength = 150; |
| boolean enableResourceAccessControl; |
| String auditDBType = AUDIT_STORE_SOLR; |
| |
| public RangerBizUtil() { |
| RangerAdminConfig config = RangerAdminConfig.getInstance(); |
| |
| allowUnauthenticatedAccessInSecureEnvironment = config.getBoolean("ranger.admin.allow.unauthenticated.access", false); |
| allowUnauthenticatedDownloadAccessInSecureEnvironment = config.getBoolean("ranger.admin.allow.unauthenticated.download.access", allowUnauthenticatedAccessInSecureEnvironment); |
| |
| maxFirstNameLength = Integer.parseInt(PropertiesUtil.getProperty("ranger.user.firstname.maxlength", "16")); |
| maxDisplayNameLength = PropertiesUtil.getIntProperty("ranger.bookmark.name.maxlen", maxDisplayNameLength); |
| |
| groupEditableClasses = new HashSet<>(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(); |
| } |
| |
| /** |
| * 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 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 { |
| 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 static String getDBFlavorType(int dbFlavor) { |
| final String dbFlavourType; |
| |
| switch (dbFlavor) { |
| case AppConstants.DB_FLAVOR_MYSQL: |
| dbFlavourType = "MYSQL"; |
| break; |
| case AppConstants.DB_FLAVOR_ORACLE: |
| dbFlavourType = "ORACLE"; |
| break; |
| case AppConstants.DB_FLAVOR_POSTGRES: |
| dbFlavourType = "POSTGRES"; |
| break; |
| case AppConstants.DB_FLAVOR_SQLANYWHERE: |
| dbFlavourType = "SQLANYWHERE"; |
| break; |
| case AppConstants.DB_FLAVOR_SQLSERVER: |
| dbFlavourType = "SQLSERVER"; |
| break; |
| default: |
| dbFlavourType = "Unknown"; |
| break; |
| } |
| |
| return dbFlavourType; |
| } |
| |
| public static String getDBVersionQuery(int dbFlavor) { |
| final String dbQuery; |
| |
| switch (dbFlavor) { |
| case AppConstants.DB_FLAVOR_ORACLE: |
| dbQuery = "SELECT banner from v$version where rownum<2"; |
| break; |
| case AppConstants.DB_FLAVOR_MYSQL: |
| case AppConstants.DB_FLAVOR_POSTGRES: |
| dbQuery = "SELECT version()"; |
| break; |
| case AppConstants.DB_FLAVOR_SQLANYWHERE: |
| case AppConstants.DB_FLAVOR_SQLSERVER: |
| dbQuery = "SELECT @@version"; |
| break; |
| default: |
| dbQuery = null; |
| break; |
| } |
| |
| return dbQuery; |
| } |
| |
| public static boolean isBulkMode() { |
| return ContextUtil.isBulkModeContext(); |
| } |
| |
| public static boolean setBulkMode(boolean val) { |
| RangerContextHolder.getOrCreateOpContext().setBulkModeContext(val); |
| |
| return isBulkMode(); |
| } |
| |
| // 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.isEmpty()) { |
| publicName = fName + " " + lastName.charAt(0) + "."; |
| } |
| |
| return publicName; |
| } |
| |
| public VXStringList mapStringListToVStringList(List<String> stringList) { |
| if (stringList == null) { |
| return null; |
| } |
| |
| List<VXString> vStringList = new ArrayList<>(); |
| |
| 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, RangerCommonEnums.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; |
| } |
| |
| return currentUserSession.isUserAdmin(); |
| } |
| |
| public boolean isAuditAdmin() { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| |
| if (currentUserSession == null) { |
| logger.debug("Unable to find session."); |
| |
| return false; |
| } |
| |
| return currentUserSession.isAuditUserAdmin(); |
| } |
| |
| /** |
| * 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 :{} with name {}", user.getId(), user.getFirstName()); |
| |
| return null; |
| } |
| |
| return xUser.getId(); |
| } |
| |
| public void failUnauthenticatedIfNotAllowed() throws Exception { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| if (currentUserSession == null && !allowUnauthenticatedAccessInSecureEnvironment) { |
| throw new Exception("Unauthenticated access not allowed"); |
| } |
| } |
| |
| public void failUnauthenticatedDownloadIfNotAllowed() throws Exception { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| if (currentUserSession == null && !allowUnauthenticatedDownloadAccessInSecureEnvironment) { |
| 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() != RangerCommonEnums.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 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; |
| } |
| |
| 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); |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * return List<Integer> |
| * <p> |
| * 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<>(); |
| |
| 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<>(); |
| List<String> wildcardPathArray = new ArrayList<>(); |
| |
| 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; |
| } |
| |
| public void createTrxLog(List<XXTrxLogV2> trxLogList) { |
| if (trxLogList == null || trxLogList.isEmpty()) { |
| return; |
| } |
| |
| if (guidUtil == null) { |
| // log a warning |
| return; |
| } |
| |
| XXTrxLogV2Dao dao = daoManager.getXXTrxLogV2(); |
| String trxId = Long.toString(guidUtil.genLong()); |
| UserSessionBase usb = ContextUtil.getCurrentUserSession(); |
| String sessionId = usb != null && usb.getSessionId() != null ? usb.getSessionId().toString() : null; |
| Long userId = usb != null ? usb.getUserId() : null; |
| |
| for (XXTrxLogV2 xTrxLog : trxLogList) { |
| xTrxLog.setTransactionId(trxId); |
| xTrxLog.setSessionId(sessionId); |
| xTrxLog.setSessionType("Spring Authenticated Session"); |
| xTrxLog.setRequestId(trxId); |
| |
| if (xTrxLog.getAddedByUserId() == null) { |
| xTrxLog.setAddedByUserId(userId); |
| } |
| |
| dao.create(xTrxLog); |
| } |
| } |
| |
| 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; |
| } |
| |
| return currentUserSession.isKeyAdmin(); |
| } |
| |
| public boolean isAuditKeyAdmin() { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| |
| if (currentUserSession == null) { |
| logger.debug("Unable to find session."); |
| return false; |
| } |
| |
| return (currentUserSession.isAuditKeyAdmin()); |
| } |
| |
| /** |
| * @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 = session.getUserRoleList().contains(RangerConstants.ROLE_USER); |
| |
| if (xxDbBase instanceof XXServiceDef) { |
| return hasAccessToXXServiceDef((XXServiceDef) xxDbBase, isKeyAdmin, isSysAdmin, isAuditor, isAuditorKeyAdmin, isUser); |
| } |
| |
| if (xxDbBase instanceof XXService) { |
| return hasAccessToXXService((XXService) xxDbBase, isKeyAdmin, isSysAdmin, isAuditor, isAuditorKeyAdmin, isUser); |
| } |
| |
| if (baseModel instanceof RangerServiceHeaderInfo) { |
| return hasAccessToRangerServiceHeaderInfo((RangerServiceHeaderInfo) baseModel, isKeyAdmin, isSysAdmin, isAuditor, isAuditorKeyAdmin, 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); |
| } |
| |
| boolean isKmsServiceType = EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME.equals(implClassName); |
| |
| if (session.isKeyAdmin() && !isKmsServiceType) { |
| throw restErrorUtil.createRESTException("KeyAdmin can create/update/delete only KMS " + objType, MessageEnums.OPER_NO_PERMISSION); |
| } |
| |
| if (session.isUserAdmin() && isKmsServiceType && "Service-Def".equalsIgnoreCase(objType)) { |
| 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.getDBRolesByLoginId(vXUser.getName()); |
| Collection<String> payloadRoles = vXUser.getUserRoleList(); |
| |
| if (isKeyAdmin()) { |
| if (StringUtil.containsIgnoreCase(payloadRoles, RangerConstants.ROLE_SYS_ADMIN) |
| || StringUtil.containsIgnoreCase(payloadRoles, RangerConstants.ROLE_ADMIN_AUDITOR) |
| || StringUtil.containsIgnoreCase(roleList, RangerConstants.ROLE_SYS_ADMIN) |
| || StringUtil.containsIgnoreCase(roleList, RangerConstants.ROLE_ADMIN_AUDITOR)) { |
| isAccessible = false; |
| } |
| } |
| if (isAdmin()) { |
| if (StringUtil.containsIgnoreCase(payloadRoles, RangerConstants.ROLE_KEY_ADMIN) |
| || StringUtil.containsIgnoreCase(payloadRoles, RangerConstants.ROLE_KEY_ADMIN_AUDITOR) |
| || StringUtil.containsIgnoreCase(roleList, RangerConstants.ROLE_KEY_ADMIN) |
| || StringUtil.containsIgnoreCase(roleList, 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(","); |
| |
| for (String u : userList) { |
| if ("*".equals(u) || (u.equalsIgnoreCase(user))) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| public boolean isUserAllowedForGrantRevoke(RangerService rangerService, String userName) { |
| return isUserInConfigParameter(rangerService, ServiceREST.Allowed_User_List_For_Grant_Revoke, userName); |
| } |
| |
| /** |
| * True when {@code username} is a full Ranger admin: DB sys/admin role, |
| * config super-user ({@code ranger.admin.super.users/groups}), or the |
| * current session is a Ranger admin ({@link UserSessionBase#isUserAdmin()}). |
| */ |
| public boolean isUserRangerAdmin(String username) { |
| if (StringUtils.isBlank(username)) { |
| return false; |
| } |
| |
| UserSessionBase userSession = ContextUtil.getCurrentUserSession(); |
| |
| // Ranger admin on current session (DB sys admin or config super-user). |
| if (userSession != null && username.equalsIgnoreCase(userSession.getLoginId()) && userSession.isUserAdmin()) { |
| return true; |
| } |
| |
| // Config super-user when no session context (e.g. grantor checks). |
| if (isConfigSuperUser(username)) { |
| return true; |
| } |
| |
| boolean isAdmin = false; |
| |
| try { |
| VXUser vxUser = xUserService.getXUserByUserName(username); |
| |
| if (vxUser != null && (vxUser.getUserRoleList().contains(RangerConstants.ROLE_ADMIN) || vxUser.getUserRoleList().contains(RangerConstants.ROLE_SYS_ADMIN))) { |
| isAdmin = true; |
| } |
| } catch (Exception ex) { |
| // ignored |
| } |
| |
| return isAdmin; |
| } |
| |
| /* True when username matches ranger.admin.super.users/groups, regardless of |
| * the current session and of the user's DB portal roles. */ |
| public boolean isConfigSuperUser(String username) { |
| if (StringUtils.isBlank(username)) { |
| return false; |
| } else if (RangerSuperUserConfig.isSuperUser(username)) { |
| return true; |
| } else if (RangerSuperUserConfig.isSuperGroupsConfigured() && xUserMgr != null) { |
| return RangerSuperUserConfig.isSuperUser(username, xUserMgr.getGroupsForUser(username)); |
| } |
| |
| return false; |
| } |
| |
| public boolean isHealthCheckUser(String user) { |
| return HEALTHCHECK_USERNAME.equalsIgnoreCase(user); |
| } |
| |
| /** |
| * True when the current session is a config super-user per |
| * {@code ranger.admin.super.users} / {@code ranger.admin.super.groups}. |
| */ |
| public boolean isSuperUser() { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| |
| return currentUserSession != null && currentUserSession.isSuperUser(); |
| } |
| |
| public boolean isUserServiceAdmin(RangerService rangerService, String userName) { |
| boolean ret = isUserInConfigParameter(rangerService, ServiceDBStore.SERVICE_ADMIN_USERS, userName); |
| |
| if (!ret && userMgr != null && userMgr.xUserMgr != null) { |
| ret = isAnyGroupInConfigParameter(rangerService, ServiceDBStore.SERVICE_ADMIN_GROUPS, userMgr.xUserMgr.getGroupsForUser(userName)); |
| } |
| |
| return ret; |
| } |
| |
| public boolean isUserInConfigParameter(RangerService rangerService, String configParamName, String userName) { |
| Map<String, String> map = rangerService.getConfigs(); |
| |
| if (map != null && map.containsKey(configParamName)) { |
| String userNames = map.get(configParamName); |
| String[] userList = userNames.split(","); |
| |
| for (String u : userList) { |
| if ("*".equals(u) || (u.equalsIgnoreCase(userName))) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| public boolean isAnyGroupInConfigParameter(RangerService rangerService, String configParamName, Set<String> groupNames) { |
| boolean ret = false; |
| Map<String, String> map = rangerService.getConfigs(); |
| String cfgValue = map != null ? map.get(configParamName) : null; |
| |
| if (StringUtils.isNotBlank(cfgValue) && CollectionUtils.isNotEmpty(groupNames)) { |
| String[] svcCfgGroupNames = cfgValue.split(","); |
| |
| for (String svcCfgGroupName : svcCfgGroupNames) { |
| if (RangerConstants.GROUP_PUBLIC.equals(svcCfgGroupName) || groupNames.contains(svcCfgGroupName)) { |
| ret = true; |
| |
| break; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| public void blockAuditorRoleUser() { |
| UserSessionBase session = ContextUtil.getCurrentUserSession(); |
| |
| if (session != null) { |
| if (!session.isSuperUser()) { |
| if (session.isAuditKeyAdmin() || session.isAuditUserAdmin()) { |
| VXResponse vXResponse = new VXResponse(); |
| |
| vXResponse.setStatusCode(HttpServletResponse.SC_FORBIDDEN); |
| 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); // user is null |
| 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()) { |
| return currentUserSession.getRangerUserPermission().getUserPermissions().contains(moduleName); |
| } |
| |
| return true; |
| } |
| |
| public void removeEmptyStrings(List<String> list) { |
| if (!CollectionUtils.isEmpty(list)) { |
| list.removeIf(StringUtils::isBlank); |
| |
| 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 boolean getCreatePrincipalsIfAbsent() { |
| RangerAdminOpContext opContext = RangerContextHolder.getOpContext(); |
| Boolean ret = opContext != null ? opContext.getCreatePrincipalsIfAbsent() : null; |
| |
| return ret != null && ret; |
| } |
| |
| //should be used only in bulk operation like importPolicies, policies delete. |
| public void bulkModeOnlyFlushAndClear() { |
| if (BATCH_CLEAR_ENABLED) { |
| XXDBBaseDao xXDBBaseDao = daoManager.getXXDBBase(); |
| |
| if (xXDBBaseDao != null) { |
| xXDBBaseDao.flush(); |
| xXDBBaseDao.clear(); |
| } |
| } |
| } |
| |
| public boolean checkAdminAccess() { |
| UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession(); |
| |
| if (currentUserSession != null) { |
| return currentUserSession.isUserAdmin(); |
| } else { |
| VXResponse vXResponse = new VXResponse(); |
| |
| vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED); // user is null |
| vXResponse.setMsgDesc("Bad Credentials"); |
| |
| throw restErrorUtil.generateRESTException(vXResponse); |
| } |
| } |
| |
| public boolean isGdsServiceDef(XXDBBase xxdbBase) { |
| return (xxdbBase instanceof XXServiceDef) && EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_GDS_NAME.equals(((XXServiceDef) xxdbBase).getName()); |
| } |
| |
| public boolean isGdsService(XXDBBase xxdbBase) { |
| return (xxdbBase instanceof XXService) && EmbeddedServiceDefsUtil.instance().getGdsServiceDefId() == ((XXService) xxdbBase).getType(); |
| } |
| |
| /** |
| * 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() != RangerCommonEnums.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() == RangerCommonEnums.BOOL_TRUE) { |
| matchFound = isRecursiveWildCardMatch(resourceName, dbResourceName); |
| } else { |
| matchFound = nonRecursiveWildCardMatch(resourceName, dbResourceName); |
| } |
| } |
| |
| if (matchFound) { |
| break; |
| } |
| } |
| |
| if (matchFound) { |
| break; |
| } |
| } |
| } |
| |
| return matchFound; |
| } |
| |
| /** |
| * 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() != RangerCommonEnums.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; |
| } |
| } else if (index == 1) { // check whether given service resource matches with any existing service resource |
| 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() != RangerCommonEnums.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(), ","); |
| 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 && 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 |
| } |
| |
| if (matchFound) { |
| policyMatched = true; |
| break; |
| } |
| } |
| } |
| |
| return policyMatched; |
| } |
| |
| /** |
| * 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 = daoManager.getXXGroup().findByUserId(xUserId); |
| List<XXPermMap> 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.equals(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; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| private Boolean hasAccessToXXServiceDef(XXServiceDef xxDbBase, boolean isKeyAdmin, boolean isSysAdmin, boolean isAuditor, boolean isAuditorKeyAdmin, boolean isUser) { |
| XXServiceDef xServiceDef = 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; |
| } |
| } |
| |
| private Boolean hasAccessToXXService(XXService xxDbBase, boolean isKeyAdmin, boolean isSysAdmin, boolean isAuditor, boolean isAuditorKeyAdmin, boolean isUser) { |
| // 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 = 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; |
| } |
| } |
| |
| private Boolean hasAccessToRangerServiceHeaderInfo(RangerServiceHeaderInfo serviceHeader, boolean isKeyAdmin, boolean isSysAdmin, boolean isAuditor, boolean isAuditorKeyAdmin, boolean isUser) { |
| // TODO: As of now we are allowing SYS_ADMIN to read all the |
| // services including KMS |
| if (isSysAdmin || isAuditor) { |
| return true; |
| } |
| |
| return EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_KMS_NAME.equals(serviceHeader.getType()) ? (isKeyAdmin || isAuditorKeyAdmin) : isUser; |
| } |
| } |