/// <summary> /// Decides whether a "subject" can access a "object" with the operation /// "action", input parameters are usually: (sub, obj, act). /// </summary> /// <param name="explains"></param> /// <param name="requestValues">The request needs to be mediated, usually an array of strings, /// can be class instances if ABAC is used.</param> /// <returns>Whether to allow the request.</returns> private bool Enforce(IReadOnlyList <object> requestValues, ICollection <IEnumerable <string> > explains = null) { if (_enabled is false) { return(true); } bool explain = explains is not null; string effect = model.Model[PermConstants.Section.PolicyEffectSection][PermConstants.DefaultPolicyEffectType].Value; var policyList = model.Model[PermConstants.Section.PolicySection][PermConstants.DefaultPolicyType].Policy; int policyCount = model.Model[PermConstants.Section.PolicySection][PermConstants.DefaultPolicyType].Policy.Count; string expressionString = model.Model[PermConstants.Section.MatcherSection][PermConstants.DefaultMatcherType].Value; int requestTokenCount = ExpressionHandler.RequestTokens.Count; if (requestTokenCount != requestValues.Count) { throw new ArgumentException($"Invalid request size: expected {requestTokenCount}, got {requestValues.Count}."); } int policyTokenCount = ExpressionHandler.PolicyTokens.Count; ExpressionHandler.SetRequestParameters(requestValues); bool hasEval = Utility.HasEval(expressionString); bool finalResult = false; IChainEffector chainEffector = _effector as IChainEffector; bool isChainEffector = chainEffector is not null; if (isChainEffector) { chainEffector.StartChain(effect); if (policyCount is not 0) { foreach (var policyValues in policyList) { if (policyTokenCount != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}."); } ExpressionHandler.SetPolicyParameters(policyValues); bool expressionResult; if (hasEval) { string expressionStringWithRule = RewriteEval(expressionString, ExpressionHandler.PolicyTokens, policyValues); expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues); } else { expressionResult = ExpressionHandler.Invoke(expressionString, requestValues); } var nowEffect = GetEffect(expressionResult); if (nowEffect is not Effect.Effect.Indeterminate && 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 }; } bool chainResult = chainEffector.TryChain(nowEffect); if (explain && chainEffector.HitPolicy) { explains.Add(policyValues); } if (chainResult is false || chainEffector.CanChain is false) { break; } } finalResult = chainEffector.Result; } else { if (hasEval) { throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher"); } IReadOnlyList <string> policyValues = Enumerable.Repeat(string.Empty, policyTokenCount).ToArray(); ExpressionHandler.SetPolicyParameters(policyValues); var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues)); if (chainEffector.TryChain(nowEffect)) { finalResult = chainEffector.Result; } if (explain && chainEffector.HitPolicy) { explains.Add(policyValues); } } #if !NET45 if (explain) { Logger?.LogEnforceResult(requestValues, finalResult, explains); } else { Logger?.LogEnforceResult(requestValues, finalResult); } #endif return(finalResult); } int hitPolicyIndex; if (policyCount != 0) { Effect.Effect[] policyEffects = new Effect.Effect[policyCount]; for (int i = 0; i < policyCount; i++) { IReadOnlyList <string> policyValues = policyList[i]; if (policyTokenCount != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}."); } ExpressionHandler.SetPolicyParameters(policyValues); bool expressionResult; if (hasEval) { string expressionStringWithRule = RewriteEval(expressionString, ExpressionHandler.PolicyTokens, policyValues); expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues); } else { expressionResult = ExpressionHandler.Invoke(expressionString, 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 (effect.Equals(PermConstants.PolicyEffect.Priority)) { break; } } finalResult = _effector.MergeEffects(effect, policyEffects, null, out hitPolicyIndex); } else { if (hasEval) { throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher"); } IReadOnlyList <string> policyValues = Enumerable.Repeat(string.Empty, policyTokenCount).ToArray(); ExpressionHandler.SetPolicyParameters(policyValues); var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues)); finalResult = _effector.MergeEffects(effect, new[] { nowEffect }, null, out hitPolicyIndex); } if (explain && hitPolicyIndex is not - 1) { explains.Add(policyList[hitPolicyIndex]); } #if !NET45 if (explain) { Logger?.LogEnforceResult(requestValues, finalResult, explains); } else { Logger?.LogEnforceResult(requestValues, finalResult); } #endif return(finalResult); }
/// <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> /// <returns>Whether to allow the request.</returns> public bool Enforce(params object[] requestValues) { if (!_enabled) { return(true); } string effect = model.Model[PermConstants.Section.PolicyEffectSection][PermConstants.DefaultPolicyEffectType].Value; var policyList = model.Model[PermConstants.Section.PolicySection][PermConstants.DefaultPolicyType].Policy; int policyCount = model.Model[PermConstants.Section.PolicySection][PermConstants.DefaultPolicyType].Policy.Count; string expressionString = model.Model[PermConstants.Section.MatcherSection][PermConstants.DefaultMatcherType].Value; int requestTokenCount = ExpressionHandler.RequestTokens.Count; if (requestTokenCount != requestValues.Length) { throw new ArgumentException($"Invalid request size: expected {requestTokenCount}, got {requestValues.Length}."); } int policyTokenCount = ExpressionHandler.PolicyTokens.Count; ExpressionHandler.SetRequestParameters(requestValues); bool hasEval = Utility.HasEval(expressionString); bool finalResult = false; IChainEffector chainEffector = _effector as IChainEffector; bool isChainEffector = chainEffector is not null; if (isChainEffector) { chainEffector.StartChain(effect); if (policyCount != 0) { foreach (var policyValues in policyList) { if (policyTokenCount != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}."); } ExpressionHandler.SetPolicyParameters(policyValues); bool expressionResult; if (hasEval) { string expressionStringWithRule = RewriteEval(expressionString, ExpressionHandler.PolicyTokens, policyValues); expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues); } else { expressionResult = ExpressionHandler.Invoke(expressionString, requestValues); } var nowEffect = GetEffect(expressionResult); if (nowEffect is not Effect.Effect.Indeterminate && 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 }; } if (chainEffector.TryChain(nowEffect) is false || chainEffector.CanChain is false) { break; } } finalResult = chainEffector.Result; } else { if (hasEval) { throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher"); } var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues)); if (chainEffector.TryChain(nowEffect)) { finalResult = chainEffector.Result; } } return(finalResult); } if (policyCount != 0) { Effect.Effect[] policyEffects = new Effect.Effect[policyCount]; for (int i = 0; i < policyCount; i++) { IReadOnlyList <string> policyValues = policyList[i]; if (policyTokenCount != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}."); } ExpressionHandler.SetPolicyParameters(policyValues); bool expressionResult; if (hasEval) { string expressionStringWithRule = RewriteEval(expressionString, ExpressionHandler.PolicyTokens, policyValues); expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues); } else { expressionResult = ExpressionHandler.Invoke(expressionString, 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 (effect.Equals(PermConstants.PolicyEffect.Priority)) { break; } } finalResult = _effector.MergeEffects(effect, policyEffects, null); } else { if (hasEval) { throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher"); } var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues)); finalResult = _effector.MergeEffects(effect, new[] { nowEffect }, null); } return(finalResult); }
/// <summary> /// Decides whether a "subject" can access a "object" with the operation /// "action", input parameters are usually: (sub, obj, act). Works specifically with IChainEffector /// </summary> /// <param name="context">Storage of enforcer variables</param> /// <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="explains">Collection of matched policy explains</param> /// <returns>Whether to allow the request.</returns> private bool InternalEnforceWithChainEffector( EnforceContext context, IChainEffector chainEffector, IReadOnlyList <object> requestValues = null, ICollection <IEnumerable <string> > explains = null) { bool finalResult = false; chainEffector.StartChain(context.Effect); bool hasPriority = context.PolicyAssertion.TryGetPriorityIndex(out int priorityIndex); bool isPriorityDenyOverrideEfffet = chainEffector.PolicyEffectType is PolicyEffectType.PriorityDenyOverride; int? priority = null; var nowEffect = Effect.Effect.Indeterminate; if (context.Policies.Count is not 0) { foreach (IReadOnlyList <string> policyValues in context.Policies) { if (context.PolicyTokens.Count != policyValues.Count) { throw new ArgumentException($"Invalid policy size: expected {context.PolicyTokens.Count}, got {policyValues.Count}."); } if (hasPriority && isPriorityDenyOverrideEfffet) { if (int.TryParse(policyValues[priorityIndex], out int nowPriority)) { if (priority.HasValue && nowPriority != priority.Value && chainEffector.HitPolicyCount > 0) { break; } priority = nowPriority; } } 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); } nowEffect = GetEffect(expressionResult); if (nowEffect is not Effect.Effect.Indeterminate && 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 }; } bool chainResult = chainEffector.TryChain(nowEffect); if (context.Explain && chainEffector.HitPolicy) { explains.Add(policyValues); } if (chainResult is false || chainEffector.CanChain is false) { break; } } finalResult = chainEffector.Result; } 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); nowEffect = GetEffect(ExpressionHandler.Invoke(context.Matcher, requestValues)); if (chainEffector.TryChain(nowEffect)) { finalResult = chainEffector.Result; } if (context.Explain && chainEffector.HitPolicy) { explains.Add(policyValues); } } #if !NET45 if (context.Explain) { Logger?.LogEnforceResult(requestValues, finalResult, explains); } else { Logger?.LogEnforceResult(requestValues, finalResult); } #endif return(finalResult); }