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