diff options
| author | Sumit Bose <sbose@nb.localdomain> | 2008-09-18 20:49:17 +0200 |
|---|---|---|
| committer | Sumit Bose <sbose@nb.localdomain> | 2008-09-18 20:49:17 +0200 |
| commit | 4f040a5754dad993ec6ee64b38f327567470ef10 (patch) | |
| tree | 0bf83c1c16f0a1dbfb9842cee0f6b1ce6dde4ef6 /sudoers | |
| parent | 7bfb88bbf648000b4c2bf853a11ad2bd3f4b2d85 (diff) | |
| download | ipa_policy-4f040a5754dad993ec6ee64b38f327567470ef10.tar.gz ipa_policy-4f040a5754dad993ec6ee64b38f327567470ef10.tar.xz ipa_policy-4f040a5754dad993ec6ee64b38f327567470ef10.zip | |
added fcusack's custom validator and two examples
Diffstat (limited to 'sudoers')
| -rw-r--r-- | sudoers/examples/sudoers_example_1 | 45 | ||||
| -rw-r--r-- | sudoers/examples/sudoers_example_2 | 130 | ||||
| -rwxr-xr-x[-rw-r--r--] | sudoers/sudoers2xml | 0 | ||||
| -rwxr-xr-x | sudoers/validate.py | 89 |
4 files changed, 264 insertions, 0 deletions
diff --git a/sudoers/examples/sudoers_example_1 b/sudoers/examples/sudoers_example_1 new file mode 100644 index 0000000..c1709b0 --- /dev/null +++ b/sudoers/examples/sudoers_example_1 @@ -0,0 +1,45 @@ +## Sample sudoers file ## +# *** Host_Alias specifications *** +# Host_Alias seems not to be useful, unless you have a +# global sudoers file that is replicated across multiple hosts. +# make LOCAL mean localhost (probably a bad idea, as this will allow it to run on any machine that has the sudoers file) +Host_Alias LOCAL = 127.0.0.1 +# Anywhere that "LAN" is specified, these hosts apply: +Host_Alias LAN = ahost.mycompany.com, anotherhost.mycompany.com + +# *** User_Alias specifications *** +# User_Alias allows you to group users. (better to use AD/NIS groups, for global/central management?) +# MAILADMINS user alias refers to users dick and jane +User_Alias MAILADMINS = dick, jane + +# *** Runas_Alias specifications *** +# This specifies an alias or grouping of whom a command can be run as. +Runas_Alias SOMEONE = larry, tom + +# *** Cmd_Alias specifications *** +# alias or group commands with full paths, to make things easier to read later. +Cmnd_Alias SU = /bin/su +Cmnd_Alias SMTP = /sbin/service postfix stop, /sbin/service postfix start, /sbin/service postfix status +Cmnd_Alias REBOOT = /usr/bin/reboot, /sbin/shutdown -r now + +# *** Defaults specification *** +# make user john.doe not have to enter a password to run commands as another user +Defaults:john.doe nopasswd +# make user kate have no timeout, and add env variable "GOO" to the sudo environment, and run as linda by default, but always require the root password +Defaults:kate timestamp_timeout=-1, env_delete+="GOO", runas_default=linda, rootpw +# make user jim have to enter the password of whoever he's running a command as, every time, with 1 attempt allowed +Defaults:jim timestamp_timeout=0, runaspw, passwd_tries=1 +# global defaults - log to a specific file. +Defaults logfile=/var/log/sudo.log, log_year=on + +# *** User Privilege specification *** +# This is where we actually say who and where (as whom) can do what +# user/%group hostname = (user) command +# by default, root can do all commands as all users +root ALL=(ALL) ALL +# users jake and jim, on localhost, can execute crond without entering a password. (probably a bad idea) +jake,jim LOCAL = NOPASSWD: /sbin/service crond restart +# allow MAILADMINS on hosts LAN to run as root the commands SMTP and REBOOT. +MAILADMINS LAN = (root) SMTP, (SOMEONE) REBOOT +# members of the group "wheel" can run, on all hosts, all commands as all users +%wheel ALL=(ALL) ALL diff --git a/sudoers/examples/sudoers_example_2 b/sudoers/examples/sudoers_example_2 new file mode 100644 index 0000000..0682301 --- /dev/null +++ b/sudoers/examples/sudoers_example_2 @@ -0,0 +1,130 @@ +# +# Sample /etc/sudoers file. +# +# This file MUST be edited with the 'visudo' command as root. +# +# See the sudoers man page for the details on how to write a sudoers file. +# + +## +# User alias specification +## +User_Alias FULLTIMERS = millert, mikef, dowdy +User_Alias PARTTIMERS = bostley, jwfox, crawl +User_Alias WEBMASTERS = will, wendy, wim + +## +# Runas alias specification +## +Runas_Alias OP = root, operator +Runas_Alias DB = oracle, sybase + +## +# Host alias specification +## +Host_Alias SPARC = bigtime, eclipse, moet, anchor:\ + SGI = grolsch, dandelion, black:\ + ALPHA = widget, thalamus, foobar:\ + HPPA = boa, nag, python +Host_Alias CUNETS = 128.138.0.0/255.255.0.0 +Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0 +Host_Alias SERVERS = master, mail, www, ns +Host_Alias CDROM = orion, perseus, hercules + +## +# Cmnd alias specification +## +Cmnd_Alias DUMPS = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, \ + /usr/sbin/rrestore, /usr/bin/mt +Cmnd_Alias KILL = /usr/bin/kill +Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm +Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown +Cmnd_Alias HALT = /usr/sbin/halt +Cmnd_Alias REBOOT = /usr/sbin/reboot +Cmnd_Alias SHELLS = /sbin/sh, /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \ + /usr/local/bin/tcsh, /usr/bin/rsh, \ + /usr/local/bin/zsh +Cmnd_Alias SU = /usr/bin/su +Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, \ + /usr/bin/chfn + +## +# Override built-in defaults +## +Defaults syslog=auth +Defaults>root !set_logname +Defaults:FULLTIMERS !lecture +Defaults:millert !authenticate +Defaults@SERVERS log_year, logfile=/var/log/sudo.log + +## +# User specification +## + +# root and users in group wheel can run anything on any machine as any user +root ALL = (ALL) ALL +%wheel ALL = (ALL) ALL + +# full time sysadmins can run anything on any machine without a password +FULLTIMERS ALL = NOPASSWD: ALL + +# part time sysadmins may run anything but need a password +PARTTIMERS ALL = ALL + +# jack may run anything on machines in CSNETS +jack CSNETS = ALL + +# lisa may run any command on any host in CUNETS (a class B network) +lisa CUNETS = ALL + +# operator may run maintenance commands and anything in /usr/oper/bin/ +operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\ + sudoedit /etc/printcap, /usr/oper/bin/ + +# joe may su only to operator +joe ALL = /usr/bin/su operator + +# pete may change passwords for anyone but root on the hp snakes +pete HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root + +# bob may run anything on the sparc and sgi machines as any user +# listed in the Runas_Alias "OP" (ie: root and operator) +bob SPARC = (OP) ALL : SGI = (OP) ALL + +# jim may run anything on machines in the biglab netgroup +jim +biglab = ALL + +# users in the secretaries netgroup need to help manage the printers +# as well as add and remove users ++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser + +# fred can run commands as oracle or sybase without a password +fred ALL = (DB) NOPASSWD: ALL + +# on the alphas, john may su to anyone but root and flags are not allowed +john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* + +# jen can run anything on all machines except the ones +# in the "SERVERS" Host_Alias +jen ALL, !SERVERS = ALL + +# jill can run any commands in the directory /usr/bin/, except for +# those in the SU and SHELLS aliases. +jill SERVERS = /usr/bin/, !SU, !SHELLS + +# steve can run any command in the directory /usr/local/op_commands/ +# as user operator. +steve CSNETS = (operator) /usr/local/op_commands/ + +# matt needs to be able to kill things on his workstation when +# they get hung. +matt valkyrie = KILL + +# users in the WEBMASTERS User_Alias (will, wendy, and wim) +# may run any command as user www (which owns the web pages) +# or simply su to www. +WEBMASTERS www = (www) ALL, (root) /usr/bin/su www + +# anyone can mount/unmount a cd-rom on the machines in the CDROM alias +ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\ + /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM diff --git a/sudoers/sudoers2xml b/sudoers/sudoers2xml index 4ce9b18..4ce9b18 100644..100755 --- a/sudoers/sudoers2xml +++ b/sudoers/sudoers2xml diff --git a/sudoers/validate.py b/sudoers/validate.py new file mode 100755 index 0000000..9844e92 --- /dev/null +++ b/sudoers/validate.py @@ -0,0 +1,89 @@ +#!/usr/bin/python + +import os, sys +import re +from lxml import etree + +def decompose(tag): + """ + Separate a tag (element name) into its namespace and unadorned tag. + """ + m = re.match('\{([^}]+)\}(.*)', tag) + try: + return (m.group(1), m.group(2)) + except: + return (None, tag) + +def validate(root, parent_ns=None): + """ + Recursively validate an XML Element object. + """ + # In order to allow "ipa global" patterns to enclose domain- or + # service-specific patterns (whose names are arbitrary and cannot be + # known beforehand since end users can add new ones at will), all of + # the ipa-provided global shemas contain a pattern which allows any + # valid XML (in some other namespace) to be present at the level at which + # the global pattern groups the service-specific elements. The simplest + # example is the top level <ipa> pattern which simply allows anything to + # be enclosed inside of it. + # + # The downside of this is that those "anything" elements will always + # validate as long as they are valid XML. + # + # So we have to walk the element tree and for each child element in + # a different namespace, revalidate it with the correct schema. It + # doesn't seem to really matter if we go breadth-first or depth-first. + + # only operate on elements, not comments or other stuff we don't know about + if type(root) is not etree._Element: + return True + + # Is this a new namespace? + (ns, tag) = decompose(root.tag) + if parent_ns == ns: + # Same ns, therefore this element has already been validated. Just descend. + for e in root: + if validate(e, ns) == False: + return False + return True + + # We found a new namespace; load the schema. + # To keep the example simple, we just use the tag to find the schema. + # IRL we would parse the ns to locate the schema in a local cache. + print "found namespace %s" % tag + parser = etree.RelaxNG(etree.parse(file("%s.rng" % tag))) + + # What we actually came here for; validate this element tree. + # Obviously, on error we would actually do something useful here. + try: + parser.assertValid(root) + except: + return False + + # Descend. + for e in root: + if validate(e, ns) == False: + return False + + return True + +def main(argv=None): + if argv is None: + argv = sys.argv + + try: + xmldoc = argv[1] + except: + xmldoc = "ipa.xml" + + root = etree.parse(file(xmldoc)).getroot() + if validate(root): + print "XML is valid" + sys.exit(0) + else: + print "try again, loser!" + sys.exit(1) + +if __name__ == "__main__": + sys.exit(main()) + |
