Produce a human-readable report from /etc/sudoers

Produce a human-readable report from /etc/sudoers

am 23.04.2008 17:18:25 von cdmonline

My /etc/sudoers file is expansive and complex and I need a way to
produce a more human readable form of its contents.

I'd like to be able to report on the following:

1) Given a user - which command(s) may be executed and on which
system(s)
2) Given a system - which command(s) may be executed by which user(s)
3) Given a command - which user(s) may executed the command on which
system(s)

All of this information is already in the /etc/sudoers file, of
course, but it is difficult to report on any of the above scenarios
without tediously trawling through the file.

I have 2 versions of the sudoers file. 1 contains netgroup information
with the + notation and the other is an expanded version where all the
netgroups (users and hosts) is already exapanded in comma-delimited
form.

I've tried shell-scripting this but can't quite get it to work exaclty
as I want it to.

- CDM

Re: Produce a human-readable report from /etc/sudoers

am 24.04.2008 01:44:43 von mop2

I think, grep is the solution.
As example:
grep 'user[, ]' /etc/sudoers|grep -v '^#'|cut -d' ' -f2-

If user, system and command are distinct "strings" (never match), it
is more easy.

Suggestion:
Select a complex line, post it and show expected filter outputs
(1,2,3).


cdmonl...@mac.com wrote:
> My /etc/sudoers file is expansive and complex and I need a way to
> produce a more human readable form of its contents.
>
> I'd like to be able to report on the following:
>
> 1) Given a user - which command(s) may be executed and on which
> system(s)
> 2) Given a system - which command(s) may be executed by which user(s)
> 3) Given a command - which user(s) may executed the command on which
> system(s)
>
> All of this information is already in the /etc/sudoers file, of
> course, but it is difficult to report on any of the above scenarios
> without tediously trawling through the file.
>
> I have 2 versions of the sudoers file. 1 contains netgroup information
> with the + notation and the other is an expanded version where all the
> netgroups (users and hosts) is already exapanded in comma-delimited
> form.
>
> I've tried shell-scripting this but can't quite get it to work exaclty
> as I want it to.
>
> - CDM

Re: Produce a human-readable report from /etc/sudoers

am 24.04.2008 09:55:59 von PK

On Wednesday 23 April 2008 17:18, cdmonline@mac.com wrote:

> My /etc/sudoers file is expansive and complex and I need a way to
> produce a more human readable form of its contents.
>
> I'd like to be able to report on the following:
>
> 1) Given a user - which command(s) may be executed and on which
> system(s)
> 2) Given a system - which command(s) may be executed by which user(s)
> 3) Given a command - which user(s) may executed the command on which
> system(s)
>
> All of this information is already in the /etc/sudoers file, of
> course, but it is difficult to report on any of the above scenarios
> without tediously trawling through the file.
>
> I have 2 versions of the sudoers file. 1 contains netgroup information
> with the + notation and the other is an expanded version where all the
> netgroups (users and hosts) is already exapanded in comma-delimited
> form.
>
> I've tried shell-scripting this but can't quite get it to work exaclty
> as I want it to.

There is a script (sudoers-lint) floating around in the Internet, which
claims to parse the sudoers file and produce some reports about number and
names of users, commands, hosts, etc. It probably doesn't do exactly what
you need, but it could be a starting point to modify. At least, it already
does the hard work of parsing the file.
Note that I haven't tried it...just googled a bit and read the description.
I'm no perl expert either so I don't know whether it would be easily
modified to suit your needs. However, hope the information helps somehow.
If anything else fails, you could always write your own parser (probably
using lex/yacc) based on the grammar provided in the sudoers man page.

--
All the commands are tested with bash and GNU tools, so they may use
nonstandard features. I try to mention when something is nonstandard (if
I'm aware of that), but I may miss something. Corrections are welcome.

Re: Produce a human-readable report from /etc/sudoers

am 24.04.2008 13:26:54 von cdmonline

On Apr 24, 8:55 am, pk wrote:
> On Wednesday 23 April 2008 17:18, cdmonl...@mac.com wrote:
>
>
>
> > My /etc/sudoers file is expansive and complex and I need a way to
> > produce a more human readable form of its contents.
>
> > I'd like to be able to report on the following:
>
> > 1) Given a user - which command(s) may be executed and on which
> > system(s)
> > 2) Given a system - which command(s) may be executed by which user(s)
> > 3) Given a command - which user(s) may executed the command on which
> > system(s)
>
> > All of this information is already in the /etc/sudoers file, of
> > course, but it is difficult to report on any of the above scenarios
> > without tediously trawling through the file.
>
> > I have 2 versions of the sudoers file. 1 contains netgroup information
> > with the + notation and the other is an expanded version where all the
> > netgroups (users and hosts) is already exapanded in comma-delimited
> > form.
>
> > I've tried shell-scripting this but can't quite get it to work exaclty
> > as I want it to.
>
> There is a script (sudoers-lint) floating around in the Internet, which
> claims to parse the sudoers file and produce some reports about number and
> names of users, commands, hosts, etc. It probably doesn't do exactly what
> you need, but it could be a starting point to modify. At least, it already
> does the hard work of parsing the file.
> Note that I haven't tried it...just googled a bit and read the description.
> I'm no perl expert either so I don't know whether it would be easily
> modified to suit your needs. However, hope the information helps somehow.
> If anything else fails, you could always write your own parser (probably
> using lex/yacc) based on the grammar provided in the sudoers man page.
>
> --
> All the commands are tested with bash and GNU tools, so they may use
> nonstandard features. I try to mention when something is nonstandard (if
> I'm aware of that), but I may miss something. Corrections are welcome.

Although the sudo-lint command is useful, it doesn't do what I'm
looking for. I eventually managed to plough through some of the
consistency issues in the sudoers file and came up with a script that
does [nearly] what I want. Here's the resulting script (which isn't
particularly pretty and is still a work in progress but does the job
for the most part). It can probably be done much better in Perl but
since I don't do Perl ...

If anyone wants to improve on this, I'd be the first to welcome it the
effort :-)

NOTE: just a single space and tab character between the [] as
indicated!

Call with a '-u username' option to list all commands a user may
execute and on what systems.

#!/bin/ksh
#
# Script name: rbcSudoReport.ksh
#
# Author: Chris Morgan
# Version: 1.0
# Purpose Generate a human readable report on sudo permissions
#
# History: 23/04/2008 - Initial Build (Chris Morgan)
#
# NOTES: There are a number of deficiencies in this script -
some of them glaring!

############################################################ ################################################
# Define all
variables.
#
############################################################ ################################################
progname=${0##*/}
SUDOERS=/users/cmorgan/bin/sudoers

############################################################ ################################################
# Define the function that will determine which individual commands
are associated with a command alias. #
############################################################ ################################################
get_individual_commands() {
COMMANDS=$1

echo
if [ "${COMMANDS}" = "ALL" ]
then
echo " !!! All commands"
elif [ "${COMMANDS}" = "ALL=(ALL)" ]
then
echo " !!! All commands"
else
for individual_command_alias in `echo ${COMMANDS} | tr
',' ' '`
do
grep "^Cmnd_Alias[ ]*$
{individual_command_alias}" ${SUDOERS} | awk -F= '{print $2}' | tr ','
'\n' | sed 's/^/ /g' # 1 space and 1 tab between []
done
fi
}

############################################################ ################################################
# Define the function that will determine which indididual servers are
associated with a server alias. #
############################################################ ################################################
get_servers() {
SERVERS=$1

if [ "${SERVERS}" = "ALL" ]
then
echo " !!! All servers"
elif [ "${SERVERS}" = "NOPASSWD:ALL" ]
then
echo " !!! All servers"
else
grep "^Host_Alias[ ]*${SERVERS}" ${SUDOERS} | awk
-F= '{print $2}' | tr ',' '\n' | sed 's/^/ /g'
fi
}

############################################################ ################################################
# Define the function that will determine which individual commands
are associated with given permissions. #
############################################################ ################################################
get_commands() {
command_alias=$1

if [ "${command_alias}" = "ALL=(ALL)" ]
then
COMMANDS=ALL
elif [ "${command_alias}" = "NOPASSWD:ALL" ]
then
COMMANDS=ALL
elif [ "${command_alias}" = "ALL=(root)" ]
then
COMMANDS=ALL
elif [ "${command_alias}" = "ALL=(root)-NOPASSWORD" ]
then
COMMANDS=ALL
else
COMMANDS=`echo ${command_alias} | awk -F: '{print
$2}'`
fi
get_individual_commands ${COMMANDS}

SERVERS=`echo ${command_alias} | awk -F= '{print $1}'`
get_servers ${SERVERS}
}

############################################################ ################################################
# Define the function that will determine which commands on which
servers a given user alias is associated #
#
with.
#
############################################################ ################################################
get_permisions() {
user_alias=$1

#echo "user_alias=$1"
for command_string in `grep ^${user_alias} ${SUDOERS} | awk
'{$1="";print}' | sed 's/^[ ]*//g;s/ /-/g'` # 1 space and 1
tab between []
do
get_commands ${command_string}
done
}

############################################################ ################################################
# Get command line
options.
#
############################################################ ################################################
while getopts ":u:h:" OPTION
do
case ${OPTION} in
u)
USER=${OPTARG}
echo "\nUser: ${USER}"

for user_alias in `grep ${USER} ${SUDOERS} |
grep "^User_Alias" | sed 's/^User_Alias[ ]*//g;s/=.*//g'` # 1 space
and 1 tab between []
do
get_permisions ${user_alias}
done
;;
h)
HOST=${OPTARG}
;;
esac
done
shift $((${OPTIND} - 1))