/// <summary> /// Resolve the attribute desingator that can't be found in the context document /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="designator">The attribute designator instance</param> public static ctx.AttributeElement GetAttribute(EvaluationContext context, pol.AttributeDesignatorBase designator) { // Resolve internal attributes switch (designator.AttributeId) { case Consts.ContextSchema.EnvironmentAttributes.CurrentDate: return new ctx.AttributeElement( designator.AttributeId, Consts.Schema1.InternalDataTypes.XsdDate, null, null, XmlConvert.ToString(DateTime.Now, "yyyy-MM-dd"), designator.SchemaVersion); case Consts.ContextSchema.EnvironmentAttributes.CurrentTime: return new ctx.AttributeElement( designator.AttributeId, Consts.Schema1.InternalDataTypes.XsdTime, null, null, XmlConvert.ToString(DateTime.Now, "HH:mm:sszzzzzz"), designator.SchemaVersion); case Consts.ContextSchema.EnvironmentAttributes.CurrentDateTime: return new ctx.AttributeElement( designator.AttributeId, Consts.Schema1.InternalDataTypes.XsdDateTime, null, null, XmlConvert.ToString(DateTime.Now, "yyyy-MM-ddTHH:mm:sszzzzzz"), designator.SchemaVersion); default: { if (Configuration.ConfigurationRoot.Config != null) { // Search for attributes in the configured repositories foreach (IAttributeRepository repository in Configuration.ConfigurationRoot.Config.AttributeRepositories) { ctx.AttributeElement attribute = repository.GetAttribute(context, designator); if (attribute != null) { return attribute; } } } return null; } } }
/// <summary> /// Search for the attribute in the context target item using the attribute designator specified. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="attributeDesignator">The attribute designator instance.</param> /// <param name="targetItem">The target item to search in.</param> /// <returns>A bag value with the values of the attributes found.</returns> public static BagValue FindAttribute(EvaluationContext context, pol.AttributeDesignatorBase attributeDesignator, ctx.TargetItemBase targetItem) { var bag = new BagValue(GetDataType(attributeDesignator.DataType)); foreach (ctx.AttributeElement attribute in targetItem.Attributes) { if (attribute.Match(attributeDesignator)) { context.Trace("Adding target item attribute designator: {0}", attribute.ToString()); bag.Add(attribute); } } return bag; }
/// <summary> /// Solves the attribute designator in the context document using the attribute designator type /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="attributeDesignator">The attribute designator to resolve</param> /// <returns>A bag value with the values found in the context document</returns> public static BagValue Resolve(EvaluationContext context, pol.AttributeDesignatorBase attributeDesignator) { if (attributeDesignator is SubjectAttributeDesignatorElement) { if (context.ContextDocument.Request != null && context.ContextDocument.Request.Subjects != null) { var bag = new BagValue(GetDataType(attributeDesignator.DataType)); foreach (ctx.SubjectElement subject in context.ContextDocument.Request.Subjects) { if (((SubjectAttributeDesignatorElement)attributeDesignator).SubjectCategory == null || ((SubjectAttributeDesignatorElement)attributeDesignator).SubjectCategory == subject.SubjectCategory) { foreach (ctx.AttributeElement attrib in FindAttribute(context, attributeDesignator, subject).Elements) { bag.Add(attrib); } } } return bag; } } else if (attributeDesignator is ResourceAttributeDesignatorElement) { if (context.ContextDocument.Request != null && context.CurrentResource != null) { return FindAttribute(context, attributeDesignator, context.CurrentResource); } else { return BagValue.Empty; } } else if (attributeDesignator is ActionAttributeDesignatorElement) { if (context.ContextDocument.Request != null && context.ContextDocument.Request.Action != null) { return FindAttribute(context, attributeDesignator, context.ContextDocument.Request.Action); } else { return BagValue.Empty; } } else if (attributeDesignator is EnvironmentAttributeDesignatorElement) { if (context.ContextDocument.Request != null && context.ContextDocument.Request.Environment != null) { return FindAttribute(context, attributeDesignator, context.ContextDocument.Request.Environment); } else { return BagValue.Empty; } } throw new EvaluationException(Properties.Resource.exc_invalid_attribute_designator); }
/// <summary> /// Resolves the PolicyReferenceId using the policy repository /// </summary> /// <param name="policyReference">The policy reference</param> /// <returns>The policy found</returns> public static pol.PolicyElement Resolve(pol.PolicyIdReferenceElement policyReference) { if (ConfigurationRoot.Config == null) return null; // Search for attributes in the configured repositories foreach (IPolicyRepository repository in ConfigurationRoot.Config.PolicyRepositories) { pol.PolicyElement policy = repository.GetPolicy(policyReference); if (policy != null) { return policy; } } return null; }
/// <summary> /// Resolves the AttributeSelector in the context document using the XPath sentence. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="attributeSelector">The attribute selector.</param> /// <returns>A bag of values with the contents of the node.</returns> public static BagValue Resolve(EvaluationContext context, pol.AttributeSelectorElement attributeSelector) { var bagValue = new BagValue(GetDataType(attributeSelector.DataType)); var content = (ctx.ResourceContentElement)context.CurrentResource.ResourceContent; if (content != null) { XmlDocument doc = context.ContextDocument.XmlDocument; if (context.ContextDocument.XmlNamespaceManager == null) { context.ContextDocument.AddNamespaces(context.PolicyDocument.Namespaces); } try { string xpath = attributeSelector.RequestContextPath; Debug.Assert(doc.DocumentElement != null, "doc.DocumentElement != null"); XmlNodeList nodeList = doc.DocumentElement.SelectNodes(xpath, context.ContextDocument.XmlNamespaceManager); if (nodeList != null) { foreach (XmlNode node in nodeList) { var ave = new pol.AttributeValueElement( attributeSelector.DataType, node.InnerText, attributeSelector.SchemaVersion); bagValue.Add(ave); } } } catch (XPathException e) { context.Trace("ERR: {0}", e.Message); bagValue = new BagValue(GetDataType(attributeSelector.DataType)); } } return bagValue; }
/// <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; }