boolean isValid()

in agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java [115:455]


    boolean isValid(RangerPolicy policy, Action action, boolean isAdmin, List<ValidationFailureDetails> failures) {
        LOG.debug("==> RangerPolicyValidator.isValid({}, {}, {}, {})", policy, action, isAdmin, failures);

        if (!(action == Action.CREATE || action == Action.UPDATE)) {
            throw new IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for create/update");
        }

        boolean valid = true;

        if (policy == null) {
            ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_NULL_POLICY_OBJECT;

            failures.add(new ValidationFailureDetailsBuilder()
                    .field("policy")
                    .isMissing()
                    .becauseOf(error.getMessage())
                    .errorCode(error.getErrorCode())
                    .build());

            valid = false;
        } else {
            Integer priority = policy.getPolicyPriority();

            if (priority != null) {
                if (priority < RangerPolicy.POLICY_PRIORITY_NORMAL || priority > RangerPolicy.POLICY_PRIORITY_OVERRIDE) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_INVALID_PRIORITY;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("policyPriority")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage("out of range"))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                }
            }

            Long         id             = policy.getId();
            RangerPolicy existingPolicy = null;

            if (action == Action.UPDATE) { // id is ignored for CREATE
                if (id == null) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_FIELD;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("id")
                            .isMissing()
                            .becauseOf(error.getMessage("id"))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                }

                existingPolicy = getPolicy(id);

                if (existingPolicy == null) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_INVALID_POLICY_ID;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("id")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage(id))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                }
            }

            String policyName        = policy.getName();
            String serviceName       = policy.getService();
            String policyServicetype = policy.getServiceType();
            String zoneName          = policy.getZoneName();

            RangerService      service          = null;
            RangerSecurityZone zone             = null;
            boolean            serviceNameValid = false;

            if (StringUtils.isBlank(serviceName)) {
                ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_FIELD;

                failures.add(new ValidationFailureDetailsBuilder()
                        .field("service name")
                        .isMissing()
                        .becauseOf(error.getMessage("service name"))
                        .errorCode(error.getErrorCode())
                        .build());

                valid = false;
            } else {
                service = getService(serviceName);

                if (service == null) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_INVALID_SERVICE_NAME;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("service name")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage(serviceName))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                } else {
                    serviceNameValid = true;

                    String serviceType = service.getType();

                    if (StringUtils.isNotEmpty(serviceType) && StringUtils.isNotEmpty(policyServicetype)) {
                        if (!serviceType.equalsIgnoreCase(policyServicetype)) {
                            ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_INVALID_SERVICE_TYPE;

                            failures.add(new ValidationFailureDetailsBuilder()
                                    .field("service type")
                                    .isSemanticallyIncorrect()
                                    .becauseOf(error.getMessage(policyServicetype, serviceName))
                                    .errorCode(error.getErrorCode())
                                    .build());
                            valid = false;
                        }
                    }
                }
            }

            if (StringUtils.isNotEmpty(zoneName)) {
                zone = getSecurityZone(zoneName);

                if (zone == null) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_NONEXISTANT_ZONE_NAME;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("zoneName")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage(id, zoneName))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                } else {
                    List<String> tagSvcList = zone.getTagServices();
                    Set<String>  svcNameSet = zone.getServices().keySet();

                    if (!svcNameSet.contains(serviceName) && !tagSvcList.contains(serviceName)) {
                        ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_SERVICE_NOT_ASSOCIATED_TO_ZONE;

                        failures.add(new ValidationFailureDetailsBuilder().field("zoneName").isSemanticallyIncorrect().becauseOf(error.getMessage(serviceName, zoneName)).errorCode(error.getErrorCode()).build());

                        valid = false;
                    }
                }
            }

            if (StringUtils.isBlank(policyName)) {
                ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_FIELD;

                failures.add(new ValidationFailureDetailsBuilder()
                        .field("name")
                        .isMissing()
                        .becauseOf(error.getMessage("name"))
                        .errorCode(error.getErrorCode())
                        .build());

                valid = false;
            } else {
                if (service != null && (StringUtils.isEmpty(zoneName) || zone != null)) {
                    Long zoneId   = zone != null ? zone.getId() : RangerSecurityZone.RANGER_UNZONED_SECURITY_ZONE_ID;
                    Long policyId = getPolicyId(service.getId(), policyName, zoneId);

                    if (policyId != null) {
                        if (action == Action.CREATE) {
                            ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_NAME_CONFLICT;

                            failures.add(new ValidationFailureDetailsBuilder()
                                    .field("policy name")
                                    .isSemanticallyIncorrect()
                                    .becauseOf(error.getMessage(policyId, serviceName))
                                    .errorCode(error.getErrorCode())
                                    .build());

                            valid = false;
                        } else if (!policyId.equals(id)) { // action == UPDATE
                            ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_NAME_CONFLICT;

                            failures.add(new ValidationFailureDetailsBuilder()
                                    .field("id/name")
                                    .isSemanticallyIncorrect()
                                    .becauseOf(error.getMessage(policyId, serviceName))
                                    .errorCode(error.getErrorCode())
                                    .build());

                            valid = false;
                        }
                    }
                }
            }

            if (existingPolicy != null) {
                if (!StringUtils.equalsIgnoreCase(existingPolicy.getService(), policy.getService())) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_UPDATE_MOVE_SERVICE_NOT_ALLOWED;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("service name")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage(policy.getId(), existingPolicy.getService(), policy.getService()))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                }

                int existingPolicyType = existingPolicy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : existingPolicy.getPolicyType();
                int policyType         = policy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : policy.getPolicyType();

                if (existingPolicyType != policyType) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_TYPE_CHANGE_NOT_ALLOWED;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("policy type")
                            .isSemanticallyIncorrect()
                            .becauseOf(error.getMessage(policy.getId(), existingPolicyType, policyType))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                }

                String existingZoneName = existingPolicy.getZoneName();

                if (StringUtils.isNotEmpty(zoneName) || StringUtils.isNotEmpty(existingZoneName)) {
                    if (!StringUtils.equals(existingZoneName, zoneName)) {
                        ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_UPDATE_ZONE_NAME_NOT_ALLOWED;

                        failures.add(new ValidationFailureDetailsBuilder()
                                .field("zoneName")
                                .isSemanticallyIncorrect()
                                .becauseOf(error.getMessage(existingZoneName, zoneName))
                                .errorCode(error.getErrorCode())
                                .build());

                        valid = false;
                    }
                }
            }

            boolean          isAuditEnabled   = getIsAuditEnabled(policy);
            String           serviceDefName;
            RangerServiceDef serviceDef       = null;
            int              policyItemsCount = 0;

            int policyType = policy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : policy.getPolicyType();

            switch (policyType) {
                case RangerPolicy.POLICY_TYPE_DATAMASK:
                    if (CollectionUtils.isNotEmpty(policy.getDataMaskPolicyItems())) {
                        policyItemsCount += policy.getDataMaskPolicyItems().size();
                    }
                    break;
                case RangerPolicy.POLICY_TYPE_ROWFILTER:
                    if (CollectionUtils.isNotEmpty(policy.getRowFilterPolicyItems())) {
                        policyItemsCount += policy.getRowFilterPolicyItems().size();
                    }
                    break;
                default:
                    if (CollectionUtils.isNotEmpty(policy.getPolicyItems())) {
                        policyItemsCount += policy.getPolicyItems().size();
                    }
                    if (CollectionUtils.isNotEmpty(policy.getDenyPolicyItems())) {
                        policyItemsCount += policy.getDenyPolicyItems().size();
                    }
                    break;
            }

            if (policyItemsCount == 0 && !isAuditEnabled) {
                ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_POLICY_ITEMS;

                failures.add(new ValidationFailureDetailsBuilder()
                        .field("policy items")
                        .isMissing()
                        .becauseOf(error.getMessage())
                        .errorCode(error.getErrorCode())
                        .build());

                valid = false;
            } else if (service != null) {
                serviceDefName = service.getType();
                serviceDef     = getServiceDef(serviceDefName);

                if (serviceDef == null) {
                    ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_SERVICE_DEF;

                    failures.add(new ValidationFailureDetailsBuilder()
                            .field("policy service def")
                            .isAnInternalError()
                            .becauseOf(error.getMessage(serviceDefName, serviceName))
                            .errorCode(error.getErrorCode())
                            .build());

                    valid = false;
                } else {
                    if (Boolean.TRUE.equals(policy.getIsDenyAllElse())) {
                        if (CollectionUtils.isNotEmpty(policy.getDenyPolicyItems()) || CollectionUtils.isNotEmpty(policy.getDenyExceptions())) {
                            ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_UNSUPPORTED_POLICY_ITEM_TYPE;

                            failures.add(new ValidationFailureDetailsBuilder()
                                    .field("policy items")
                                    .becauseOf(error.getMessage())
                                    .errorCode(error.getErrorCode())
                                    .build());

                            valid = false;
                        }
                    }

                    valid = isValidPolicyItems(policy.getPolicyItems(), failures, serviceDef) && valid;
                    valid = isValidPolicyItems(policy.getDenyPolicyItems(), failures, serviceDef) && valid;
                    valid = isValidPolicyItems(policy.getAllowExceptions(), failures, serviceDef) && valid;
                    valid = isValidPolicyItems(policy.getDenyExceptions(), failures, serviceDef) && valid;

                    @SuppressWarnings("unchecked")
                    List<RangerPolicyItem> dataMaskPolicyItems = (List<RangerPolicyItem>) (List<?>) policy.getDataMaskPolicyItems();
                    valid = isValidPolicyItems(dataMaskPolicyItems, failures, serviceDef) && valid;

                    @SuppressWarnings("unchecked")
                    List<RangerPolicyItem> rowFilterPolicyItems = (List<RangerPolicyItem>) (List<?>) policy.getRowFilterPolicyItems();
                    valid = isValidPolicyItems(rowFilterPolicyItems, failures, serviceDef) && valid;
                }
            }

            if (serviceNameValid) { // resource checks can't be done meaningfully otherwise
                valid = isValidValiditySchedule(policy, failures, action) && valid;
                valid = isValidResources(policy, failures, action, isAdmin, serviceDef) && valid;
                valid = isValidAccessTypeDef(policy, failures, action, isAdmin, serviceDef) && valid;
            }
        }

        LOG.debug("<== RangerPolicyValidator.isValid({}, {}, {}, {}): {}", policy, action, isAdmin, failures, valid);

        return valid;
    }