r5356 - trunk/cumin/python/cumin
by tmckay@fedoraproject.org
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)
11 years, 12 months
r5355 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2012-05-02 14:44:58 +0000 (Wed, 02 May 2012)
New Revision: 5355
Modified:
trunk/cumin/python/cumin/grid/dashboard.strings
Log:
Fixing alignment of data tables on grid::overview page
Modified: trunk/cumin/python/cumin/grid/dashboard.strings
===================================================================
--- trunk/cumin/python/cumin/grid/dashboard.strings 2012-05-02 13:21:05 UTC (rev 5354)
+++ trunk/cumin/python/cumin/grid/dashboard.strings 2012-05-02 14:44:58 UTC (rev 5355)
@@ -145,6 +145,7 @@
text-align: right;
width: 2em;
display: block;
+ float:right;
}
.DefinitionSet span.chart.blank {
11 years, 12 months
r5354 - trunk/cumin/python/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-05-02 13:21:05 +0000 (Wed, 02 May 2012)
New Revision: 5354
Modified:
trunk/cumin/python/cumin/authenticator.py
Log:
Allow multiple occurrences of %s in filterstr, all to be replaced with
username.
Modified: trunk/cumin/python/cumin/authenticator.py
===================================================================
--- trunk/cumin/python/cumin/authenticator.py 2012-05-02 12:50:21 UTC (rev 5353)
+++ trunk/cumin/python/cumin/authenticator.py 2012-05-02 13:21:05 UTC (rev 5354)
@@ -55,11 +55,18 @@
return False
return conn
+ def _gen_filter(self, filterstr, value):
+ count = filterstr.count("%s")
+ if count > 0:
+ vals = (value,) * count
+ return filterstr % vals
+ return filterstr
+
def _find_user(self, user):
res = False
conn = self.__prep_con()
if conn:
- filter = self.url.filterstr % user
+ filter = self._gen_filter(self.url.filterstr, user)
try:
res = conn.search_s(self.url.dn, self.url.scope, filter)
except Exception, e:
@@ -92,7 +99,7 @@
conn = self.__prep_con()
error = not conn
if not error:
- filter = self.url.filterstr % '*'
+ filter = self._gen_filter(self.url.filterstr, "*")
try:
res = conn.search_s(self.url.dn, self.url.scope, filter)
except Exception, e:
11 years, 12 months
r5353 - trunk/cumin/python/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-05-02 12:50:21 +0000 (Wed, 02 May 2012)
New Revision: 5353
Modified:
trunk/cumin/python/cumin/authenticator.py
Log:
Improve log messages related to LDAP
Modified: trunk/cumin/python/cumin/authenticator.py
===================================================================
--- trunk/cumin/python/cumin/authenticator.py 2012-05-01 15:57:45 UTC (rev 5352)
+++ trunk/cumin/python/cumin/authenticator.py 2012-05-02 12:50:21 UTC (rev 5353)
@@ -27,6 +27,7 @@
class CuminAuthenticatorLDAP(object):
def __init__(self, url):
+ self.valid = False
log.info("Initializing %s", self)
myurl = url.split("=",1)[1]
try:
@@ -34,6 +35,7 @@
scope=ldapurl.LDAP_SCOPE_SUBTREE,
filterstr="uid=%s")
log.info("Authenticator: parsed LDAP url successfully.")
+ self.valid = True
except Exception,e:
log.error("Authenticator: cannot parse LDAP url %s", e)
@@ -136,12 +138,11 @@
except Exception, e:
log.info("Authenticator: LDAP authentication "\
"returned exception %s" % e)
- _syslog.log("cumin: authentication via LDAP failed "\
- "for user %s" % dn)
return False
class CuminAuthenticatorScript(object):
def __init__(self, commandline):
+ self.valid = False
self.params = {}
self.cap = []
me = self.__class__.__name__
@@ -168,7 +169,8 @@
for cap in ("auth", "change", "list", "find"):
if self.params.has_key(cap):
log.debug(msg % (cap, me))
- self.cap.append(cap[0])
+ self.cap.append(cap[0])
+ self.valid = True
else:
log.error('Authenticator: script parameter missing or target file '\
'not executable in %s', me)
@@ -190,7 +192,6 @@
if res.returncode == 0:
_syslog.log("cumin: authenticated user %s via script" % username)
return True
- _syslog.log("cumin: authentication via script failed for user %s" % username)
return False
def find_user(self, username):
@@ -277,14 +278,17 @@
authmech = "ldap=" + authmech
else:
mechname = authmech.split('=',1)[0]
- log.info("Authenticator: adding auth mechanism %s", mechname)
classname = authen_map[mechname]
except KeyError:
log.error("Authenticator: unsupported authenticator type %s",
mechname)
continue
- self.authenticators.append(classname(authmech))
+ c = classname(authmech)
+ if c.valid:
+ log.info("Authenticator: adding auth mechanism %s", mechname)
+ self.authenticators.append(c)
+
def batch_import(self, backend, output_on=False):
numusers = 0
numconflicts = 0
@@ -336,23 +340,30 @@
return numusers, numconflicts, errors
def authenticate(self, username, password):
- log.debug("Authenticator: calling authenticate")
cursor = self.app.database.get_read_cursor()
cls = self.app.model.com_redhat_cumin.User
user = cls.get_object(cursor, name=username)
if user is None or len(user.password) == 0:
res = False
log.debug("Authenticator: authenticating external user")
+ if len(self.authenticators) == 0:
+ log.debug("Authenticator: no external mechanisms available")
for authenticator in self.authenticators:
log.debug("Authenticator: authenticate, try %s", authenticator)
res = authenticator.authenticate(username, password)
if res:
break
+ log.debug("Authenticator: authentication %s for external user" \
+ % (res and "succeeded" or "failed"))
+ msg = "cumin: authentication %s for external user %s" \
+ % (res and "succeeded" or "failed", username)
else:
res = crypt(password, user.password) == user.password
+ log.debug("Authenticator: authentication %s for user" \
+ % (res and "succeeded" or "failed"))
msg = "cumin: authentication %s for user %s" \
% (res and "succeeded" or "failed", username)
- _syslog.log(msg)
+ _syslog.log(msg)
return user, res
def find_user(self, username):
11 years, 12 months
r5352 - in trunk/cumin: etc python/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-05-01 15:57:45 +0000 (Tue, 01 May 2012)
New Revision: 5352
Modified:
trunk/cumin/etc/cumin.conf
trunk/cumin/python/cumin/authenticator.py
Log:
Add defaults for auth mechanism parsing.
Let 'ldap=' be dropped if the mechanism begins with "ldap://".
Allow parameters to be dropped for script capabilities.
Assume a script has all capabilities if none are specified
Modified: trunk/cumin/etc/cumin.conf
===================================================================
--- trunk/cumin/etc/cumin.conf 2012-04-27 16:46:08 UTC (rev 5351)
+++ trunk/cumin/etc/cumin.conf 2012-05-01 15:57:45 UTC (rev 5352)
@@ -28,12 +28,14 @@
# job servers. If the Aviary locator is used, this value will be overriden
# but must still be non-empty to enable use of Aviary job servers.
# Default value is shown. Uncomment and leave the value blank to disable.
+# More details in 'Some parameter explanations by section' below.
# aviary-job-servers: http://localhost:9090
# The value for this parameter is a comma separated list of URLs for Aviary
# query servers. If the Aviary locator is used, this value will be overriden
# but must still be non-empty to enable use of Aviary query servers.
# Default value is shown. Uncomment and leave the value blank to disable.
+# More details in 'Some parameter explanations by section' below.
# aviary-query-servers: http://localhost:9091
# The locator allows Cumin to retrive values for Aviary job servers and
@@ -41,7 +43,8 @@
# values for aviary-job-servers and aviary-query-servers will be overriden
# (but those parameters must still be non-empty to be enabled).
# Default is empty string (aviary locator will not be used). Uncomment the
-# following line and edit as needed to enable.
+# following line and edit as needed to enable. More details in
+# 'Some parameter explanations by section' below.
# aviary-locator: http://localhost:9000
# Full path to private key file used for ssl communication with aviary servers.
@@ -252,6 +255,14 @@
## query servers to be used, even if aviary-locator
## has been set.
+## aviary-locator: http://localhost:9000
+## Specifies the URI for the aviary locator. This is
+## a single value, not a list of URIs. The form of
+## the URI is the same as that of aviary-job-servers.
+## The port will default to 9000 and the path will
+## default to /services/locator/locate. Other defaults
+## are as noted for aviary-job-servers.
+
## log-max-mb: 10
## Maximum size in MB of *.log files created by cumin.
## A log file reaching maximum size will be rolled over.
Modified: trunk/cumin/python/cumin/authenticator.py
===================================================================
--- trunk/cumin/python/cumin/authenticator.py 2012-04-27 16:46:08 UTC (rev 5351)
+++ trunk/cumin/python/cumin/authenticator.py 2012-05-01 15:57:45 UTC (rev 5352)
@@ -30,7 +30,9 @@
log.info("Initializing %s", self)
myurl = url.split("=",1)[1]
try:
- self.url = ldapurl.LDAPUrl(myurl)
+ self.url = ldapurl.LDAPUrl(myurl,
+ scope=ldapurl.LDAP_SCOPE_SUBTREE,
+ filterstr="uid=%s")
log.info("Authenticator: parsed LDAP url successfully.")
except Exception,e:
log.error("Authenticator: cannot parse LDAP url %s", e)
@@ -144,23 +146,29 @@
self.cap = []
me = self.__class__.__name__
for a in commandline.split(','):
- param,val = a.split('=')
+ # Allow capability with a null value
+ args = a.split('=')
+ if len(args) == 1:
+ args.append("")
+ param,val = args
self.params[param] = val
if self.params.has_key('script') and \
os.access(self.params['script'], os.X_OK):
- if self.params.has_key('auth'):
- log.debug("Authenticator: adding auth capability to %s", me)
- self.cap.append('a')
- if self.params.has_key('change'):
- log.debug("Authenticator: adding change capability to %s", me)
- self.cap.append('c')
- if self.params.has_key('list'):
- log.debug("Authenticator: adding list capability to %s", me)
- self.cap.append('l')
- if self.params.has_key('find'):
- log.debug("Authenticator: adding find capability to %s", me)
- self.cap.append('f')
+
+ # Allow default with all operations and no specific
+ # parameters per operation. The convention here is
+ # to store the first letter in self.cap, but anything
+ # unambiguous would do.
+ if len(self.params) == 1:
+ self.cap = ['a','c','l','f']
+ log.debug("Authenticator: adding all capabilities to %s", me)
+ else:
+ msg = "Authenticator: adding %s capability to %s"
+ for cap in ("auth", "change", "list", "find"):
+ if self.params.has_key(cap):
+ log.debug(msg % (cap, me))
+ self.cap.append(cap[0])
else:
log.error('Authenticator: script parameter missing or target file '\
'not executable in %s', me)
@@ -262,8 +270,13 @@
"ldap mechanism not available")
for authmech in app.authmech:
if authmech != "internal":
+ # Allow initial ldap= to be skipped
try:
- mechname = authmech.split('=')[0]
+ if authmech.startswith("ldap://"):
+ mechname = "ldap"
+ authmech = "ldap=" + authmech
+ else:
+ mechname = authmech.split('=',1)[0]
log.info("Authenticator: adding auth mechanism %s", mechname)
classname = authen_map[mechname]
except KeyError:
11 years, 12 months