[Kimchi-devel] [PATCHv2 2/7] Split PAM and LDAP authentication

Aline Manera alinefm at linux.vnet.ibm.com
Mon Nov 10 16:02:47 UTC 2014


On 11/06/2014 04:16 AM, Royce Lv wrote:
> On 2014年10月31日 01:09, Aline Manera wrote:
>>
>> On 10/28/2014 11:37 AM, lvroyce0210 at gmail.com wrote:
>>> From: Royce Lv <lvroyce at linux.vnet.ibm.com>
>>>
>>> Split PAM authentication implementation and abstract a common class.
>>>
>>> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
>>> ---
>>> src/kimchi/auth.py | 113 
>>> ++++++++++++++++++++++++++++++++++-------------------
>>> 1 file changed, 73 insertions(+), 40 deletions(-)
>>>
>>> diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
>>> index c8801a5..ad3f3ac 100644
>>> --- a/src/kimchi/auth.py
>>> +++ b/src/kimchi/auth.py
>>> @@ -31,6 +31,7 @@ import urllib2
>>>
>>>
>>> from kimchi import template
>>> +from kimchi.config import config
>>> from kimchi.exception import InvalidOperation, OperationFailed
>>> from kimchi.utils import get_all_tabs, run_command
>>>
>>> @@ -39,6 +40,7 @@ USER_NAME = 'username'
>>> USER_GROUPS = 'groups'
>>> USER_ROLES = 'roles'
>>> REFRESH = 'robot-refresh'
>>
>>> +AUTH = 'auth_method'
>>
>>
>>>
>>> tabs = get_all_tabs()
>>>
>>> @@ -59,6 +61,22 @@ def debug(msg):
>>>
>>>
>>> class User(object):
>>> + @classmethod
>>> + def create(cls, auth_args):
>>> + auth_type = auth_args.pop('auth_type')
>>> + for klass in cls.__subclasses__():
>>> + if auth_type == klass.auth_type:
>>> + try:
>>> + if not klass.authenticate(**auth_args):
>>> + debug("cannot verify user with the given password")
>>> + return None
>>> + except OperationFailed:
>>> + raise
>>> + return klass(auth_args['username'])
>>> +
>>> +
>>> +class PAMUser(User):
>>> + auth_type = "pam"
>>>
>>> def __init__(self, username):
>>> self.user = {}
>>> @@ -124,40 +142,54 @@ class User(object):
>>> def get_user(self):
>>> return self.user
>>>
>>> + @staticmethod
>>> + def authenticate(username, password, service="passwd"):
>>> + '''Returns True if authenticate is OK via PAM.'''
>>> + def _pam_conv(auth, query_list, userData=None):
>>> + resp = []
>>> + for i in range(len(query_list)):
>>> + query, qtype = query_list[i]
>>> + if qtype == PAM.PAM_PROMPT_ECHO_ON:
>>> + resp.append((username, 0))
>>> + elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
>>> + resp.append((password, 0))
>>> + elif qtype == PAM.PAM_PROMPT_ERROR_MSG:
>>> + cherrypy.log.error_log.error(
>>> + "PAM authenticate prompt error: %s" % query)
>>> + resp.append(('', 0))
>>> + elif qtype == PAM.PAM_PROMPT_TEXT_INFO:
>>> + resp.append(('', 0))
>>> + else:
>>> + return None
>>> + return resp
>>> +
>>> + auth = PAM.pam()
>>> + auth.start(service)
>>> + auth.set_item(PAM.PAM_USER, username)
>>> + auth.set_item(PAM.PAM_CONV, _pam_conv)
>>> + try:
>>> + auth.authenticate()
>>> + except PAM.error, (resp, code):
>>> + msg_args = {'username': username, 'code': code}
>>> + raise OperationFailed("KCHAUTH0001E", msg_args)
>>>
>>> -def authenticate(username, password, service="passwd"):
>>> - '''Returns True if authenticate is OK via PAM.'''
>>> - def _pam_conv(auth, query_list, userData=None):
>>> - resp = []
>>> - for i in range(len(query_list)):
>>> - query, qtype = query_list[i]
>>> - if qtype == PAM.PAM_PROMPT_ECHO_ON:
>>> - resp.append((username, 0))
>>> - elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
>>> - resp.append((password, 0))
>>> - elif qtype == PAM.PAM_PROMPT_ERROR_MSG:
>>> - cherrypy.log.error_log.error("PAM authenticate prompt error "
>>> - "message: %s" % query)
>>> - resp.append(('', 0))
>>> - elif qtype == PAM.PAM_PROMPT_TEXT_INFO:
>>> - resp.append(('', 0))
>>> - else:
>>> - return None
>>> - return resp
>>> -
>>> - auth = PAM.pam()
>>> - auth.start(service)
>>> - auth.set_item(PAM.PAM_USER, username)
>>> - auth.set_item(PAM.PAM_CONV, _pam_conv)
>>> -
>>> - try:
>>> - auth.authenticate()
>>> - except PAM.error:
>>> - raise
>>> -
>>> - return True
>>> + return True
>>>
>>>
>>> +class LDAPUser(User):
>>> + auth_type = "ldap"
>>> + def __init__(self, username):
>>> + self.user = {}
>>> + self.user[USER_NAME] = username
>>> + self.user[USER_GROUPS] = None
>>> + # FIXME: user roles will be changed according roles assignment after
>>> + # objstore is integrated
>>> + self.user[USER_ROLES] = dict.fromkeys(tabs, 'user')
>>> +
>>> + @staticmethod
>>> + def authenticate(username, password):
>>> + return False
>>> +
>>> def from_browser():
>>> # Enable Basic Authentication for REST tools.
>>> # Ajax request sent from jQuery in browser will have "X-Requested-With"
>>> @@ -216,21 +248,22 @@ def check_auth_httpba():
>>>
>>>
>>> def login(username, password, **kwargs):
>>> - try:
>>> - if not authenticate(username, password):
>>> - debug("User cannot be verified with the supplied password")
>>> - return None
>>> - except PAM.error, (resp, code):
>>> - msg_args = {'username': username, 'code': code}
>>> - raise OperationFailed("KCHAUTH0001E", msg_args)
>>> -
>>> - user = User(username)
>>> + auth_args = {'auth_type': config.get("authentication", "method"),
>>> + 'username': username,
>>> + 'password': password}
>>> +
>>> + user = User.create(auth_args)
>>> + if not user:
>>> + debug("User cannot be verified with the supplied password")
>>> + return None
>>> +
>>> debug("User verified, establishing session")
>>> cherrypy.session.acquire_lock()
>>> cherrypy.session.regenerate()
>>> cherrypy.session[USER_NAME] = username
>>> cherrypy.session[USER_GROUPS] = user.get_groups()
>>> cherrypy.session[USER_ROLES] = user.get_roles()
>>
>>> + cherrypy.session[AUTH] = config.get("authentication", "method")
>>
>> Do we really need to store it on the session? It was not used in the 
>> other patches.
> As UI will be interested in what kind of authentication backend is 
> using to choose display "pam" permission tagging or "ldap" permission 
> tagging
> After talked with YuXin, he suggested to move it to /host/capabilities 
> rather than put it in cookie, because not every part of UI interested 
> in authentication method,
> do you agree?

Yeap. Sounds good for me.

>>
>>> cherrypy.session[REFRESH] = time.time()
>>> cherrypy.session.release_lock()
>>> return user.get_user()
>>
>> _______________________________________________
>> Kimchi-devel mailing list
>> Kimchi-devel at ovirt.org
>> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>>
>




More information about the Kimchi-devel mailing list