def _createXacmlRequestCtx(self, samlAuthzDecisionQuery):
        """Translate SAML authorisation decision query into a XACML request
        context
        @param authzDecisionQuery: SAML Authorisation Decision Query
        @type authzDecisionQuery: ndg.saml.saml2.core.AuthzDecisionQuery
        """
        xacmlRequest = _xacmlContext.request.Request()
        xacmlSubject = _xacmlContext.subject.Subject()
        
        xacmlAttributeValueFactory = XacmlAttributeValueClassFactory()
        
        openidSubjectAttribute = XacmlAttribute()
        roleAttribute = XacmlAttribute()
        
        openidSubjectAttribute.attributeId = \
                                samlAuthzDecisionQuery.subject.nameID.format
                                        
        XacmlAnyUriAttributeValue = xacmlAttributeValueFactory(
                                            XacmlAttributeValue.ANY_TYPE_URI)
        
        openidSubjectAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        
        openidSubjectAttribute.attributeValues.append(
                                                    XacmlAnyUriAttributeValue())
        openidSubjectAttribute.attributeValues[-1].value = \
                                samlAuthzDecisionQuery.subject.nameID.value
        
        xacmlSubject.attributes.append(openidSubjectAttribute)

        XacmlStringAttributeValue = xacmlAttributeValueFactory(
                                            XacmlAttributeValue.STRING_TYPE_URI)
                                  
        xacmlRequest.subjects.append(xacmlSubject)
        
        resource = _xacmlContext.resource.Resource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)
        
        resourceAttribute.attributeId = Identifiers.Resource.RESOURCE_ID
                            
        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = \
                                                samlAuthzDecisionQuery.resource

        xacmlRequest.resources.append(resource)
        
        xacmlRequest.action = _xacmlContext.action.Action()
        
        for action in samlAuthzDecisionQuery.actions:
            xacmlActionAttribute = XacmlAttribute()
            xacmlRequest.action.attributes.append(xacmlActionAttribute)
            
            xacmlActionAttribute.attributeId = Identifiers.Action.ACTION_ID
            xacmlActionAttribute.dataType = XacmlStringAttributeValue.IDENTIFIER
            xacmlActionAttribute.attributeValues.append(
                                                    XacmlStringAttributeValue())
            xacmlActionAttribute.attributeValues[-1].value = action.value
        
        return xacmlRequest
    def _createXacmlRequestCtx(self, samlAuthzDecisionQuery):
        """Translate SAML authorisation decision query into a XACML request
        context
        @param authzDecisionQuery: SAML Authorisation Decision Query
        @type authzDecisionQuery: ndg.saml.saml2.core.AuthzDecisionQuery
        """
        xacmlRequest = _xacmlContext.request.Request()
        xacmlSubject = _xacmlContext.subject.Subject()

        xacmlAttributeValueFactory = XacmlAttributeValueClassFactory()

        openidSubjectAttribute = XacmlAttribute()

        openidSubjectAttribute.attributeId = \
                                samlAuthzDecisionQuery.subject.nameID.format

        XacmlAnyUriAttributeValue = xacmlAttributeValueFactory(
            XacmlAttributeValue.ANY_TYPE_URI)

        openidSubjectAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER

        openidSubjectAttribute.attributeValues.append(
            XacmlAnyUriAttributeValue())
        openidSubjectAttribute.attributeValues[-1].value = \
                                samlAuthzDecisionQuery.subject.nameID.value

        xacmlSubject.attributes.append(openidSubjectAttribute)

        XacmlStringAttributeValue = xacmlAttributeValueFactory(
            XacmlAttributeValue.STRING_TYPE_URI)

        xacmlRequest.subjects.append(xacmlSubject)

        resource = _xacmlContext.resource.Resource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)

        resourceAttribute.attributeId = Identifiers.Resource.RESOURCE_ID

        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = \
                                                samlAuthzDecisionQuery.resource

        xacmlRequest.resources.append(resource)

        xacmlRequest.action = _xacmlContext.action.Action()

        for action in samlAuthzDecisionQuery.actions:
            xacmlActionAttribute = XacmlAttribute()
            xacmlRequest.action.attributes.append(xacmlActionAttribute)

            xacmlActionAttribute.attributeId = Identifiers.Action.ACTION_ID
            xacmlActionAttribute.dataType = XacmlStringAttributeValue.IDENTIFIER
            xacmlActionAttribute.attributeValues.append(
                XacmlStringAttributeValue())
            xacmlActionAttribute.attributeValues[-1].value = action.value

        return xacmlRequest
Exemplo n.º 3
0
 def create_string_attribute(self, attrib_id, id):
     attribute = Attribute()
     attribute.attributeId = attrib_id
     attribute.dataType = StringAttributeValue.IDENTIFIER
     attribute.attributeValues.append(StringAttributeValue())
     attribute.attributeValues[-1].value = id
     return attribute
Exemplo n.º 4
0
    def _createXacmlRequestCtx(self, resourceURI):
        """Wrapper to create a request context for a local PDP - see 
        isApplicableRequest
        
        :param resourceURI: URI of requested resource
        :type resourceURI: basestring
        """
        request = _xacmlCtx.request.Request()
        
        resource = _xacmlCtx.request.Resource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)
        
        resourceAttribute.attributeId = XacmlIdentifiers.Resource.RESOURCE_ID
                                        
        XacmlAnyUriAttributeValue = \
            self.__class__.XACML_ATTRIBUTEVALUE_CLASS_FACTORY(
                                            XacmlAttributeValue.ANY_TYPE_URI)
                                    
        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceURI

        request.resources.append(resource)
        
        return request
Exemplo n.º 5
0
 def create_string_attribute(self, attrib_id, id):
     attribute = Attribute()
     attribute.attributeId = attrib_id
     attribute.dataType = StringAttributeValue.IDENTIFIER
     attribute.attributeValues.append(StringAttributeValue())
     attribute.attributeValues[-1].value = id
     return attribute
Exemplo n.º 6
0
 def create_attribute(self, attrib_class, attrib_id, val):
     attribute = Attribute()
     attribute.attributeId = attrib_id
     attribute.dataType = attrib_class.IDENTIFIER
     attribute.attributeValues.append(attrib_class())
     attribute.attributeValues[-1].value = val
     return attribute
Exemplo n.º 7
0
 def create_attribute(self, attrib_class, attrib_id, val):
     attribute = Attribute()
     attribute.attributeId = attrib_id
     attribute.dataType = attrib_class.IDENTIFIER
     attribute.attributeValues.append(attrib_class())
     attribute.attributeValues[-1].value = val
     return attribute
Exemplo n.º 8
0
    def _createXacmlRequestCtx(self, resourceURI):
        """Wrapper to create a request context for a local PDP - see 
        is_applicable_request
        
        :param resourceURI: URI of requested resource
        :type resourceURI: basestring
        """
        request = _xacmlCtx.request.Request()

        resource = _xacmlCtx.request.Resource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)

        resourceAttribute.attributeId = XacmlIdentifiers.Resource.RESOURCE_ID

        XacmlAnyUriAttributeValue = \
            self.__class__.XACML_ATTRIBUTEVALUE_CLASS_FACTORY(
                                            XacmlAttributeValue.ANY_TYPE_URI)

        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceURI

        request.resources.append(resource)

        return request
    def _createXacmlRequestCtx(cls):
        """Helper to create a XACML request context"""
        ctx = Request()

        ctx.subjects.append(Subject())
        openidAttr = Attribute()
        ctx.subjects[-1].attributes.append(openidAttr)
        openidAttr.attributeId = cls.OPENID_ATTR_ID
        openidAttr.dataType = 'http://www.w3.org/2001/XMLSchema#anyURI'

        anyUriAttrValue = cls.attributeValueClassFactory(openidAttr.dataType)

        openidAttrVal = anyUriAttrValue(TestUserDatabase.OPENID_URI)
        openidAttr.attributeValues.append(openidAttrVal)

        return ctx
 def _createXacmlRequestCtx(cls):
     """Helper to create a XACML request context"""
     ctx = Request()
     
     ctx.subjects.append(Subject())
     openidAttr = Attribute()
     ctx.subjects[-1].attributes.append(openidAttr)
     openidAttr.attributeId = cls.OPENID_ATTR_ID
     openidAttr.dataType = 'http://www.w3.org/2001/XMLSchema#anyURI'
     
     anyUriAttrValue = cls.attributeValueClassFactory(openidAttr.dataType)
     
     openidAttrVal = anyUriAttrValue(cls.OPENID_URI)
     openidAttr.attributeValues.append(openidAttrVal) 
     
     return ctx
Exemplo n.º 11
0
    def fromXML(cls, elem):
        """Parse an ElementTree XACML Attribute element into a
        Attribute object
        
        @type elem: ElementTree.Element
        @param elem: ElementTree element containing the attribute
        @rtype: ndg.xacml.core.attribute.Attribute
        @return: Attribute object
        """
        localName = QName.getLocalPart(elem.tag)
        if localName != cls.ELEMENT_LOCAL_NAME:
            raise XMLParseError('No "%s" element found' % 
                                cls.ELEMENT_LOCAL_NAME)

        attribute = Attribute()

        # Handle attributes.
        attribute.attributeId = elem.get(Attribute.ATTRIBUTE_ID_ATTRIB_NAME)
        attribute.dataType = elem.get(Attribute.DATA_TYPE_ATTRIB_NAME)
        issuer = elem.get(Attribute.ISSUER_ATTRIB_NAME)
        if issuer is not None:
            attribute.issuer = issuer

        # Parse sub-elements
        if len(elem.getchildren()) == 0:
            raise XMLParseError("XACML context Attribute element has no "
                                "AttributeValues")
        AttributeValueClass = cls.attributeValueClassFactory(attribute.dataType)
        for childElem in getElementChildren(elem):
            localName = QName.getLocalPart(childElem.tag)

            if localName == Attribute.ATTRIBUTE_VALUE_ELEMENT_LOCAL_NAME:
                attributeValue = AttributeValueClass(childElem.text)
                attribute.attributeValues.append(attributeValue)

            else:
                raise XMLParseError("XACML context Request child element name "
                                    "%r not recognised" % localName)
        return attribute
Exemplo n.º 12
0
    def _create_request_ctx(resourceId, 
                          includeSubject=True,
                          subjectId=SUBJECT_ID,
                          subjectRoles=None,
                          roleAttributeId=ROLE_ATTRIBUTE_ID,
                          action='read',
                          resourceContent=None):
        """Create an example XACML Request Context for tests"""
        if subjectRoles is None:
            subjectRoles = ('staff',)
            
        request = Request()
        
        if includeSubject:
            subject = CtxSubject()
            openidSubjectAttribute = Attribute()
            
            openidSubjectAttribute.attributeId = "urn:esg:openid"
            openidSubjectAttribute.dataType = AnyUriAttributeValue.IDENTIFIER
            
            openidSubjectAttribute.attributeValues.append(
                                                        AnyUriAttributeValue())
            openidSubjectAttribute.attributeValues[-1].value = subjectId
                                        
            
            subject.attributes.append(openidSubjectAttribute)
    
            for role in subjectRoles:
                roleAttribute = Attribute()
                
                roleAttribute.attributeId = roleAttributeId
                roleAttribute.dataType = StringAttributeValue.IDENTIFIER
                
                roleAttribute.attributeValues.append(StringAttributeValue())
                roleAttribute.attributeValues[-1].value = role 
            
                subject.attributes.append(roleAttribute)
                                      
            request.subjects.append(subject)
        
        resource = ResourceCtx()
        resourceAttribute = Attribute()
        resource.attributes.append(resourceAttribute)
        
        resourceAttribute.attributeId = Identifiers.Resource.RESOURCE_ID
                            
        resourceAttribute.dataType = AnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(AnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceId

        resource.resourceContent = resourceContent

        request.resources.append(resource)
        
        request.action = Action()
        actionAttribute = Attribute()
        request.action.attributes.append(actionAttribute)
        
        actionAttribute.attributeId = Identifiers.Action.ACTION_ID
        actionAttribute.dataType = StringAttributeValue.IDENTIFIER
        actionAttribute.attributeValues.append(StringAttributeValue())
        actionAttribute.attributeValues[-1].value = action

        request.environment = Environment()
        
        return request
Exemplo n.º 13
0
    def attributeQuery(self, context, attributeDesignator):
        """Query this PIP for the given request context attribute specified by
        the attribute designator.  Nb. this implementation is only intended to
        accept queries for a given *subject* in the request

        @param context: the request context
        @type context: ndg.xacml.core.context.request.Request
        @param designator:
        @type designator: ndg.xacml.core.attributedesignator.SubjectAttributeDesignator
        @rtype: ndg.xacml.utils.TypedList(<attributeDesignator.dataType>) / None
        @return: attribute values found for query subject or None if none
        could be found
        @raise PIPConfigException: if attribute ID -> Attribute Authority
        mapping is empty
        """

        # Check the attribute designator type - this implementation takes
        # queries for request context subjects only
        if not isinstance(attributeDesignator, SubjectAttributeDesignator):
            log.debug('This PIP query interface can only accept subject '
                      'attribute designator related queries')
            return None

        attributeFormat = attributeDesignator.dataType
        attributeId = attributeDesignator.attributeId
        exptd_attribute_id = self.attribute_query.subject.nameID.format

        if not isinstance(context, XacmlRequestCtx):
            raise TypeError('Expecting %r type for context input; got %r' %
                            (XacmlRequestCtx, type(context)))

        # Look up mapping from request attribute ID to Attribute Authority to
        # query
        if len(self.__attributeId2AttributeAuthorityMap) == 0:
            raise PIPConfigException('No entries found in attribute ID to '
                                     'Attribute Authority mapping')

        attributeAuthorityURI = self.__attributeId2AttributeAuthorityMap.get(
            attributeId, None)
        if attributeAuthorityURI is None:
            log.debug(
                "No matching attribute authority endpoint found in "
                "mapping file %r for input attribute ID %r",
                self.mappingFilePath, attributeId)
            return None

        # Get subject from the request context
        subject = None
        subjectId = None
        for subject in context.subjects:
            for attribute in subject.attributes:
                if attribute.attributeId == exptd_attribute_id:
                    if len(attribute.attributeValues) != 1:
                        raise PIPRequestCtxException("Expecting a single "
                                                     "attribute value "
                                                     "for query subject ID")
                    subjectId = attribute.attributeValues[0].value
                    break

        if subjectId is None:
            raise PIPRequestCtxException('No subject found of type %r in '
                                         'request context' %
                                         exptd_attribute_id)
        elif not subjectId:
            # Empty string
            return None
        else:
            # Keep a reference to the matching Subject instance
            xacmlCtxSubject = subject

        # Check for cached attributes for this subject (i.e. user)
        # If none found send a query to the attribute authority
        assertions = None
        attributeIdFoundInCache = False
        if self.cacheSessions:
            attributeIdFoundInCache = False
            sessionCache = SessionCache(subjectId,
                                    data_dir=self.sessionCacheDataDir,
                                    timeout=self.sessionCacheTimeout,
                                    assertionClockSkewTolerance=\
                                        self.sessionCacheAssertionClockSkewTol)

            assertions = sessionCache.retrieve(attributeAuthorityURI)
            if assertions is not None:
                # Check for attributes matching the requested ID
                for assertion in assertions:
                    for statement in assertion.attributeStatements:
                        for attribute in statement.attributes:
                            if attribute.name == attributeId:
                                attributeIdFoundInCache = True
                                break

        if not attributeIdFoundInCache:
            # No cached assertions are available for this Attribute Authority,
            # for the required attribute ID - make a fresh call to the
            # Attribute Authority

            # Initialise the attribute to be queried for and add it to the
            # SAML query
            samlAttribute = SamlAttribute()
            samlAttribute.name = attributeId
            samlAttribute.nameFormat = attributeFormat

            # Copy attributes for this query from constants set at
            # initialisation
            query = AttributeQueryFactory.create()
            query.subject.nameID.value = subjectId
            query.subject.nameID.format = exptd_attribute_id
            query.issuer.value = self.attribute_query.issuer.value
            query.issuer.format = self.attribute_query.issuer.format
            query.attributes.append(samlAttribute)

            # Dispatch query
            try:
                response = self.attribute_query_binding.send(
                    query, uri=attributeAuthorityURI)

                log.debug('Retrieved response from attribute service %r',
                          attributeAuthorityURI)
            except Exception:
                log.exception(
                    'Error querying Attribute service %r with '
                    'subject %r', attributeAuthorityURI, subjectId)
                raise

            if assertions is None:
                assertions = SamlTypedList(SamlAssertion)

            assertions.extend(response.assertions)

            if self.cacheSessions:
                sessionCache.add(assertions, attributeAuthorityURI)

        # Unpack SAML assertion attribute corresponding to the name
        # format specified and copy into XACML attributes
        xacmlAttribute = XacmlAttribute()
        xacmlAttribute.attributeId = attributeId
        xacmlAttribute.dataType = attributeFormat

        # Create XACML class from SAML type identifier
        factory = self.__class__.XACML_ATTR_VAL_CLASS_FACTORY
        xacmlAttrValClass = factory(attributeFormat)

        for assertion in assertions:
            for statement in assertion.attributeStatements:
                for attribute in statement.attributes:
                    if attribute.nameFormat == attributeFormat:
                        # Convert SAML Attribute values to XACML equivalent
                        # types
                        for samlAttrVal in attribute.attributeValues:
                            # Instantiate and initial new XACML value
                            xacmlAttrVal = xacmlAttrValClass(
                                value=samlAttrVal.value)

                            xacmlAttribute.attributeValues.append(xacmlAttrVal)

        # Update the XACML request context subject with the new attributes
        matchFound = False
        for attr in xacmlCtxSubject.attributes:
            matchFound = attr.attributeId == attributeId
            if matchFound:
                # Weed out duplicates
                newAttrVals = [
                    attrVal for attrVal in xacmlAttribute.attributeValues
                    if attrVal not in attr.attributeValues
                ]
                attr.attributeValues.extend(newAttrVals)
                break

        if not matchFound:
            xacmlCtxSubject.attributes.append(xacmlAttribute)

        # Return the attributes to the caller to comply with the interface
        return xacmlAttribute.attributeValues
Exemplo n.º 14
0
    def _createXacmlProfileRequestCtx(subjectNameIdFormat, subjectNameId,
                                      resourceUri, resourceContent, actions):
        """Translate SAML authorisation decision query into a XACML request
        context
        :type subjectNameIdFormat: str
        :param subjectNameIdFormat: subject ID format
        :type subjectNameId: str
        :param subjectNameId: subject ID
        :type resourceUri: str
        :param resourceUri: resource URI
        :type resourceContent: ElementTree.Element
        :param resourceContent: data to include as resource content
        :type actions: list of str
        :param actions: action values
        """
        xacmlRequest = XacmlRequest()
        xacmlSubject = XacmlSubject()

        xacmlAttributeValueFactory = XacmlAttributeValueClassFactory()

        openidSubjectAttribute = XacmlAttribute()
        openidSubjectAttribute.attributeId = subjectNameIdFormat

        XacmlAnyUriAttributeValue = xacmlAttributeValueFactory(
            XacmlAttributeValue.ANY_TYPE_URI)

        openidSubjectAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        openidSubjectAttribute.attributeValues.append(
            XacmlAnyUriAttributeValue())
        openidSubjectAttribute.attributeValues[-1].value = subjectNameId

        xacmlSubject.attributes.append(openidSubjectAttribute)

        XacmlStringAttributeValue = xacmlAttributeValueFactory(
            XacmlAttributeValue.STRING_TYPE_URI)

        xacmlRequest.subjects.append(xacmlSubject)

        resource = XacmlResource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)
        if resourceContent is not None:
            resource.resourceContent = resourceContent

        resourceAttribute.attributeId = XacmlIdentifiers.Resource.RESOURCE_ID

        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceUri

        xacmlRequest.resources.append(resource)

        xacmlRequest.action = XacmlAction()

        for action in actions:
            xacmlActionAttribute = XacmlAttribute()
            xacmlRequest.action.attributes.append(xacmlActionAttribute)

            xacmlActionAttribute.attributeId = XacmlIdentifiers.Action.ACTION_ID
            xacmlActionAttribute.dataType = XacmlStringAttributeValue.IDENTIFIER
            xacmlActionAttribute.attributeValues.append(
                XacmlStringAttributeValue())
            xacmlActionAttribute.attributeValues[-1].value = action.value

        xacmlRequest.environment = XacmlEnvironment()

        return xacmlRequest
Exemplo n.º 15
0
# with no action and no target.
# It just has a subject telling us that the user
# is in the role 'adminstrators'
request = Request()

# Build up the "role" attribute
#   type:   http://www.w3.org/2001/XMLSchema#string
#   value:  administrator
attributeValueFactory = AttributeValueClassFactory()
role = attributeValueFactory("http://www.w3.org/2001/XMLSchema#string")
arole = role("administrator")

# Add the role-attribute to the request-subject
#   id:     urn:oasis:names:tc:xacml:2.0:example:attribute:role
attr = Attribute()
attr.attributeId = "urn:oasis:names:tc:xacml:2.0:example:attribute:role"
attr.dataType = role.IDENTIFIER  # = http://www.w3.org/2001/XMLSchema#string
attr.attributeValues.append(arole)

subject = Subject()
subject.attributes.append(attr)
request.subjects.append(subject)

# See what we've received as result
res = pdp.evaluate(request)
for result in res.results:
    print result.decision


"""
Exemplo n.º 16
0
 def attributeQuery(self, context, attributeDesignator):
     """Query this PIP for the given request context attribute specified by
     the attribute designator.  Nb. this implementation is only intended to
     accept queries for a given *subject* in the request
     
     @param context: the request context
     @type context: ndg.xacml.core.context.request.Request
     @param designator: 
     @type designator: ndg.xacml.core.attributedesignator.SubjectAttributeDesignator
     @rtype: ndg.xacml.utils.TypedList(<attributeDesignator.dataType>) / None
     @return: attribute values found for query subject or None if none 
     could be found
     @raise PIPConfigException: if attribute ID -> Attribute Authority 
     mapping is empty  
     """
     
     # Check the attribute designator type - this implementation takes
     # queries for request context subjects only
     if not isinstance(attributeDesignator, SubjectAttributeDesignator):
         log.debug('This PIP query interface can only accept subject '
                   'attribute designator related queries')
         return None
         
     attributeFormat = attributeDesignator.dataType
     attributeId = attributeDesignator.attributeId
     
     if not isinstance(context, XacmlRequestCtx):
         raise TypeError('Expecting %r type for context input; got %r' %
                         (XacmlRequestCtx, type(context)))
     
     # Look up mapping from request attribute ID to Attribute Authority to
     # query 
     if len(self.__attributeId2AttributeAuthorityMap) == 0:
         raise PIPConfigException('No entries found in attribute ID to '
                                  'Attribute Authority mapping')
         
     attributeAuthorityURI = self.__attributeId2AttributeAuthorityMap.get(
                                         attributeId, None)
     if attributeAuthorityURI is None:
         log.debug("No matching attribute authority endpoint found in "
                   "mapping file %r for input attribute ID %r", 
                   self.mappingFilePath, attributeId)
         return None
     
     # Get subject from the request context
     subject = None
     subjectId = None
     for subject in context.subjects:
         for attribute in subject.attributes:
             if attribute.attributeId == self.subjectAttributeId:
                 if len(attribute.attributeValues) != 1:
                     raise PIPRequestCtxException("Expecting a single "
                                                  "attribute value "
                                                  "for query subject ID")
                 subjectId = attribute.attributeValues[0].value
                 break
     
     if subjectId is None:
         raise PIPRequestCtxException('No subject found of type %r in '
                                      'request context' %
                                      self.subjectAttributeId)
     elif not subjectId:
         # Empty string
         return None
     else:
         # Keep a reference to the matching Subject instance
         xacmlCtxSubject = subject
         
     # Check for cached attributes for this subject (i.e. user)        
     # If none found send a query to the attribute authority
     assertions = None
     attributeIdFoundInCache = False
     if self.cacheSessions:
         attributeIdFoundInCache = False
         sessionCache = SessionCache(subjectId,
                                 data_dir=self.sessionCacheDataDir,
                                 timeout=self.sessionCacheTimeout,
                                 assertionClockSkewTolerance=\
                                     self.sessionCacheAssertionClockSkewTol)
         
         assertions = sessionCache.retrieve(attributeAuthorityURI)
         if assertions is not None:
             # Check for attributes matching the requested ID
             for assertion in assertions:
                 for statement in assertion.attributeStatements:
                     for attribute in statement.attributes:
                         if attribute.name == attributeId:
                             attributeIdFoundInCache = True
                             break
         
     if not attributeIdFoundInCache:
         # No cached assertions are available for this Attribute Authority,
         # for the required attribute ID - make a fresh call to the 
         # Attribute Authority 
         
         # Initialise the attribute to be queried for and add it to the 
         # SAML query
         samlAttribute = SamlAttribute()
         samlAttribute.name = attributeId
         samlAttribute.nameFormat = attributeFormat
         self.attributeQueryBinding.subjectIdFormat = \
                                                     self.subjectAttributeId
         query = self.attributeQueryBinding.makeQuery()
         query.attributes.append(samlAttribute)
         
         # Dispatch query
         try:
             self.attributeQueryBinding.setQuerySubjectId(query, subjectId)
             response = self.attributeQueryBinding.send(query,
                                                 uri=attributeAuthorityURI)
             
             log.debug('Retrieved response from attribute service %r',
                       attributeAuthorityURI)
         except Exception:
             log.exception('Error querying Attribute service %r with '
                           'subject %r', attributeAuthorityURI, subjectId)
             raise
         finally:
             # !Ensure relevant query attributes are reset ready for any 
             # subsequent query!
             self.attributeQueryBinding.subjectIdFormat = ''
     
         if assertions is None:
             assertions = SamlTypedList(SamlAssertion)
             
         assertions.extend(response.assertions)
         
         if self.cacheSessions:
             sessionCache.add(assertions, attributeAuthorityURI)
         
     # Unpack SAML assertion attribute corresponding to the name 
     # format specified and copy into XACML attributes      
     xacmlAttribute = XacmlAttribute()
     xacmlAttribute.attributeId = attributeId
     xacmlAttribute.dataType = attributeFormat
     
     # Create XACML class from SAML type identifier
     factory = self.__class__.XACML_ATTR_VAL_CLASS_FACTORY
     xacmlAttrValClass = factory(attributeFormat)
     
     for assertion in assertions:
         for statement in assertion.attributeStatements:
             for attribute in statement.attributes:
                 if attribute.nameFormat == attributeFormat:
                     # Convert SAML Attribute values to XACML equivalent 
                     # types
                     for samlAttrVal in attribute.attributeValues:  
                         # Instantiate and initial new XACML value
                         xacmlAttrVal = xacmlAttrValClass(
                                                     value=samlAttrVal.value)
                         
                         xacmlAttribute.attributeValues.append(xacmlAttrVal)
     
     # Update the XACML request context subject with the new attributes
     matchFound = False
     for attr in xacmlCtxSubject.attributes:
         matchFound = attr.attributeId == attributeId
         if matchFound:
             # Weed out duplicates
             newAttrVals = [attrVal 
                            for attrVal in xacmlAttribute.attributeValues 
                            if attrVal not in attr.attributeValues]
             attr.attributeValues.extend(newAttrVals)
             break
         
     if not matchFound:
         xacmlCtxSubject.attributes.append(xacmlAttribute)
     
     # Return the attributes to the caller to comply with the interface
     return xacmlAttribute.attributeValues
    def _createXacmlProfileRequestCtx(subjectNameIdFormat, subjectNameId,
                                      resourceUri, resourceContent, actions):
        """Translate SAML authorisation decision query into a XACML request
        context
        :type subjectNameIdFormat: str
        :param subjectNameIdFormat: subject ID format
        :type subjectNameId: str
        :param subjectNameId: subject ID
        :type resourceUri: str
        :param resourceUri: resource URI
        :type resourceContent: ElementTree.Element
        :param resourceContent: data to include as resource content
        :type actions: list of str
        :param actions: action values
        """
        xacmlRequest = XacmlRequest()
        xacmlSubject = XacmlSubject()
        
        xacmlAttributeValueFactory = XacmlAttributeValueClassFactory()
        
        openidSubjectAttribute = XacmlAttribute()
        openidSubjectAttribute.attributeId = subjectNameIdFormat
                                        
        XacmlAnyUriAttributeValue = xacmlAttributeValueFactory(
                                            XacmlAttributeValue.ANY_TYPE_URI)
        
        openidSubjectAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER        
        openidSubjectAttribute.attributeValues.append(
                                                    XacmlAnyUriAttributeValue())
        openidSubjectAttribute.attributeValues[-1].value = subjectNameId
        
        xacmlSubject.attributes.append(openidSubjectAttribute)

        XacmlStringAttributeValue = xacmlAttributeValueFactory(
                                            XacmlAttributeValue.STRING_TYPE_URI)
                                  
        xacmlRequest.subjects.append(xacmlSubject)
        
        resource = XacmlResource()
        resourceAttribute = XacmlAttribute()
        resource.attributes.append(resourceAttribute)
        if resourceContent is not None:
            resource.resourceContent = resourceContent
        
        resourceAttribute.attributeId = XacmlIdentifiers.Resource.RESOURCE_ID
                            
        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceUri

        xacmlRequest.resources.append(resource)
        
        xacmlRequest.action = XacmlAction()
        
        for action in actions:
            xacmlActionAttribute = XacmlAttribute()
            xacmlRequest.action.attributes.append(xacmlActionAttribute)
            
            xacmlActionAttribute.attributeId = XacmlIdentifiers.Action.ACTION_ID
            xacmlActionAttribute.dataType = XacmlStringAttributeValue.IDENTIFIER
            xacmlActionAttribute.attributeValues.append(
                                                    XacmlStringAttributeValue())
            xacmlActionAttribute.attributeValues[-1].value = action.value

        xacmlRequest.environment = XacmlEnvironment()

        return xacmlRequest
    def _createRequestCtx(resourceId, 
                          includeSubject=True,
                          subjectGroupRoles=None,
                          groupRoleAttributeId='urn:esg:attr',
                          action='read'):
        """Create an example XACML Request Context for tests"""
        if subjectGroupRoles is None:
            subjectGroupRoles = [('ACME', 'default')]
            
        request = Request()
        
        if includeSubject:
            subject = Subject()
            openidSubjectAttribute = Attribute()
            
            openidSubjectAttribute.attributeId = "urn:esg:openid"
            openidSubjectAttribute.dataType = AnyUriAttributeValue.IDENTIFIER
            
            openidSubjectAttribute.attributeValues.append(
                                                        AnyUriAttributeValue())
            openidSubjectAttribute.attributeValues[-1].value = SUBJECT_ID
                                        
            
            subject.attributes.append(openidSubjectAttribute)
    
            for group, role in subjectGroupRoles:
                groupRoleAttribute = Attribute()
                
                groupRoleAttribute.attributeId = groupRoleAttributeId
                groupRoleAttribute.dataType = 'urn:grouprole'
                
                groupRoleAttribute.attributeValues.append(
                                                    GroupRoleAttributeValue())
                groupRoleAttribute.attributeValues[-1].group = group 
                groupRoleAttribute.attributeValues[-1].role = role 
            
                subject.attributes.append(groupRoleAttribute)
                                      
            request.subjects.append(subject)
        
        resource = Resource()
        resourceAttribute = Attribute()
        resource.attributes.append(resourceAttribute)
        
        resourceAttribute.attributeId = Identifiers.Resource.RESOURCE_ID
                            
        resourceAttribute.dataType = AnyUriAttributeValue.IDENTIFIER
        resourceAttribute.attributeValues.append(AnyUriAttributeValue())
        resourceAttribute.attributeValues[-1].value = resourceId

        request.resources.append(resource)
        
        request.action = Action()
        actionAttribute = Attribute()
        request.action.attributes.append(actionAttribute)
        
        actionAttribute.attributeId = Identifiers.Action.ACTION_ID
        actionAttribute.dataType = StringAttributeValue.IDENTIFIER
        actionAttribute.attributeValues.append(StringAttributeValue())
        actionAttribute.attributeValues[-1].value = action
        
        return request