wget https:\/\/raw.githubusercontent.com\/lbt\/sudo\/master\/plugins\/sudoers\/sudoers2ldif<\/code><\/pre>\n\n\n\nThe script simply looks like;<\/p>\n\n\n\n
less sudoers2ldif<\/code><\/pre>\n\n\n\n\n#!\/usr\/bin\/env perl\n#\n# Copyright (c) 2007, 2010-2011, 2013 Todd C. Miller \n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n#\nuse strict;\n#\n# Converts a sudoers file to LDIF format in prepration for loading into\n# the LDAP server.\n#\n# BUGS:\n# Does not yet handle multiple lines with : in them\n# Does not yet remove quotation marks from options\n# Does not yet escape + at the beginning of a dn\n# Does not yet handle line wraps correctly\n# Does not yet handle multiple roles with same name (needs tiebreaker)\n#\n# CAVEATS:\n# Sudoers entries can have multiple RunAs entries that override former ones,\n#\twith LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole\nmy %RA;\nmy %UA;\nmy %HA;\nmy %CA;\nmy $base=$ENV{SUDOERS_BASE} or die \"$0: Container SUDOERS_BASE undefined\\n\";\nmy @options=();\nmy $did_defaults=0;\nmy $order = 0;\n# parse sudoers one line at a time\nwhile (<>){\n # remove comment\n s\/#.*\/\/;\n # line continuation\n $_.=<> while s\/\\\\\\s*$\/\/s;\n # cleanup newline\n chomp;\n # ignore blank lines\n next if \/^\\s*$\/;\n if (\/^Defaults\\s+\/i) {\n my $opt=$';\n $opt=~s\/\\s+$\/\/; # remove trailing whitespace\n push @options,$opt;\n } elsif (\/^(\\S+)\\s+([^=]+)=\\s*(.*)\/) {\n # Aliases or Definitions\n my ($p1,$p2,$p3)=($1,$2,$3);\n $p2=~s\/\\s+$\/\/; # remove trailing whitespace\n $p3=~s\/\\s+$\/\/; # remove trailing whitespace\n if ($p1 eq \"User_Alias\") {\n $UA{$p2}=$p3;\n } elsif ($p1 eq \"Runas_Alias\") {\n $RA{$p2}=$p3;\n } elsif ($p1 eq \"Host_Alias\") {\n $HA{$p2}=$p3;\n } elsif ($p1 eq \"Cmnd_Alias\") {\n $CA{$p2}=$p3;\n } else {\n if (!$did_defaults++){\n # do this once\n print \"dn: cn=defaults,$base\\n\";\n print \"objectClass: top\\n\";\n print \"objectClass: sudoRole\\n\";\n print \"cn: defaults\\n\";\n print \"description: Default sudoOption's go here\\n\";\n print \"sudoOption: $_\\n\" foreach @options;\n printf \"sudoOrder: %d\\n\", ++$order;\n print \"\\n\";\n }\n # Definition\n my @users=split \/\\s*,\\s*\/,$p1;\n my @hosts=split \/\\s*,\\s*\/,$p2;\n my @cmds= split \/\\s*,\\s*\/,$p3;\n @options=();\n print \"dn: cn=$users[0],$base\\n\";\n print \"objectClass: top\\n\";\n print \"objectClass: sudoRole\\n\";\n print \"cn: $users[0]\\n\";\n # will clobber options\n print \"sudoUser: $_\\n\" foreach expand(\\%UA,@users);\n print \"sudoHost: $_\\n\" foreach expand(\\%HA,@hosts);\n foreach (@cmds) {\n\tif (s\/^\\(([^\\)]+)\\)\\s*\/\/) {\n\t my @runas = split(\/:\\s*\/, $1);\n\t if (defined($runas[0])) {\n\t print \"sudoRunAsUser: $_\\n\" foreach expand(\\%RA, split(\/,\\s*\/, $runas[0]));\n\t }\n\t if (defined($runas[1])) {\n\t print \"sudoRunAsGroup: $_\\n\" foreach expand(\\%RA, split(\/,\\s*\/, $runas[1]));\n\t }\n\t}\n }\n print \"sudoCommand: $_\\n\" foreach expand(\\%CA,@cmds);\n print \"sudoOption: $_\\n\" foreach @options;\n printf \"sudoOrder: %d\\n\", ++$order;\n print \"\\n\";\n }\n } else {\n print \"parse error: $_\\n\";\n }\n}\n#\n# recursively expand hash elements\nsub expand{\n my $ref=shift;\n my @a=();\n # preen the line a little\n foreach (@_){\n # if NOPASSWD: directive found, mark entire entry as not requiring\n s\/NOPASSWD:\\s*\/\/ && push @options,\"!authenticate\";\n s\/PASSWD:\\s*\/\/ && push @options,\"authenticate\";\n s\/NOEXEC:\\s*\/\/ && push @options,\"noexec\";\n s\/EXEC:\\s*\/\/ && push @options,\"!noexec\";\n s\/SETENV:\\s*\/\/ && push @options,\"setenv\";\n s\/NOSETENV:\\s*\/\/ && push @options,\"!setenv\";\n s\/LOG_INPUT:\\s*\/\/ && push @options,\"log_input\";\n s\/NOLOG_INPUT:\\s*\/\/ && push @options,\"!log_input\";\n s\/LOG_OUTPUT:\\s*\/\/ && push @options,\"log_output\";\n s\/NOLOG_OUTPUT:\\s*\/\/ && push @options,\"!log_output\";\n s\/[[:upper:]]+:\/\/; # silently remove other tags\n s\/\\s+$\/\/; # right trim\n }\n # do the expanding\n push @a,$ref->{$_} ? expand($ref,split \/\\s*,\\s*\/,$ref->{$_}):$_ foreach @_;\n @a;\n}\n\ufeff<\/code><\/pre>\n\n\n\nCreate a bash environment variable defining your SUDOers organization unit entry created above.<\/p>\n\n\n\n
export SUDOERS_BASE=\"ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\"<\/code><\/pre>\n\n\n\necho $SUDOERS_BASE<\/code><\/pre>\n\n\n\nNext, convert the \/etc\/sudoers<\/code> file into LDAP ldif file to create the required SUDOers ou defaults entry.<\/p>\n\n\n\nperl sudoers2ldif \/etc\/sudoers > sudoers_defaults.ldif<\/code><\/pre>\n\n\n\nYou can as well use cvtsudoers<\/code> command to convert the sudoers file to an LDIF format.<\/p>\n\n\n\ncvtsudoers \/etc\/sudoers -f ldif -o sudoers_defaults.ldif<\/code><\/pre>\n\n\n\nSo what are the contents of the sudoers_defaults.ldif<\/code>?<\/p>\n\n\n\ncat sudoers_defaults.ldif<\/code><\/pre>\n\n\n\ndn: cn=defaults,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: defaults\ndescription: Default sudoOption's go here\nsudoOption: !visiblepw\nsudoOption: always_set_home\nsudoOption: match_group_by_gid\nsudoOption: always_query_group_plugin\nsudoOption: env_reset\nsudoOption: env_keep = \"COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS\"\nsudoOption: env_keep += \"MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE\"\nsudoOption: env_keep += \"LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES\"\nsudoOption: env_keep += \"LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE\"\nsudoOption: env_keep += \"LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY\"\nsudoOption: secure_path = \/sbin:\/bin:\/usr\/sbin:\/usr\/bin\nsudoOrder: 1\n\ndn: cn=root,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: root\nsudoUser: root\nsudoHost: ALL\nsudoRunAsUser: ALL\nsudoCommand: ALL\nsudoOrder: 2\n\ndn: cn=%wheel,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: %wheel\nsudoUser: %wheel\nsudoHost: ALL\nsudoRunAsUser: ALL\nsudoCommand: ALL\nsudoOrder: 3\n<\/code><\/pre>\n\n\n\nAs you can see, the sudoers file in LDAP ldif format contains the SUDOers OU, multi-valued sudoOption<\/code> attributes, the root user cn, and wheel group defined.<\/p>\n\n\n\nSudo attributes used above:<\/p>\n\n\n\n
\n- sudoOption<\/strong>: Similar to Defaults option in
\/etc\/sudoers<\/code> file.\n\n- For example, below are the \/etc\/sudoers options and how you can use them on LDAP SUDO:<\/strong>\n
\n- NOPASSWD: !authenticate<\/strong><\/li>\n\n\n\n
- PASSWD: authenticate<\/strong><\/li>\n\n\n\n
- NOEXEC: noexec<\/strong><\/li>\n\n\n\n
- EXEC: !noexec<\/strong><\/li>\n\n\n\n
- SETENV: setenv<\/strong><\/li>\n\n\n\n
- NOSETENV: !setenv<\/strong><\/li>\n\n\n\n
- LOG_INPUT: log_input<\/strong><\/li>\n\n\n\n
- NOLOG_INPUT: !log_input<\/strong><\/li>\n\n\n\n
- LOG_OUTPUT: log_output<\/strong><\/li>\n\n\n\n
- NOLOG_OUTPUT: !log_output<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n
\n- sudoUser<\/strong>: defines a user name, user ID (prefixed with \u2018
#<\/code>\u2019), Unix group name or ID (prefixed with \u2018%<\/code>\u2019 or \u2018%#<\/code>\u2019 respectively), user netgroup (prefixed with \u2018+<\/code>\u2019), or non-Unix group name or ID (prefixed with \u2018%:<\/code>\u2019 or \u2018%:#<\/code>\u2019 respectively)<\/li>\n\n\n\n- sudoHost<\/strong>: A hostname, IP address, IP network, or host netgroup (prefixed with a \u2018
+<\/code>\u2019) or ALL<\/code> value to match any host.<\/li>\n\n\n\n- sudoRunAsUser<\/strong>: A username or uid (prefixed with \u2018
#<\/code>\u2019) that commands may be run as or a Unix group (prefixed with a \u2018%<\/code>\u2019) or user netgroup (prefixed with a \u2018+<\/code>\u2019) that contains a list of users that commands may be run as. ALL<\/code> value matches any user.<\/li>\n\n\n\n- sudoCommand<\/strong>: Specifies a fully-qualified Unix command name with optional command line arguments. Use
ALL<\/code> to match any command.<\/li>\n<\/ul>\n\n\n\nSo, before updating the OpenLDAP database with SUDOers configurations, you can modify the SUDOers LDAP ldif file above.<\/p>\n\n\n\n
For example, remove the defined root user and wheel group and add the users that you want to assign SUDO rights via LDAP on the remote clients.<\/p>\n\n\n\n
Also, remove the sudoOrder<\/code> attributes.<\/p>\n\n\n\n\ncat > modified-sudoer2ldif.ldif << 'EOL'\ndn: cn=defaults,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: defaults\ndescription: Kifarunix-demo SUDO via LDAP\nsudoOption: !visiblepw\nsudoOption: always_set_home\nsudoOption: match_group_by_gid\nsudoOption: always_query_group_plugin\nsudoOption: env_reset\nsudoOption: env_keep = \"COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS\"\nsudoOption: env_keep += \"MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE\"\nsudoOption: env_keep += \"LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES\"\nsudoOption: env_keep += \"LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE\"\nsudoOption: env_keep += \"LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY\"\nsudoOption: env_keep+=SSH_AUTH_SOCK\nsudoOption: secure_path = \/sbin:\/bin:\/usr\/sbin:\/usr\/bin\n\ndn: cn=sudo,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: sudo\nsudoUser: janedoe\nsudoHost: ALL\nsudoRunAsUser: ALL\nsudoCommand: ALL\nEOL\n<\/code><\/pre>\n\n\n\nIn the above, we created an entry called sudo under the SUDOers ou and assign a user called janedoe<\/strong> SUDO rights to run all commands as any user on any system, which is similar to the line below on \/etc\/sudoers<\/code> file.<\/p>\n\n\n\njanedoe ALL=(ALL:ALL) ALL<\/code><\/pre>\n\n\n\nNote that the user must be existing on the OpenLDAP database.<\/p>\n\n\n\n
Update OpenLDAP Database<\/h3>\n\n\n\n
Next, load the SUDOers configuration into the OpenLDAP database.<\/p>\n\n\n\n
ldapadd -Y EXTERNAL -H ldapi:\/\/\/ -f modified-sudoer2ldif.ldif<\/code><\/pre>\n\n\n\nIf you need to add another user to the role above;<\/p>\n\n\n\n
cat > add-to-sudo-role.ldif << 'EOL'\ndn: cn=sudo,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nchangetype: modify\nadd: sudoUser\nsudoUser: johndoe\nEOL<\/code><\/pre>\n\n\n\nldapmodify -Y EXTERNAL -H ldapi:\/\/\/ -f add-to-sudo-role.ldif<\/code><\/pre>\n\n\n\nTo create a different sudo role, say to allow users to run specific commands,see below. The role names can be anything descriptive.<\/p>\n\n\n\n
For example, to allow a user called mibeyam to run useradd command only with sudo, create an ldif file like as shown below and update OpenLDAP database.<\/p>\n\n\n\n
cat > sudo-specific-cmd.ldif << 'EOL'\ndn: cn=cmdrole,ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com\nobjectClass: top\nobjectClass: sudoRole\ncn: cmdrole\nsudoUser: mibeyam\nsudoHost: ALL\nsudoRunAsUser: ALL\nsudoCommand: \/usr\/sbin\/useradd\n'EOL'<\/code><\/pre>\n\n\n\nldapadd -Y EXTERNAL -H ldapi:\/\/\/ -f sudo-specific-cmd.ldif<\/code><\/pre>\n\n\n\n