Puppet – Overriding Parameters in Previously Declared Puppet Resource

authenticationpuppetsssd

I'm attempting to rebuild nwaller's sssd puppet module to be entirely LDAP based and to be a little cleaner. In it we have a resource defined for each authentication domain of the form

define sssd::domain ( 
  $domain = $name,
  $domain_description = '',
  $domain_type,
  $ldap_uri = 'ldap://example.com',
  $ldap_search_base = 'dc=example,dc=com',
  $simple_allow_groups,
....
)

This definition is then passed as a concat::fragment which fills out a template for building the final sssd.conf.

This all works great if I define the LDAP server within each node, as in:

nodes.pp

node "node1.systems.private" {
  include "puppet::client"
  class {
    'sssd':
      domains => [ 'LDAP' ],
      make_home_dir => true;
  }
  sssd::domain { 'LDAP':
    domain_type            => 'ldap',
    ldap_uri               => 'ldaps://ldap.site.com:636',
    ldap_search_base       => 'DC=site,DC=com',
    ldap_user_search_base  => 'OU=People,DC=site,DC=com',
    ldap_group_search_base => 'OU=Groups,DC=site,DC=com',
    ldap_default_bind_dn   => 'CN=bindaccount,OU=Service Accounts,OU=People,DC=site,DC=com',
    ldap_default_authtok   => 'soopersekretbindpw',
    simple_allow_groups    => ['SysAdmins','AppAdmins'],
  }
} 

What I would rather do is a much more hierarchical setup. Keep the sssd::domain definition as generic as possible, so I can maintain it as a module independent of our organization configurations. Define the LDAP server in a global config, and then within each node define which specific groups need access. So something more like:

modules/org/manifests/default.pp

class org::default {
  include "puppet::client"
  class {
    'sssd':
      domains => [ 'LDAP' ],
      make_home_dir => true;
  }
  sssd::domain { 'LDAP':
    domain_type            => 'ldap',
    ldap_uri               => 'ldaps://ldap.site.com:636',
    ldap_search_base       => 'DC=site,DC=com',
    ldap_user_search_base  => 'OU=People,DC=site,DC=com',
    ldap_group_search_base => 'OU=Groups,DC=site,DC=com',
    ldap_default_bind_dn   => 'CN=bindaccount,OU=Service Accounts,OU=People,DC=site,DC=com',
    ldap_default_authtok   => 'soopersekretbindpw',
  }
} 

nodes.pp

node "node1.systems.private" {
  include "org::default"

  sssd::domain { 'LDAP':
    simple_allow_groups    => ['SysAdmins','AppAdmins'],
  }
}

As expected this results in a duplicate declaration error when attempting to apply the definition. Is there a way to do this, selectively override parameters, or am I stuck with defining the authentication domain within the original definition and then overriding the authorization parameters within each node?

Best Answer

I would use Hiera.

Hiera lets you decouple your variable data from your Puppet manifests.

Hiera, as the name implies, is hierarchical, allowing for some interesting ways to override, as well as combine, variable data.

First, modify your sssd:: domain declaration to perform Hiera lookups for the parameters:

sssd::domain { 'LDAP':
    domain_type            => 'ldap',
    ldap_uri               => hiera('ldap_uri', 'ldaps://ldap.site.com:636'),
    ldap_search_base       => hiera('ldap_search_base', 'DC=site,DC=com'),
    ldap_user_search_base  => hiera('ldap_user_search_base', 'OU=People,DC=site,DC=com'),
    ldap_group_search_base => hiera('ldap_group_search_base', 'OU=Groups,DC=site,DC=com'),
    ldap_default_bind_dn   => hiera('ldap_default_bind', 'CN=bindaccount,OU=ServiceAccounts,OU=People,DC=site,DC=com'),
    ldap_default_authtok   => hiera('ldap_default_authtok', 'soopersekretbindpw'),
    simple_allow_groups    => hiera_array('ldap_simple_allow_groups', ['SysAdmins','AppAdmins']),
}

In the code above, I've defined default values for each of the lookups. You could exclude those, if you like, by sticking the defaults in your most-generic Hiera data file (typically "common.yaml" or "common.json"):

common.yaml:

---
ldap_uri: ldaps://ldap.site.com:636
ldap_search_base: DC=site,DC=com
ldap_simple_allow_groups:
 - SysAdmins
 - AppAdmins

For the bits you want to personalize on a per-host basis, you'd create a YAML or JSON file named after the FQDN of the host in question, and put the necessary values in there.

node1.systems.private.yaml:

---
ldap_simple_allow_groups:
 - SomeOtherGroup

In this example, note that ldap_simple_allow_groups is using the hiera_array lookup function. This will concatenate ALL the valid founds in the hierarchy. As such, node1 will get the values defined in common.yaml as well as the "SomeOtherGroup" defined in its own YAML file.

Read the Hiera lookup types documentation for more details.

Related Topic