def test_dss_merge_identifiers_runas_withsession( default_subject_store, delegating_subject, monkeypatch, mock_session): """ unit tested: merge_identifiers test case: - run_as set for the DS - current_identifiers gets assigned to subject._identifiers attribute (bypassing the property logic), - current_identifiers is saved to the session """ dss = default_subject_store ds = delegating_subject sic1 = SimpleIdentifierCollection(source_name='Current', identifier='Current') cids = collections.deque([sic1]) monkeypatch.setattr(ds, '_identifiers', cids) sic2 = SimpleIdentifierCollection(source_name='Existing', identifier='Existing') eids = collections.deque([sic2]) monkeypatch.setattr(mock_session, 'get_internal_attribute', lambda x: eids) monkeypatch.setattr(ds, 'get_run_as_identifiers_stack', lambda: True) monkeypatch.setattr(ds, 'get_session', lambda x: mock_session) with mock.patch.object(mock_session, 'set_internal_attribute') as mock_sa: mock_sa.return_value = None dss.merge_identifiers(ds) mock_sa.assert_called_once_with(dss.dsc_isk, cids)
def test_sic_by_type(): """ unit tested: by_type test case: returns all identifiers of a requested type """ sic = SimpleIdentifierCollection(source_name='realm1', identifier='identifier') result = set(sic.by_type(str)) # convert to set to always match assert result == frozenset(['identifier'])
def test_is_permitted_account_doesnt_exist(modular_realm_authorizer, permission_resolver): """ when an account cannot be obtained from the account_store, all permissions checked return False """ mra = modular_realm_authorizer perm1 = permission_resolver('money:write:bankcheck_19911109069') perm2 = permission_resolver('money:withdrawal') perm3 = permission_resolver('leatherduffelbag:transport:theringer') perm4 = permission_resolver('leatherduffelbag:access:theringer') perms = [perm1, perm2, perm3, perm4] expected_results = frozenset([(perm1, False), (perm2, False), (perm3, False), (perm4, False)]) unrecognized_identifier = \ SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='jackietreehorn') event_detected = None def event_listener(identifiers=None, items=None): nonlocal event_detected event_detected = items event_bus.register(event_listener, 'AUTHORIZATION.RESULTS') results = mra.is_permitted(unrecognized_identifier, perms) assert (expected_results == results and frozenset(event_detected) == results)
def test_dss_merge_identifiers_notrunas_withoutsession( default_subject_store, delegating_subject, monkeypatch, mock_session): """ unit tested: merge_identifiers test case: get_session returns None """ dss = default_subject_store ds = delegating_subject def get_session(create): if create == 'False': return None return mock_session sic1 = SimpleIdentifierCollection(source_name='Current', identifier='Current') cids = collections.deque([sic1]) monkeypatch.setattr(ds, '_identifiers', cids) monkeypatch.setattr(ds, 'get_run_as_identifiers_stack', lambda: False) monkeypatch.setattr(ds, 'get_session', get_session) with mock.patch.object(mock_session, 'set_internal_attribute') as mock_sa: mock_sa.return_value = None dss.merge_identifiers(ds) mock_sa.assert_called_once_with(dss.dsc_isk, cids)
def test_dss_merge_identifiers_notrunas_withsession( default_subject_store, delegating_subject, monkeypatch, mock_session): """ unit tested: merge_identifiers test case: with run_as NOT set for the DS, current_identifiers is obtained from the identifiers property, and then the current_identifiers are saved to the session """ dss = default_subject_store ds = delegating_subject sic1 = SimpleIdentifierCollection(source_name='Current', identifier='Current') cids = collections.deque([sic1]) monkeypatch.setattr(ds, '_identifiers', cids) monkeypatch.setattr(mock_session, 'get_internal_attribute', lambda x: None) monkeypatch.setattr(ds, 'get_run_as_identifiers_stack', lambda: False) monkeypatch.setattr(ds, 'get_session', lambda x: mock_session) with mock.patch.object(mock_session, 'set_internal_attribute') as mock_sa: mock_sa.return_value = None dss.merge_identifiers(ds) mock_sa.assert_called_once_with(dss.dsc_isk, cids)
def authenticate_account(self, authc_token): """ :type authc_token: authc_abcs.AuthenticationToken :raises IncorrectCredentialsException: when authentication fails """ try: identifier = authc_token.identifier except AttributeError: msg = 'Failed to obtain authc_token.identifiers' raise InvalidArgumentException(msg) account = self.get_credentials(identifier) self.assert_credentials_match(authc_token, account) # TBD: clear immediately or keep for life of session: # at this point, authentication is confirmed, so clear # the cache of credentials (however, they should have a short ttl anyway) # self.clear_cached_credentials(identifier) # authc_token.clear() identifiers = SimpleIdentifierCollection(source_name=self.name, identifier=account.account_id) # new to yosai: until a better approach is found, is the overriding / # enrichment of the account_id attribute with a SIC account.account_id = identifiers return account
def get_authentication_info(self, identifier): """ The default authentication caching policy is to cache an account's credentials that are queried from an account store, for a specific user, so to facilitate any subsequent authentication attempts for that user. Naturally, in order to cache one must have a CacheHandler. If a user were to fail to authenticate, perhaps due to an incorrectly entered password, during the the next authentication attempt (of that user id) the cached account will be readily available from cache and used to match credentials, boosting performance. :returns: an Account object """ account_info = None ch = self.cache_handler def query_authc_info(self): msg = ("Could not obtain cached credentials for [{0}]. " "Will try to acquire credentials from account store.". format(identifier)) logger.debug(msg) # account_info is a dict account_info = self.account_store.get_authc_info(identifier) if account_info is None: msg = "Could not get stored credentials for {0}".format( identifier) raise ValueError(msg) return account_info try: msg2 = ("Attempting to get cached credentials for [{0}]".format( identifier)) logger.debug(msg2) # account_info is a dict account_info = ch.get_or_create(domain='authentication:' + self.name, identifier=identifier, creator_func=query_authc_info, creator=self) except AttributeError: # this means the cache_handler isn't configured account_info = query_authc_info(self) except ValueError: msg3 = ("No account credentials found for identifiers [{0}]. " "Returning None.".format(identifier)) logger.warning(msg3) if account_info: account_info['account_id'] = SimpleIdentifierCollection( source_name=self.name, identifier=identifier) return account_info
def test_sic_deserialize(sic_serialized, simple_identifiers_collection): """ unit tested: deserialize test case: deserializing a serialized SIC results in a new SIC instance """ sic = simple_identifiers_collection deserialized = SimpleIdentifierCollection.deserialize(sic_serialized) assert deserialized.source_identifiers == sic.source_identifiers
def get_authorization_info(self, identifiers): """ The default caching policy is to cache an account's authorization info, obtained from an account store so to facilitate subsequent authorization checks. In order to cache, a realm must have a CacheHandler. :type identifiers: subject_abcs.IdentifierCollection :returns: Account """ account_info = None ch = self.cache_handler identifier = identifiers.primary_identifier # TBD def query_authz_info(self): msg = ("Could not obtain cached authz_info for [{0}]. " "Will try to acquire authz_info from account store." .format(identifier)) logger.debug(msg) account_info = self.account_store.get_authz_info(identifier) if account_info is None: msg = "Could not get authz_info for {0}".format(identifier) raise ValueError(msg) return account_info try: msg2 = ("Attempting to get cached authz_info for [{0}]" .format(identifier)) logger.debug(msg2) account_info = ch.get_or_create(domain='authorization:' + self.name, identifier=identifier, creator_func=query_authz_info, creator=self) except AttributeError: # this means the cache_handler isn't configured account_info = query_authz_info(self) except ValueError: msg3 = ("No account authz_info found for identifier [{0}]. " "Returning None.".format(identifier)) logger.warning(msg3) if account_info: account_info['account_id'] = SimpleIdentifierCollection(source_name=self.name, identifier=identifier) return account_info
def test_sic_add(source_name, identifiers, collection): """ unit tested: add test case: the add method accepts two forms of input: 1) a source_name/identifiers pair - either a scalar identifiers value or collection of identifiers (set) 2) an identifiers collection object """ sic = SimpleIdentifierCollection(source_name, identifiers, collection) if collection: assert sic.source_identifiers == collection.source_identifiers elif isinstance(identifiers, set): assert sic.source_identifiers[source_name] == identifiers else: assert sic.source_identifiers[source_name] == identifiers
def test_delete_cached_session(session_store, session, cache_handler): """ this test will pass if test_create_cache_session runs first """ css = session_store sic = SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='user12345678') session.set_internal_attribute('identifiers_session_key', sic) sessionid = css.create(session) css.delete(session) cached_session = css.read(sessionid) cached_session_token = cache_handler.get('session', 'user12345678') assert cached_session is None assert cached_session_token is None
def test_create_cache_session(session_store, session, cache_handler): """ test objective: cache new session entry and read session from cache aspects tested: - session.set_internal_attribute - session_store.create - session_store.read - session_store.delete - cache_handler.get - session.__eq__ """ css = session_store sic = SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='user12345678') session.set_internal_attribute('identifiers_session_key', sic) sessionid = css.create(session) cached_session = css.read(sessionid) assert isinstance(cached_session, SimpleSession)
def walter_identifier(): return SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='walter')
def simple_identifiers_collection(): return SimpleIdentifierCollection(source_name='realm1', identifier='username')
unit tested: primary_identifier test case: the primary identifiers is initially lazy loaded """ sic = simple_identifiers_collection monkeypatch.delattr(sic, 'source_identifiers') result = sic.primary_identifier out, err = capsys.readouterr() assert result is None @pytest.mark.parametrize( 'source_name, identifiers, collection', [('realm1', 'identifiers1', None), (None, None, SimpleIdentifierCollection('realm2', 'identifiers1'))]) def test_sic_add(source_name, identifiers, collection): """ unit tested: add test case: the add method accepts two forms of input: 1) a source_name/identifiers pair - either a scalar identifiers value or collection of identifiers (set) 2) an identifiers collection object """ sic = SimpleIdentifierCollection(source_name, identifiers, collection) if collection: assert sic.source_identifiers == collection.source_identifiers elif isinstance(identifiers, set): assert sic.source_identifiers[source_name] == identifiers
unit tested: primary_identifier test case: the primary identifiers is initially lazy loaded """ sic = simple_identifiers_collection monkeypatch.delattr(sic, 'source_identifiers') result = sic.primary_identifier out, err = capsys.readouterr() assert result is None @pytest.mark.parametrize('source_name, identifiers, collection', [('realm1', 'identifiers1', None), (None, None, SimpleIdentifierCollection('realm2', 'identifiers1')) ]) def test_sic_add(source_name, identifiers, collection): """ unit tested: add test case: the add method accepts two forms of input: 1) a source_name/identifiers pair - either a scalar identifiers value or collection of identifiers (set) 2) an identifiers collection object """ sic = SimpleIdentifierCollection(source_name, identifiers, collection) if collection: assert sic.source_identifiers == collection.source_identifiers elif isinstance(identifiers, set):
asr = account_store_realm if "Could not" in expected_in: keys = cache_handler.keys('*authentication*') for key in keys: cache_handler.cache_region.delete(key) asr.get_authentication_info(identifier=identifier) out = caplog.text assert (expected_in in out and expected_out not in out) @pytest.mark.parametrize('identifiers, expected_in, expected_out', [(SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='thedude'), "Could not obtain cached", "No account"), (SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='thedude'), "get cached", "Could not obtain cached")]) def test_get_authzd_permissions(identifiers, expected_in, expected_out, caplog, account_store_realm, cache_handler): """ I) Obtains from account store, caches II) Obtains from cache III) Fails to obtain from any source """ asr = account_store_realm if "Could not" in expected_in: keys = cache_handler.keys('*authorization*')
def simple_identifier_collection(): return SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='identifier')
def thedude_identifier(): return SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='thedude')
if "Could not" in expected_in: keys = cache_handler.keys('*authentication*') for key in keys: cache_handler.cache_region.delete(key) result = asr.get_authentication_info(identifier=identifier) out = caplog.text assert (expected_in in out and expected_out not in out) @pytest.mark.parametrize( 'identifiers, expected_in, expected_out', [(SimpleIdentifierCollection( source_name='AccountStoreRealm', identifier='thedude'), "Could not obtain cached", "No account"), (SimpleIdentifierCollection( source_name='AccountStoreRealm', identifier='thedude'), "get cached", "Could not obtain cached"), (SimpleIdentifierCollection( source_name='AccountStoreRealm', identifier='anonymous'), "No account", "blabla")]) def test_get_authz_info(identifiers, expected_in, expected_out, caplog, account_store_realm, cache_handler): """ I) Obtains from account store, caches II) Obtains from cache III) Fails to obtain from any source """ asr = account_store_realm
def jackie_identifier(): return SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='jackie')
asr = account_store_realm if "Could not" in expected_in: cache_handler.delete(domain="credentials", identifier=thedude.identifier) result = asr.get_credentials(identifier=identifier) out = caplog.text assert (expected_in in out and expected_out not in out) assert isinstance(result, expected_class) @pytest.mark.parametrize( 'identifiers, expected_in, expected_out, expected_class', [(SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='thedude'), "Could not obtain cached", "No account", Account), (SimpleIdentifierCollection(source_name='AccountStoreRealm', identifier='thedude'), "get cached", "Could not obtain cached", Account), (SimpleIdentifierCollection( source_name='AccountStoreRealm', identifier='anonymous'), "No account", "blabla", type(None))]) def test_get_authz_info(identifiers, expected_in, expected_out, expected_class, caplog, account_store_realm, authz_info, cache_handler, thedude): """ I) Obtains from account store, caches II) Obtains from cache III) Fails to obtain from any source """