def _initResponse(self):
        """Create a SAML Response object with basic settings if any have been
        provided at initialisation of this class - see initialise
        
        :return: SAML response object
        :rtype: ndg.saml.saml2.core.Response
        """
        samlResponse = Response()
        utcNow = datetime.utcnow()
        
        samlResponse.issueInstant = utcNow
        samlResponse.id = str(uuid4())
        samlResponse.issuer = Issuer()
        
        if self.issuerName is not None:
            samlResponse.issuer.value = self.issuerName
        
        if self.issuerFormat is not None:
            # TODO: Check SAML 2.0 spec says issuer format must be omitted??
            samlResponse.issuer.format = self.issuerFormat
        
        # Initialise to success status but reset on error
        samlResponse.status = Status()
        samlResponse.status.statusCode = StatusCode()
        samlResponse.status.statusMessage = StatusMessage()
        samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI
        
        samlResponse.status.statusMessage = StatusMessage()

        return samlResponse
Beispiel #2
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
Beispiel #3
0
    def _createAttributeQueryResponse(self):
        response = Response()
        response.issueInstant = datetime.utcnow()
        
        # 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 = \
                        SAMLTestCase.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 = self._createAttributeAssertionHelper()
        
        # Add a conditions statement for a validity of 8 hours
        assertion.conditions = Conditions()
        assertion.conditions.notBefore = datetime.utcnow()
        assertion.conditions.notOnOrAfter = (assertion.conditions.notBefore + 
                                             timedelta(seconds=60*60*8))
        
        assertion.subject = Subject()  
        assertion.subject.nameID = NameID()
        assertion.subject.nameID.format = SAMLTestCase.NAMEID_FORMAT
        assertion.subject.nameID.value = SAMLTestCase.NAMEID_VALUE    
            
        assertion.issuer = Issuer()
        assertion.issuer.format = Issuer.X509_SUBJECT
        assertion.issuer.value = SAMLTestCase.ISSUER_DN

        response.assertions.append(assertion)
        
        return response
    def test05SamlAttributeQuery(self):
        if self.skipTests:
            return
        
        # Prepare a client query
        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=ESG/OU=NCAR/CN=Gateway'
                        
                        
        attributeQuery.subject = Subject()  
        attributeQuery.subject.nameID = NameID()
        attributeQuery.subject.nameID.format = ESGFSamlNamespaces.NAMEID_FORMAT
        attributeQuery.subject.nameID.value = \
                                SQLAlchemyAttributeInterfaceTestCase.OPENID_URI
    
        emailAddressAttribute = Attribute()
        emailAddressAttribute.name = ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME
        emailAddressAttribute.nameFormat = "InvalidFormat"
        emailAddressAttribute.friendlyName = "EmailAddress"

        attributeQuery.attributes.append(emailAddressAttribute)                                   
    
        authzAttribute = Attribute()
        authzAttribute.name = \
            SQLAlchemyAttributeInterfaceTestCase.ATTRIBUTE_NAMES[0]
        authzAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        authzAttribute.friendlyName = "authz"

        attributeQuery.attributes.append(authzAttribute)                                   
        
        # Add the response - the interface will populate with an assertion as
        # appropriate
        samlResponse = Response()
        
        samlResponse.issueInstant = datetime.utcnow()
        samlResponse.id = str(uuid4())
        samlResponse.issuer = Issuer()
        
        # Initialise to success status but reset on error
        samlResponse.status = Status()
        samlResponse.status.statusCode = StatusCode()
        samlResponse.status.statusMessage = StatusMessage()
        samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI
        
        # Nb. SAML 2.0 spec says issuer format must be omitted
        samlResponse.issuer.value = "CEDA"
        
        samlResponse.inResponseTo = attributeQuery.id
        
        # Set up the interface object
        
        # Define queries for SAML attribute names
        samlAttribute2SqlQuery = {
            ESGFSamlNamespaces.FIRSTNAME_ATTRNAME: 
                SQLAlchemyAttributeInterfaceTestCase.SAML_FIRSTNAME_SQLQUERY,
            
            ESGFSamlNamespaces.LASTNAME_ATTRNAME: 
                SQLAlchemyAttributeInterfaceTestCase.SAML_LASTNAME_SQLQUERY,
        
            ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME: 
                SQLAlchemyAttributeInterfaceTestCase.SAML_EMAILADDRESS_SQLQUERY,
        
            SQLAlchemyAttributeInterfaceTestCase.ATTRIBUTE_NAMES[0]: 
                SQLAlchemyAttributeInterfaceTestCase.SAML_ATTRIBUTES_SQLQUERY
        }
        
        attributeInterface = SQLAlchemyAttributeInterface(
                                samlAttribute2SqlQuery=samlAttribute2SqlQuery)
        
        attributeInterface.connectionString = \
                        SQLAlchemyAttributeInterfaceTestCase.DB_CONNECTION_STR
                
        attributeInterface.samlValidRequestorDNs = (
            '/O=STFC/OU=CEDA/CN=AuthorisationService',
            '/O=ESG/OU=NCAR/CN=Gateway')
        
        attributeInterface.setProperties(samlAssertionLifetime=28800.)
        
        attributeInterface.samlSubjectSqlQuery = (
            SQLAlchemyAttributeInterfaceTestCase.SAML_SUBJECT_SQLQUERY)
        
        # Make the query
        try:
            attributeInterface.getAttributes(attributeQuery, samlResponse)
        except InvalidAttributeFormat:
            print("PASSED: caught InvalidAttributeFormat exception")
        else:
            self.fail("Expecting InvalidAttributeFormat exception")
    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 test05SamlAttributeQuery(self):
        if self.skipTests:
            return

        # Prepare a client query
        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=ESG/OU=NCAR/CN=Gateway'

        attributeQuery.subject = Subject()
        attributeQuery.subject.nameID = NameID()
        attributeQuery.subject.nameID.format = ESGFSamlNamespaces.NAMEID_FORMAT
        attributeQuery.subject.nameID.value = TestUserDatabase.OPENID_URI

        emailAddressAttribute = Attribute()
        emailAddressAttribute.name = ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME
        emailAddressAttribute.nameFormat = "InvalidFormat"
        emailAddressAttribute.friendlyName = "EmailAddress"

        attributeQuery.attributes.append(emailAddressAttribute)

        authzAttribute = Attribute()
        authzAttribute.name = TestUserDatabase.ATTRIBUTE_NAMES[0]
        authzAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        authzAttribute.friendlyName = "authz"

        attributeQuery.attributes.append(authzAttribute)

        # Add the response - the interface will populate with an assertion as
        # appropriate
        samlResponse = Response()

        samlResponse.issueInstant = datetime.utcnow()
        samlResponse.id = str(uuid4())
        samlResponse.issuer = Issuer()

        # Initialise to success status but reset on error
        samlResponse.status = Status()
        samlResponse.status.statusCode = StatusCode()
        samlResponse.status.statusMessage = StatusMessage()
        samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI

        # Nb. SAML 2.0 spec says issuer format must be omitted
        samlResponse.issuer.value = "CEDA"

        samlResponse.inResponseTo = attributeQuery.id

        # Set up the interface object

        # Define queries for SAML attribute names
        samlAttribute2SqlQuery = {
            ESGFSamlNamespaces.FIRSTNAME_ATTRNAME:
            self.__class__.SAML_FIRSTNAME_SQLQUERY,
            ESGFSamlNamespaces.LASTNAME_ATTRNAME:
            self.__class__.SAML_LASTNAME_SQLQUERY,
            ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME:
            self.__class__.SAML_EMAILADDRESS_SQLQUERY,
            TestUserDatabase.ATTRIBUTE_NAMES[0]:
            self.__class__.SAML_ATTRIBUTES_SQLQUERY
        }

        attributeInterface = SQLAlchemyAttributeInterface(
            samlAttribute2SqlQuery=samlAttribute2SqlQuery)

        attributeInterface.connectionString = TestUserDatabase.DB_CONNECTION_STR

        attributeInterface.samlValidRequestorDNs = (
            '/O=STFC/OU=CEDA/CN=AuthorisationService',
            '/O=ESG/OU=NCAR/CN=Gateway')

        attributeInterface.setProperties(samlAssertionLifetime=28800.)

        attributeInterface.samlSubjectSqlQuery = (
            SQLAlchemyAttributeInterfaceTestCase.SAML_SUBJECT_SQLQUERY)

        # Make the query
        attributeInterface.getAttributes(attributeQuery, samlResponse)
    def test04SamlAttributeQuery(self):
        if self.skipTests:
            return

        # Prepare a client query
        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=ESG/OU=NCAR/CN=Gateway'


        attributeQuery.subject = Subject()
        attributeQuery.subject.nameID = NameID()
        attributeQuery.subject.nameID.format = ESGFSamlNamespaces.NAMEID_FORMAT
        attributeQuery.subject.nameID.value = \
                                TestUserDatabase.OPENID_URI

        fnAttribute = Attribute()
        fnAttribute.name = ESGFSamlNamespaces.FIRSTNAME_ATTRNAME
        fnAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        fnAttribute.friendlyName = "FirstName"

        attributeQuery.attributes.append(fnAttribute)

        lnAttribute = Attribute()
        lnAttribute.name = ESGFSamlNamespaces.LASTNAME_ATTRNAME
        lnAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        lnAttribute.friendlyName = "LastName"

        attributeQuery.attributes.append(lnAttribute)

        emailAddressAttribute = Attribute()
        emailAddressAttribute.name = ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME
        emailAddressAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        emailAddressAttribute.friendlyName = "EmailAddress"

        attributeQuery.attributes.append(emailAddressAttribute)

        authzAttribute = Attribute()
        authzAttribute.name = \
            TestUserDatabase.ATTRIBUTE_NAMES[0]
        authzAttribute.nameFormat = XSStringAttributeValue.DEFAULT_FORMAT
        authzAttribute.friendlyName = "authz"

        attributeQuery.attributes.append(authzAttribute)

        # Add the response - the interface will populate with an assertion as
        # appropriate
        samlResponse = Response()

        samlResponse.issueInstant = datetime.utcnow()
        samlResponse.id = str(uuid4())
        samlResponse.issuer = Issuer()

        # Initialise to success status but reset on error
        samlResponse.status = Status()
        samlResponse.status.statusCode = StatusCode()
        samlResponse.status.statusMessage = StatusMessage()
        samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI

        # Nb. SAML 2.0 spec says issuer format must be omitted
        samlResponse.issuer.value = "CEDA"

        samlResponse.inResponseTo = attributeQuery.id

        # Set up the interface object

        # Define queries for SAML attribute names
        samlAttribute2SqlQuery = {
            ESGFSamlNamespaces.FIRSTNAME_ATTRNAME:
                self.__class__.SAML_FIRSTNAME_SQLQUERY,

            ESGFSamlNamespaces.LASTNAME_ATTRNAME:
                self.__class__.SAML_LASTNAME_SQLQUERY,

            ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME:
                self.__class__.SAML_EMAILADDRESS_SQLQUERY,

            TestUserDatabase.ATTRIBUTE_NAMES[0]:
                self.__class__.SAML_ATTRIBUTES_SQLQUERY,
        }

        attributeInterface = SQLAlchemyAttributeInterface(
                                samlAttribute2SqlQuery=samlAttribute2SqlQuery)

        attributeInterface.connectionString = TestUserDatabase.DB_CONNECTION_STR

        attributeInterface.samlValidRequestorDNs = (
            '/O=STFC/OU=CEDA/CN=AuthorisationService',
            '/O=ESG/OU=NCAR/CN=Gateway')

        attributeInterface.setProperties(samlAssertionLifetime=28800.)

        attributeInterface.samlSubjectSqlQuery = (
            SQLAlchemyAttributeInterfaceTestCase.SAML_SUBJECT_SQLQUERY)

        # Make the query
        attributeInterface.getAttributes(attributeQuery, samlResponse)

        self.assert_(
                samlResponse.status.statusCode.value == StatusCode.SUCCESS_URI)
        self.assert_(samlResponse.inResponseTo == attributeQuery.id)
        self.assert_(samlResponse.assertions[0].subject.nameID.value == \
                     attributeQuery.subject.nameID.value)
        self.assert_(
            samlResponse.assertions[0].attributeStatements[0].attributes[1
                ].attributeValues[0].value == 'Kershaw')

        self.assert_(
            len(samlResponse.assertions[0].attributeStatements[0].attributes[3
                ].attributeValues) == TestUserDatabase.N_ATTRIBUTE_VALUES)