
Merci le CRI de faire la gueule, mais on va se dbrouiller sans vous. Ariane pense qu'il est secondaire sur crans.org, il croit donc qu'il est autoritaire sur crans.org et ne connat pas l'existence des zones wifi et ferme. On lui prsente donc un fichier o ces zones sont inclues dans crans.org darcs-hash:20050310231006-d1718-60babf704589ca2efceb43a03d0143e030341b2f.gz
272 lines
11 KiB
Python
Executable file
272 lines
11 KiB
Python
Executable file
#! /usr/bin/env python
|
|
# -*- coding: iso-8859-15 -*-
|
|
|
|
""" Génération de la configuration pour bind9
|
|
|
|
Copyright (C) Frédéric Pauget
|
|
Licence : GPLv2
|
|
"""
|
|
import time, sys
|
|
sys.path.append('/usr/scripts/gestion')
|
|
from gen_confs import gen_config
|
|
from iptools import AddrInNet, AddrInNets
|
|
|
|
class dns(gen_config) :
|
|
"""
|
|
Génération des fichiers de configuration de bind9 :
|
|
* fichier DNS_CONF qui contient les définitions de zone conformément
|
|
à zone_template. Ce fichier doit être inclus à partir de la config statique
|
|
de bind
|
|
* les fichiers de zones, ce sont eux qui contiennent les données du
|
|
dns, ils ont appellés par le fichier DNS_CONF et sont générés dans DNS_DIR
|
|
Leur entète est générée à partir de zone_entete.
|
|
|
|
Les fichiers générés placent bind comme autoritaire sur les noms de
|
|
zones_direct et les adresses de zones_reverse. Les données proviennent de
|
|
la base LDAP
|
|
"""
|
|
######################################PARTIE DE CONFIGURATION
|
|
|
|
### Fichiers à écrire
|
|
# Répertoire d'écriture des fichiers de zone
|
|
DNS_DIR='/etc/bind/generated/' # Avec un / à la fin
|
|
# Fichier de définition des zones pour le maître
|
|
DNS_CONF=DNS_DIR + 'zones_crans'
|
|
|
|
### Sur quelles zones on a autorité ?
|
|
# Résolution directe
|
|
zones_direct = [ 'crans.org' , 'crans.ens-cachan.fr', 'wifi.crans.org' , 'ferme.crans.org' , 'clubs.ens-cachan.fr' ]
|
|
# Résolution inverse
|
|
zones_reverse = [ '138.231.136.0/21', '138.231.148.0/22' ]
|
|
|
|
### Liste DNS
|
|
# Le premier est doit être le maitre
|
|
DNSs = [ 'zamok.crans.org' , 'sila.crans.org' , 'freebox.crans.org' ]
|
|
|
|
### Serveurs de mail
|
|
# format : [ priorité serveur , .... ]
|
|
MXs = ['10 zamok.crans.org', '20 freebox.crans.org' ]
|
|
|
|
### Entète des fichiers de zone
|
|
zone_entete="""
|
|
$ORIGIN %(zone)s.
|
|
$TTL 86400
|
|
@\tIN\tSOA zamok.crans.org. root.crans.org. (
|
|
%(serial)i ; numero de serie
|
|
21600 ; refresh (s)
|
|
3600 ; retry (s)
|
|
1209600 ; expire (s)
|
|
86400 ; TTL (s)
|
|
)
|
|
"""
|
|
|
|
# Syntaxe utilisée dans le fichier DNS_CONF pour définir une zone sur le maître
|
|
zone_template="""
|
|
zone "%(NOM_zone)s" {
|
|
type master;
|
|
file "%(FICHIER_zone)s";
|
|
};
|
|
"""
|
|
# Syntaxe utilisée dans le fichier DNS_CONF pour définir une zone sur le maître
|
|
zone_template_slave="""
|
|
zone "%(NOM_zone)s" {
|
|
type slave;
|
|
file "%(FICHIER_zone)s";
|
|
masters { 138.231.136.6; };
|
|
};
|
|
"""
|
|
|
|
### Verbosité
|
|
# Si =1 ralera (chaine warnings) si machines hors zone trouvée
|
|
# Si =0 ralera seulement contre les machines ne pouvant être classées
|
|
verbose = 1
|
|
|
|
restart_cmd = '/etc/init.d/bind9 reload'
|
|
######################################FIN PARTIE DE CONFIGURATION
|
|
|
|
def __str__(self) :
|
|
return "DNS"
|
|
|
|
def gen_slave(self) :
|
|
""" Génération du fichier de config de zone pour les esclaves """
|
|
zones = self.zones_direct
|
|
|
|
# Ajout des zones reverse
|
|
for net in self.zones_reverse :
|
|
print net
|
|
n = map(int,net.split('/')[0].split('.')[:3])
|
|
print n
|
|
while 1 :
|
|
n[2] += 1
|
|
print n
|
|
if not AddrInNet("%d.%d.%d.1" % tuple(n),net):
|
|
break
|
|
else :
|
|
n.reverse()
|
|
zones.append("%d.%d.%d.in-addr.arpa" % tuple(n))
|
|
n.reverse()
|
|
|
|
# Ecriture
|
|
fd = self._open_conf(self.DNS_CONF,'//')
|
|
for zone in zones :
|
|
fd.write(self.zone_template_slave % { 'NOM_zone' : zone,
|
|
'FICHIER_zone' : self.DNS_DIR + 'db.' + zone })
|
|
fd.close()
|
|
|
|
|
|
def _gen(self) :
|
|
### Génération du numéro de série
|
|
# Le + 1000.... s'explique pas l'idée précédente et peu pratique d'avoir
|
|
# le numéro de série du type AAAAMMJJNN (année, mois, jour, incrément par jour)
|
|
serial = time.time() + 1000000000
|
|
|
|
### DNS
|
|
DNS='; DNS de la zone par ordre de priorité\n'
|
|
for d in self.DNSs :
|
|
DNS += '@\tIN\tNS %s.\n' % d
|
|
DNS += '\n'
|
|
|
|
### Serveurs de mail
|
|
MX='; Serveurs de mails\n'
|
|
for m in self.MXs :
|
|
MX += '%(zone)s.\t' # Sera remplacé par le nom de zone plus tard
|
|
MX += 'IN\tMX\t%s.\n' % m
|
|
MX += '\n'
|
|
|
|
### Tri des machines
|
|
direct = {} # format : { zone : [ lignes correspondantes] }
|
|
direct['ariane'] = "" # Pour Ariane
|
|
reverse = {}
|
|
warnings = ''
|
|
|
|
self.anim.iter=len(self.machines)
|
|
for machine in self.machines :
|
|
self.anim.cycle()
|
|
|
|
# Calculs préliminaires
|
|
try :
|
|
nom , zone = machine.nom().split('.',1)
|
|
zone = zone.encode('iso-8859-1')
|
|
except :
|
|
warnings += u'Machine ignorée (mid=%s) : format nom incorrect (%s)\n' % ( machine.id().encode('iso-8859-1'), machine.nom().encode('iso-8859-1') )
|
|
continue
|
|
|
|
# Le direct
|
|
if zone in self.zones_direct :
|
|
ligne = "%s\tIN\tA\t%s\n" % ( nom, machine.ip() )
|
|
try : direct[zone] += ligne
|
|
except : direct[zone] = ligne
|
|
if zone[-9:] == "crans.org":
|
|
direct['ariane'] += ("%s\tIN\tA\t%s\n" % ((nom + "." + zone)[:-10],
|
|
machine.ip() )).encode('iso-8859-15')
|
|
elif self.verbose :
|
|
warnings += u'Résolution directe ignorée (mid=%s) : zone non autoritaire (%s)\n' % ( machine.id().encode('iso-8859-1'), zone.encode('iso-8859-1') )
|
|
|
|
# Le direct avec alias
|
|
for alias in machine.alias() :
|
|
# Cas particulier : nom de l'alias = nom de la zone
|
|
if alias in self.zones_direct :
|
|
ligne = "@\tIN\tA\t%s\n" % machine.ip()
|
|
ligne = ligne.encode('iso-8859-1')
|
|
alias = alias.encode('iso-8859-1')
|
|
try : direct[alias] += ligne
|
|
except : direct[alias] = ligne
|
|
if alias == "crans.org":
|
|
direct['ariane'] += ("@\tIN\tA\t%s\n" % machine.ip()).encode('iso-8859-15')
|
|
elif alias[-9:] == "crans.org":
|
|
direct['ariane'] += ("%s\tIN\tA\t%s\n" % (alias[:-10], machine.ip())).encode('iso-8859-15')
|
|
continue
|
|
|
|
# Bon format ?
|
|
alias_l = alias.split('.')
|
|
ok = 0
|
|
for i in range(len(alias_l)) :
|
|
zone_essai = '.'.join(alias_l[i:])
|
|
if zone_essai in self.zones_direct :
|
|
# On est autoritaire sur cette zone
|
|
# On place donc l'alias dans le fichier de cette zone
|
|
zone = zone_essai
|
|
nom = '.'.join(alias_l[:i])
|
|
ok = 1
|
|
break
|
|
if not ok :
|
|
warnings += u'Alias ignoré (mid=%s) : %s\n' % ( machine.id().encode('iso-8859-1'), alias.encode('iso-8859-1') )
|
|
continue
|
|
zone = zone.encode('iso-8859-1')
|
|
ligne = "%s\tIN\tCNAME\t%s.\n" % ( nom, machine.nom() )
|
|
try : direct[zone] += ligne
|
|
except : direct[zone] = ligne
|
|
if zone[-9:] == "crans.org":
|
|
direct['ariane'] += ("%s\tIN\tCNAME\t%s.\n" % ((nom + "." + zone)[:-10],
|
|
machine.nom() )).encode('iso-8859-15')
|
|
|
|
# Le reverse
|
|
if AddrInNets(machine.ip(), self.zones_reverse) :
|
|
base_ip = machine.ip().split('.')
|
|
base_ip.reverse()
|
|
zone = "%s.%s.%s.in-addr.arpa" % tuple(base_ip[1:])
|
|
zone = zone.encode('iso-8859-1')
|
|
ligne = '%s\tIN\tPTR\t%s.\n' % (base_ip[0],machine.nom())
|
|
try : reverse[zone] += ligne
|
|
except : reverse[zone] = ligne
|
|
elif self.verbose :
|
|
warnings += u'Résolution inverse ignorée (mid=%s) : ip sur zone non autoritaire (%s)\n' % ( machine.id().encode('iso-8859-1'), machine.ip().encode('iso-8859-1') )
|
|
|
|
### Ajouts pour les fichiers de résolution directs
|
|
for zone in filter(lambda x: x != 'ariane', direct.keys()) :
|
|
# MXs
|
|
direct[zone] = MX % { 'zone' : zone } + direct[zone]
|
|
if zone[-9:] == "crans.org":
|
|
direct['ariane'] = MX % { 'zone' : zone } + direct['ariane']
|
|
|
|
### Ecriture des fichiers de zone et préparation du fichier de définition
|
|
f = ''
|
|
for zone, lignes in direct.items() + reverse.items() :
|
|
if zone == 'ariane':
|
|
continue
|
|
file = self.DNS_DIR + 'db.' + zone
|
|
fd = self._open_conf(file,';')
|
|
if zone != 'ariane':
|
|
fd.write(self.zone_entete % \
|
|
{ 'zone' : zone, 'serveur_autoritaire' : self.DNSs[0] ,
|
|
'serial' : serial } )
|
|
else:
|
|
fd.write(self.zone_entete % \
|
|
{ 'zone' : 'crans.org', 'serveur_autoritaire' : self.DNSs[0] ,
|
|
'serial' : serial } )
|
|
fd.write('\n')
|
|
fd.write(DNS)
|
|
fd.write(lignes)
|
|
fd.close()
|
|
f += self.zone_template % { 'NOM_zone' : zone, 'FICHIER_zone' : file }
|
|
|
|
### Ecriture fichier de définition
|
|
fd = self._open_conf(self.DNS_CONF,'//')
|
|
fd.write(f)
|
|
fd.close()
|
|
|
|
# Pour ariane
|
|
fd = self._open_conf("%s.ariane" % self.DNS_CONF, '//')
|
|
for zone in filter(lambda x: x!= 'ariane', direct):
|
|
if zone == "crans.org":
|
|
fd.write(self.zone_template % { 'NOM_zone' : zone,
|
|
'FICHIER_zone' : self.DNS_DIR + 'db.ariane' })
|
|
elif zone[-9:] != "crans.org":
|
|
fd.write(self.zone_template % { 'NOM_zone' : zone,
|
|
'FICHIER_zone' : self.DNS_DIR + 'db.' + zone })
|
|
for zone in reverse :
|
|
fd.write(self.zone_template % { 'NOM_zone' : zone,
|
|
'FICHIER_zone' : self.DNS_DIR + 'db.' + zone })
|
|
fd.close()
|
|
|
|
return warnings
|
|
|
|
|
|
if __name__ == '__main__' :
|
|
from socket import gethostname
|
|
if gethostname().split(".")[0] == 'zamok' :
|
|
print "Ce serveur est maître !, utiliser generate."
|
|
else :
|
|
print "Reconfiguration de bind en esclave (penser à le relancer)."
|
|
c = dns()
|
|
c.gen_slave()
|