summaryrefslogtreecommitdiffstats
path: root/sudoers
diff options
context:
space:
mode:
authorSumit Bose <sbose@nb.localdomain>2008-09-18 20:49:17 +0200
committerSumit Bose <sbose@nb.localdomain>2008-09-18 20:49:17 +0200
commit4f040a5754dad993ec6ee64b38f327567470ef10 (patch)
tree0bf83c1c16f0a1dbfb9842cee0f6b1ce6dde4ef6 /sudoers
parent7bfb88bbf648000b4c2bf853a11ad2bd3f4b2d85 (diff)
downloadipa_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_145
-rw-r--r--sudoers/examples/sudoers_example_2130
-rwxr-xr-x[-rw-r--r--]sudoers/sudoers2xml0
-rwxr-xr-xsudoers/validate.py89
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())
+