public void checkPrivileges()

in hive-agent/src/main/java/org/apache/ranger/authorization/hive/authorizer/RangerHiveAuthorizer.java [712:1063]


    public void checkPrivileges(HiveOperationType hiveOpType, List<HivePrivilegeObject> inputHObjs, List<HivePrivilegeObject> outputHObjs, HiveAuthzContext context) throws HiveAccessControlException {
        UserGroupInformation ugi = getCurrentUserGroupInfo();

        if (ugi == null) {
            throw new HiveAccessControlException("Permission denied: user information not available");
        }

        RangerHiveAuditHandler auditHandler = new RangerHiveAuditHandler(hivePlugin.getConfig());
        RangerPerfTracer       perf         = null;

        try {
            HiveAuthzSessionContext sessionContext = getHiveAuthzSessionContext();
            String                  user           = ugi.getShortUserName();
            Set<String>             groups         = Sets.newHashSet(ugi.getGroupNames());
            Set<String>             roles          = getCurrentRolesForUser(user, groups);
            Map<String, String>     objOwners      = new HashMap<>();

            if (LOG.isDebugEnabled()) {
                LOG.debug(toString(hiveOpType, inputHObjs, outputHObjs, context, sessionContext));
            }

            if (hiveOpType == HiveOperationType.DFS) {
                handleDfsCommand(hiveOpType, inputHObjs, user, auditHandler);

                return;
            }

            if (RangerPerfTracer.isPerfTraceEnabled(PERF_HIVEAUTH_REQUEST_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_HIVEAUTH_REQUEST_LOG, "RangerHiveAuthorizer.checkPrivileges(hiveOpType=" + hiveOpType + ")");
            }

            List<RangerHiveAccessRequest> requests = new ArrayList<>();

            if (!CollectionUtils.isEmpty(inputHObjs)) {
                for (HivePrivilegeObject hiveObj : inputHObjs) {
                    RangerHiveResource resource = getHiveResource(hiveOpType, hiveObj, inputHObjs, outputHObjs, objOwners);

                    if (resource == null) { // possible if input object/object is of a kind that we don't currently authorize
                        continue;
                    }

                    String         pathStr     = hiveObj.getObjectName();
                    HiveObjectType hiveObjType = resource.getObjectType();

                    if (hiveObjType == HiveObjectType.URI && isPathInFSScheme(pathStr)) {
                        FsAction   permission = getURIAccessType(hiveOpType);
                        Path       path       = new Path(pathStr);
                        FileSystem fs;

                        try {
                            fs = FileSystem.get(path.toUri(), getHiveConf());
                        } catch (IOException e) {
                            LOG.error("Error getting permissions for {}", path, e);

                            throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have [%s] privilege on [%s]", user, permission.name(), path), e);
                        }

                        boolean shouldCheckAccess = true;

                        if (isMountedFs(fs)) {
                            Path resolvedPath = resolvePath(path, fs);

                            if (resolvedPath != null) {
                                // we know the resolved path scheme. Let's check the resolved path
                                // scheme is part of hivePlugin.getFSScheme.
                                shouldCheckAccess = isPathInFSScheme(resolvedPath.toUri().toString());
                            }
                        }

                        if (shouldCheckAccess) {
                            if (!isURIAccessAllowed(user, permission, path, fs)) {
                                throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have [%s] privilege on [%s]", user, permission.name(), path));
                            }

                            continue;
                        }
                        // This means we got resolved path scheme is not part of
                        // hivePlugin.getFSScheme
                    }

                    HiveAccessType accessType = getAccessType(hiveObj, hiveOpType, hiveObjType, true);

                    if (accessType == HiveAccessType.NONE) {
                        continue;
                    }

                    if (!existsByResourceAndAccessType(requests, resource, accessType)) {
                        RangerHiveAccessRequest request = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType, accessType, context, sessionContext);

                        requests.add(request);
                    }
                }
            } else {
                // this should happen only for SHOWDATABASES
                if (hiveOpType == HiveOperationType.SHOWDATABASES) {
                    RangerHiveResource      resource = new RangerHiveResource(HiveObjectType.DATABASE, null);
                    RangerHiveAccessRequest request  = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType.name(), HiveAccessType.USE, context, sessionContext);

                    requests.add(request);
                } else if (hiveOpType == HiveOperationType.SHOW_GRANT) {
                    String  command                  = context.getCommandString();
                    String  regexForShowGrantCommand = "SHOW GRANT\\s*(\\w+)?\\s*(\\w+)?\\s*ON\\s*(\\w+)?\\s*(\\S+)";
                    Pattern pattern                  = Pattern.compile(regexForShowGrantCommand, Pattern.CASE_INSENSITIVE);
                    Matcher matcher                  = pattern.matcher(command);

                    if (matcher.find()) {
                        String hiveObjectType  = matcher.group(3);
                        String hiveObjectValue = matcher.group(4);
                        String dbName          = hiveObjectValue;
                        String tableName       = "";

                        if (hiveObjectValue.contains(".")) {
                            String[] parts = hiveObjectValue.split("\\.");

                            dbName    = parts[0];
                            tableName = parts[1];
                        }

                        if (hiveObjectType.toUpperCase().equals(HiveObjectType.DATABASE.name())) {
                            RangerHiveResource      resource = new RangerHiveResource(HiveObjectType.DATABASE, dbName);
                            RangerHiveAccessRequest request  = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType.name(), HiveAccessType.USE, context, sessionContext);

                            requests.add(request);
                        } else if (hiveObjectType.toUpperCase().equals(HiveObjectType.TABLE.name())) {
                            RangerHiveResource      resource = new RangerHiveResource(HiveObjectType.TABLE, dbName, tableName);
                            RangerHiveAccessRequest request  = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType.name(), HiveAccessType.USE, context, sessionContext);

                            requests.add(request);
                        }
                    }
                } else if (hiveOpType == HiveOperationType.REPLDUMP) {
                    // This happens when REPL DUMP command with null inputHObjs is sent in checkPrivileges()
                    // following parsing is done for Audit info
                    RangerHiveResource resource;
                    HiveObj            hiveObj   = new HiveObj(context);
                    String             dbName    = hiveObj.getDatabaseName();
                    String             tableName = hiveObj.getTableName();

                    LOG.debug("Database: {} Table: {}", dbName, tableName);

                    if (!StringUtil.isEmpty(tableName)) {
                        resource = new RangerHiveResource(HiveObjectType.TABLE, dbName, tableName);
                    } else {
                        resource = new RangerHiveResource(HiveObjectType.DATABASE, dbName, null);
                    }

                    RangerHiveAccessRequest request = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType.name(), HiveAccessType.REPLADMIN, context, sessionContext);

                    requests.add(request);
                } else if (hiveOpType.equals(HiveOperationType.ALTERTABLE_OWNER)) {
                    RangerHiveAccessRequest request = buildRequestForAlterTableSetOwnerFromCommandString(user, groups, roles, hiveOpType.name(), context, sessionContext);

                    if (request != null) {
                        requests.add(request);
                    } else {
                        throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have privilege for [%s] command", user, hiveOpType.name()));
                    }
                } else {
                    LOG.debug("RangerHiveAuthorizer.checkPrivileges: Unexpected operation type[{}] received with empty input objects list!", hiveOpType);
                }
            }

            if (!CollectionUtils.isEmpty(outputHObjs)) {
                for (HivePrivilegeObject hiveObj : outputHObjs) {
                    RangerHiveResource resource = getHiveResource(hiveOpType, hiveObj, inputHObjs, outputHObjs, objOwners);

                    if (resource == null) { // possible if input object/object is of a kind that we don't currently authorize
                        continue;
                    }

                    String         pathStr     = hiveObj.getObjectName();
                    HiveObjectType hiveObjType = resource.getObjectType();

                    if (hiveObjType == HiveObjectType.URI && isPathInFSScheme(pathStr)) {
                        FsAction   permission = getURIAccessType(hiveOpType);
                        Path       path       = new Path(pathStr);
                        FileSystem fs;

                        try {
                            fs = FileSystem.get(path.toUri(), getHiveConf());
                        } catch (IOException e) {
                            LOG.error("Error getting permissions for {}", path, e);

                            throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have [%s] privilege on [%s]", user, permission.name(), path), e);
                        }

                        boolean shouldCheckAccess = true;

                        if (isMountedFs(fs)) {
                            Path resolvedPath = resolvePath(path, fs);

                            if (resolvedPath != null) {
                                // we know the resolved path scheme. Let's check the resolved path
                                // scheme is part of hivePlugin.getFSScheme.
                                shouldCheckAccess = isPathInFSScheme(resolvedPath.toUri().toString());
                            }
                        }

                        if (shouldCheckAccess) {
                            if (!isURIAccessAllowed(user, permission, path, fs)) {
                                throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have [%s] privilege on [%s]", user, permission.name(), path));
                            }

                            continue;
                        }
                        // This means we got resolved path scheme is not part of
                        // hivePlugin.getFSScheme
                    }

                    HiveAccessType accessType = getAccessType(hiveObj, hiveOpType, hiveObjType, false);

                    if (accessType == HiveAccessType.NONE) {
                        continue;
                    }

                    if (!existsByResourceAndAccessType(requests, resource, accessType)) {
                        RangerHiveAccessRequest request = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType, accessType, context, sessionContext);

                        requests.add(request);
                    }
                }
            } else {
                if (hiveOpType == HiveOperationType.REPLLOAD) {
                    // This happens when REPL LOAD command with null inputHObjs is sent in checkPrivileges()
                    // following parsing is done for Audit info
                    RangerHiveResource resource;
                    HiveObj            hiveObj   = new HiveObj(context);
                    String             dbName    = hiveObj.getDatabaseName();
                    String             tableName = hiveObj.getTableName();

                    LOG.debug("Database: {} Table: {}", dbName, tableName);

                    if (!StringUtil.isEmpty(tableName)) {
                        resource = new RangerHiveResource(HiveObjectType.TABLE, dbName, tableName);
                    } else {
                        resource = new RangerHiveResource(HiveObjectType.DATABASE, dbName, null);
                    }

                    RangerHiveAccessRequest request = new RangerHiveAccessRequest(resource, user, groups, roles, hiveOpType.name(), HiveAccessType.REPLADMIN, context, sessionContext);

                    requests.add(request);
                }
            }

            buildRequestContextWithAllAccessedResources(requests);

            for (RangerHiveAccessRequest request : requests) {
                LOG.debug("request: {}", request);

                RangerHiveResource resource = (RangerHiveResource) request.getResource();
                RangerAccessResult result   = null;

                if (resource.getObjectType() == HiveObjectType.COLUMN && StringUtils.contains(resource.getColumn(), COLUMN_SEP)) {
                    List<RangerAccessRequest> colRequests = new ArrayList<>();
                    String[]                  columns     = StringUtils.split(resource.getColumn(), COLUMN_SEP);

                    // in case of multiple columns, original request is not sent to the plugin; hence service-def will not be set
                    resource.setServiceDef(hivePlugin.getServiceDef());

                    for (String column : columns) {
                        if (column != null) {
                            column = column.trim();
                        }

                        if (StringUtils.isBlank(column)) {
                            continue;
                        }

                        RangerHiveResource colResource = new RangerHiveResource(HiveObjectType.COLUMN, resource.getDatabase(), resource.getTable(), column);

                        colResource.setOwnerUser(resource.getOwnerUser());

                        RangerHiveAccessRequest colRequest = request.copy();

                        colRequest.setResource(colResource);

                        colRequests.add(colRequest);
                    }

                    Collection<RangerAccessResult> colResults = hivePlugin.isAccessAllowed(colRequests, auditHandler);

                    if (colResults != null) {
                        for (RangerAccessResult colResult : colResults) {
                            result = colResult;

                            if (result != null && !result.getIsAllowed()) {
                                break;
                            }
                        }
                    }
                } else {
                    result = hivePlugin.isAccessAllowed(request, auditHandler);
                }

                if ((result == null || result.getIsAllowed()) && isBlockAccessIfRowfilterColumnMaskSpecified(hiveOpType, request)) {
                    // check if row-filtering is applicable for the table/view being accessed
                    HiveAccessType     savedAccessType = request.getHiveAccessType();
                    RangerHiveResource tblResource     = new RangerHiveResource(HiveObjectType.TABLE, resource.getDatabase(), resource.getTable());

                    request.setHiveAccessType(HiveAccessType.SELECT); // filtering/masking policies are defined only for SELECT
                    request.setResource(tblResource);

                    RangerAccessResult rowFilterResult = getRowFilterResult(request);

                    if (isRowFilterEnabled(rowFilterResult)) {
                        if (result == null) {
                            result = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, rowFilterResult.getServiceName(), rowFilterResult.getServiceDef(), request);
                        }

                        result.setIsAllowed(false);
                        result.setPolicyId(rowFilterResult.getPolicyId());
                        result.setPolicyVersion(rowFilterResult.getPolicyVersion());
                        result.setReason("User does not have access to all rows of the table");
                    } else {
                        // check if masking is enabled for any column in the table/view
                        request.setResourceMatchingScope(RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS);

                        RangerAccessResult dataMaskResult = getDataMaskResult(request);

                        if (isDataMaskEnabled(dataMaskResult)) {
                            if (result == null) {
                                result = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, dataMaskResult.getServiceName(), dataMaskResult.getServiceDef(), request);
                            }

                            result.setIsAllowed(false);
                            result.setPolicyId(dataMaskResult.getPolicyId());
                            result.setPolicyVersion(dataMaskResult.getPolicyVersion());
                            result.setReason("User does not have access to unmasked column values");
                        }
                    }

                    request.setHiveAccessType(savedAccessType);
                    request.setResource(resource);

                    if (result != null && !result.getIsAllowed()) {
                        auditHandler.processResult(result);
                    }
                }

                if (result == null || !result.getIsAllowed()) {
                    String path = resource.getAsString();

                    path = (path == null) ? "Unknown resource!!" : buildPathForException(path, hiveOpType);

                    throw new HiveAccessControlException(String.format("Permission denied: user [%s] does not have [%s] privilege on [%s]", user, request.getHiveAccessType().name(), path));
                }
            }
        } finally {
            auditHandler.flushAudit();
            RangerPerfTracer.log(perf);
        }
    }