diff --git a/src/idp_test/saml2int.py b/src/idp_test/saml2int.py index f8b0e6e..21d3f99 100644 --- a/src/idp_test/saml2int.py +++ b/src/idp_test/saml2int.py @@ -14,7 +14,6 @@ from idp_test.check import VerifyLogout from idp_test.check import VerifyContent from idp_test.check import VerifySuccessStatus from idp_test.check import VerifyNameIDMapping -from idp_test.check import VerifySPProvidedID from saml2.samlp import NameIDPolicy @@ -166,6 +165,15 @@ class ManageNameIDRequest(Request): assertion = resp.assertion[0] self.args["name_id"] = assertion.subject.name_id +class AttributeQuery(Request): + request = "attribute_query" + _args = {"binding":BINDING_SOAP} + + def setup(self, environ): + resp = environ["response"][-1].response + assertion = resp.assertion[0] + self.args["name_id"] = assertion.subject.name_id + # ----------------------------------------------------------------------------- OPERATIONS = { @@ -224,5 +232,9 @@ OPERATIONS = { 'manage_nameid':{ "name": "Setting the SP provided ID by using ManageNameID", "sequence":[AuthnRequest, ManageNameIDRequest] + }, + 'attribute-query':{ + "name": "Setting the SP provided ID by using ManageNameID", + "sequence":[AuthnRequest, AttributeQuery] } } \ No newline at end of file diff --git a/tests/attributemaps/saml_uri.py b/tests/attributemaps/saml_uri.py index 4d772b5..9696fba 100644 --- a/tests/attributemaps/saml_uri.py +++ b/tests/attributemaps/saml_uri.py @@ -7,6 +7,7 @@ NETSCAPE_LDAP = "urn:oid:2.16.840.1.113730.3.1." UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.' PKCS_9 = "urn:oid:1.2.840.113549.1.9.1." UMICH = "urn:oid:1.3.6.1.4.1.250.1.57." +SCHAC = "urn:oid:1.3.6.1.4.1.25178.2." MAP = { "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", @@ -94,6 +95,26 @@ MAP = { NOREDUPERSON_OID+'3': 'norEduPersonBirthDate', UMICH+'57': 'labeledURI', UCL_DIR_PILOT+'1': 'uid', + SCHAC+'1': 'schacMotherTongue', + SCHAC+'2': 'schacGender', + SCHAC+'3': 'schacDateOfBirth', + SCHAC+'4': 'schacPlaceOfBirth', + SCHAC+'5': 'schacCountryOfCitizenship', + SCHAC+'6': 'schacSn1', + SCHAC+'7': 'schacSn2', + SCHAC+'8': 'schacPersonalTitle', + SCHAC+'9': 'schacHomeOrganization', + SCHAC+'10': 'schacHomeOrganizationType', + SCHAC+'11': 'schacCountryOfResidence', + SCHAC+'12': 'schacUserPresenceID', + SCHAC+'13': 'schacPersonalPosition', + SCHAC+'14': 'schacPersonalUniqueCode', + SCHAC+'15': 'schacPersonalUniqueID', + SCHAC+'17': 'schacExpiryDate', + SCHAC+'18': 'schacUserPrivateAttribute', + SCHAC+'19': 'schacUserStatus', + SCHAC+'20': 'schacProjectMembership', + SCHAC+'21': 'schacProjectSpecificRole', }, "to": { 'roleOccupant': X500ATTR_OID+'33', @@ -195,6 +216,26 @@ MAP = { 'sn': X500ATTR_OID+'4', 'domainComponent': UCL_DIR_PILOT+'25', 'labeledURI': UMICH+'57', - 'uid': UCL_DIR_PILOT+'1' + 'uid': UCL_DIR_PILOT+'1', + 'schacMotherTongue':SCHAC+'1', + 'schacGender': SCHAC+'2', + 'schacDateOfBirth':SCHAC+'3', + 'schacPlaceOfBirth': SCHAC+'4', + 'schacCountryOfCitizenship':SCHAC+'5', + 'schacSn1': SCHAC+'6', + 'schacSn2': SCHAC+'7', + 'schacPersonalTitle':SCHAC+'8', + 'schacHomeOrganization': SCHAC+'9', + 'schacHomeOrganizationType': SCHAC+'10', + 'schacCountryOfResidence': SCHAC+'11', + 'schacUserPresenceID': SCHAC+'12', + 'schacPersonalPosition': SCHAC+'13', + 'schacPersonalUniqueCode': SCHAC+'14', + 'schacPersonalUniqueID': SCHAC+'15', + 'schacExpiryDate': SCHAC+'17', + 'schacUserPrivateAttribute': SCHAC+'18', + 'schacUserStatus': SCHAC+'19', + 'schacProjectMembership': SCHAC+'20', + 'schacProjectSpecificRole': SCHAC+'21', } } \ No newline at end of file diff --git a/tests/config_file.py b/tests/config_file.py index e3323e7..9035b0a 100755 --- a/tests/config_file.py +++ b/tests/config_file.py @@ -24,6 +24,7 @@ CONFIG = { ("%s/acs/post" % BASE, BINDING_HTTP_POST), ("%s/acs/redirect" % BASE, BINDING_HTTP_REDIRECT), ("%s/acs/artifact" % BASE, BINDING_HTTP_ARTIFACT), + #("%s/acs/soap" % BASE, BINDING_SOAP), ("%s/ecp" % BASE, BINDING_PAOS) ], "single_logout_service": [ diff --git a/tests/idp/idp.py b/tests/idp/idp.py index 487d639..a9576d0 100755 --- a/tests/idp/idp.py +++ b/tests/idp/idp.py @@ -609,6 +609,45 @@ def authn_query_service(environ, start_response, user=None): return resp(environ, start_response) +# ---------------------------------------------------------------------------- +# === Attribute query service === +# ---------------------------------------------------------------------------- + +# Only SOAP binding +def attribute_query_service(environ, start_response, user=None): + """ + :param environ: Execution environment + :param start_response: Function to start the response with + """ + logger.info("--- Attribute Query Service ---") + _dict = unpack_soap(environ) + _binding = BINDING_SOAP + + if not _dict: + resp = BadRequest("Missing or faulty request") + return resp(environ, start_response) + + _req = IDP.parse_attribute_query("%s" % _dict["SAMLRequest"], _binding) + _query = _req.message + + name_id = _query.subject.name_id + uid = IDP.ident.find_local_id(name_id) + logger.debug("Local uid: %s" % uid) + identity = EXTRA[uid] + + # Comes in over SOAP so only need to construct the response + args = IDP.response_args(_query, [BINDING_SOAP]) + msg = IDP.create_attribute_response(identity, destination="", + name_id=name_id, **args) + + logger.debug("response: %s" % msg) + hinfo = IDP.apply_binding(_binding, "%s" % msg, "","",response=True) + + resp = Response(hinfo["data"], headers=hinfo["headers"]) + return resp(environ, start_response) + + + # ---------------------------------------------------------------------------- # Name ID Mapping service # When an entity that shares an identifier for a principal with an identity @@ -706,7 +745,8 @@ AUTHN_URLS = [ (r'nim$', nim_soap), (r'nim/(.*)$', nim_soap), # - (r'aqs$', authn_query_service) + (r'aqs$', authn_query_service), + (r'attr$', attribute_query_service) ] NON_AUTHN_URLS = [ @@ -785,6 +825,7 @@ LOOKUP = TemplateLookup(directories=[ROOT + 'templates', ROOT + 'htdocs'], if __name__ == '__main__': import sys from idp_user import USERS + from idp_user import EXTRA from wsgiref.simple_server import make_server PORT = 8088 diff --git a/tests/idp/idp_conf.py b/tests/idp/idp_conf.py index dad6af0..6a32680 100644 --- a/tests/idp/idp_conf.py +++ b/tests/idp/idp_conf.py @@ -27,8 +27,7 @@ CONFIG={ "aa": { "endpoints" : { "attribute_service": [ - ("%s/attr/post" % BASE, BINDING_HTTP_POST), - ("%s/attr/soap" % BASE, BINDING_SOAP) + ("%s/attr" % BASE, BINDING_SOAP) ] }, "name_id_format": [NAMEID_FORMAT_TRANSIENT, diff --git a/tests/idp/idp_user.py b/tests/idp/idp_user.py index 4263352..bd8c5ac 100644 --- a/tests/idp/idp_user.py +++ b/tests/idp/idp_user.py @@ -15,4 +15,12 @@ USERS = { "givenName": "Derek", "eduPersonAffiliation": "affiliate" }, +} + +EXTRA = { + "roland": { + "eduPersonEntitlement" : "urn:mace:swamid.se:foo:bar", + "schacGender": "male", + "schacUserPresenceID": "skype:pepe.perez" + } } \ No newline at end of file