augeas / sudoers

1,251 views
Skip to first unread message

walexey

unread,
Nov 19, 2010, 7:50:05 AM11/19/10
to Puppet Users
Hello everybody!
How can i create with puppet following sudoers file:

User_Alias CENTREON=apache,nagios
CENTREON ALL = NOPASSWD: /etc/init.d/nagios* restart
CENTREON ALL = NOPASSWD: /etc/init.d/nagios* reload
CENTREON ALL = NOPASSWD: /usr/bin/nagios* -v *

The problem that augeas create only last line, replacing previous one.

luke.bigum

unread,
Nov 19, 2010, 7:56:48 AM11/19/10
to Puppet Users
Hi Walexey,

Can you post the augeas resource that you've got so far?

walexey

unread,
Nov 19, 2010, 8:04:44 AM11/19/10
to Puppet Users
define sudoentry ($user, $host = "ALL", $command = "ALL", $tag
= "NOPASSWD", $runas = "ALL") {
$sudo_changes = $tag ? {
false => [
"set spec[user = '$user']/user $user",
"set spec[user = '$user']/host_group/
host $host",
"set spec[user = '$user']/host_group/
command '$command'",
"remove spec[user = '$user']/
host_group/command/tag",
"set spec[user = '$user']/host_group/
command/runas_user $runas",
],
# this isn't a real tag, but a sneaky hack to
remove entries
DELETE => "remove spec[user = '$user']",
default => [
"set spec[user = '$user']/user $user",
"set spec[user = '$user']/host_group/
host $host",
"set spec[user = '$user']/host_group/
command '$command'",
"set spec[user = '$user']/host_group/
command/tag $tag",
"set spec[user = '$user']/host_group/
command/runas_user $runas",
],
}
augeas { "sudo-$name":
context => "/files/etc/sudoers",
changes => $sudo_changes,
}
}

sudo::sudoentry { "centreon_sudoers1": user => "apache",
command => "/etc/init.d/nagios* restart" }
sudo::sudoentry { "centreon_sudoers2": user => "apache",
command => "/etc/init.d/nagios* reload" }

Rob McBroom

unread,
Nov 19, 2010, 8:49:05 AM11/19/10
to puppet...@googlegroups.com
That looks like the define I wrote. Whenever/wherever I posted it, I probably also mentioned that it isn't complete because it only identifies entries by user, when in practice, there can be multiple entries with the same user (as you've seen).

The problem with incorporating other attributes to uniquely identify sudo entries is that you would then need two versions of the Augeas changes: one to create an entry and one to update an entry. Such a thing is not easily accomplished in Puppet manifests.

See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Limitations

In cases where I need multiple entries for the same user, I just use the Augeas type directly instead of the define. I would love it if the define could be updated to reliably handle this. Anyone have any ideas?

--
Rob McBroom
<http://www.skurfer.com/>


luke.bigum

unread,
Nov 19, 2010, 10:00:14 AM11/19/10
to Puppet Users
The sudoers tree is pretty complex, you've got four possible 'key
nodes' of information to match on: user, host, command and tag. This
is an augeas match line for all four key nodes (command changed to
something without asterisks for readability):

match /files/etc/sudoers/spec[user="CENTREON"]/host_group/command[../
host="ALL"]/tag[../../command='/bin/ls'][.='NOPASSWD']

So you can put that in an onlyif parameter, then "insert after last"
and then one by one augeas sets to build up the exact command you
want. If you try do straight sets, without an insert, you risk
modifying existing sudoers lines, which is probably why your define is
overwriting itself, you're matching existing lines with only a subset
of the key nodes you need to uniquely define one line.

Example from Augtool:

augtool> print /files/etc/sudoers/spec[user="CENTREON"]
/files/etc/sudoers/spec[5]
/files/etc/sudoers/spec[5]/user = "CENTREON"
/files/etc/sudoers/spec[5]/host_group
/files/etc/sudoers/spec[5]/host_group/host = "ALL"
/files/etc/sudoers/spec[5]/host_group/command = "/etc/init.d/nagios*
restart"
/files/etc/sudoers/spec[5]/host_group/command/tag = "NOPASSWD"
/files/etc/sudoers/spec[6]
/files/etc/sudoers/spec[6]/user = "CENTREON"
/files/etc/sudoers/spec[6]/host_group
/files/etc/sudoers/spec[6]/host_group/host = "ALL"
/files/etc/sudoers/spec[6]/host_group/command = "/etc/init.d/nagios*
reload"
/files/etc/sudoers/spec[6]/host_group/command/tag = "NOPASSWD"

augtool> ins spec after /files/etc/sudoers/spec[last()]

augtool> print /files/etc/sudoers/spec
...
/files/etc/sudoers/spec[5]
/files/etc/sudoers/spec[5]/user = "CENTREON"
/files/etc/sudoers/spec[5]/host_group
/files/etc/sudoers/spec[5]/host_group/host = "ALL"
/files/etc/sudoers/spec[5]/host_group/command = "/etc/init.d/nagios*
restart"
/files/etc/sudoers/spec[5]/host_group/command/tag = "NOPASSWD"
/files/etc/sudoers/spec[6]
/files/etc/sudoers/spec[6]/user = "CENTREON"
/files/etc/sudoers/spec[6]/host_group
/files/etc/sudoers/spec[6]/host_group/host = "ALL"
/files/etc/sudoers/spec[6]/host_group/command = "/etc/init.d/nagios*
reload"
/files/etc/sudoers/spec[6]/host_group/command/tag = "NOPASSWD"
/files/etc/sudoers/spec[7]

Now that you have a unique index for the new insert (spec[last()]) the
four set commands are easy:

augtool> set /files/etc/sudoers/spec[last()]/user "CENTREON"
augtool> set /files/etc/sudoers/spec[last()]/host_group/host "ALL"
augtool> set /files/etc/sudoers/spec[last()]/host_group/command '/bin/
ls'
augtool> set /files/etc/sudoers/spec[last()]/host_group/command/tag
"NOPASSWD"

augtool> print /files/etc/sudoers/spec
...
/files/etc/sudoers/spec[7]
/files/etc/sudoers/spec[7]/user = "CENTREON"
/files/etc/sudoers/spec[7]/host_group
/files/etc/sudoers/spec[7]/host_group/host = "ALL"
/files/etc/sudoers/spec[7]/host_group/command = "/bin/ls"
/files/etc/sudoers/spec[7]/host_group/command/tag = "NOPASSWD"

Then, if you want to adjust an existing record that you KNOW exists
you can use individual sets to adjust the key nodes in a line one by
one. This could be useful in adjusting a sudoers line you pushed out
previously and now want to adjust. Here's a few examples:

#change the user of the original line inserted
set /files/etc/sudoers/spec[*]/user[.="CENTREON"][../host_group/
host="ALL"][../host_group/command="/bin/ls"][../host_group/command/
tag="NOPASSWD"] ANOTHERUSER

#Change the command of the original line inserted
set /files/etc/sudoers/spec[user="CENTREON"]/host_group/command[../
host="ALL"][.='/bin/ls'][tag="NOPASSWD"] /bin/cp

Unfortunately you can't do this:

set /files/etc/sudoers/spec[user="CENTREON"]/host_group/command[../
host="ALL"]/tag[../../command='/bin/ls'][.='NOPASSWD'] NOPASSWD

I think its because you're trying to set multiple nodes that don't
exist at once that aren't in a direct parent-child relationship,
because you CAN do this:

set /files/etc/sudoers/spec[8]/host_group/command/tag woof

As for modifying the define, the above might help, but if you want
fine grained control of the sudoers file I'd almost suggest you look
at R.I.P's concat module and change the define to declare
concat::fragments. Sometimes it's just easier than fighting with
augeas if you don't care so much about local modifications (and
hopefully for sudoers you don't).

-Luke

On Nov 19, 1:49 pm, Rob McBroom <mailingli...@skurfer.com> wrote:
> That looks like the define I wrote. Whenever/wherever I posted it, I probably also mentioned that it isn't complete because it only identifies entries by user, when in practice, there can be multiple entries with the same user (as you've seen).
>
> The problem with incorporating other attributes to uniquely identify sudo entries is that you would then need two versions of the Augeas changes: one to create an entry and one to update an entry. Such a thing is not easily accomplished in Puppet manifests.
>
> Seehttp://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Lim...

Dan Bode

unread,
Nov 19, 2010, 12:03:17 PM11/19/10
to puppet...@googlegroups.com
Hi,


if you are interested, you can try out a custom sudoers type/provider that I wrote, the puppet code for your example would be something like:

Sudoers{
  users => ['apache', 'nagios'],
  hosts => 'ALL',
  type => 'user_spec',
}
sudoers{
  'nagios-restart':
    commands => 'NOPASSWD: /etc/init.d/nagios* restart',
  ;
  'nagios-reload':
    commands => 'NOPASSWD: /etc/init.d/nagios* reload',
  ;
  'nagios-splat':
    commands => 'NOPASSWD: /etc/init.d/nagios* -v *',
}

It should work, although it still needs some work :)


https://github.com/bodepd/puppet-sudo
 
--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.


Andrew Heagle

unread,
Nov 19, 2010, 11:04:08 PM11/19/10
to puppet...@googlegroups.com

On Friday, November 19, 2010 07:50 EST, walexey <wal...@gmail.com> wrote:

> Hello everybody!
> How can i create with puppet following sudoers file:
>
> User_Alias CENTREON=apache,nagios
> CENTREON ALL = NOPASSWD: /etc/init.d/nagios* restart
> CENTREON ALL = NOPASSWD: /etc/init.d/nagios* reload
> CENTREON ALL = NOPASSWD: /usr/bin/nagios* -v *
>
> The problem that augeas create only last line, replacing previous one.

If you are using a more recent Linux distribution and you have at least sudo >= 1.7.1 (I think), then you can have a #includedir line in your /etc/sudoers file (eg, #includedir /etc/sudoers.d) and you can simply just put a file in there containing your sudo rules. Might be easier than trying to use Augeas, but might not suit your needs. Check your man page for more details!

Regards,
Andrew

Reply all
Reply to author
Forward
0 new messages