[gen_conf] Ajout d'un début de refonte de la génération du dns en utlisant lc_ldap
This commit is contained in:
parent
6c25c4da74
commit
9e203163d4
1 changed files with 245 additions and 0 deletions
245
gestion/gen_confs/bind2.py
Normal file
245
gestion/gen_confs/bind2.py
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import netaddr
|
||||||
|
sys.path.append('/usr/scripts/')
|
||||||
|
|
||||||
|
from gestion import config
|
||||||
|
|
||||||
|
class ResourceRecord(object):
|
||||||
|
def __init__(self, type, name, value, ttl=None):
|
||||||
|
self._type=type
|
||||||
|
self._name=name
|
||||||
|
self._value=value
|
||||||
|
self._ttl=ttl
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self._ttl:
|
||||||
|
return "%s\t%s\tIN\t%s\t%s" % (self._name, self._ttl, self._type, self._value)
|
||||||
|
else:
|
||||||
|
return "%s\tIN\t%s\t%s" % (self._name, self._type, self._value)
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
class SOA(ResourceRecord):
|
||||||
|
def __init__(self, master, email, serial, refresh, retry, expire, ttl):
|
||||||
|
super(SOA, self).__init__('SOA', '', '%s. %s. (\n %s ; numero de serie\n %s ; refresh (s)\n %s ; retry (s)\n %s ; expire (s)\n %s ; TTL (s)\n )' % (master, email, serial, refresh, retry, expire, ttl))
|
||||||
|
class A(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(A, self).__init__('A', name, value, ttl)
|
||||||
|
class PTR(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(PTR, self).__init__('PTR', name, value, ttl)
|
||||||
|
class AAAA(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(AAAA, self).__init__('AAAA', name, value, ttl)
|
||||||
|
class TXT(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(TXT, self).__init__('TXT', name, value, ttl)
|
||||||
|
class CNAME(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(CNAME, self).__init__('CNAME', name, value, ttl)
|
||||||
|
class DNAME(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(DNAME, self).__init__('DNAME', name, value, ttl)
|
||||||
|
class MX(ResourceRecord):
|
||||||
|
def __init__(self, name, priority, value, ttl=None):
|
||||||
|
super(MX, self).__init__('MX', name, '%s\t%s' % (priority, value), ttl)
|
||||||
|
class NS(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(NS, self).__init__('NS', name, value, ttl)
|
||||||
|
class SPF(ResourceRecord):
|
||||||
|
def __init__(self, name, value, ttl=None):
|
||||||
|
super(SPF, self).__init__('SPF', name, value, ttl)
|
||||||
|
class SRV(ResourceRecord):
|
||||||
|
def __init__(self, service, proto, name, priority, weight, port, target, ttl=None):
|
||||||
|
super(SRV, self).__init__('SRV', '_%s._%s.%s' % (service, proto, name), '%s\t%s\t%s\t%s' % (priority, weight, port, target), ttl)
|
||||||
|
class NAPTR(ResourceRecord):
|
||||||
|
def __init__(self, order, preference, flag, service, replace_regexpr, value, ttl=None):
|
||||||
|
super(NAPTR, self).__init__('NAPTR', name, '%s\t%s\t"%s"\t"%s"\t"%s"\t%s' % (order, preference, flag, service, replace_regexpr, value), ttl)
|
||||||
|
class SSHFP(ResourceRecord):
|
||||||
|
def __init__(self, name, hash, algo, key, ttl=None):
|
||||||
|
if not hash in config.sshfp_hash.keys():
|
||||||
|
raise ValueError('Hash %s invalid, valid hash are %s' % (hash, ', '.join(config.sshfp_host.keys())))
|
||||||
|
if not algo in config.sshfp_algo.keys():
|
||||||
|
raise ValueError('Algo %s unknown, valid values are %s' % (algo, ', '.join(config.sshfp_algo.keys())))
|
||||||
|
super(SSHFP, self).__init__('SSHFP', name, '%s\t%s\t%s' % (config.sshfp_algo[algo][0], config.sshfp_hash[hash], getattr(hashlib, hash)(base64.b64decode(key)).hexdigest()), ttl)
|
||||||
|
|
||||||
|
class ZoneBase(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._rrlist=[]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ret=""";***********************************************************
|
||||||
|
; Ce fichier est genere par les scripts de gen_confs
|
||||||
|
; Les donnees proviennent de la base LDAP et de la conf
|
||||||
|
; presente au debut du script.
|
||||||
|
;
|
||||||
|
; NE PAS EDITER
|
||||||
|
;
|
||||||
|
;***********************************************************
|
||||||
|
|
||||||
|
$ORIGIN %s.
|
||||||
|
$TTL %s
|
||||||
|
""" % (self.zone_name, self.ttl)
|
||||||
|
for rr in self._rrlist:
|
||||||
|
ret+="%s\n" % rr
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def add(self, rr):
|
||||||
|
if isinstance(rr, ResourceRecord):
|
||||||
|
self._rrlist.append(rr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ZoneClone(ZoneBase):
|
||||||
|
def __init__(self, zone_name, zone_clone, soa):
|
||||||
|
super(ZoneClone, self).__init__()
|
||||||
|
self.zone_name = zone_name
|
||||||
|
self.zone_clone = zone_clone
|
||||||
|
|
||||||
|
self.add(soa)
|
||||||
|
self.add(DNAME('', "%s." % self.zone_clone.zone_name))
|
||||||
|
for rr in self.zone_clone._rrlist[1:]:
|
||||||
|
if rr._name in ['', '@']:
|
||||||
|
self.add(rr)
|
||||||
|
if rr._name in ["%s." % self.zone_clone.zone_name]:
|
||||||
|
self.add(ResourceRecord(rr._type, "%s." % "%s.", rr._value))
|
||||||
|
|
||||||
|
|
||||||
|
class Zone(ZoneBase):
|
||||||
|
def __init__(self, zone_name, ttl, soa, ns_list, ipv6=True, ipv4=True):
|
||||||
|
super(Zone, self).__init__()
|
||||||
|
self.zone_name = zone_name
|
||||||
|
self.ttl = ttl
|
||||||
|
self.ipv4=ipv4
|
||||||
|
self.ipv6=ipv6
|
||||||
|
|
||||||
|
self.add(soa)
|
||||||
|
for ns in ns_list:
|
||||||
|
self.add(NS('@', '%s.' % ns))
|
||||||
|
|
||||||
|
|
||||||
|
def get_name(self, hostname):
|
||||||
|
if str(hostname).endswith(self.zone_name):
|
||||||
|
ret=str(hostname)[0:- len(self.zone_name) -1]
|
||||||
|
if ret == "":
|
||||||
|
return "@"
|
||||||
|
else:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
print "%s not in zone %s" % (hostname, self.zone_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_delegation(zone, server):
|
||||||
|
zone = self.het_name(zone)
|
||||||
|
if zone:
|
||||||
|
self.add(NS('@', '%s.' % server))
|
||||||
|
|
||||||
|
def add_a_record(self, nom, machine):
|
||||||
|
if self.ipv4:
|
||||||
|
for ip in machine.get('ipHostNumber', []):
|
||||||
|
self.add(A(nom, ip))
|
||||||
|
if self.ipv6:
|
||||||
|
if nom == '@':
|
||||||
|
self.add(A("v4", ip))
|
||||||
|
else:
|
||||||
|
self.add(A("%s.v4" % nom, ip))
|
||||||
|
|
||||||
|
def add_aaaa_record(self, nom, machine):
|
||||||
|
if self.ipv6:
|
||||||
|
for ip in machine.get('ip6HostNumber', []):
|
||||||
|
self.add(AAAA(nom, ip))
|
||||||
|
if self.ipv4:
|
||||||
|
if nom == '@':
|
||||||
|
self.add(AAAA("v6", ip))
|
||||||
|
else:
|
||||||
|
self.add(AAAA("%s.v6" % nom, ip))
|
||||||
|
|
||||||
|
def add_sshfp_record(self, nom, machine):
|
||||||
|
for sshkey in machine.get('sshFingerprint', []):
|
||||||
|
algo_txt, key = str(sshkey).split()[:2]
|
||||||
|
algo=config.sshfs_ralgo[algo_txt][1]
|
||||||
|
for hash in config.sshfp_hash.keys():
|
||||||
|
self.add(SSHFP(nom, hash, algo, key))
|
||||||
|
if self.ipv4 and self.ipv6:
|
||||||
|
if nom == '@':
|
||||||
|
self.add(SSHFP("v4", hash, algo, key))
|
||||||
|
self.add(SSHFP("v6", hash, algo, key))
|
||||||
|
else:
|
||||||
|
self.add(SSHFP("%s.v4" % nom, hash, algo, key))
|
||||||
|
self.add(SSHFP("%s.v6" % nom, hash, algo, key))
|
||||||
|
|
||||||
|
def add_machine(self, machine):
|
||||||
|
for host in machine['host']:
|
||||||
|
nom=self.get_name(host)
|
||||||
|
if nom is None: continue
|
||||||
|
|
||||||
|
self.add_a_record(nom, machine)
|
||||||
|
self.add_aaaa_record(nom, machine)
|
||||||
|
self.add_sshfp_record(nom, machine)
|
||||||
|
|
||||||
|
|
||||||
|
if machine['host']:
|
||||||
|
for alias in machine.get('hostAlias', []):
|
||||||
|
alias = self.get_name(alias)
|
||||||
|
if alias is None: continue
|
||||||
|
to_nom, to_zone = str(machine['host'][0]).split('.', 1)
|
||||||
|
if alias in ['@', '%s.' % self.zone_name]:
|
||||||
|
self.add_a_record(alias, machine)
|
||||||
|
self.add_aaaa_record(alias, machine)
|
||||||
|
self.add_sshfp_record(alias, machine)
|
||||||
|
elif to_zone == self.zone_name:
|
||||||
|
self.add(CNAME(alias, "%s" % to_nom))
|
||||||
|
if self.ipv4 and self.ipv6:
|
||||||
|
self.add(CNAME("%s.v4" % alias, "%s.v4" % to_nom))
|
||||||
|
self.add(CNAME("%s.v6" % alias, "%s.v6" % to_nom))
|
||||||
|
else:
|
||||||
|
self.add(CNAME(alias, "%s." % machine['host'][0]))
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(net, ip):
|
||||||
|
"""Renvoie la zone DNS inverse correspondant au réseau et à
|
||||||
|
l'adresse donnés, ainsi que le nombre d'éléments de l'ip a
|
||||||
|
mettre dans le fichier de zone."""
|
||||||
|
n = netaddr.IPNetwork(net)
|
||||||
|
a = netaddr.IPAddress(ip)
|
||||||
|
rev_dns_a = a.reverse_dns.split('.')[:-1]
|
||||||
|
assert a in n
|
||||||
|
if n.version == 4:
|
||||||
|
if n.prefixlen == 8:
|
||||||
|
return ('.'.join(rev_dns_a[3:]), 3)
|
||||||
|
elif n.prefixlen == 16:
|
||||||
|
return ('.'.join(rev_dns_a[2:]), 2)
|
||||||
|
else:
|
||||||
|
return ('.'.join(rev_dns_a[1:]), 1)
|
||||||
|
elif n.version == 6:
|
||||||
|
return ('.'.join(rev_dns_a[(128-n.prefixlen)/4:]), (128-n.prefixlen)/4)
|
||||||
|
|
||||||
|
class ZoneReverse(Zone):
|
||||||
|
def __init__(self, net, ttl, soa, ns_list):
|
||||||
|
self.net = net
|
||||||
|
zone_name = reverse(net, net.split('/')[0])[0]
|
||||||
|
if '.' in net:
|
||||||
|
ipv6=False
|
||||||
|
ipv4=True
|
||||||
|
elif ':' in net:
|
||||||
|
ipv6=True
|
||||||
|
ipv4=False
|
||||||
|
else:
|
||||||
|
raise ValueError("net should be an ipv4 ou ipv6 network")
|
||||||
|
super(ZoneReverse, self).__init__(zone_name, ttl, soa, ns_list, ipv6=ipv6, ipv4=ipv4)
|
||||||
|
|
||||||
|
|
||||||
|
def add_machine(self, machine):
|
||||||
|
if machine['host']:
|
||||||
|
if self.ipv4:
|
||||||
|
for ip in machine['ipHostNumber']:
|
||||||
|
zone, length = reverse(self.net, str(ip))
|
||||||
|
nom = '.'.join(ip.value.reverse_dns.split('.')[:length])
|
||||||
|
if zone != self.zone_name:
|
||||||
|
continue
|
||||||
|
self.add(PTR(nom, '%s.' % machine['host'][0]))
|
Loading…
Add table
Add a link
Reference in a new issue