Yuvipanda has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/196628

Change subject: [WIP] ldap+yaml file puppet ENC for self hosted puppetmasters
......................................................................

[WIP] ldap+yaml file puppet ENC for self hosted puppetmasters

Don't shoot me yet!

Change-Id: Ic7c6c4492488f559ce00480c6cfc3e8710be1033
---
M manifests/role/puppet.pp
M modules/puppet/manifests/self/config.pp
M modules/puppet/manifests/self/master.pp
A modules/puppetmaster/files/ldap-yaml-enc.py
4 files changed, 109 insertions(+), 13 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/operations/puppet 
refs/changes/28/196628/1

diff --git a/manifests/role/puppet.pp b/manifests/role/puppet.pp
index fa7f073..2a950e3 100644
--- a/manifests/role/puppet.pp
+++ b/manifests/role/puppet.pp
@@ -52,6 +52,7 @@
 class role::puppet::self(
     $master = $::puppetmaster,
     $autoupdate_master = $::puppetmaster_autoupdate,
+    $enc = 'ldap', # 'ldap' or 'yaml+ldap'
 ) {
     # If $::puppetmaster is not set, assume
     # this is a self hosted puppetmaster, not allowed
@@ -69,8 +70,18 @@
     # If localhost or if $server matches this node's
     # $fqdn, then this is a puppetmaster.
     if ($server == 'localhost' or $server == $::fqdn) {
+        if $enc == 'yaml+ldap' {
+            $enc_script_path = '/usr/local/bin/ldap-yaml-enc.py'
+            file { $enc_script_path:
+                source => 'puppet:///modules/puppetmaster/ldap-yaml-enc.py',
+                owner  => 'root',
+                group  => 'root',
+                mode   => '0555',
+            }
+        }
         class { 'puppet::self::master':
-            server => $server,
+            server          => $server,
+            enc_script_path => $enc_script_path,
         }
         # If this parameter / variable variable is set, then
         # run a cron job that automatically tries to update the local
diff --git a/modules/puppet/manifests/self/config.pp 
b/modules/puppet/manifests/self/config.pp
index 345dd9d..b369a7b 100644
--- a/modules/puppet/manifests/self/config.pp
+++ b/modules/puppet/manifests/self/config.pp
@@ -18,24 +18,33 @@
     $is_puppetmaster      = false,
     $bindaddress          = undef,
     $puppet_client_subnet = undef,
-    $certname             = "${::ec2id}.${::domain}") inherits base::puppet
-{
+    $certname             = "${::ec2id}.${::domain}",
+    $enc_script_path        = undef,
+) inherits base::puppet {
     include ldap::role::config::labs
 
     $ldapconfig = $ldap::role::config::labs::ldapconfig
     $basedn = $ldapconfig['basedn']
 
-    $config = {
-        'dbadapter'     => 'sqlite3',
-        'node_terminus' => 'ldap',
-        'ldapserver'    => $ldapconfig['servernames'][0],
-        'ldapbase'      => "ou=hosts,${basedn}",
-        'ldapstring'    => 
'(&(objectclass=puppetClient)(associatedDomain=%s))',
-        'ldapuser'      => $ldapconfig['proxyagent'],
-        'ldappassword'  => $ldapconfig['proxypass'],
-        'ldaptls'       => true
+    if $enc_script_path {
+        $config = {
+            'node_terminus'  => 'exec',
+            'external_nodes' => $enc_script,
+        }
+    } else {
+        $config = {
+            'node_terminus' => 'ldap',
+            'ldapserver'    => $ldapconfig['servernames'][0],
+            'ldapbase'      => "ou=hosts,${basedn}",
+            'ldapstring'    => 
'(&(objectclass=puppetClient)(associatedDomain=%s))',
+            'ldapuser'      => $ldapconfig['proxyagent'],
+            'ldappassword'  => $ldapconfig['proxypass'],
+            'ldaptls'       => true,
+        }
     }
 
+    $config['dbadapter'] = 'sqlite'
+
     # This is set to something different than the default
     # /var/lib/puppet/ssl to avoid conflicts with previously
     # generated puppet certificates from the normal puppet setup.
diff --git a/modules/puppet/manifests/self/master.pp 
b/modules/puppet/manifests/self/master.pp
index c2aa0a9..9dcec7e 100644
--- a/modules/puppet/manifests/self/master.pp
+++ b/modules/puppet/manifests/self/master.pp
@@ -12,7 +12,10 @@
 # == Parameters
 # $server - hostname of the puppetmaster.
 #
-class puppet::self::master($server) {
+class puppet::self::master(
+    $server,
+    $enc_script_path = undef,
+) {
     system::role { 'puppetmaster':
         description  => $server ? {
             'localhost' => 'Puppetmaster for itself',
@@ -52,6 +55,7 @@
         bindaddress          => $bindaddress,
         puppet_client_subnet => $puppet_client_subnet,
         certname             => $certname,
+        enc_script_path      => $enc_script_path,
         require              => File['/etc/ldap/ldap.conf', '/etc/ldap.conf', 
'/etc/nslcd.conf'],
     }
     class { 'puppet::self::gitclone':
diff --git a/modules/puppetmaster/files/ldap-yaml-enc.py 
b/modules/puppetmaster/files/ldap-yaml-enc.py
new file mode 100644
index 0000000..f6b2525
--- /dev/null
+++ b/modules/puppetmaster/files/ldap-yaml-enc.py
@@ -0,0 +1,72 @@
+import re
+import yaml
+from collections import OrderedDict
+import sys
+import ldapsupportlib
+import ldap
+import os
+
+
+def ordered_load(stream):
+    """
+    Load an ordered dict from a given yaml stream
+    :return: a yaml document where dicts retain their ordering
+    """
+    class OrderedLoader(yaml.SafeLoader):
+        pass
+
+    def construct_mapping(loader, node):
+        loader.flatten_mapping(node)
+        return OrderedDict(loader.construct_pairs(node))
+    OrderedLoader.add_constructor(
+        yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
+        construct_mapping)
+    return yaml.load(stream, OrderedLoader)
+
+
+class RolesRules(object):
+    """
+    A set of rules that help map a hostname to a set of roles.
+    """
+    def __init__(self, rules):
+        self.rules = {
+            re.compile(key): value
+            for key, value in rules.items()
+        }
+
+    def roles_for(self, instancename):
+        """
+        Return list of roles for given instancename
+        """
+        matched_roles = []
+        for check, roles in self.rules.items():
+            if check.match(instancename):
+                matched_roles += roles
+
+        return matched_roles
+
+
+with open('/etc/wmflabs-project') as f:
+    path = os.path.join('/var/lib/git/operations/production/nodes/labs/', 
f.readall().strip())
+
+with open(path) as f:
+    rolesrules = RolesRules(ordered_load(f))
+
+ldapConn = ldapsupportlib.LDAPSupportLib().connect()
+
+ec2id_name = sys.argv[1]
+query = 'dc=%s' % (ec2id_name)
+result = ldapConn.search_s('ou=hosts,dc=wikimedia,dc=org', ldap.SCOPE_SUBTREE, 
query)
+if result:
+    host_info = result[0][1]
+    roles = host_info['puppetClass']
+    puppetvars = {
+        var[0]: var[1]
+        for var in [pv.split("=") for pv in host_info['puppetVar']]
+    }
+    roles += rolesrules.roles_for(puppetvars['instancename'])
+    yaml.dump({
+        'classes': roles,
+        'parameters': puppetvars,
+    }, sys.stdout)
+

-- 
To view, visit https://gerrit.wikimedia.org/r/196628
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic7c6c4492488f559ce00480c6cfc3e8710be1033
Gerrit-PatchSet: 1
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Yuvipanda <yuvipa...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to