diff --git a/dns/files/dnsdump.py b/dns/files/dnsdump.py new file mode 100755 index 0000000..832daf7 --- /dev/null +++ b/dns/files/dnsdump.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +import re +import sys +import time +import os +import glob +import difflib +from subprocess import Popen, PIPE + +# Example templates: +# +# --(A#(&(objectClass=ipHost)(cn=ap*.panoulu.local)(!(cn=*.*.panoulu.local)))-- +# --(PTR#(&(objectClass=ipHost)(cn=ap*.panoulu.local)(ipHostNumber=10.40.*.*)(!(cn=*.*.panoulu.local)))-- +# --(serial)-- + +def main(): + if len(sys.argv) != 4: + print >>sys.stderr, 'Usage: %s --test/--notest ' % sys.argv[0] + sys.exit(1) + + + for template in glob.glob( os.path.join(sys.argv[2], '*.in')): + infile = open(template, 'r') + input = infile.readlines() + input_string = "" + output = "" + for line in input: + input_string += line + m = re.match('([ \t]*)--(.+)--[ \t]*$', line) + if m is not None: + indent = m.group(1) + if (m.group(2) == "(serial)"): + serial = time.localtime(time.time()) + output += '\t\t\t%s\t; serial\n' % (time.strftime("%Y%m%d%H")) + else: + for entry in ldapsearch(m.group(2)): + output += '%s%s\n' % (indent, entry) + else: + output += line + if sys.argv[1] == "--test": + o = open(os.path.join(sys.argv[3], os.path.basename(template[:-3])), 'r') + str = "" + for line in o.readlines(): + str += line + o.close() + for a, b in zip(str.splitlines(), output.splitlines()): + if a != b: + if not "serial" in a: + print a,b + sys.exit(1) + else: + outfile = open(os.path.join(sys.argv[3], os.path.basename(template[:-3])), 'w') + outfile.write(output) + outfile.close() + infile.close() + + +def ldapsearch(f): + filter_list = f.split("#") + type = filter_list[0][1:] + filter = filter_list[1] + p = Popen(['ldapsearch', '-x', '-z', '0', '-LLL', filter, 'cn', 'macAddress', 'ipHostNumber'], + bufsize=1024, stdout=PIPE, close_fds=True) + ret = [] + cur = {} + for l in p.stdout.readlines(): + l = l.strip() + if l == '': + try: + if (type == "A"): + ret.append('%s.\tA\t%s' % ( + cur["cn"], cur["ipHostNumber"])) + elif type == "PTR": + ip_list = cur["ipHostNumber"].split(".") + ret.append('%s.%s.%s.%s.in-addr.arpa.\tPTR\t%s.' % ( + ip_list[-1], ip_list[-2], ip_list[-3], ip_list[-4], cur["cn"])) + else: + raise "missing record type" + except KeyError: + print >>sys.stderr, "skipping: %s" % repr(cur) + cur = {} + continue + l = l.split() + if l[0] in ('cn:', 'macAddress:', 'ipHostNumber:'): + cur[l[0][0:-1]] = l[1] + return ret + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + sys.exit() + diff --git a/dns/manifests/init.pp b/dns/manifests/init.pp index fc24b5f..ee3ec43 100644 --- a/dns/manifests/init.pp +++ b/dns/manifests/init.pp @@ -173,6 +173,45 @@ class dns::server { } } +# Generate named config from LDAP +# +# Usage: +# +# Put templates you want to generate to master.in directory. +# See dnsdump.py for example template tags. + +class dns::server::ldap inherits dns::server { + + include ldap::client::python + + file { "/usr/local/sbin/dnsdump.py": + ensure => present, + source => "puppet:///modules/dns/dnsdump.py", + mode => 0755, + owner => root, + group => $operatingsystem ? { + OpenBSD => wheel, + default => root, + }, + } + + file { "/var/named/master.in": + ensure => directory, + source => "puppet:///files/dns/master.in", + recurse => true, + mode => 0755, + owner => root, + purge => true, + } + + exec { "generate-dns-conf": + path => "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", + command => "dnsdump.py --notest /var/named/master.in /var/named/master", + require => File["/usr/local/sbin/dnsdump.py"], + unless => "dnsdump.py --test /var/named/master.in /var/named/master", + notify => Service["named"] + } +} # Configure DNS zone. #