Example #1
0
 def buildAssertion(self):
     """Create a SAML Assertion containing ESG core attributes: First
     Name, Last Name, e-mail Address; ESG Group/Role type attributes
     and generic attributes
     @rtype: ndg.security.common.saml.Assertion
     @return: new SAML Assertion object
     """
     
     assertion = Assertion()
     assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
     assertion.id = str(uuid4())
     assertion.issueInstant = datetime.utcnow()
     attributeStatement = AttributeStatement()
     
     for attribute in self.createAttributes():
         attributeStatement.attributes.append(attribute)
         
     assertion.attributeStatements.append(attributeStatement)
     
     return assertion
Example #2
0
        def authzDecisionQuery(query, response):
            now = datetime.utcnow()
            response.issueInstant = now

            # Make up a request ID that this response is responding to
            response.inResponseTo = query.id
            response.id = str(uuid4())
            response.version = SAMLVersion(SAMLVersion.VERSION_20)

            response.status = Status()
            response.status.statusCode = StatusCode()
            response.status.statusCode.value = StatusCode.SUCCESS_URI
            response.status.statusMessage = StatusMessage()
            response.status.statusMessage.value = \
                                                "Response created successfully"

            assertion = Assertion()
            assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
            assertion.id = str(uuid4())
            assertion.issueInstant = now

            authzDecisionStatement = AuthzDecisionStatement()
            authzDecisionStatement.decision = DecisionType.PERMIT
            authzDecisionStatement.resource = \
                TestAuthorisationServiceMiddleware.RESOURCE_URI
            authzDecisionStatement.actions.append(Action())
            authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI
            authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION
            assertion.authzDecisionStatements.append(authzDecisionStatement)

            # Add a conditions statement for a validity of 8 hours
            assertion.conditions = Conditions()
            assertion.conditions.notBefore = now
            assertion.conditions.notOnOrAfter = now + timedelta(seconds=60 *
                                                                60 * 8)

            assertion.subject = Subject()
            assertion.subject.nameID = NameID()
            assertion.subject.nameID.format = query.subject.nameID.format
            assertion.subject.nameID.value = query.subject.nameID.value

            assertion.issuer = Issuer()
            assertion.issuer.format = Issuer.X509_SUBJECT
            assertion.issuer.value = \
                                    TestAuthorisationServiceMiddleware.ISSUER_DN

            response.assertions.append(assertion)
            return response
Example #3
0
    def create_authz_decision_query_response(cls):
        """Helper method for Authz Decision Response"""
        response = Response()
        now = datetime.utcnow()
        response.issueInstant = now
        
        # Make up a request ID that this response is responding to
        response.inResponseTo = str(uuid4())
        response.id = str(uuid4())
        response.version = SAMLVersion(SAMLVersion.VERSION_20)
            
        response.issuer = Issuer()
        response.issuer.format = Issuer.X509_SUBJECT
        response.issuer.value = cls.ISSUER_DN
        
        response.status = Status()
        response.status.statusCode = StatusCode()
        response.status.statusCode.value = StatusCode.SUCCESS_URI
        response.status.statusMessage = StatusMessage()        
        response.status.statusMessage.value = "Response created successfully"
           
        assertion = Assertion()
        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = now
        
        authzDecisionStatement = AuthzDecisionStatement()
        authzDecisionStatement.decision = DecisionType.PERMIT
        authzDecisionStatement.resource = cls.RESOURCE_URI
        authzDecisionStatement.actions.append(Action())
        authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI
        authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION
        assertion.authzDecisionStatements.append(authzDecisionStatement)
        
        # Add a conditions statement for a validity of 8 hours
        assertion.conditions = Conditions()
        assertion.conditions.notBefore = now
        assertion.conditions.notOnOrAfter = now + timedelta(seconds=60*60*8)
               
        assertion.subject = Subject()  
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = cls.NAMEID_FORMAT
        assertion.subject.nameID.value = cls.NAMEID_VALUE    
            
        assertion.issuer = Issuer()
        assertion.issuer.format = Issuer.X509_SUBJECT
        assertion.issuer.value = cls.ISSUER_DN

        response.assertions.append(assertion)
        
        return response
     def authzDecisionQuery(query, response):
         now = datetime.utcnow()
         response.issueInstant = now
         
         # Make up a request ID that this response is responding to
         response.inResponseTo = query.id
         response.id = str(uuid4())
         response.version = SAMLVersion(SAMLVersion.VERSION_20)
         
         response.status = Status()
         response.status.statusCode = StatusCode()
         response.status.statusCode.value = StatusCode.SUCCESS_URI
         response.status.statusMessage = StatusMessage()        
         response.status.statusMessage.value = \
                                             "Response created successfully"
            
         assertion = Assertion()
         assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
         assertion.id = str(uuid4())
         assertion.issueInstant = now
         
         authzDecisionStatement = AuthzDecisionStatement()
         authzDecisionStatement.decision = DecisionType.PERMIT
         authzDecisionStatement.resource = \
             TestAuthorisationServiceMiddleware.RESOURCE_URI
         authzDecisionStatement.actions.append(Action())
         authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI
         authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION
         assertion.authzDecisionStatements.append(authzDecisionStatement)
         
         # Add a conditions statement for a validity of 8 hours
         assertion.conditions = Conditions()
         assertion.conditions.notBefore = now
         assertion.conditions.notOnOrAfter = now + timedelta(seconds=60*60*8)
                
         assertion.subject = Subject()  
         assertion.subject.nameID = NameID()
         assertion.subject.nameID.format = query.subject.nameID.format
         assertion.subject.nameID.value = query.subject.nameID.value
             
         assertion.issuer = Issuer()
         assertion.issuer.format = Issuer.X509_SUBJECT
         assertion.issuer.value = \
                                 TestAuthorisationServiceMiddleware.ISSUER_DN
 
         response.assertions.append(assertion)
         return response
        def attributeQuery(query, response):
            """Attribute Query interface called by the next middleware in the 
            stack the SAML SOAP Query interface middleware instance
            (ndg.saml.saml2.binding.soap.server.wsgi.queryinterface.SOAPQueryInterfaceMiddleware)
            """
            response.issueInstant = datetime.utcnow()
            response.id = str(uuid4())            
            response.inResponseTo = query.id

            if query.issuer.value not in self.__class__.VALID_QUERY_ISSUERS:
                response.status.statusCode.value = \
                                            StatusCode.REQUEST_DENIED_URI 
                response.status.statusMessage.value = 'Invalid issuer'  
                return response    

            if query.subject.nameID.value not in self.__class__.VALID_SUBJECTS:
                response.status.statusCode.value = \
                                            StatusCode.UNKNOWN_PRINCIPAL_URI 
                response.status.statusMessage.value = 'Unknown user'  
                return response    
                
            assertion = Assertion()
            
            assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
            assertion.id = str(uuid4())
            assertion.issueInstant = response.issueInstant
            
            assertion.conditions = Conditions()
            assertion.conditions.notBefore = assertion.issueInstant
            assertion.conditions.notOnOrAfter = \
                assertion.conditions.notBefore + timedelta(seconds=60*60*8)
            
            assertion.subject = Subject()  
            assertion.subject.nameID = NameID()
            assertion.subject.nameID.format = query.subject.nameID.format
            assertion.subject.nameID.value = query.subject.nameID.value
    
            assertion.attributeStatements.append(AttributeStatement())                
            
            for attribute in query.attributes:
                if attribute.name == self.__class__.FIRSTNAME_ATTRNAME:
                    # special case handling for 'FirstName' attribute
                    fnAttribute = Attribute()
                    fnAttribute.name = attribute.name
                    fnAttribute.nameFormat = attribute.nameFormat
                    fnAttribute.friendlyName = attribute.friendlyName
        
                    firstName = XSStringAttributeValue()
                    firstName.value = self.firstName
                    fnAttribute.attributeValues.append(firstName)
        
                    assertion.attributeStatements[0].attributes.append(
                                                                    fnAttribute)
                
                elif attribute.name == self.__class__.LASTNAME_ATTRNAME:
                    lnAttribute = Attribute()
                    lnAttribute.name = attribute.name
                    lnAttribute.nameFormat = attribute.nameFormat
                    lnAttribute.friendlyName = attribute.friendlyName
        
                    lastName = XSStringAttributeValue()
                    lastName.value = self.lastName
                    lnAttribute.attributeValues.append(lastName)
        
                    assertion.attributeStatements[0].attributes.append(
                                                                    lnAttribute)
                   
                elif (attribute.name == self.__class__.EMAILADDRESS_ATTRNAME and
                      query.issuer.value == 
                                        self.__class__.VALID_QUERY_ISSUERS[0]):
                    emailAddressAttribute = Attribute()
                    emailAddressAttribute.name = attribute.name
                    emailAddressAttribute.nameFormat = attribute.nameFormat
                    emailAddressAttribute.friendlyName = attribute.friendlyName
        
                    emailAddress = XSStringAttributeValue()
                    emailAddress.value = self.emailAddress
                    emailAddressAttribute.attributeValues.append(emailAddress)
        
                    assertion.attributeStatements[0].attributes.append(
                                                        emailAddressAttribute)
                else:
                    response.status.statusCode.value = \
                                        StatusCode.INVALID_ATTR_NAME_VALUE_URI
                    return response
                                    
            
            response.assertions.append(assertion)
            response.status.statusCode.value = StatusCode.SUCCESS_URI        
    
            return response
     def authzDecisionQuery(query, response):
         """Authorisation Decision Query interface called by the next 
         middleware in the stack the SAML SOAP Query interface middleware 
         instance
         (ndg.saml.saml2.binding.soap.server.wsgi.queryinterface.SOAPQueryInterfaceMiddleware)
         """
         now = datetime.utcnow()
         response.issueInstant = now
         
         # Make up a request ID that this response is responding to
         response.inResponseTo = query.id
         response.id = str(uuid4())
         response.version = SAMLVersion(SAMLVersion.VERSION_20)
         
         response.status = Status()
         response.status.statusCode = StatusCode()
         response.status.statusCode.value = StatusCode.SUCCESS_URI
         response.status.statusMessage = StatusMessage()        
         response.status.statusMessage.value = \
                                             "Response created successfully"
            
         assertion = Assertion()
         assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
         assertion.id = str(uuid4())
         assertion.issueInstant = now
         
         authzDecisionStatement = AuthzDecisionStatement()
         
         # Make some simple logic to simulate a full access policy
         if query.resource == self.__class__.RESOURCE_URI:
             if query.actions[0].value == Action.HTTP_GET_ACTION:
                 authzDecisionStatement.decision = DecisionType.PERMIT
             else:
                 authzDecisionStatement.decision = DecisionType.DENY
         else:
             authzDecisionStatement.decision = DecisionType.INDETERMINATE
             
         authzDecisionStatement.resource = query.resource
             
         authzDecisionStatement.actions.append(Action())
         authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI
         authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION
         assertion.authzDecisionStatements.append(authzDecisionStatement)
         
         # Add a conditions statement for a validity of 8 hours
         assertion.conditions = Conditions()
         assertion.conditions.notBefore = now
         assertion.conditions.notOnOrAfter = now + timedelta(seconds=60*60*8)
                
         assertion.subject = Subject()  
         assertion.subject.nameID = NameID()
         assertion.subject.nameID.format = query.subject.nameID.format
         assertion.subject.nameID.value = query.subject.nameID.value
             
         assertion.issuer = Issuer()
         assertion.issuer.format = Issuer.X509_SUBJECT
         assertion.issuer.value = \
                                 TestAuthorisationServiceMiddleware.ISSUER_DN
 
         response.assertions.append(assertion)
         return response
    def getAttributes(self, attributeQuery, response):
        """Attribute Authority SAML AttributeQuery

        @type attributeQuery: saml.saml2.core.AttributeQuery
        @param userId: query containing requested attributes
        @type response: saml.saml2.core.Response
        @param response: add an assertion with the list of attributes
        for the given subject ID in the query or set an error Status code and
        message
        @raise AttributeInterfaceError: an error occured requesting
        attributes
        @raise AttributeReleaseDeniedError: Requestor was denied release of the
        requested attributes
        @raise AttributeNotKnownError: Requested attribute names are not known
        to this authority
        """
        userId = attributeQuery.subject.nameID.value
        requestedAttributeNames = [attribute.name
                                   for attribute in attributeQuery.attributes]

        requestorDN = X500DN.from_string(attributeQuery.issuer.value)

        if not self._queryDbForSamlSubject(userId):
            raise UserIdNotKnown('Subject Id "%s" is not known to this '
                                 'authority' % userId)

        if (len(self.samlValidRequestorDNs) > 0 and
            requestorDN not in self.samlValidRequestorDNs):
            raise InvalidRequestorId('Requester identity "%s" is invalid' %
                                     requestorDN)

        unknownAttrNames = [attrName for attrName in requestedAttributeNames
                            if attrName not in self.__samlAttribute2SqlQuery]

        if len(unknownAttrNames) > 0:
            raise AttributeNotKnownError("Unknown attributes requested: %r" %
                                         unknownAttrNames)

        # Create a new assertion to hold the attributes to be returned
        assertion = Assertion()

        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = response.issueInstant

        # Assumes SAML response issuer details as set by -
        # ndg.security.server.wsgi.saml.SOAPQueryInterfaceMiddleware
        assertion.issuer = Issuer()
        assertion.issuer.value = response.issuer.value

        if response.issuer.format:
            assertion.issuer.format = response.issuer.format

        assertion.conditions = Conditions()
        assertion.conditions.notBefore = assertion.issueInstant
        assertion.conditions.notOnOrAfter = (assertion.conditions.notBefore +
                                             self.samlAssertionLifetime)

        assertion.subject = Subject()
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = attributeQuery.subject.nameID.format
        assertion.subject.nameID.value = attributeQuery.subject.nameID.value

        attributeStatement = AttributeStatement()

        # Query the database for the requested attributes and return them
        # mapped to their attribute names as specified by the attributeNames
        # property
        for requestedAttribute in attributeQuery.attributes:
            attributeVals = self._queryDbForSamlAttributes(
                                                    requestedAttribute.name,
                                                    userId)

            # Make a new SAML attribute object to hold the values obtained
            attribute = Attribute()
            attribute.name = requestedAttribute.name
            attribute.nameFormat = requestedAttribute.nameFormat

            if requestedAttribute.friendlyName is not None:
                attribute.friendlyName = requestedAttribute.friendlyName

            # Call specific conversion utility to convert the retrieved field
            # to the correct SAML attribute value type
            try:
                field2SamlAttributeVal = self.__samlAttribute2SqlQuery[
                                        requestedAttribute.name][-1]
            except (IndexError, TypeError) as e:
                raise AttributeInterfaceConfigError('Bad format for SAML '
                                                    'attribute to SQL query '
                                                    'look-up for attribute '
                                                    'name %r: %s' %
                                                    (requestedAttribute.name,
                                                    e))

            for val in attributeVals:
                attributeValue = field2SamlAttributeVal(val)
                attribute.attributeValues.append(attributeValue)

            attributeStatement.attributes.append(attribute)

        assertion.attributeStatements.append(attributeStatement)
        response.assertions.append(assertion)
    def getAttributes(self, attributeQuery, response):
        '''Test Attribute Authority SAML Attribute Query interface'''
        
        userId = attributeQuery.subject.nameID.value
        requestedAttributeNames = [attribute.name 
                                   for attribute in attributeQuery.attributes]
        if attributeQuery.issuer.format != Issuer.X509_SUBJECT:
            raise InvalidRequestorId('Requestor issuer format "%s" is invalid' %
                                     attributeQuery.issuerFormat.value)
            
        requestorId = X500DN.fromString(attributeQuery.issuer.value)
        
        if userId not in TestUserRoles.VALID_USER_IDS:
            raise UserIdNotKnown('Subject Id "%s" is not known to this '
                                 'authority' % userId)
            
        if requestorId not in TestUserRoles.VALID_REQUESTOR_IDS:
            raise InvalidRequestorId('Requestor identity "%s" is invalid' %
                                     requestorId)
        
        unknownAttrNames = [attrName for attrName in requestedAttributeNames
                            if attrName not in 
                            TestUserRoles.SAML_ATTRIBUTE_NAMES]
        
        if len(unknownAttrNames) > 0:
            raise AttributeNotKnownError("Unknown attributes requested: %r" %
                                         unknownAttrNames)
            
        if requestorId == TestUserRoles.INSUFFICIENT_PRIVILEGES_REQUESTOR_ID:
            raise AttributeReleaseDenied("Attribute release denied for the "
                                         'requestor "%s"' % requestorId)
        
        # Create a new assertion to hold the attributes to be returned
        assertion = Assertion()
        
        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = response.issueInstant
    
        assertion.issuer = Issuer()
        assertion.issuer.value = response.issuer.value
        assertion.issuer.format = Issuer.X509_SUBJECT
        
        assertion.conditions = Conditions()
        assertion.conditions.notBefore = assertion.issueInstant
        assertion.conditions.notOnOrAfter = assertion.conditions.notBefore + \
            timedelta(seconds=TestUserRoles.SAML_ASSERTION_LIFETIME)
        
        assertion.subject = Subject()  
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = attributeQuery.subject.nameID.format
        assertion.subject.nameID.value = attributeQuery.subject.nameID.value

        attributeStatement = AttributeStatement()
        
        # Add test set of attributes
        for name in requestedAttributeNames:
            attributeFound = False
            for attribute in TestUserRoles.SAML_ATTRIBUTES:
                if attribute.name == name:
                    attributeFound = True
                    break
            
            if attributeFound:
                attributeStatement.attributes.append(attribute)
            else:
                raise AttributeNotKnownError("Unknown attribute requested: %s"%
                                             name)
 
        assertion.attributeStatements.append(attributeStatement)       
        response.assertions.append(assertion)
    def __call__(self, environ, start_response):
        soapRequestStream = environ['wsgi.input']
        soapRequest = SOAPEnvelope()
        soapRequest.parse(soapRequestStream)
        attributeQueryElem = soapRequest.body.elem[0]
        attributeQuery = AttributeQueryElementTree.fromXML(attributeQueryElem)
        
        print("Received request from client:\n")
        print soapRequest.prettyPrint()
        
        samlResponse = Response()
        
        samlResponse.issueInstant = datetime.utcnow()
        samlResponse.id = str(uuid4())
        samlResponse.issuer = Issuer()
        
        # SAML 2.0 spec says format must be omitted
        #samlResponse.issuer.format = Issuer.X509_SUBJECT
        samlResponse.issuer.value = \
                        "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk"
        
        samlResponse.inResponseTo = attributeQuery.id
        
        assertion = Assertion()
        
        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = samlResponse.issueInstant
        
        assertion.conditions = Conditions()
        assertion.conditions.notBefore = assertion.issueInstant
        assertion.conditions.notOnOrAfter = assertion.conditions.notBefore + \
            timedelta(seconds=60*60*8)
        
        assertion.subject = Subject()  
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = attributeQuery.subject.nameID.format
        assertion.subject.nameID.value = attributeQuery.subject.nameID.value

        assertion.attributeStatements.append(AttributeStatement())
        
        for attribute in attributeQuery.attributes:
            if attribute.name == SamlSoapBindingApp.FIRSTNAME_ATTRNAME:
                # special case handling for 'FirstName' attribute
                fnAttribute = Attribute()
                fnAttribute.name = attribute.name
                fnAttribute.nameFormat = attribute.nameFormat
                fnAttribute.friendlyName = attribute.friendlyName
    
                firstName = XSStringAttributeValue()
                firstName.value = self.firstName
                fnAttribute.attributeValues.append(firstName)
    
                assertion.attributeStatements[0].attributes.append(fnAttribute)
            
            elif attribute.name == SamlSoapBindingApp.LASTNAME_ATTRNAME:
                lnAttribute = Attribute()
                lnAttribute.name = attribute.name
                lnAttribute.nameFormat = attribute.nameFormat
                lnAttribute.friendlyName = attribute.friendlyName
    
                lastName = XSStringAttributeValue()
                lastName.value = self.lastName
                lnAttribute.attributeValues.append(lastName)
    
                assertion.attributeStatements[0].attributes.append(lnAttribute)
               
            elif attribute.name == SamlSoapBindingApp.EMAILADDRESS_ATTRNAME:
                emailAddressAttribute = Attribute()
                emailAddressAttribute.name = attribute.name
                emailAddressAttribute.nameFormat = attribute.nameFormat
                emailAddressAttribute.friendlyName = attribute.friendlyName
    
                emailAddress = XSStringAttributeValue()
                emailAddress.value = self.emailAddress
                emailAddressAttribute.attributeValues.append(emailAddress)
    
                assertion.attributeStatements[0].attributes.append(
                                                        emailAddressAttribute)
        
        samlResponse.assertions.append(assertion)
        
        samlResponse.status = Status()
        samlResponse.status.statusCode = StatusCode()
        samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI        

        
        # Convert to ElementTree representation to enable attachment to SOAP
        # response body
        samlResponseElem = ResponseElementTree.toXML(samlResponse)
        xml = ElementTree.tostring(samlResponseElem)
        log.debug('Sending response to query:\n%s', xml)
        
        # Create SOAP response and attach the SAML Response payload
        soapResponse = SOAPEnvelope()
        soapResponse.create()
        soapResponse.body.elem.append(samlResponseElem)
        
        response = soapResponse.serialize()
        
        start_response("200 OK",
                       [('Content-length', str(len(response))),
                        ('Content-type', 'text/xml')])
        return [response]
        def authzDecisionQuery(query, response):
            """Authorisation Decision Query interface called by the next 
            middleware in the stack the SAML SOAP Query interface middleware 
            instance
            (ndg.saml.saml2.binding.soap.server.wsgi.queryinterface.SOAPQueryInterfaceMiddleware)
            """
            now = datetime.utcnow()
            response.issueInstant = now

            # Make up a request ID that this response is responding to
            response.inResponseTo = query.id
            response.id = str(uuid4())
            response.version = SAMLVersion(SAMLVersion.VERSION_20)

            response.status = Status()
            response.status.statusCode = StatusCode()
            response.status.statusCode.value = StatusCode.SUCCESS_URI
            response.status.statusMessage = StatusMessage()
            response.status.statusMessage.value = \
                                                "Response created successfully"

            assertion = Assertion()
            assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
            assertion.id = str(uuid4())
            assertion.issueInstant = now

            authzDecisionStatement = AuthzDecisionStatement()

            # Make some simple logic to simulate a full access policy
            if query.resource == self.__class__.RESOURCE_URI:
                if query.actions[0].value == Action.HTTP_GET_ACTION:
                    authzDecisionStatement.decision = DecisionType.PERMIT
                else:
                    authzDecisionStatement.decision = DecisionType.DENY
            else:
                authzDecisionStatement.decision = DecisionType.INDETERMINATE

            authzDecisionStatement.resource = query.resource

            authzDecisionStatement.actions.append(Action())
            authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI
            authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION
            assertion.authzDecisionStatements.append(authzDecisionStatement)

            # Add a conditions statement for a validity of 8 hours
            assertion.conditions = Conditions()
            assertion.conditions.notBefore = now
            assertion.conditions.notOnOrAfter = now + timedelta(seconds=60 *
                                                                60 * 8)

            assertion.subject = Subject()
            assertion.subject.nameID = NameID()
            assertion.subject.nameID.format = query.subject.nameID.format
            assertion.subject.nameID.value = query.subject.nameID.value

            assertion.issuer = Issuer()
            assertion.issuer.format = Issuer.X509_SUBJECT
            assertion.issuer.value = \
                                    TestAuthorisationServiceMiddleware.ISSUER_DN

            response.assertions.append(assertion)
            return response
    def getAttributes(self, attributeQuery, response):
        '''Test Attribute Authority SAML Attribute Query interface'''

        userId = attributeQuery.subject.nameID.value
        requestedAttributeNames = [
            attribute.name for attribute in attributeQuery.attributes
        ]
        if attributeQuery.issuer.format != Issuer.X509_SUBJECT:
            raise InvalidRequestorId(
                'Requestor issuer format "%s" is invalid' %
                attributeQuery.issuerFormat.value)

        requestorId = X500DN.fromString(attributeQuery.issuer.value)

        if userId not in TestUserRoles.VALID_USER_IDS:
            raise UserIdNotKnown('Subject Id "%s" is not known to this '
                                 'authority' % userId)

        if requestorId not in TestUserRoles.VALID_REQUESTOR_IDS:
            raise InvalidRequestorId('Requestor identity "%s" is invalid' %
                                     requestorId)

        unknownAttrNames = [
            attrName for attrName in requestedAttributeNames
            if attrName not in TestUserRoles.SAML_ATTRIBUTE_NAMES
        ]

        if len(unknownAttrNames) > 0:
            raise AttributeNotKnownError("Unknown attributes requested: %r" %
                                         unknownAttrNames)

        if requestorId == TestUserRoles.INSUFFICIENT_PRIVILEGES_REQUESTOR_ID:
            raise AttributeReleaseDenied("Attribute release denied for the "
                                         'requestor "%s"' % requestorId)

        # Create a new assertion to hold the attributes to be returned
        assertion = Assertion()

        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = response.issueInstant

        assertion.issuer = Issuer()
        assertion.issuer.value = response.issuer.value
        assertion.issuer.format = Issuer.X509_SUBJECT

        assertion.conditions = Conditions()
        assertion.conditions.notBefore = assertion.issueInstant
        assertion.conditions.notOnOrAfter = assertion.conditions.notBefore + \
            timedelta(seconds=TestUserRoles.SAML_ASSERTION_LIFETIME)

        assertion.subject = Subject()
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = attributeQuery.subject.nameID.format
        assertion.subject.nameID.value = attributeQuery.subject.nameID.value

        attributeStatement = AttributeStatement()

        # Add test set of attributes
        for name in requestedAttributeNames:
            attributeFound = False
            for attribute in TestUserRoles.SAML_ATTRIBUTES:
                if attribute.name == name:
                    attributeFound = True
                    break

            if attributeFound:
                attributeStatement.attributes.append(attribute)
            else:
                raise AttributeNotKnownError(
                    "Unknown attribute requested: %s" % name)

        assertion.attributeStatements.append(attributeStatement)
        response.assertions.append(assertion)
Example #12
0
    def getAttributes(self, attributeQuery, response):
        """Attribute Authority SAML AttributeQuery

        @type attributeQuery: saml.saml2.core.AttributeQuery
        @param userId: query containing requested attributes
        @type response: saml.saml2.core.Response
        @param response: add an assertion with the list of attributes
        for the given subject ID in the query or set an error Status code and
        message
        @raise AttributeInterfaceError: an error occured requesting
        attributes
        @raise AttributeReleaseDeniedError: Requestor was denied release of the
        requested attributes
        @raise AttributeNotKnownError: Requested attribute names are not known
        to this authority
        """
        userId = attributeQuery.subject.nameID.value
        requestedAttributeNames = [
            attribute.name for attribute in attributeQuery.attributes
        ]

        requestorDN = X500DN.from_string(attributeQuery.issuer.value)

        if not self._queryDbForSamlSubject(userId):
            raise UserIdNotKnown('Subject Id "%s" is not known to this '
                                 'authority' % userId)

        if (len(self.samlValidRequestorDNs) > 0
                and requestorDN not in self.samlValidRequestorDNs):
            raise InvalidRequestorId('Requester identity "%s" is invalid' %
                                     requestorDN)

        unknownAttrNames = [
            attrName for attrName in requestedAttributeNames
            if attrName not in self.__samlAttribute2SqlQuery
        ]

        if len(unknownAttrNames) > 0:
            raise AttributeNotKnownError("Unknown attributes requested: %r" %
                                         unknownAttrNames)

        # Create a new assertion to hold the attributes to be returned
        assertion = Assertion()

        assertion.version = SAMLVersion(SAMLVersion.VERSION_20)
        assertion.id = str(uuid4())
        assertion.issueInstant = response.issueInstant

        # Assumes SAML response issuer details as set by -
        # ndg.security.server.wsgi.saml.SOAPQueryInterfaceMiddleware
        assertion.issuer = Issuer()
        assertion.issuer.value = response.issuer.value

        if response.issuer.format:
            assertion.issuer.format = response.issuer.format

        assertion.conditions = Conditions()
        assertion.conditions.notBefore = assertion.issueInstant
        assertion.conditions.notOnOrAfter = (assertion.conditions.notBefore +
                                             self.samlAssertionLifetime)

        assertion.subject = Subject()
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = attributeQuery.subject.nameID.format
        assertion.subject.nameID.value = attributeQuery.subject.nameID.value

        attributeStatement = AttributeStatement()

        # Query the database for the requested attributes and return them
        # mapped to their attribute names as specified by the attributeNames
        # property
        for requestedAttribute in attributeQuery.attributes:
            attributeVals = self._queryDbForSamlAttributes(
                requestedAttribute.name, userId)

            # Make a new SAML attribute object to hold the values obtained
            attribute = Attribute()
            attribute.name = requestedAttribute.name
            attribute.nameFormat = requestedAttribute.nameFormat

            if requestedAttribute.friendlyName is not None:
                attribute.friendlyName = requestedAttribute.friendlyName

            # Call specific conversion utility to convert the retrieved field
            # to the correct SAML attribute value type
            try:
                field2SamlAttributeVal = self.__samlAttribute2SqlQuery[
                    requestedAttribute.name][-1]
            except (IndexError, TypeError) as e:
                raise AttributeInterfaceConfigError(
                    'Bad format for SAML '
                    'attribute to SQL query '
                    'look-up for attribute '
                    'name %r: %s' % (requestedAttribute.name, e))

            for val in attributeVals:
                attributeValue = field2SamlAttributeVal(val)
                attribute.attributeValues.append(attributeValue)

            attributeStatement.attributes.append(attribute)

        assertion.attributeStatements.append(attributeStatement)
        response.assertions.append(assertion)