def decorate(self, session): """ :type session: session_abcs.Session """ if not isinstance(session, session_abcs.Session): raise InvalidArgumentException('incorrect session argument passed') return self.StoppingAwareProxiedSession(session, self)
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 context_attribute(self, attribute_key, attribute_value=None): """ Allows custom attributes to be added to the underlying context Map used to construct the Subject instance. A None key throws an ``InvalidArgumentException``. A None value effectively removes any previously stored attribute under the given key from the context map. NOTE: This method is only useful when configuring Yosai with a custom ``SubjectFactory`` implementation. This method allows end-users to append additional data to the context map which the ``SubjectFactory`` implementation can use when building custom ``Subject`` instances. As such, this method is only useful when a custom ``SubjectFactory`` implementation has been configured. :param attribute_key: the key under which the corresponding value will be stored in the context Map :param attribute_value: the value to store in the context map under the specified attribute_key :raises InvalidArgumentException: if the attribute_key is None """ if (not attribute_key): msg = "Subject context map key cannot be None" raise InvalidArgumentException(msg) if (not attribute_value): self.subject_context.remove(attribute_key) else: self.subject_context.put(attribute_key, attribute_value)
def realms(self, realm_s): """ :realm_s: an immutable collection of one or more realms :type realm_s: tuple """ if realm_s: self._realms = realm_s self.apply_cache_handler(self._realms) # new to yosai.core (shiro v2 alpha is missing it): self.apply_credential_resolver(self._realms) self.apply_authz_info_resolver(self._realms) self.apply_permission_resolver(self._realms) self.apply_role_resolver(self._realms) try: self.authenticator.realms = self._realms except AttributeError: msg = "no authenticator attribute set yet" # log debug here try: self.authorizer.realms = self._realms except AttributeError: msg = "no authorizer attribute set yet" # log debug here else: msg = 'realms argument must have a value' raise InvalidArgumentException(msg)
def ensure_security_manager(self, subject_context): """ Determines whether there is a ``SecurityManager`` instance in the context, and if not, adds 'self' to the context. This ensures that the ``SubjectFactory`` instance will have access to a ``SecurityManager`` during Subject construction. :param subject_context: the subject context data that may contain a SecurityManager instance :returns: the SubjectContext intended for a SubjectFactory's Subject creation """ try: if (subject_context.resolve_security_manager() is not None): msg = ("Subject Context already contains a security_manager " "instance. Returning.") logger.debug(msg) return subject_context msg = ("No security_manager found in context. Adding self " "reference.") logger.debug(msg) subject_context.security_manager = self except AttributeError: msg = 'subject_context is invalid' raise InvalidArgumentException(msg) return subject_context
def authenticated(self, authc): """ :type authc: bool """ if not isinstance(authc, bool): raise InvalidArgumentException('authenticated must be Boolean') self._authenticated = authc
def remember_identity(self, subject, identifiers=None, account=None): """ Yosai consolidates rememberIdentity, an overloaded method in java, to a method that will use an identifier-else-account logic. Remembers a subject-unique identity for retrieval later. This implementation first resolves the exact identifying attributes to remember. It then remembers these identifying attributes by calling remember_identity(Subject, IdentifierCollection) :param subject: the subject for which the identifying attributes are being remembered :param identifiers: the identifying attributes to remember for retrieval later on :param account: the account containing authentication info resulting from the successful authentication attempt """ if not identifiers: # then account must not be None try: identifiers = self.get_identity_to_remember(subject, account) except AttributeError: msg = "Neither account nor identifier arguments passed" raise InvalidArgumentException(msg) serialized = self.convert_identifiers_to_bytes(identifiers) self.remember_serialized_identity(subject, serialized)
def authorizer(self, authorizer): if authorizer: self._authorizer = authorizer self.apply_event_bus(self._authorizer) self._authorizer.realms = self.realms else: msg = "authorizer argument must have a value" raise InvalidArgumentException(msg)
def session(self, session): """ :type session: session_abcs.Session """ if (isinstance(session, session_abcs.Session) or session is None): self._session = session else: raise InvalidArgumentException('must use Session object')
def put_all(self, contextobj): try: self.context.update(contextobj.context) except AttributeError: msg = "passed invalid argument to put_all" print(msg) # log exception here raise InvalidArgumentException(msg)
def identifiers(self, identifiers): """ :type identifiers: subject_abcs.IdentifierCollection """ if (isinstance(identifiers, subject_abcs.IdentifierCollection) or identifiers is None): self._identifiers = identifiers else: raise InvalidArgumentException('must use IdentifierCollection')
def security_manager(self, security_manager): """ :type security_manager: mgt_abcs.SecurityManager """ if (isinstance(security_manager, mgt_abcs.SecurityManager) or security_manager is None): self._security_manager = security_manager else: raise InvalidArgumentException('must use SecurityManager')
def setparts(self, wildcard_string, case_sensitive=DEFAULT_CASE_SENSITIVE): """ :type wildcard_string: str :case_sensitive: bool """ if (not wildcard_string): msg = ("Wildcard string cannot be None or empty. Make sure " "permission strings are properly formatted.") raise InvalidArgumentException(msg) wildcard_string = wildcard_string.strip() if not any(x != self.PART_DIVIDER_TOKEN for x in wildcard_string): msg = ("Wildcard string cannot contain JUST dividers. Make " "sure permission strings are properly formatted.") raise InvalidArgumentException(msg) if (not self.case_sensitive): wildcard_string = wildcard_string.lower() parts = wildcard_string.split(self.PART_DIVIDER_TOKEN) part_indices = {0: 'domain', 1: 'action', 2: 'target'} for index, part in enumerate(parts): if not any(x != self.SUBPART_DIVIDER_TOKEN for x in part): msg = ("Wildcard string cannot contain parts consisting JUST " "of sub-part dividers or nothing at all. Ensure that " "permission strings are properly formatted.") raise InvalidArgumentException(msg) myindex = part_indices.get(index) # NOTE: Shiro uses LinkedHashSet objects to maintain order and # Uniqueness. Unlike Shiro, Yosai disregards order as it # presents seemingly unecessary additional overhead (TBD) self.parts[myindex] = set() subparts = part.split(self.SUBPART_DIVIDER_TOKEN) for sp in subparts: self.parts[myindex].add(sp) # final step is to make it immutable: self.parts.update((k, frozenset(v)) for k, v in self.parts.items())
def add_collection(self, identifier_collection): """ :type identifier_collection: a SimpleIdentifierCollection """ try: new_source_identifiers = identifier_collection.source_identifiers self.source_identifiers.update(new_source_identifiers) except AttributeError: msg = "Invalid identifier collection passed as argument" raise InvalidArgumentException(msg)
def event_bus(self, eventbus): if eventbus: self._event_bus = eventbus self.apply_event_bus(self._authenticator) self.apply_event_bus(self._authorizer) self.apply_event_bus(self._session_manager) else: msg = 'eventbus argument must have a value' raise InvalidArgumentException(msg)
def cache_handler(self, cachehandler): if (cachehandler): self._cache_handler = cachehandler self.apply_cache_handler(self.realms) self.authenticator.realms = self.realms self.authorizer.realms = self.realms self.apply_cache_handler(self.session_manager) else: msg = ('Incorrect argument. If you want to disable caching, ' 'configure a disabled cachemanager instance') raise InvalidArgumentException(msg)
def logout(self, subject): """ Logs out the specified Subject from the system. Note that most application developers should not call this method unless they have a good reason for doing so. The preferred way to logout a Subject is to call ``Subject.logout()``, not by calling ``SecurityManager.logout`` directly. However, framework developers might find calling this method directly useful in certain cases. :param subject the subject to log out: :type subject: subject_abcs.Subject """ if (subject is None): msg = "Subject argument cannot be None." raise InvalidArgumentException(msg) self.before_logout(subject) identifiers = copy.copy(subject.identifiers) # copy is new to yosai if (identifiers): if logger.getEffectiveLevel() <= logging.DEBUG: msg = ("Logging out subject with primary identifier {0}".format( identifiers.primary_identifier)) logger.debug(msg) # yosai excludes call to authenticator's on_logout as shiro's observer # pattern has been replaced by the event bus interaction and # logout results in session expire event transmission, which is tracked # by the authenticator try: self.delete(subject) except Exception: if logger.getEffectiveLevel() <= logging.DEBUG: msg = "Unable to cleanly unbind Subject. Ignoring (logging out)." logger.debug(msg, exc_info=True) finally: try: # passing identifiers is new to yosai: self.stop_session(subject, identifiers) except Exception: if logger.getEffectiveLevel() <= logging.DEBUG: msg2 = ("Unable to cleanly stop Session for Subject. " "Ignoring (logging out).") logger.debug(msg2, exc_info=True)
def push_identity(self, identifiers): """ :type identifiers: subject_abcs.IdentifierCollection """ if (not identifiers): msg = ("Specified Subject identifiers cannot be None or empty " "for 'run as' functionality.") raise InvalidArgumentException(msg) stack = self.get_run_as_identifiers_stack() if (not stack): stack = collections.deque() stack.appendleft(identifiers) session = self.get_session() session.set_internal_attribute(self.run_as_identifiers_session_key, stack)