Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
        }