public void StartChain(string effectExpression) { EffectExpression = effectExpression ?? throw new ArgumentNullException(nameof(effectExpression)); PolicyEffectType = ParsePolicyEffectType(EffectExpression); CanChain = true; Result = false; HitPolicyCount = 0; }
/// <summary> /// Merges all matching results collected by the enforcer into a single decision. /// </summary> /// <param name="policyEffectType"></param> /// <param name="effects"></param> /// <param name="results"></param> /// <returns></returns> private bool MergeEffects(PolicyEffectType policyEffectType, Span <Effect> effects, Span <float> results) { bool finalResult = false; foreach (var effect in effects) { if (EffectEvaluator.TryEvaluate(effect, policyEffectType, ref finalResult)) { return(finalResult); } } return(finalResult); }
/// <summary> /// Merges all matching results collected by the enforcer into a single decision. /// </summary> /// <param name="policyEffectType"></param> /// <param name="effects"></param> /// <param name="results"></param> /// <param name="hitPolicyIndex"></param> /// <returns></returns> private static bool MergeEffects(PolicyEffectType policyEffectType, Span <Effect> effects, Span <float> results, out int hitPolicyIndex) { bool finalResult = false; hitPolicyIndex = -1; for (int index = 0; index < effects.Length; index++) { if (EffectEvaluator.TryEvaluate(effects[index], policyEffectType, ref finalResult, out bool hitPolicy)) { if (hitPolicy) { hitPolicyIndex = index; } return(finalResult); } } return(finalResult); }
internal static bool TryEvaluate(Effect.Effect effect, PolicyEffectType policyEffectType, ref bool result, out bool hitPolicy) { hitPolicy = false; switch (policyEffectType) { case PolicyEffectType.AllowOverride: { result = false; if (effect is Effect.Effect.Allow) { result = true; hitPolicy = true; return(true); } } break; case PolicyEffectType.DenyOverride: { result = true; if (effect is Effect.Effect.Deny) { result = false; hitPolicy = true; return(true); } } break; case PolicyEffectType.AllowAndDeny: switch (effect) { case Effect.Effect.Allow: result = true; hitPolicy = true; return(false); case Effect.Effect.Deny: result = false; hitPolicy = true; return(true); } break; case PolicyEffectType.Priority: switch (effect) { case Effect.Effect.Allow: result = true; hitPolicy = true; return(true); case Effect.Effect.Deny: result = false; hitPolicy = true; return(true); } break; case PolicyEffectType.Custom: // TODO: Support custom policy effect. break; default: throw new NotSupportedException("Not supported policy effect type."); } return(false); }
/// <summary> /// Decides whether a "subject" can access a "object" with the operation /// "action", input parameters are usually: (sub, obj, act). /// </summary> /// <param name="requestValues">The request needs to be mediated, usually an array of strings, /// can be class instances if ABAC is used.</param> /// <param name="matcher">The custom matcher.</param> /// <param name="explains">Collection of matched policy explains</param> /// <returns>Whether to allow the request.</returns> private bool InternalEnforce(IReadOnlyList <object> requestValues, string matcher = null, ICollection <IEnumerable <string> > explains = null) { var context = EnforceContext.Create(model, matcher, explains is not null); if (context.RequestTokens.Count != requestValues.Count) { throw new ArgumentException($"Invalid request size: expected {context.RequestTokens.Count}, got {requestValues.Count}."); } ExpressionHandler.SetRequestParameters(requestValues); IChainEffector chainEffector = _effector as IChainEffector; PolicyEffectType effectType = chainEffector.PolicyEffectType; if (chainEffector is not null) { return(InternalEnforceWithChainEffector(context, chainEffector, requestValues, explains)); } if (effectType is PolicyEffectType.PriorityDenyOverride) { ThrowHelper.ThrowNotSupportException($"Only {nameof(IChainEffector)} support {nameof(PolicyEffectType.PriorityDenyOverride)} policy effect expression."); } bool finalResult = false; int hitPolicyIndex; int policyCount = context.Policies.Count; if (policyCount != 0) { Effect.Effect[] policyEffects = new Effect.Effect[policyCount]; for (int i = 0; i < context.Policies.Count; i++) { IReadOnlyList <string> policyValues = context.Policies[i]; if (context.PolicyTokens.Count != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {context.PolicyTokens.Count}, got {policyValues.Count}."); } ExpressionHandler.SetPolicyParameters(policyValues); bool expressionResult; if (context.HasEval) { string expressionStringWithRule = RewriteEval(context.Matcher, ExpressionHandler.PolicyTokens, policyValues); expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues); } else { expressionResult = ExpressionHandler.Invoke(context.Matcher, requestValues); } var nowEffect = GetEffect(expressionResult); if (nowEffect is Effect.Effect.Indeterminate) { policyEffects[i] = nowEffect; continue; } if (ExpressionHandler.Parameters.TryGetValue("p_eft", out Parameter parameter)) { string policyEffect = parameter.Value as string; nowEffect = policyEffect switch { "allow" => Effect.Effect.Allow, "deny" => Effect.Effect.Deny, _ => Effect.Effect.Indeterminate }; } policyEffects[i] = nowEffect; if (context.Effect.Equals(PermConstants.PolicyEffect.Priority)) { break; } } finalResult = _effector.MergeEffects(context.Effect, policyEffects, null, out hitPolicyIndex); } else { if (context.HasEval) { throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher"); } IReadOnlyList <string> policyValues = Enumerable.Repeat(string.Empty, context.PolicyTokens.Count).ToArray(); ExpressionHandler.SetPolicyParameters(policyValues); Effect.Effect nowEffect = GetEffect(ExpressionHandler.Invoke(context.Matcher, requestValues)); finalResult = _effector.MergeEffects(context.Effect, new[] { nowEffect }, null, out hitPolicyIndex); } if (context.Explain && hitPolicyIndex is not - 1) { explains.Add(context.Policies[hitPolicyIndex]); } #if !NET45 if (context.Explain) { Logger?.LogEnforceResult(requestValues, finalResult, explains); } else { Logger?.LogEnforceResult(requestValues, finalResult); } #endif return(finalResult); }