Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Aug 8, 2023
2 parents 6acc6b9 + b6f5590 commit efd97c4
Show file tree
Hide file tree
Showing 112 changed files with 2,675 additions and 933 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ public abstract class ConfigurationItemOrigin implements Serializable {
* Use with care! Careless use of this origin may render expression profiles ineffective.
*/
public static ConfigurationItemOrigin undetermined() {
return new ConfigurationItemOrigin.Undetermined();
return new ConfigurationItemOrigin.Undetermined(false);
}

/** Undetermined but safe, because it is never used to determine the expression profile. */
public static ConfigurationItemOrigin undeterminedSafe() {
return new ConfigurationItemOrigin.Undetermined(true);
}

/** Use with care! Careless use of this origin may render expression profiles ineffective. */
Expand Down Expand Up @@ -132,11 +137,29 @@ public ConfigurationItemOrigin child(Object... pathSegments) {
/** Returns the description of the origin, e.g. "in role:xxx(xxx) @assignment[102]/condition". */
public abstract @NotNull String fullDescription();

public @NotNull ConfigurationItemOrigin toApproximate() {
return this; // usually this is the case
}

/** Represents an origin we are not currently able to determine exactly. */
public static class Undetermined extends ConfigurationItemOrigin {

/**
* Safe means that it is safe to use this origin, as is is NEVER used to determine the expression profile.
* So, the possible damage is limited to imprecise information in error or diagnostic messages.
*
* OTOH, _unsafe_ means that this is a temporary situation during the migration to full implementation of expression
* profiles. Such cases should be found and fixed.
*/
private final boolean safe;

Undetermined(boolean safe) {
this.safe = safe;
}

@Override
public String toString() {
return "undetermined";
return safe ? "undetermined" : "undetermined (unsafe)";
}

@Override
Expand All @@ -146,7 +169,11 @@ public ConfigurationItemOrigin child(@NotNull ItemPath path) {

@Override
public @NotNull String fullDescription() {
return "(undetermined origin)";
return safe ? "(undetermined origin)" : "(undetermined origin; unsafe)";
}

public boolean isSafe() {
return safe;
}
}

Expand Down Expand Up @@ -212,6 +239,15 @@ private InObject(
this.precise = precise;
}

@Override
public @NotNull ConfigurationItemOrigin toApproximate() {
if (precise) {
return new InObject(originatingObject, path, false);
} else {
return this;
}
}

public @NotNull ObjectType getOriginatingObject() {
return originatingObject;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.config;

import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType;
import org.jetbrains.annotations.NotNull;

/** Currently used for custom event handlers, as they are security-sensitive. */
public class EventHandlerConfigItem
extends ConfigurationItem<EventHandlerType>
implements PrivilegesMixin<EventHandlerType> {

@SuppressWarnings("unused") // called dynamically
public EventHandlerConfigItem(@NotNull ConfigurationItem<EventHandlerType> original) {
super(original);
}

protected EventHandlerConfigItem(@NotNull EventHandlerType value, @NotNull ConfigurationItemOrigin origin) {
super(value, origin);
}

public static EventHandlerConfigItem of(@NotNull EventHandlerType bean, @NotNull ConfigurationItemOrigin origin) {
return new EventHandlerConfigItem(bean, origin);
}

public static EventHandlerConfigItem of(
@NotNull EventHandlerType bean,
@NotNull OriginProvider<? super EventHandlerType> originProvider) {
return new EventHandlerConfigItem(bean, originProvider.origin(bean));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,12 @@ public abstract class SchemaConstants {
/** ID of "allow all" expression profile. */
public static final String FULL_EXPRESSION_PROFILE_ID = "##full";

/** ID of "allow none" expression profile. */
public static final String NONE_EXPRESSION_PROFILE_ID = "##none";

/** ID of "legacy unprivileged mode" expression profile for scripting (bulk actions). */
public static final String LEGACY_UNPRIVILEGED_SCRIPTING_PROFILE_ID = "##legacyUnprivilegedScripting";

/**
* The ID for built-in Groovy permission and script expression profiles.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.error;

import java.util.ArrayList;
import java.util.List;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ExceptionUtil;
import com.evolveum.midpoint.util.annotation.Experimental;

/**
* PoC implementation of dumping a "logical" stack, consisting of a sequence of nested {@link OperationResult} objects.
*
* Should produce something like this:
*
* ----
* Already evaluated: EvaluatedPolicyRuleImpl(create-children-on-new-project-creation)
* at com.evolveum.midpoint.model.api.ModelService.executeChanges (UNKNOWN)
* [p]options=null
* at com.evolveum.midpoint.model.impl.lens.Clockwork.run (FATAL_ERROR)
* at com.evolveum.midpoint.model.impl.lens.Clockwork.runWithConflictDetection (FATAL_ERROR)
* at com.evolveum.midpoint.model.impl.lens.Clockwork.click (FATAL_ERROR)
* [c]task=Task(id:1691493171681-1613-1, name:null, oid:null)
* [c]context=LensContext(s=SECONDARY, W(e=1,p=1): LensFocusContext(OrgType:28cc620b-3122-4d74-954c-93f5ea0d8c00), [])
* at com.evolveum.midpoint.model.impl.lens.projector.Projector.project (FATAL_ERROR)
* [p]fromStart=true
* [c]projectionWave=1
* at com.evolveum.midpoint.model.impl.lens.projector.Projector.focus (FATAL_ERROR)
* at com.evolveum.midpoint.model.impl.lens.projector.Projector.focusPolicyRules (FATAL_ERROR)
* at com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyRuleEvaluator.evaluateRule (FATAL_ERROR)
* [p]policyRule=create-children-on-new-project-creation:(omod)->(executeX)
* [p]policyRuleId=4d3280a1-6514-4984-ac2c-7e56c05af258:3
* [c]context=org: ariane5 (OID:28cc620b-3122-4d74-954c-93f5ea0d8c00) / AFTER
* -----
*/
@Experimental
public class ErrorStackDumper {

public static String dump(@NotNull Throwable throwable, @NotNull OperationResult result) {
for (var cause : ExceptionUtil.getCausesFromBottomUp(throwable)) {
var path = findInResult(result, cause);
if (path != null) {
return dump(path);
}
}
return "(no dump available)";
}

private static String dump(List<OperationResult> path) {
StringBuilder sb = new StringBuilder();
var message = getMessage(path);
if (message != null) {
sb.append(message).append("\n");
}
for (OperationResult result : path) {
result.dumpBasicInfo(sb, "at ", 1);
}
return sb.toString();
}

private static String getMessage(List<OperationResult> path) {
for (OperationResult result : path) {
var msg = result.getMessage();
if (msg != null) {
return msg;
}
}
return null;
}

private static List<OperationResult> findInResult(@NotNull OperationResult root, @NotNull Throwable cause) {
List<OperationResult> workingPath = new ArrayList<>();
if (tryFinding(workingPath, root, cause)) {
return workingPath;
} else {
return null;
}
}

private static boolean tryFinding(List<OperationResult> workingPath, OperationResult result, Throwable cause) {
workingPath.add(result);
for (OperationResult child : result.getSubresults()) {
if (tryFinding(workingPath, child, cause)) {
return true; // return immediately - we have found the path in a child
}
}
if (matches(result, cause)) {
return true; // not in child, but maybe in us?
}
// nope, not in us nor in our children
workingPath.remove(workingPath.size() - 1);
return false;
}

private static boolean matches(OperationResult result, Throwable cause) {
return result.getCause() == cause;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public class ExpressionEvaluatorsProfile implements Serializable {
AccessDecision.ALLOW,
List.of());

/** "Allow none" profile. */
private static final ExpressionEvaluatorsProfile NONE = new ExpressionEvaluatorsProfile(
AccessDecision.DENY,
List.of());

public ExpressionEvaluatorsProfile(
@NotNull AccessDecision defaultDecision,
@NotNull List<ExpressionEvaluatorProfile> evaluatorProfiles) {
Expand All @@ -46,6 +51,10 @@ public ExpressionEvaluatorsProfile(
return FULL;
}

public static @NotNull ExpressionEvaluatorsProfile none() {
return NONE;
}

public @NotNull AccessDecision getDefaultDecision() {
return defaultDecision;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ public class ExpressionProfile implements Serializable { // TODO: DebugDumpable
ScriptingProfile.full(), // TODO what about scripts etc that currently require #all authorization?
FunctionLibrariesProfile.full());

/**
* Profile that mimics the legacy non-root behavior for bulk actions:
* no expressions - this limits all of "execute-script", "notification" (with unsafe custom event handler), and
* the new "evaluate-expression" actions.
*/
private static final ExpressionProfile SCRIPTING_LEGACY_UNPRIVILEGED = new ExpressionProfile(
SchemaConstants.LEGACY_UNPRIVILEGED_SCRIPTING_PROFILE_ID,
ExpressionEvaluatorsProfile.none(),
ScriptingProfile.full(), // actions without scripts/expressions are safe
FunctionLibrariesProfile.none());

/**
* Identifier of the expression profile, referencable from e.g. archetypes on which it is used.
*
Expand Down Expand Up @@ -60,6 +71,10 @@ public ExpressionProfile(
return FULL;
}

public static @NotNull ExpressionProfile scriptingLegacyUnprivileged() {
return SCRIPTING_LEGACY_UNPRIVILEGED;
}

public @NotNull String getIdentifier() {
return identifier;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public class FunctionLibrariesProfile extends AbstractSecurityProfile {
AccessDecision.ALLOW,
Map.of());

/** "Allow nothing" profile. */
private static final FunctionLibrariesProfile NONE = new FunctionLibrariesProfile(
SchemaConstants.NONE_EXPRESSION_PROFILE_ID,
AccessDecision.DENY,
Map.of());

private FunctionLibrariesProfile(
@NotNull String identifier,
@NotNull AccessDecision defaultDecision,
Expand All @@ -44,6 +50,10 @@ private FunctionLibrariesProfile(
return FULL;
}

public static @NotNull FunctionLibrariesProfile none() {
return NONE;
}

public static FunctionLibrariesProfile of(@NotNull FunctionLibrariesProfileType bean) throws ConfigurationException {
String identifier = MiscUtil.configNonNull(bean.getIdentifier(), "No identifier in libraries profile %s", bean);
Map<String, FunctionLibraryProfile> libraryProfileMap = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@
*/
package com.evolveum.midpoint.schema.expression;

import com.evolveum.midpoint.schema.AccessDecision;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import com.evolveum.midpoint.schema.constants.SchemaConstants;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.schema.AccessDecision;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptingActionProfileType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptingProfileType;

import org.jetbrains.annotations.NotNull;

import java.io.Serializable;
import java.util.*;

/**
* Specifies limitations on the use of a scripting actions. It is a compiled form of a {@link ScriptingProfileType}.
*
Expand Down

0 comments on commit efd97c4

Please sign in to comment.