def test_attributes_general(self, ldap_attribute_store): ldap_to_internal_map = (self.ldap_attribute_store_config['default'] ['ldap_to_internal_map']) for dn, attributes in self.ldap_person_records: # Mock up the internal response the LDAP attribute store is # expecting to receive. response = InternalData(auth_info=AuthenticationInformation()) # The LDAP attribute store configuration and the mock records # expect to use a LDAP search filter for the uid attribute. uid = attributes['uid'] response.attributes = {'uid': uid} context = Context() context.state = dict() ldap_attribute_store.process(context, response) # Verify that the LDAP attribute store has retrieved the mock # records from the mock LDAP server and has added the appropriate # internal attributes. for ldap_attr, ldap_value in attributes.items(): if ldap_attr in ldap_to_internal_map: internal_attr = ldap_to_internal_map[ldap_attr] response_attr = response.attributes[internal_attr] assert(ldap_value in response_attr)
def handle_response(self, context): auth_info = AuthenticationInformation("test", str(datetime.now()), "test_issuer") internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = context.request internal_resp.user_id = "test_user" return self.auth_callback_func(context, internal_resp)
def internal_response(self, idp_conf): auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"]) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = AttributeMapper( INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) return internal_response
def internal_response(self): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalData(auth_info=auth_info) internal_response.requester = "client" internal_response.attributes = ATTRIBUTES return internal_response
def setup_for_authn_response(self, context, frontend, auth_req): context.state[frontend.name] = {"oidc_request": auth_req.to_urlencoded()} auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", "unittest_idp.xml") internal_response = InternalData(auth_info=auth_info) internal_response.attributes = AttributeMapper(INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) internal_response.subject_id = USERS["testuser1"]["eduPersonTargetedID"][0] return internal_response
def test_perun_identity_none_user(self, mock_adapter): mock_adapter.get_perun_user.return_value = None service = self.create_perun_identity_service() service.adapter = mock_adapter resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = self.ATTRIBUTES returned_service = service.process(None, resp) assert 'perun_id' not in returned_service.attributes.keys()
def test_filter_attribute_not_in_response(self): attribute_filters = {"": {"": {"a0": "foo:bar"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["abc:xyz", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["abc:xyz", "1:foo:bar:2"]}
def test_perun_identity_test_user(self, mock_adapter): user = User(1, 'Test user') mock_adapter.get_perun_user.return_value = user service = self.create_perun_identity_service() service.adapter = mock_adapter resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = self.ATTRIBUTES returned_service = service.process(None, resp) assert 'perun_id' in returned_service.attributes.keys() assert returned_service.attributes.get('perun_id') == [user.id]
def test_auth_resp_callback_func_respects_user_id_to_attr(self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_to_attr"] = "user_id" base = SATOSABase(satosa_config) internal_resp = InternalData(auth_info=AuthenticationInformation("", "", "")) internal_resp.subject_id = "user1234" context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing.STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] base._auth_resp_callback_func(context, internal_resp) assert internal_resp.attributes["user_id"] == [internal_resp.subject_id]
def test_filter_one_attribute_for_one_target_provider(self): target_provider = "test_provider" attribute_filters = {target_provider: {"": {"a1": "foo:bar"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalData(auth_info=AuthenticationInformation( issuer=target_provider)) resp.attributes = { "a1": ["abc:xyz", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["1:foo:bar:2"]}
def test_filter_one_attribute_from_all_target_providers_for_all_requesters( self): attribute_filters = {"": {"": {"a2": "^foo:bar$"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalData(AuthenticationInformation()) resp.attributes = { "a1": ["abc:xyz"], "a2": ["foo:bar", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["abc:xyz"], "a2": ["foo:bar"]}
def _translate_response(self, response, state): """ Translates a saml authorization response to an internal response :type response: saml2.response.AuthnResponse :rtype: satosa.internal.InternalData :param response: The saml authorization response :return: A translated internal response """ # The response may have been encrypted by the IdP so if we have an # encryption key, try it. if self.encryption_keys: response.parse_assertion(keys=self.encryption_keys) issuer = response.response.issuer.text authn_context_ref, authenticating_authorities, authn_instant = next( iter(response.authn_info()), [None, None, None] ) authenticating_authority = ( authenticating_authorities[-1] if authenticating_authorities else None ) auth_info = AuthenticationInformation( auth_class_ref=authn_context_ref, timestamp=authn_instant, authority=authenticating_authority, issuer=issuer, ) # The SAML response may not include a NameID. subject = response.get_subject() name_id = subject.text if subject else None name_id_format = subject.format if subject else None attributes = self.converter.to_internal( self.attribute_profile, response.ava, ) internal_resp = InternalData( auth_info=auth_info, attributes=attributes, subject_type=name_id_format, subject_id=name_id, ) msg = "backend received attributes:\n{}".format( json.dumps(response.ava, indent=4) ) logline = lu.LOG_FMT.format(id=lu.get_session_id(state), message=msg) logger.debug(logline) return internal_resp
def test_generate_static(self): synthetic_attributes = {"": {"default": {"a0": "value1;value2"}}} authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["*****@*****.**"], } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("value1" in resp.attributes['a0']) assert ("value2" in resp.attributes['a0']) assert ("*****@*****.**" in resp.attributes['a1'])
def auth_info(self, request): """ Creates the SATOSA authentication information object. :type request: dict[str, str] :rtype: AuthenticationInformation :param request: The request parameters in the authentication response sent by the AS. :return: How, who and when the autentication took place. """ auth_info = AuthenticationInformation( UNSPECIFIED, None, self.config["server_info"]["authorization_endpoint"]) return auth_info
def from_dict(cls, data): """ :type data: dict[str, dict[str, str] | str] :rtype: satosa.internal_data.InternalResponse :param data: A dict representation of an InternalResponse object :return: An InternalResponse object """ auth_info = _AuthenticationInformation.from_dict(data.get("auth_info")) instance = cls(auth_info=auth_info) instance.user_id_hash_type = data.get("hash_type") instance.attributes = data.get("attributes", {}) instance.user_id = data.get("user_id") instance.requester = data.get("requester") return instance
def from_dict(cls, data): """ :type data: dict[str, dict[str, str] | str] :rtype: satosa.internal_data.InternalResponse :param data: A dict representation of an InternalResponse object :return: An InternalResponse object """ auth_info = _AuthenticationInformation.from_dict(data.get("auth_info")) instance = cls(auth_info=auth_info) instance.user_id_hash_type = data.get("hash_type") instance.attributes = data.get("attributes", {}) instance.user_id = data.get("user_id") instance.requester = data.get("requester") return instance
def test_auth_resp_callback_func_user_id_from_attrs_is_used_to_override_user_id(self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_from_attrs"] = ["user_id", "domain"] base = SATOSABase(satosa_config) internal_resp = InternalData(auth_info=AuthenticationInformation("", "", "")) internal_resp.attributes = {"user_id": ["user"], "domain": ["@example.com"]} internal_resp.requester = "test_requester" context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing.STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] base._auth_resp_callback_func(context, internal_resp) expected_user_id = "*****@*****.**" assert internal_resp.subject_id == expected_user_id
def test_authz_deny_fail(self): attribute_deny = {"": {"default": {"a0": ['foo1', 'foo2']}}} attribute_allow = {} authz_service = self.create_authz_service(attribute_allow, attribute_deny) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a0": ["foo3"], } try: ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) except SATOSAAuthenticationError as ex: assert False
def _translate_response(self, response, state): """ Translates a saml authorization response to an internal response :type response: saml2.response.AuthnResponse :rtype: satosa.internal.InternalData :param response: The saml authorization response :return: A translated internal response """ # The response may have been encrypted by the IdP so if we have an # encryption key, try it. if self.encryption_keys: response.parse_assertion(self.encryption_keys) authn_info = response.authn_info()[0] auth_class_ref = authn_info[0] timestamp = response.assertion.authn_statement[0].authn_instant issuer = response.response.issuer.text auth_info = AuthenticationInformation( auth_class_ref, timestamp, issuer, ) # The SAML response may not include a NameID. subject = response.get_subject() name_id = subject.text if subject else None name_id_format = subject.format if subject else None attributes = self.converter.to_internal( self.attribute_profile, response.ava, ) internal_resp = InternalData( auth_info=auth_info, attributes=attributes, subject_type=name_id_format, subject_id=name_id, ) satosa_logging( logger, logging.DEBUG, "backend received attributes:\n%s" % json.dumps(response.ava, indent=4), state) return internal_resp
def test_auth_resp_callback_func_hashes_all_specified_attributes(self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["hash"] = ["user_id", "mail"] base = SATOSABase(satosa_config) attributes = {"user_id": ["user"], "mail": ["*****@*****.**", "*****@*****.**"]} internal_resp = InternalData(auth_info=AuthenticationInformation("", "", "")) internal_resp.attributes = copy.copy(attributes) internal_resp.subject_id = "test_user" context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing.STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] base._auth_resp_callback_func(context, internal_resp) for attr in satosa_config["INTERNAL_ATTRIBUTES"]["hash"]: assert internal_resp.attributes[attr] == [ util.hash_data(satosa_config.get("USER_ID_HASH_SALT", ""), v) for v in attributes[attr] ]
def _translate_response(self, response, issuer): """ Translates oidc response to SATOSA internal response. :type response: dict[str, str] :type issuer: str :type subject_type: str :rtype: InternalData :param response: Dictioary with attribute name as key. :param issuer: The oidc op that gave the repsonse. :param subject_type: public or pairwise according to oidc standard. :return: A SATOSA internal response. """ auth_info = AuthenticationInformation(UNSPECIFIED, str(datetime.now()), issuer) internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = self.converter.to_internal("openid", response) internal_resp.subject_id = response["sub"] return internal_resp
def test_attribute_policy(self): requester = "requester" attribute_policies = { "attribute_policy": { "requester_everything_allowed": {}, "requester_nothing_allowed": { "allowed": {} }, "requester_subset_allowed": { "allowed": { "attr1", "attr2", }, }, }, } attributes = { "attr1": ["foo"], "attr2": ["foo", "bar"], "attr3": ["foo"] } results = { "requester_everything_allowed": attributes.keys(), "requester_nothing_allowed": set(), "requester_subset_allowed": {"attr1", "attr2"}, } for requester, result in results.items(): attribute_policy_service = self.create_attribute_policy_service( attribute_policies) ctx = Context() ctx.state = dict() resp = InternalData(auth_info=AuthenticationInformation()) resp.requester = requester resp.attributes = { "attr1": ["foo"], "attr2": ["foo", "bar"], "attr3": ["foo"] } filtered = attribute_policy_service.process(ctx, resp) assert (filtered.attributes.keys() == result)
def test_generate_mustache_empty_attribute(self): synthetic_attributes = { "": { "default": { "a0": "{{kaka.first}}#{{eppn.scope}}" } } } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "kaka": ["kaka1", "kaka2"], "eppn": None, } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("kaka1#" in resp.attributes['a0']) assert ("kaka1" in resp.attributes['kaka']) assert ("kaka2" in resp.attributes['kaka'])
def test_generate_mustache1(self): synthetic_attributes = { "": { "default": { "a0": "{{kaka}}#{{eppn.scope}}" } } } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "kaka": ["kaka1"], "eppn": ["*****@*****.**", "*****@*****.**"] } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("kaka1#example.com" in resp.attributes['a0']) assert ("kaka1" in resp.attributes['kaka']) assert ("*****@*****.**" in resp.attributes['eppn']) assert ("*****@*****.**" in resp.attributes['eppn'])
def test_filter_all_attributes_from_all_target_providers_for_all_requesters( self): attribute_filters = { "": { # all providers "": { # all requesters "": "foo:bar" # all attributes } } } filter_service = self.create_filter_service(attribute_filters) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["abc:xyz"], "a2": ["foo:bar", "1:foo:bar:2"], "a3": ["a:foo:bar:b"] } filtered = filter_service.process(None, resp) assert filtered.attributes == { "a1": [], "a2": ["foo:bar", "1:foo:bar:2"], "a3": ["a:foo:bar:b"] }
def start_auth(self, context, internal_req): """ See super class method satosa.backends.base.BackendModule#start_auth :type context: satosa.context.Context :type internal_req: satosa.internal.InternalData :rtype: satosa.response.Response """ timestamp = datetime.utcnow().timestamp() auth_info = AuthenticationInformation( auth_class_ref=ReflectorBackend.AUTH_CLASS_REF, timestamp=timestamp, issuer=ReflectorBackend.ENTITY_ID, ) internal_resp = InternalData( auth_info=auth_info, attributes={}, subject_type=None, subject_id=ReflectorBackend.SUBJECT_ID, ) return self.auth_callback_func(context, internal_resp)
def auth_info(self, requrest): return AuthenticationInformation( UNSPECIFIED, None, self.config['server_info']['authorization_endpoint'])
def internal_response(self): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalData(auth_info=auth_info) internal_response.subject_id = "user1" return internal_response