Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 5 down vote accepted

I would use Hiera: http://docs.puppetlabs.com/hiera/latest/

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: http://docs.puppetlabs.com/hiera/latest/lookup_types.html

share|improve this answer
    
+1, I was halfway through typing the same answer. –  Shane Madden Nov 27 '13 at 17:16
2  
Great. Now I have to learn Heira. NEWMAN! –  Scott Pack Nov 27 '13 at 20:41
    
I am loathe to admit that this worked out pretty well. It certainly adds some extra complexity but I'm seeing some real flexibility advantages that I'm liking the idea of. –  Scott Pack Dec 3 '13 at 13:50

While Hiera is the best way and is duely accepted, I'd like to add for completeness' sake: There is a syntax to do just this override you had in mind:

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

  Sssd::Domain<| title == 'LDAP' |> {
    simple_allow_groups => ['SysAdmins','AppAdmins'],
  }
}

Note that this syntax also serves to collect virtual resources, but may well be used to override resource parameters.

Obviously, this technique will lead to chaos if used consequently, so again - Hiera is superior in most cases.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.