Author: tmckay
Date: 2012-05-02 15:48:47 +0000 (Wed, 02 May 2012)
New Revision: 5356
Modified:
trunk/cumin/python/cumin/authenticator.py
Log:
Updates to the script authentication mechanism.
* Separate arguments to the script with "," instead of " "
* Improve logging
* Allow for empty parameter lists for script operations in cumin.conf
The current operations that can be delegated to scripts are unambiguous
by the number of arguments, so an initial value stating the operation type
is not needed. It can be either, for example:
script=script,auth,change,list
script=script,auth=auth
The specifier should match what the script expects. Cumin will pass
arguments appropriately.
Modified: trunk/cumin/python/cumin/authenticator.py
===================================================================
--- trunk/cumin/python/cumin/authenticator.py 2012-05-02 14:44:58 UTC (rev 5355)
+++ trunk/cumin/python/cumin/authenticator.py 2012-05-02 15:48:47 UTC (rev 5356)
@@ -182,6 +182,11 @@
log.error('Authenticator: script parameter missing or target file '\
'not executable in %s', me)
+ def _gen_input(self, op, *args):
+ if op in self.params and len(self.params[op]) > 0:
+ args = (self.params[op],)+args
+ return ",".join(["%s" % x for x in args])
+
def authenticate(self, username, password):
me = self.__class__.__name__
if 'a' in self.cap:
@@ -190,15 +195,24 @@
# If they are passed as arguments they show up in the output
# of ps, etc. This way is secure.
# Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input="%s %s %s" % \
- (self.params['auth'], username,
password))
- log.debug("Authenticator: authenticate, script returned "\
- "%s, %s, exitcode %s", out, err, res.returncode)
+ try:
+ cmd = [self.params['script']]
+ args = self._gen_input("auth", username, password)
+ res = subprocess.Popen(cmd,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ out, err = res.communicate(input=args)
+ log.debug("Authenticator: authenticate, script returned "\
+ "%s, %s, exitcode %s", out, err, res.returncode)
+ except:
+ log.error("Authenticator: authenticate, "\
+ "exception running script, return False")
+ return False
+
if res.returncode == 0:
_syslog.log("cumin: authenticated user %s via script" %
username)
return True
+ else:
+ log.debug("Authenticator: 'auth' not supported by script")
return False
def find_user(self, username):
@@ -209,14 +223,23 @@
# If they are passed as arguments they show up in the output
# of ps, etc. This way is secure.
# Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input="%s %s" % \
- (self.params['find'], username))
- log.debug("Authenticator: find_user, script returned "\
- "%s, %s, exitcode %s", out, err, res.returncode)
+ try:
+ cmd = [self.params['script']]
+ args = self._gen_input("find", username)
+ res = subprocess.Popen(cmd,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ out, err = res.communicate(input=args)
+ log.debug("Authenticator: find_user, script returned "\
+ "%s, %s, exitcode %s", out, err, res.returncode)
+ except:
+ log.error("Authenticator: find_user, "\
+ "exception running script, return False")
+ return False
+
if res.returncode == 0:
return True
+ else:
+ log.debug("Authenticator: 'find' not supported by script")
return False
def batch_import(self):
@@ -227,12 +250,22 @@
# If they are passed as arguments they show up in the output
# of ps, etc. This way is secure.
# Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input=self.params['list'])
- log.debug("Authenticator: batch import, script returned "\
+ try:
+ cmd = [self.params['script']]
+ args = self._gen_input("list")
+ res = subprocess.Popen(cmd,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ out, err = res.communicate(input=args)
+ log.debug("Authenticator: batch import, script returned "\
"%s, %s, exitcode %s", out, err, res.returncode)
+ except:
+ log.error("Authenticator: batch_import, "\
+ "exception running script, return False")
+ return []. False
+
return out.split(','), False
+ else:
+ log.debug("Authenticator: 'list' not supported by script")
return [], False
def change_pw(self, user, newpass, oldpass):
@@ -244,21 +277,24 @@
# If they are passed as arguments they show up in the output
# of ps, etc. This way is secure.
# Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
try:
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input="%s %s %s %s" % \
- (self.params['change'], user, newpass,
oldpass))
- log.debug("Authenticator: update password, script returned "\
+ cmd = [self.params['script']]
+ args = self._gen_input("change", user, newpass, oldpass)
+ res = subprocess.Popen(cmd,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ out, err = res.communicate(args)
+ log.debug("Authenticator: change password, script returned "\
"%s, %s, exitcode %s", out, err, res.returncode)
- except Exception, e:
- import traceback
- traceback.print_exc()
- res.returncode = -1
+ except:
+ log.error("Authenticator: change_pw, "\
+ "exception running script, return False")
+ return False
if res.returncode == 0:
- _syslog.log("cumin: updated password via script for user %s" %
user)
+ _syslog.log("cumin: change password via script for user %s" %
user)
return True
+ else:
+ log.debug("Authenticator: 'change' not supported by
script")
return False
if have_ldap:
@@ -384,6 +420,8 @@
if not res:
# Try to find the user externally
log.debug("Authenticator: finding external user")
+ if len(self.authenticators) == 0:
+ log.debug("Authenticator: no external mechanisms available")
for authenticator in self.authenticators:
log.debug("Authenticator: find_user, try %s", authenticator)
res = authenticator.find_user(username)