[augeas-devel] [PATCH] Add sudoers lens and associated test
Raphael Pinson
raphink at gmail.com
Tue Aug 12 09:28:00 UTC 2008
# HG changeset patch
# User Raphael Pinson <raphink at gmail.com>
# Date 1218533244 -7200
# Node ID fe8236ec9a82e500be65689abd79de394c253e8a
# Parent 5697b74b2d7341f923ee889187a9d8d6276744ae
Add sudoers lens and associated test
diff -r 5697b74b2d73 -r fe8236ec9a82 lenses/sudoers.aug
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lenses/sudoers.aug Tue Aug 12 11:27:24 2008 +0200
@@ -0,0 +1,187 @@
+(* Sudoers module for Augeas
+ Author: Raphael Pinson <raphink at gmail.com>
+
+ Reference: `man sudoers`
+ This lens tries to keep as close as possible to `man sudoers` where possible.
+ For example, recursive definitions such as:
+
+ Cmnd_Spec_List ::= Cmnd_Spec |
+ Cmnd_Spec ',' Cmnd_Spec_List
+
+ are replaced by
+
+ let cmnd_spec_list = cmnd_spec . ( sep_com . cmnd_spec )*
+
+ since Augeas cannot deal with recursive definitions.
+ The definitions from `man sudoers` are put as commentaries for reference
+ throughout the file. More information can be found in the manual.
+*)
+
+
+
+module Sudoers =
+ autoload xfm
+
+ (***********************************************************************************
+ * USEFUL PRIMITIVES
+ ***********************************************************************************)
+
+ let eol = del /[ \t]*\n/ "\n"
+
+ (* Define separators *)
+ let sep_spc = del /[ \t]+/ " "
+ let sep_cont = del /([ \t]+|[ \t]*\\\\\n[ \t]*)/ " "
+ let sep_com = sep_cont? . Util.del_str "," . sep_cont?
+ let sep_eq = sep_cont? . Util.del_str "=" . sep_cont?
+ let sep_col = sep_cont? . Util.del_str ":" . sep_cont?
+
+ (* Define fields *)
+ let sto_to_com_cmnd = store /([^,=:#() \t\n\\\\][^,=:#()\n\\\\]*[^,=:#() \t\n\\\\])|[^,=:#() \t\n\\\\]/
+ let sto_to_com = store /[^,=:#() \t\n\\\\]+/
+
+ (* sto_to_com does not begin or end with a space *)
+ (* TODO: there could be a \ in the middle of a command... *)
+ let sto_to_com_user = store ( /[^,=:#() \t\n]+/ - /(User|Runas|Host|Cmnd)_Alias|Defaults/ )
+ let sto_to_eq = store /[^,=:#() \t\n\\\\]+/
+ let sto_to_spc = store /[^() \t\n\\\\]+/
+
+
+ (* define comments and empty lines *)
+ let comment =
+ let value_to_eol = del /[ \t]*/ " " . store /([^ \t\n].*[^ \t\n]|[^ \t\n])/ in
+ [ label "comment" . del /[ \t]*#/ "# " . value_to_eol? . eol ]
+
+ let empty = [ del /[ \t]*\n/ "" ]
+
+
+ (***********************************************************************************
+ * ALIASES
+ ***********************************************************************************)
+
+ (***********************************************************************************
+ * User_Alias ::= NAME '=' User_List
+ * Runas_Alias ::= NAME '=' Runas_List
+ * Host_Alias ::= NAME '=' Host_List
+ * Cmnd_Alias ::= NAME '=' Cmnd_List
+ ***********************************************************************************)
+ let alias_field (kw:string) (sto:lens) = [ label kw . sto ]
+ let alias_list (kw:string) (sto:lens) = alias_field kw sto . ( sep_com . alias_field kw sto )*
+
+ (***********************************************************************************
+ * NAME ::= [A-Z]([A-Z][0-9]_)*
+ ***********************************************************************************)
+ let alias_name = [ label "name" . store /[A-Z][A-Z0-9_]*/ ]
+
+ (***********************************************************************************
+ * Alias_Type NAME = item1, item2, ...
+ ***********************************************************************************)
+ let alias_entry_single (field:string) (sto:lens) = [ label "alias" . alias_name . sep_eq . alias_list field sto ]
+
+ (***********************************************************************************
+ * Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+ ***********************************************************************************)
+ let alias_entry (kw:string) (field:string) (sto:lens) = [ key kw . sep_cont . alias_entry_single field sto
+ . ( sep_col . alias_entry_single field sto )* . eol ]
+
+ (* TODO: go further in user definitions *)
+ let user_alias = alias_entry "User_Alias" "user" sto_to_com
+ let runas_alias = alias_entry "Runas_Alias" "runas_user" sto_to_com
+ let host_alias = alias_entry "Host_Alias" "host" sto_to_com
+ let cmnd_alias = alias_entry "Cmnd_Alias" "command" sto_to_com_cmnd
+
+
+ (***********************************************************************************
+ * Alias ::= 'User_Alias' User_Alias (':' User_Alias)* |
+ * 'Runas_Alias' Runas_Alias (':' Runas_Alias)* |
+ * 'Host_Alias' Host_Alias (':' Host_Alias)* |
+ * 'Cmnd_Alias' Cmnd_Alias (':' Cmnd_Alias)*
+ ***********************************************************************************)
+ let alias = user_alias | runas_alias | host_alias | cmnd_alias
+
+
+
+ (***********************************************************************************
+ * DEFAULTS
+ ***********************************************************************************)
+
+ (***********************************************************************************
+ * Default_Type ::= 'Defaults' |
+ * 'Defaults' '@' Host_List |
+ * 'Defaults' ':' User_List |
+ * 'Defaults' '>' Runas_List
+ **********************************************************************************)
+ let default_type =
+ let value = store /(@|:|>)[^ \t\n\\\\]+/ in
+ [ label "type" . value ]
+
+ (***********************************************************************************
+ * Parameter ::= Parameter '=' Value |
+ * Parameter '+=' Value |
+ * Parameter '-=' Value |
+ * '!'* Parameter
+ ***********************************************************************************)
+ let parameter = [ label "parameter" . sto_to_com ]
+
+ (***********************************************************************************
+ * Parameter_List ::= Parameter |
+ * Parameter ',' Parameter_List
+ ***********************************************************************************)
+ let parameter_list = parameter . ( sep_com . parameter )*
+
+ (***********************************************************************************
+ * Default_Entry ::= Default_Type Parameter_List
+ ***********************************************************************************)
+ let defaults = [ key "Defaults" . default_type? . sep_cont . parameter_list . eol ]
+
+
+
+ (***********************************************************************************
+ * USER SPECIFICATION
+ ***********************************************************************************)
+
+ (***********************************************************************************
+ * Runas_Spec ::= '(' Runas_List ')'
+ ***********************************************************************************)
+ let runas_spec = Util.del_str "(" . alias_list "runas_user" sto_to_com . Util.del_str ")" . sep_cont
+
+ (***********************************************************************************
+ * Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' |
+ * 'SETENV:' | 'NOSETENV:')
+ ***********************************************************************************)
+ let tag_spec = [ label "tag" . store /(NO)?(PASSWD|EXEC|SETENV)/ . sep_col ]
+
+ (***********************************************************************************
+ * Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd
+ ***********************************************************************************)
+ let cmnd_spec = [ label "command" . runas_spec? . tag_spec* . sto_to_com ]
+
+ (***********************************************************************************
+ * Cmnd_Spec_List ::= Cmnd_Spec |
+ * Cmnd_Spec ',' Cmnd_Spec_List
+ ***********************************************************************************)
+ let cmnd_spec_list = cmnd_spec . ( sep_com . cmnd_spec )*
+
+
+ (***********************************************************************************
+ * User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
+ * (':' Host_List '=' Cmnd_Spec_List)*
+ ***********************************************************************************)
+ let spec_list = [ label "host_group" . alias_list "host" sto_to_com . sep_eq . cmnd_spec_list ]
+
+ let spec = [ label "spec"
+ . alias_list "user" sto_to_com_user . sep_cont
+ . spec_list
+ . ( sep_col . spec_list )* . eol ]
+
+
+ (***********************************************************************************
+ * LENS & FILTER
+ ***********************************************************************************)
+
+ let lns = ( empty | comment | alias | defaults | spec )*
+
+ let filter = (incl "/etc/sudoers")
+ . Util.stdexcl
+
+ let xfm = transform lns filter
+
diff -r 5697b74b2d73 -r fe8236ec9a82 lenses/tests/test_sudoers.aug
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lenses/tests/test_sudoers.aug Tue Aug 12 11:27:24 2008 +0200
@@ -0,0 +1,106 @@
+module Test_sudoers =
+
+ let conf = "
+Host_Alias LOCALNET = 192.168.0.0/24, localhost
+
+# User alias specification
+
+# Cmnd alias specification
+
+Cmnd_Alias \
+ DEBIAN_TOOLS \
+ = \
+ /usr/bin/apt-get,\
+ /usr/bin/auto-get, \
+ /usr/bin/dpkg, /usr/bin/dselect, /usr/sbin/dpkg-reconfigure \
+ : PBUILDER = /usr/sbin/pbuilder
+
+Cmnd_Alias ICAL = /bin/cat /home/rpinson/.kde/share/apps/korganizer/std.ics
+
+Defaults at LOCALNET !lecture, \
+ tty_tickets,!fqdn
+
+# User privilege specification
+root ALL=(ALL) ALL
+
+# Members of the admin group may gain root privileges
+%admin ALL=(ALL) ALL, NOPASSWD : NOSETENV: \
+ DEBIAN_TOOLS
+%pbuilder LOCALNET = NOPASSWD: PBUILDER
+www-data ALL=(rpinson) NOEXEC: ICAL \
+ : \
+ localhost = NOPASSWD: /usr/bin/test
+"
+
+ test Sudoers.lns get conf =
+ {}
+ { "Host_Alias"
+ { "alias"
+ { "name" = "LOCALNET" }
+ { "host" = "192.168.0.0/24" }
+ { "host" = "localhost" } } }
+ {}
+ { "comment" = "User alias specification" }
+ {}
+ { "comment" = "Cmnd alias specification" }
+ {}
+ { "Cmnd_Alias"
+ { "alias"
+ { "name" = "DEBIAN_TOOLS" }
+ { "command" = "/usr/bin/apt-get" }
+ { "command" = "/usr/bin/auto-get" }
+ { "command" = "/usr/bin/dpkg" }
+ { "command" = "/usr/bin/dselect" }
+ { "command" = "/usr/sbin/dpkg-reconfigure" } }
+ { "alias"
+ { "name" = "PBUILDER" }
+ { "command" = "/usr/sbin/pbuilder" } } }
+ {}
+ { "Cmnd_Alias"
+ { "alias"
+ { "name" = "ICAL" }
+ { "command" = "/bin/cat /home/rpinson/.kde/share/apps/korganizer/std.ics" } } }
+ {}
+ { "Defaults"
+ { "type" = "@LOCALNET" }
+ { "parameter" = "!lecture" }
+ { "parameter" = "tty_tickets" }
+ { "parameter" = "!fqdn" } }
+ {}
+ { "comment" = "User privilege specification" }
+ { "spec"
+ { "user" = "root" }
+ { "host_group"
+ { "host" = "ALL" }
+ { "command" = "ALL"
+ { "runas_user" = "ALL" } } } }
+ {}
+ { "comment" = "Members of the admin group may gain root privileges" }
+ { "spec"
+ { "user" = "%admin" }
+ { "host_group"
+ { "host" = "ALL" }
+ { "command" = "ALL"
+ { "runas_user" = "ALL" } }
+ { "command" = "DEBIAN_TOOLS"
+ { "tag" = "NOPASSWD" }
+ { "tag" = "NOSETENV" } } } }
+ { "spec"
+ { "user" = "%pbuilder" }
+ { "host_group"
+ { "host" = "LOCALNET" }
+ { "command" = "PBUILDER"
+ { "tag" = "NOPASSWD" } } } }
+ { "spec"
+ { "user" = "www-data" }
+ { "host_group"
+ { "host" = "ALL" }
+ { "command" = "ICAL"
+ { "runas_user" = "rpinson" }
+ { "tag" = "NOEXEC" } } }
+ { "host_group"
+ { "host" = "localhost" }
+ { "command" = "/usr/bin/test"
+ { "tag" = "NOPASSWD" } } } }
+
+
More information about the augeas-devel
mailing list