Пример #1
0
def attribute_query(environ,
                    attribute_requests,
                    subject_id,
                    subject_id_format='urn:esg:openid'):
    """
    Make a query for a set of attributes
    Returns a dictionary of values for each attribute in the query
    
    @param attribute_requests: SAML Attribute instances
    @param subject_id: The ID of the subject, e.g. openid
    @param subject_id_format: optional format of the ID, default is openid
    """

    # Grab info from the environ
    saml_trusted_ca_dir = environ.get('saml_trusted_ca_dir', '')
    attr_service_uri = environ.get('attr_service_uri', '')

    client_binding = AttributeQuerySslSOAPBinding()
    client_binding.sslCACertDir = saml_trusted_ca_dir
    client_binding.clockSkewTolerance = 1  # 1 second tolerance

    # Make a new query object
    query = AttributeQuery()

    query.version = SAMLVersion(SAMLVersion.VERSION_20)
    query.id = str(uuid4())
    query.issueInstant = datetime.utcnow()

    query.issuer = Issuer()
    query.issuer.format = Issuer.X509_SUBJECT
    query.issuer.value = '/O=STFC/OU=SPBU/CN=test'

    query.subject = Subject()
    query.subject.nameID = NameID()
    query.subject.nameID.format = subject_id_format
    query.subject.nameID.value = subject_id

    # Specify what attributes to query for
    for attribute_request in attribute_requests:
        query.attributes.append(attribute_request)

    try:
        response = client_binding.send(query, uri=attr_service_uri)
        attribute_results = {}

        assertion = next(iter(response.assertions or []), None)
        if assertion:
            statement = next(iter(assertion.attributeStatements or []), None)
            if statement:
                for attribute in statement.attributes:
                    values = []
                    for attribute_value in attribute.attributeValues:
                        values.append(attribute_value.value)

                    attribute_results[attribute.name] = values

        return attribute_results

    except (RequestResponseError, Error) as e:
        logger.error("Error processing SOAP query for {0}: {1}".format(id, e))
Пример #2
0
    def _createAttributeQuery(
            self,
            issuer="/O=Site A/CN=Authorisation Service",
            subject="https://openid.localhost/philip.kershaw"):
        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 = issuer

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

        # special case handling for 'FirstName' attribute
        fnAttribute = Attribute()
        fnAttribute.name = ESGFSamlNamespaces.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 = ESGFSamlNamespaces.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 = ESGFSamlNamespaces.EMAILADDRESS_ATTRNAME
        emailAddressAttribute.nameFormat = XMLConstants.XSD_NS+"#"+\
                                    XSStringAttributeValue.TYPE_LOCAL_NAME
        emailAddressAttribute.friendlyName = "emailAddress"

        attributeQuery.attributes.append(emailAddressAttribute)

        return attributeQuery
    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)