diff options
Diffstat (limited to 'macaroonbakery/bakery/_identity.py')
-rw-r--r-- | macaroonbakery/bakery/_identity.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/macaroonbakery/bakery/_identity.py b/macaroonbakery/bakery/_identity.py new file mode 100644 index 0000000..4389cd9 --- /dev/null +++ b/macaroonbakery/bakery/_identity.py @@ -0,0 +1,126 @@ +# Copyright 2017 Canonical Ltd. +# Licensed under the LGPLv3, see LICENCE file for details. +import abc + +from ._error import IdentityError + + +class Identity(object): + ''' Holds identity information declared in a first party caveat added when + discharging a third party caveat. + ''' + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def id(self): + ''' Returns the id of the user. + + May be an opaque blob with no human meaning. An id is only considered + to be unique with a given domain. + :return string + ''' + raise NotImplementedError('id method must be defined in subclass') + + @abc.abstractmethod + def domain(self): + '''Return the domain of the user. + + This will be empty if the user was authenticated + directly with the identity provider. + :return string + ''' + raise NotImplementedError('domain method must be defined in subclass') + + +class ACLIdentity(Identity): + ''' ACLIdentity may be implemented by Identity implementations + to report group membership information. + ''' + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def allow(self, ctx, acls): + ''' reports whether the user should be allowed to access + any of the users or groups in the given acl list. + :param ctx(AuthContext) is the context of the authorization request. + :param acls array of string acl + :return boolean + ''' + raise NotImplementedError('allow method must be defined in subclass') + + +class SimpleIdentity(ACLIdentity): + ''' A simple form of identity where the user is represented by a string. + ''' + def __init__(self, user): + self._identity = user + + def domain(self): + ''' A simple identity has no domain. + ''' + return '' + + def id(self): + '''Return the user name as the id. + ''' + return self._identity + + def allow(self, ctx, acls): + '''Allow access to any ACL members that was equal to the user name. + + That is, some user u is considered a member of group u and no other. + ''' + for acl in acls: + if self._identity == acl: + return True + return False + + +class IdentityClient(object): + ''' Represents an abstract identity manager. User identities can be based + on local informaton (for example HTTP basic auth) or by reference to an + external trusted third party (an identity manager). + ''' + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def identity_from_context(self, ctx): + ''' Returns the identity based on information in the context. + + If it cannot determine the identity based on the context, then it + should return a set of caveats containing a third party caveat that, + when discharged, can be used to obtain the identity with + declared_identity. + + It should only raise an error if it cannot check the identity + (for example because of a database access error) - it's + OK to return all zero values when there's + no identity found and no third party to address caveats to. + @param ctx an AuthContext + :return: an Identity and array of caveats + ''' + raise NotImplementedError('identity_from_context method must be ' + 'defined in subclass') + + @abc.abstractmethod + def declared_identity(self, ctx, declared): + '''Parses the identity declaration from the given declared attributes. + + TODO take the set of first party caveat conditions instead? + @param ctx (AuthContext) + @param declared (dict of string/string) + :return: an Identity + ''' + raise NotImplementedError('declared_identity method must be ' + 'defined in subclass') + + +class NoIdentities(IdentityClient): + ''' Defines the null identity provider - it never returns any identities. + ''' + + def identity_from_context(self, ctx): + return None, None + + def declared_identity(self, ctx, declared): + raise IdentityError('no identity declared or possible') |