So, once again usability is sacrificed in favor of purity.

If you are using Puppet 2.6.1, you can move evaluation of the
sshd_config.erb template to a "post" stage, and then generate your
AllowGroups stanza from the class list (which will be complete).  Here's an
excerpt from my sshd_config.erb that I used before upgrading to 2.6.3 (which
broke this behavior):

# This is where the access control bits live
<%
my_login_groups = ['root', 'wheel', 'sysadmin']
my_login_groups << 'oinstall' if classes.index('oracle') != nil
my_login_groups << 'dba' if classes.index('oracle') != nil
my_login_groups << 'puppet' if classes.index('puppet::master') != nil
my_login_groups << 'jboss' if classes.index('jboss') != nil
my_login_groups << 'nagios' if classes.index('nagios::server') != nil
# more deleted
%>
AllowGroups <%= my_login_groups.join(' ') %>

With 2.6.3, you have to do this in a two-stage process.  First, write a
custom fact that returns the contents of classlist.txt on the client.  Then
change the above code to work with that fact.  In my environment, the
equivalent to the above looks like this:

# This is where the access control bits live
<%
### "pps" stands for "Puppet purity sucks"
pps = cprt_classes.split(',')
my_login_groups = ['root', 'wheel', 'sysadmin']
my_login_groups << 'oinstall' if pps.index('oracle') != nil
my_login_groups << 'dba' if pps.index('oracle') != nil
my_login_groups << 'puppet' if pps.index('puppet::master') != nil
my_login_groups << 'jboss' if pps.index('jboss') != nil
my_login_groups << 'nagios' if pps.index('nagios::server') != nil
# more deleted
%>
AllowGroups <%= my_login_groups.join(' ') %>


My irritation with the behavioral change aside, this works just as well as
the code above, except that it takes two Puppet runs to be correct.

If the Puppet DSL had some kind of useful container type, we could put all
the configuration bits in the manifests instead of duplicating this crazy
templating all over the place.


On Wed, Dec 22, 2010 at 5:21 PM, Hugo Cisneiros (Eitch) <
[email protected]> wrote:

> Hi,
>
> After extensively looking into puppet + augeas for managing the
> AllowGroups in sshd_config, I came to the conclusion that it won't
> work as I expected :( So I'm sharing my thoughts here.
>
> The main objective is allowing multiple groups per-node, depending on
> what the security team wants. Since I want this to be dynamic, I
> created a define in a class:
>
> class ssh::server::config inherits ssh::config {
>    define addallowgroup() {
>        augeas {
>            "sshd_conf_group_${name}":
>                context => "/files/etc/ssh/sshd_config",
>                require => File["/etc/ssh/sshd_config"],
>                notify => Service["sshd"],
>                changes => "set AllowGroups/*[last()+1] ${name}",
>                onlyif => " match AllowGroups/*[.='${name}'] size == 0";
>        }
>    }
> }
>
> Then on a node, I can use this:
>
> node "webserver" {
>    ssh::server::config::addallowgroup { ["test1", "test2", "test3"]: }
> }
>
> Sadly, the "changes" and "onlyif" lines in the augeas type does not
> work because the sshd_config's lens creates a unique node/label for
> each option. Quoting Augeas' website:
>
> "
> http://augeas.net/page/Adding_nodes_to_the_tree
>
> You can use a special trick to append to a list of nodes that all have
> the same name, for example to append a new alias to an entry in
> /etc/hosts:
>
> set $hosts/1/alias[last()+1] myhost.example.com
>
> The predicate [last()+1] forces set to create a new node. Of course,
> after the node is created, it is now reachable as
> $hosts/1/alias[last()]. It's important to remember that creating nodes
> with set can only work if the labels for all the nodes that need to be
> created are known explicitly. In particular, you can't add a new host
> entry using something like set $hosts/*[last()+1]/ipaddr 192.168.0.1 —
> there's no way for Augeas to know what the new node for *[last()+1]
> should be called.
> "
>
> In the example on hosts, the "alias" label is already named. So I
> can't think on adding another node/label dynamically.
>
> The alternative could be creating one augeas type for each group and
> using them on the nodes, like this:
>
> augeas {
>    "sshd_conf_group_test1":
>        context => "/files/etc/ssh/sshd_config",
>        require => File["/etc/ssh/sshd_config"],
>        notify => Service["sshd"],
>        changes => "set AllowGroups/1 test1",
>        onlyif => " match AllowGroups/1[.='test1'] size == 0";
>
>    "sshd_conf_group_test2":
>        context => "/files/etc/ssh/sshd_config",
>        require => File["/etc/ssh/sshd_config"],
>        notify => Service["sshd"],
>        changes => "set AllowGroups/2 test2",
>        onlyif => " match AllowGroups/2[.='test2'] size == 0";
>
>    "sshd_conf_group_test1":
>        context => "/files/etc/ssh/sshd_config",
>        require => File["/etc/ssh/sshd_config"],
>        notify => Service["sshd"],
>        changes => "set AllowGroups/3 test3",
>        onlyif => " match AllowGroups/3[.='test3'] size == 0";
> }
>
> When we have much groups, this becomes very long :(
>
>  Anyone here have some idea for a good practice? :) Or maybe this is
> just plain impossible.
>
> Versions:
> puppet-0.25.5
> augeas-0.7.3
>
> Thanks!
>
> --
> []'s
> Hugo
> www.devin.com.br
>
> --
> You received this message because you are subscribed to the Google Groups
> "Puppet Users" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<puppet-users%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/puppet-users?hl=en.
>
>

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

Reply via email to