示例#1
0
    def _makeRequestForQuery(self, query):
        """Wraps an XACMLAuthzDecisionQuery in a SOAP request.
        """
        elem = XACMLAuthzDecisionQueryElementTree.toXML(query)
        soapRequest = SOAPEnvelope()
        soapRequest.create()
        soapRequest.body.elem.append(elem)

        request = soapRequest.serialize()

        return request
示例#2
0
 def test01SendRequest(self):
     requestEnvelope = SOAPEnvelope()
     requestEnvelope.create()
     request = requestEnvelope.serialize()
     
     response = self.app.post('/my-soap-endpoint', 
                              params=request, 
                              status=200)
     print((response.headers))
     print((response.status))
     print((response.body))
示例#3
0
    def _do_test(self, resourceContentsStr, expected_status, expected_decision):
        """Constructs, sends and evaluates the response from a SAML SOAP request
        using the XACML-SAML profile, with specified resource contents.
        """
        # Load the AuthorisationServiceMiddleware and
        # SOAPQueryInterfaceMiddleware so that the authorisation service can be
        # called.
        self.__class__.INI_FILEPATH = os.path.join(self.__class__.THIS_DIR, 
                                                   self.__class__.INI_FILE)
        wsgiapp = loadapp('config:'+self.__class__.INI_FILEPATH)
        self.app = paste.fixture.TestApp(wsgiapp)

        # Construct a SOAP request.
        (header, request) = self._makeRequest(resourceContentsStr,
                                              issuer=self.ISSUER_DN)

        # Send the SOAP request to the authorisation service.
        httpResponse = self.app.post(self.AUTHZ_SERVICE_URI, 
                                          params=request,
                                          headers=header,
                                          status=200)
        log.debug("Response status=%d", httpResponse.status)

        # Parse the SOAP response.
        envelope = SOAPEnvelope()
        respFile = StringIO(httpResponse.body)
        envelope.parse(respFile)

        # Extract the SAML response.
        samlAuthzResponse = ResponseElementTree.fromXML(envelope.body.elem[0])

#        serialisedResponse = pickle.dumps(samlAuthzResponse)
#        response2 = pickle.loads(serialisedResponse)

        assertions = samlAuthzResponse.assertions
        (assertion,
         error_status,
         error_message) = XacmlSamlPepFilter._evaluate_assertions(assertions,
                                                        self.SUBJECT_ID,
                                                        self.RESOURCE_URI,
                                                        self.AUTHZ_SERVICE_URI)
        if expected_status is None:
            self.assertTrue(error_status is None,
                            ("Unexpected error %d: %s" %
                             (0 if error_status is None else error_status,
                              error_message)))

            self.assertEqual(
                assertion.statements[0].xacmlContextResponse.results[0
                                                            ].decision.value,
                expected_decision)
        else:
            self.assertEqual(error_status, expected_status)
示例#4
0
 def _makeRequest(self, attributeQuery=None, **kw):
     """Convenience method to construct queries for tests"""
     
     if attributeQuery is None:
         attributeQuery = self._createAttributeQuery(**kw)
         
     elem = AttributeQueryElementTree.toXML(attributeQuery)
     soapRequest = SOAPEnvelope()
     soapRequest.create()
     soapRequest.body.elem.append(elem)
     
     request = soapRequest.serialize()
     
     return request
示例#5
0
 def __call__(self, environ, start_response):
     requestFile = environ['wsgi.input']
     
     print(("Server received request from client:\n\n%s" % 
           requestFile.read()))
     
     soapResponse = SOAPEnvelope()
     soapResponse.create()
     
     response = soapResponse.serialize()
     start_response("200 OK",
                    [('Content-length', str(len(response))),
                     ('Content-type', 'text/xml')])
     return [response]
 def _parseResponse(self, responseStr):
     """Helper to parse a response from a string"""
     soapResponse = SOAPEnvelope()
     
     responseStream = StringIO()
     responseStream.write(responseStr)
     responseStream.seek(0)
     
     soapResponse.parse(responseStream)
     
     print("Parsed response ...")
     print(soapResponse.serialize())
     
     response = ResponseElementTree.fromXML(soapResponse.body.elem[0])
     return response
示例#7
0
 def _getSAMLResponse(self, responseBody):
     """Deserialise response string into ElementTree element"""
     soapResponse = SOAPEnvelope()
     
     responseStream = StringIO()
     responseStream.write(responseBody.decode())
     responseStream.seek(0)
     
     soapResponse.parse(responseStream)
     
     print("Parsed response ...")
     print((soapResponse.serialize()))
     
     response = ResponseElementTree.fromXML(soapResponse.body.elem[0])
     
     return response
示例#8
0
 def test01Envelope(self):
     envelope = SOAPEnvelope()
     envelope.create()
     soap = envelope.serialize().decode()
     
     self.assertTrue(len(soap) > 0)
     self.assertTrue("Envelope" in soap)
     self.assertTrue("Body" in soap)
     self.assertTrue("Header" in soap)
     
     print((envelope.prettyPrint()))
     stream = StringIO()
     stream.write(soap)
     stream.seek(0)
     
     envelope2 = SOAPEnvelope()
     envelope2.parse(stream)
     soap2 = envelope2.serialize().decode()
     self.assertTrue(soap2 == soap)
示例#9
0
 def test06CreateSOAPFaultResponse(self):
     # Create full SOAP Response containing a SOAP Fault
     envelope = SOAPEnvelope()
     envelope.body.fault = self._createSOAPFault()
     envelope.create()
     soap = envelope.serialize()
     
     self.assert_(len(soap) > 0)
     self.assert_("Envelope" in soap)
     self.assert_("Body" in soap)
     self.assert_("Header" in soap)
     self.assert_("Fault" in soap)
     
     print(envelope.prettyPrint())
     stream = StringIO()
     stream.write(soap)
     stream.seek(0)
     
     envelope2 = SOAPEnvelope()
     envelope2.parse(stream)
     soap2 = envelope2.serialize()
     self.assert_(soap2 == soap)
    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 test01AttributeQuery(self):
        attributeQuery = AttributeQuery()
        attributeQuery.version = SAMLVersion(SAMLVersion.VERSION_20)
        attributeQuery.id = str(uuid4())
        attributeQuery.issueInstant = datetime.utcnow()
        
        attributeQuery.issuer = Issuer()
        attributeQuery.issuer.format = Issuer.X509_SUBJECT
        attributeQuery.issuer.value = \
                        "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk"
                        
                        
        attributeQuery.subject = Subject()  
        attributeQuery.subject.nameID = NameID()
        attributeQuery.subject.nameID.format = SamlSoapBindingApp.NAMEID_FORMAT
        attributeQuery.subject.nameID.value = \
                                    "https://openid.localhost/philip.kershaw"
        
        # special case handling for 'FirstName' attribute
        fnAttribute = Attribute()
        fnAttribute.name = SamlSoapBindingApp.FIRSTNAME_ATTRNAME
        fnAttribute.nameFormat = "http://www.w3.org/2001/XMLSchema#string"
        fnAttribute.friendlyName = "FirstName"

        attributeQuery.attributes.append(fnAttribute)
    
        # special case handling for 'LastName' attribute
        lnAttribute = Attribute()
        lnAttribute.name = SamlSoapBindingApp.LASTNAME_ATTRNAME
        lnAttribute.nameFormat = "http://www.w3.org/2001/XMLSchema#string"
        lnAttribute.friendlyName = "LastName"

        attributeQuery.attributes.append(lnAttribute)
    
        # special case handling for 'LastName' attribute
        emailAddressAttribute = Attribute()
        emailAddressAttribute.name = SamlSoapBindingApp.EMAILADDRESS_ATTRNAME
        emailAddressAttribute.nameFormat = XMLConstants.XSD_NS+"#"+\
                                    XSStringAttributeValue.TYPE_LOCAL_NAME
        emailAddressAttribute.friendlyName = "emailAddress"

        attributeQuery.attributes.append(emailAddressAttribute)                                   
        
        elem = AttributeQueryElementTree.toXML(attributeQuery)
        soapRequest = SOAPEnvelope()
        soapRequest.create()
        soapRequest.body.elem.append(elem)
        
        request = soapRequest.serialize()
        
        header = {
            'soapAction': "http://www.oasis-open.org/committees/security",
            'Content-length': str(len(request)),
            'Content-type': 'text/xml'
        }
        response = self.app.post('/attributeauthority', 
                                 params=request, 
                                 headers=header, 
                                 status=200)
        print("Response status=%d" % response.status)

        soapResponse = SOAPEnvelope()
        
        responseStream = StringIO()
        responseStream.write(response.body)
        responseStream.seek(0)
        
        soapResponse.parse(responseStream)
        
        print("Parsed response ...")
        print(soapResponse.serialize())
#        print(prettyPrint(soapResponse.elem))
        
        response = ResponseElementTree.fromXML(soapResponse.body.elem[0])
        self.assert_(response.status.statusCode.value==StatusCode.SUCCESS_URI)
        self.assert_(response.inResponseTo == attributeQuery.id)
        self.assert_(response.assertions[0].subject.nameID.value == \
                     attributeQuery.subject.nameID.value)
示例#12
0
    def __call__(self, environ, start_response):
        """Check for and parse a SOAP SAML Attribute Query and return a
        SAML Response
        
        :type environ: dict
        :param environ: WSGI environment variables dictionary
        :type start_response: function
        :param start_response: standard WSGI start response function
        """
    
        # Ignore non-matching path
        if environ['PATH_INFO'] not in (self.mountPath, self.mountPath + '/'):
            return self._app(environ, start_response)
          
        # Ignore non-POST requests
        if environ.get('REQUEST_METHOD') != 'POST':
            return self._app(environ, start_response)
        
        soapRequestStream = environ.get('wsgi.input')
        if soapRequestStream is None:
            raise SOAPQueryInterfaceMiddlewareError('No "wsgi.input" in '
                                                    'environ')
        
        # TODO: allow for chunked data
        contentLength = environ.get('CONTENT_LENGTH')
        if contentLength is None:
            raise SOAPQueryInterfaceMiddlewareError('No "CONTENT_LENGTH" in '
                                                    'environ')

        contentLength = int(contentLength)
        if contentLength <= 0:
            raise SOAPQueryInterfaceMiddlewareError('"CONTENT_LENGTH" in '
                                                    'environ is %d' %
                                                    contentLength)
            
        soapRequestTxt = soapRequestStream.read(contentLength)
        
        # Parse into a SOAP envelope object
        soapRequest = SOAPEnvelope()
        soapRequest.parse(StringIO(soapRequestTxt))
        
        log.debug("SOAPQueryInterfaceMiddleware.__call__: received SAML "
                  "SOAP Query: %s", soapRequestTxt)
       
        queryElem = soapRequest.body.elem[0]
        
        # Create a response with basic attributes if provided in the 
        # initialisation config
        samlResponse = self._initResponse()
        
        try:
            queryType = QName.getLocalPart(queryElem.tag)
            if queryType == XACMLAuthzDecisionQuery.DEFAULT_ELEMENT_LOCAL_NAME:
                # Set up additional ElementTree parsing for XACML profile.
                etree_xacml_profile.setElementTreeMap()
                samlQuery = self.deserialiseXacmlProfile(queryElem)
            else:
                samlQuery = self.deserialise(queryElem)

        except UnknownAttrProfile, e:
            log.exception("%r raised parsing incoming query: %s" % 
                          (type(e), traceback.format_exc()))
            samlResponse.status.statusCode.value = \
                                            StatusCode.UNKNOWN_ATTR_PROFILE_URI
示例#13
0
                 (queryInterface, self.queryInterfaceKeyName))
         
         # Basic validation
         self._validateQuery(samlQuery, samlResponse)
         
         samlResponse.inResponseTo = samlQuery.id
         
         # Call query interface        
         queryInterface(samlQuery, samlResponse)
     
     # Convert to ElementTree representation to enable attachment to SOAP
     # response body
     samlResponseElem = self.serialise(samlResponse)
     
     # Create SOAP response and attach the SAML Response payload
     soapResponse = SOAPEnvelope()
     soapResponse.create()
     soapResponse.body.elem.append(samlResponseElem)
     
     response = soapResponse.serialize()
     
     log.debug("SOAPQueryInterfaceMiddleware.__call__: sending response "
               "...\n\n%s",
               response)
     start_response("200 OK",
                    [('Content-length', str(len(response))),
                     ('Content-type', 'text/xml')])
     return [response]
 
 def _validateQuery(self, query, response):
     """Checking incoming query issue instant and version