[Kimchi-devel] [PATCH 3/5] Find out user groups and sudo status during login.
Leonardo Garcia
lagarcia at linux.vnet.ibm.com
Mon Feb 10 02:32:32 UTC 2014
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]
+
+ 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):
--
1.8.5.3
More information about the Kimchi-devel
mailing list