/// <summary> /// Creates a new runtime policy set evaluation. /// </summary> /// <param name="engine">The evaluation engine.</param> /// <param name="policySet">The policy set defined in the policy document.</param> public PolicySet(EvaluationEngine engine, PolicySetElement policySet) { if (engine == null) { throw new ArgumentNullException("engine"); } if (policySet == null) { throw new ArgumentNullException("policySet"); } _policySet = policySet; // Create a runtime target of this policy set. if (policySet.Target != null) { _target = new Target((TargetElement)policySet.Target); foreach (ResourceElement resource in policySet.Target.Resources.ItemsList) { foreach (ResourceMatchElement rmatch in resource.Match) { if (!_allResources.Contains(rmatch.AttributeValue.Contents)) { _allResources.Add(rmatch.AttributeValue.Contents); } } } } // Add all the policies (or policy set) inside this policy set. foreach (object child in policySet.Policies) { var childPolicySet = child as PolicySetElement; var childPolicyElement = child as PolicyElement; var childPolicySetIdReference = child as PolicySetIdReferenceElement; var childPolicyIdReferenceElement = child as PolicyIdReferenceElement; if (childPolicySet != null) { var policySetEv = new PolicySet(engine, childPolicySet); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else if (childPolicyElement != null) { var policyEv = new Policy(childPolicyElement); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else if (childPolicySetIdReference != null) { PolicySetElement policySetDefinition = EvaluationEngine.Resolve(childPolicySetIdReference); if (policySetDefinition != null) { var policySetEv = new PolicySet(engine, policySetDefinition); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policyset_reference_not_resolved, ((PolicySetIdReferenceElement)child).PolicySetId)); } } else if (childPolicyIdReferenceElement != null) { PolicyElement policyDefinition = EvaluationEngine.Resolve(childPolicyIdReferenceElement); if (policyDefinition != null) { var policyEv = new Policy(policyDefinition); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policy_reference_not_resolved, ((PolicyIdReferenceElement)child).PolicyId)); } } } }
/// <summary> /// Evaluate the context document using a specified policy /// </summary> /// <param name="policyDocument">The policy instance</param> /// <param name="contextDocument">The context document instance</param> /// <returns>The response document</returns> public ctx.ResponseElement Evaluate(pol.PolicyDocument policyDocument, ctx.ContextDocument contextDocument) { if (policyDocument == null) throw new ArgumentNullException("policyDocument"); if (contextDocument == null) throw new ArgumentNullException("contextDocument"); var context = new EvaluationContext(this, policyDocument, contextDocument); context.Trace("Start evaluation"); context.AddIndent(); // Check if both documents are valid if (!policyDocument.IsValidDocument || !contextDocument.IsValidDocument) { // If a validation error was found a response is created with the syntax error message var response = new ctx.ResponseElement( new[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement(Consts.ContextSchema.StatusCodes.SyntaxError, null, policyDocument.Version ), null, null, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version); return response; } // Create a new response contextDocument.Response = new ctx.ResponseElement((ctx.ResultElement[])null, policyDocument.Version); try { // Create the evaluable policy intance IMatchEvaluable policy = null; if (policyDocument.PolicySet != null) { policy = new PolicySet(this, (pol.PolicySetElement)policyDocument.PolicySet); } else if (policyDocument.Policy != null) { policy = new Policy((pol.PolicyElement)policyDocument.Policy); } // Evaluate the policy or policy set if (policy != null) { // Creates the evaluable policy set if (policy.AllResources.Count == 0) { policy.AllResources.Add(""); } string requestedResourceString = String.Empty; Uri requestedResource = null; foreach (ctx.ResourceElement resource in contextDocument.Request.Resources) { // Keep the requested resource if (resource.IsHierarchical) { foreach (ctx.AttributeElement attribute in resource.Attributes) { if (attribute.AttributeId == Consts.ContextSchema.ResourceElement.ResourceId) { if (context.PolicyDocument.Version == XacmlVersion.Version10 || context.PolicyDocument.Version == XacmlVersion.Version11) { requestedResourceString = attribute.AttributeValues[0].Contents; } else { if (attribute.AttributeValues.Count > 1) { throw new NotSupportedException("resources contains a bag of values"); } requestedResourceString = attribute.AttributeValues[0].Contents; } } } if (!string.IsNullOrEmpty(requestedResourceString)) { requestedResource = new Uri(requestedResourceString); } } // Iterate through the policy resources evaluating each resource in the context document request foreach (string resourceName in policy.AllResources) { bool mustEvaluate = false; if (resource.IsHierarchical) { //Validate if the resource is hierarchically desdendant or children //of the requested resource Uri policyResource = new Uri(resourceName); Debug.Assert(requestedResource != null, "requestedResource != null"); if (!(mustEvaluate = requestedResource.Equals(policyResource))) { // Perform the hierarchical evaluation if (resource.ResourceScopeValue == ctx.ResourceScope.Children) { mustEvaluate = typ.AnyUri.IsChildrenOf(requestedResource, policyResource); } else if (resource.ResourceScopeValue == ctx.ResourceScope.Descendants) { mustEvaluate = typ.AnyUri.IsDescendantOf(requestedResource, policyResource); } } if (mustEvaluate) { foreach (ctx.AttributeElementReadWrite attribute in context.CurrentResource.Attributes) { if (attribute.AttributeId == Consts.ContextSchema.ResourceElement.ResourceId) { attribute.AttributeValues[0].Contents = resourceName; break; } } } } else { context.CurrentResource = resource; mustEvaluate = true; } if (mustEvaluate) { // Evaluates the policy set Decision decision = policy.Evaluate(context); // Create a status code using the policy execution state ctx.StatusCodeElement scode; if (context.IsMissingAttribute) { scode = new ctx.StatusCodeElement( Consts.ContextSchema.StatusCodes.MissingAttribute, null, policyDocument.Version); } else if (context.ProcessingError) { scode = new ctx.StatusCodeElement( Consts.ContextSchema.StatusCodes.ProcessingError, null, policyDocument.Version); } else { scode = new ctx.StatusCodeElement( Consts.ContextSchema.StatusCodes.Ok, null, policyDocument.Version); } //Stop the iteration if there is not a hierarchical request if (!resource.IsHierarchical) { // Ussually when a single resource is requested the ResourceId is not specified in the result var oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement("", decision, new ctx.StatusElement(scode, "", "", policyDocument.Version), oblig.Obligations, policyDocument.Version)); break; } else { // Adding a resource for each requested resource, using the resourceName as the resourceId of the result var oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement(resourceName, decision, new ctx.StatusElement(scode, "", "", policyDocument.Version), oblig.Obligations, policyDocument.Version)); } } // if( mustEvaluate ) } // foreach( string resourceName in policy.AllResources ) } } //if( policy != null ) } catch (EvaluationException e) { // If a validation error was found a response is created with the syntax error message contextDocument.Response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement(Consts.ContextSchema.StatusCodes.ProcessingError, null, policyDocument.Version ), e.Message, e.StackTrace, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version); } return contextDocument.Response; }
/// <summary> /// Creates a new runtime policy set evaluation. /// </summary> /// <param name="engine">The evaluation engine.</param> /// <param name="policySet">The policy set defined in the policy document.</param> public PolicySet(EvaluationEngine engine, PolicySetElement policySet) { if (engine == null) throw new ArgumentNullException("engine"); if (policySet == null) throw new ArgumentNullException("policySet"); _policySet = policySet; // Create a runtime target of this policy set. if (policySet.Target != null) { _target = new Target((TargetElement)policySet.Target); foreach (ResourceElement resource in policySet.Target.Resources.ItemsList) { foreach (ResourceMatchElement rmatch in resource.Match) { if (!_allResources.Contains(rmatch.AttributeValue.Contents)) { _allResources.Add(rmatch.AttributeValue.Contents); } } } } // Add all the policies (or policy set) inside this policy set. foreach (object child in policySet.Policies) { var childPolicySet = child as PolicySetElement; var childPolicyElement = child as PolicyElement; var childPolicySetIdReference = child as PolicySetIdReferenceElement; var childPolicyIdReferenceElement = child as PolicyIdReferenceElement; if (childPolicySet != null) { var policySetEv = new PolicySet(engine, childPolicySet); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else if (childPolicyElement != null) { var policyEv = new Policy(childPolicyElement); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else if (childPolicySetIdReference != null) { PolicySetElement policySetDefinition = EvaluationEngine.Resolve(childPolicySetIdReference); if (policySetDefinition != null) { var policySetEv = new PolicySet(engine, policySetDefinition); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policyset_reference_not_resolved, ((PolicySetIdReferenceElement)child).PolicySetId)); } } else if (childPolicyIdReferenceElement != null) { PolicyElement policyDefinition = EvaluationEngine.Resolve(childPolicyIdReferenceElement); if (policyDefinition != null) { var policyEv = new Policy(policyDefinition); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policy_reference_not_resolved, ((PolicyIdReferenceElement)child).PolicyId)); } } } }