/** * Copyright (c) 2016 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.model.impl.hooks; import java.util.Collection; import javax.annotation.PostConstruct; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.evolveum.midpoint.model.api.context.EvaluatedAssignment; import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRuleTrigger; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.api.context.ModelElementContext; import com.evolveum.midpoint.model.api.context.ModelState; import com.evolveum.midpoint.model.api.hooks.ChangeHook; import com.evolveum.midpoint.model.api.hooks.HookOperationMode; import com.evolveum.midpoint.model.api.hooks.HookRegistry; import com.evolveum.midpoint.prism.delta.DeltaSetTriple; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.PolicyViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.EnforcementPolicyActionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyActionsType; /** * Hook used to enforce the policy rules that have the enforce action. * * @author semancik * */ @Component public class PolicyRuleEnforcerHook implements ChangeHook { private static final Trace LOGGER = TraceManager.getTrace(PolicyRuleEnforcerHook.class); public static final String HOOK_URI = SchemaConstants.NS_MODEL + "/policy-rule-enforcer-hook-3"; @Autowired(required = true) private HookRegistry hookRegistry; @PostConstruct public void init() { hookRegistry.registerChangeHook(HOOK_URI, this); if (LOGGER.isTraceEnabled()) { LOGGER.trace("PolicyRuleEnforcerHook registered."); } } /* (non-Javadoc) * @see com.evolveum.midpoint.model.api.hooks.ChangeHook#invoke(com.evolveum.midpoint.model.api.context.ModelContext, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult) */ @Override public <O extends ObjectType> HookOperationMode invoke(@NotNull ModelContext<O> context, @NotNull Task task, @NotNull OperationResult result) throws PolicyViolationException { if (context.getState() != ModelState.PRIMARY) { return HookOperationMode.FOREGROUND; } ModelElementContext<O> focusContext = context.getFocusContext(); if (focusContext == null) { return HookOperationMode.FOREGROUND; } if (!FocusType.class.isAssignableFrom(focusContext.getObjectTypeClass())) { return HookOperationMode.FOREGROUND; } evaluateFocusRules((ModelContext<FocusType>) context, task, result); evaluateAssignmentRules((ModelContext<FocusType>) context, task, result); return HookOperationMode.FOREGROUND; } private <F extends FocusType> void evaluateFocusRules(ModelContext<F> context, Task task, OperationResult result) throws PolicyViolationException { ModelElementContext<F> focusContext = context.getFocusContext(); StringBuilder compositeMessageSb = new StringBuilder(); enforceTriggeredRules(compositeMessageSb, focusContext.getPolicyRules()); if (compositeMessageSb.length() != 0) { throw new PolicyViolationException(compositeMessageSb.toString()); } } private <F extends FocusType> void evaluateAssignmentRules(ModelContext<F> context, Task task, OperationResult result) throws PolicyViolationException { DeltaSetTriple<? extends EvaluatedAssignment> evaluatedAssignmentTriple = context.getEvaluatedAssignmentTriple(); if (evaluatedAssignmentTriple == null) { return; } StringBuilder compositeMessageSb = new StringBuilder(); evaluatedAssignmentTriple.accept(assignment -> { enforceTriggeredRules(compositeMessageSb, assignment.getFocusPolicyRules()); enforceTriggeredRules(compositeMessageSb, assignment.getAllTargetsPolicyRules()); }); if (compositeMessageSb.length() != 0) { throw new PolicyViolationException(compositeMessageSb.toString()); } } private <F extends FocusType> void enforceTriggeredRules(StringBuilder compositeMessageSb, Collection<EvaluatedPolicyRule> policyRules) { for (EvaluatedPolicyRule policyRule: policyRules) { Collection<EvaluatedPolicyRuleTrigger<?>> triggers = policyRule.getTriggers(); if (triggers.isEmpty()) { continue; } if (!isEnforce(policyRule)) { continue; } for (EvaluatedPolicyRuleTrigger trigger: triggers) { if (trigger.getMessage() != null) { if (compositeMessageSb.length() != 0) { compositeMessageSb.append("; "); } compositeMessageSb.append(trigger.getMessage()); } } } } private boolean isEnforce(EvaluatedPolicyRule policyRule) { PolicyActionsType actions = policyRule.getActions(); if (actions == null) { // enforce is NO LONGER the default return false; } EnforcementPolicyActionType enforcement = actions.getEnforcement(); if (enforcement == null) { return false; } return true; } /* (non-Javadoc) * @see com.evolveum.midpoint.model.api.hooks.ChangeHook#invokeOnException(com.evolveum.midpoint.model.api.context.ModelContext, java.lang.Throwable, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult) */ @Override public void invokeOnException(@NotNull ModelContext context, @NotNull Throwable throwable, @NotNull Task task, @NotNull OperationResult result) { // Nothing to do } }