scripts/gestion/gen_confs/bind.py
bernat 5e533c467e Fichier de zone spcial pour Ariane.
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
2005-03-11 00:10:06 +01:00

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()