[Kimchi-devel] [PATCH 3/5] Find out user groups and sudo status during login.
Aline Manera
alinefm at linux.vnet.ibm.com
Mon Feb 10 18:55:00 UTC 2014
On 02/10/2014 12:32 AM, Leonardo Garcia wrote:
> From: Leonardo Garcia <lagarcia at br.ibm.com>
>
> When the /login REST API is called with a valid username and password,
> Kimchi will find out the user groups and sudo status, store these values
> in sessions variables, and return them in a JSON message with the
> following format:
>
> {"sudo": true | false, "userid": "<username>", "groups": [<list of
> groups>]}
>
> For example:
>
> {"sudo": false, "userid": "guest", "groups": ["guest", "foo"]}
>
> This JSON return message can be used by the UI to figure out which
> tabs/options should be shown in the web interface according to the user
> rights.
>
> It is important to notice that sudo configuration for a given user is
> not as simple as an on/off key. Sudo permits various levels of access
> controls. For instance, it is possible to specify which executables a
> user can run with sudo. For the purpose of this implementation, we only
> consider a user to have sudo rights if this user can run any command in
> the system with sudo (which is equivalent to have root rights).
>
> Signed-off-by: Leonardo Garcia <lagarcia at br.ibm.com>
> ---
> src/kimchi/auth.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++----
> src/kimchi/root.py | 4 ++--
> 2 files changed, 58 insertions(+), 6 deletions(-)
>
> diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
> index f9873ca..3ffe4b1 100644
> --- a/src/kimchi/auth.py
> +++ b/src/kimchi/auth.py
> @@ -30,9 +30,12 @@ import re
>
> from kimchi import template
> from kimchi.exception import OperationFailed
> +from kimchi.utils import run_command, parse_cmd_output
>
>
> -SESSION_USER = 'userid'
> +USER_ID = 'userid'
> +USER_GROUPS = 'groups'
> +USER_SUDO = 'sudo'
>
>
> def debug(msg):
> @@ -40,6 +43,52 @@ def debug(msg):
> # cherrypy.log.error(msg)
>
>
> +class User(object):
> +
> + def __init__(self, userid):
> + self.user = {}
> + self.user[USER_ID] = userid
> + self.user[USER_GROUPS] = []
> + self.user[USER_SUDO] = False
> +
> + def get_groups(self):
> + out, err, exit = run_command(['groups', self.user[USER_ID]])
> + # the output of the groups command is of the form:
> + # <userid> : <list of groups separated by space>
> + if exit == 0:
> + out = parse_cmd_output(out, ['userid', 'groups'], ':')
> + self.user[USER_GROUPS] = out[0]['groups'].split()
> + debug("Groups for %s: %s" % (self.user[USER_ID],
> + self.user[USER_GROUPS]))
> + return self.user[USER_GROUPS]
You can use grp module here.
http://stackoverflow.com/questions/9323834/python-how-to-get-group-ids-of-one-username-like-id-gn
> +
> + def has_sudo(self):
> + out, err, exit = run_command(['sudo', '-l', '-U', self.user[USER_ID],
> + 'sudo'])
> + if exit == 0:
> + debug("User %s is allowed to run sudo" % self.user[USER_ID])
> + # sudo allows a wide range of configurations, such as controlling
> + # which binaries the user can execute with sudo.
> + # For now, we will just check whether the user is allowed to run any
> + # command with sudo.
> + out, err, exit = run_command(['sudo', '-l', '-U',
> + self.user[USER_ID]])
> + for line in out.split('\n'):
> + if line and re.search("(ALL)", line):
> + self.user[USER_SUDO] = True
> + debug("User %s can run any command with sudo" %
> + self.user[USER_ID])
> + return self.user[USER_SUDO]
> + debug("User %s can only run some commands with sudo" %
> + self.user[USER_ID])
> + else:
> + debug("User %s is not allowed to run sudo" % self.user[USER_ID])
> + return self.user[USER_SUDO]
> +
> + def get_user(self):
> + return self.user
> +
> +
> def authenticate(username, password, service="passwd"):
> '''Returns True if authenticate is OK via PAM.'''
> def _pam_conv(auth, query_list, userData=None):
> @@ -122,13 +171,16 @@ def check_auth_httpba():
> def login(userid, password):
> if not authenticate(userid, password):
> debug("User cannot be verified with the supplied password")
> - return False
> + return None
> + user = User(userid)
> debug("User verified, establishing session")
> cherrypy.session.acquire_lock()
> cherrypy.session.regenerate()
> - cherrypy.session[SESSION_USER] = cherrypy.request.login = userid
> + cherrypy.session[USER_ID] = userid
> + cherrypy.session[USER_GROUPS] = user.get_groups()
> + cherrypy.session[USER_SUDO] = user.has_sudo()
> cherrypy.session.release_lock()
> - return True
> + return user.get_user()
>
>
> def logout():
> diff --git a/src/kimchi/root.py b/src/kimchi/root.py
> index ce4a49c..8e90b7f 100644
> --- a/src/kimchi/root.py
> +++ b/src/kimchi/root.py
> @@ -106,11 +106,11 @@ class KimchiRoot(Root):
> raise cherrypy.HTTPError(400, "Missing parameter: '%s'" % key)
>
> try:
> - auth.login(userid, password)
> + user_info = auth.login(userid, password)
> except OperationFailed:
> raise cherrypy.HTTPError(401)
>
> - return '{}'
> + return json.dumps(user_info)
>
> @cherrypy.expose
> def logout(self):
More information about the Kimchi-devel
mailing list