Openstuff Wiki : HowtoSVNDNS

HomePage :: Categories :: PageIndex :: RecentChanges :: RecentlyCommented :: Login/Register

Revision [524]

This is an old revision of HowtoSVNDNS made by StanKju on 2007-11-17 10:38:15.
 

Allons plus loin avec Subversion: application aux DNS


Nous allons voir comment utiliser SVN pour gérer des zones DNS. En effet, Subversion s'intègre particulièrement bien au sein d'une architecture DNS multimaster. Attention, nous considérons que vous êtes déjà familier avec SVN et que vous maîtrisez le fonctionnement du DNS (architecture, configuration, ...).

Dans cet article, nous utiliserons Bind comme serveur DNS.

1. Motivation de l'architecture DNS avec l'utilisation de SVN


Classiquement, les DNS sont mis en maître/esclave avec des transferts de zone entre eux. L'idée ici est de n'avoir plus qu'une machine centrale qui poussera les zones sur tous les serveurs DNS qui seront tous master. C'est ce que nous appelons une architecture DNS multimaster. Les intérêts sont multiples :

L'utilisation de Subversion est motivée par les éléments suivants:

2. La mise en place


Nous considérons que l'architecture DNS multimaster est déjà en place. Vous devriez avoir les directives suivantes dans la configuration de vos serveurs (section options):
recursion   no;
allow-transfer { none; }
notify         no;


Les zones seront maintenant sur un repository Subversion. Deux scripts de "hook" vont être créés qui permettront d'effectuer automatiquement la vérification et la propagation des zones lors d'un commit.

Les serials seront gérés par nos scripts, ils seront donc mis à "0000000000" dans le repository. Un remplacement sera fait automatiquement lors du post-commit via la commande zsu. Le fichier /var/lib/misc/zones.serialZ servira de stockage pour l'ensemble des serials. son format est le suivant:
mazone.com 2007010502
mazone.reverse 2007010502


Script Hook Subversion: pre-commit


Rôle: vérification que les zones sont correcte

#!/bin/bash

#################################################
#                                               #
#       SVN pre-commit (DNS zone edition)       #
#                                               #
#################################################

# Redirect all output to standard error output
exec >&2

# uncomment this for debugging
#set -x

# required utils
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SVNLOOK="/usr/bin/svnlook"

# misc variables
REPOS="$1"
TXN="$2"
DATE=`date +%Y%m%d%H%M`
TMPDIR="/tmp/svndnstmp-$DATE-$TXN"
EDITED_ZONES="`$SVNLOOK changed -t $TXN $REPOS | grep -v '^D' | awk '{ print $2 }' | grep -v '\.inc$'`"   # Do not get Deleted files
LOG_FILE="/var/log/svn/debug.log"

echo ">>> Starting PRE-COMMIT ... (`date '+%X %x'`)" >> $LOG_FILE

# get the edited zones and put them into temporary files
mkdir $TMPDIR
for i in $EDITED_ZONES
do
        echo "extracting: "$i >> $LOG_FILE
        $SVNLOOK cat -t $TXN $REPOS $i > "$TMPDIR/$i"
done


# checking the edited zones
ERRZONE=0
cd $TMPDIR
for i in $EDITED_ZONES
do
        echo "checking: "$i >> $LOG_FILE

        # Check SERIAL
        val=`grep -E "^[[:blank:]]*[0-9]{10}($|[[:blank:]]*;.*$)" $i | awk '{ print $1 }'`
        [ -z "$val" ] && { echo -e "\033[00;31m>>> NO SERIAL on zone $i ! \033[00;00m" ; ERRZONE=1 ; continue ; }
        if [ "$val" != '0000000000' ]
        then
                ERRZONE=1
                echo -e "\033[00;31m>>> BAD SERIAL on zone $i : serial != '000000000' !\033[00;00m"
        fi

        # Check ORIGIN
        ZONE=`echo $i | grep '$ORIGIN' "$i" | awk '{print $2}'`
        [ -z "$ZONE" ] && { echo -e "\033[00;31m>>> ORIGIN IS MISSING on zone $i ! \033[00;00m" ; ERRZONE=1 ; continue ; }

        # Check zone file
        ERRMSG=`named-checkzone $ZONE "$i"`
        if [ $? != 0 ]
        then
                ERRZONE=1
                echo -e "\033[00;31m>>> ERROR on zone $i\033[00;00m"
                echo $ERRMSG
        fi
done

# if anything gone wrong, start yelling
rm -rf $TMPDIR
echo ">>> End PRE-COMMIT ... (`date '+%X %x'`)" >> $LOG_FILE

exit $ERRZONE


Script Hook Subversion: post-commit


Rôle: déploiement des modifications sur les serveurs

#!/bin/sh
REPOS="$1"
REV="$2"

# Program PATH
DNS_ALL="/usr/local/sbin/dns_all_ng.sh"
SVNLOOK="/usr/bin/svnlook"
SVN="/usr/bin/svn"
RSYNC="/usr/bin/rsync"
PERL="/usr/bin/perl"
ECHO="/bin/echo"
AWK="/usr/bin/awk"
RM="/bin/rm"
GREP="/bin/grep"
ZSU="/usr/local/bin/zsu"
DATE="/bin/date"
SUDO="/usr/bin/sudo"
CHMOD="/bin/chmod"

# Var def
FILE="/tmp/svn.$$"
BIND_REPOS="/etc/bind/zones/master"
MAIL_ADDR="admin@example.com"
FILE_SERIAL="/var/lib/misc/zones.serialZ"
LOG_FILE="/var/log/svn/debug.log"
SUDO_USER="dns"

echo ">>> Starting POST-COMMIT ... (`$DATE '+%X %x'`)" >> $LOG_FILE

# Get infos from SVNLOOK
SVN_AUTHOR=`$SVNLOOK author --revision $REV $REPOS`
SVN_DATE=`$SVNLOOK date --revision $REV $REPOS`
SVN_LOG=`$SVNLOOK log --revision $REV $REPOS`
SVN_CHANGED=`$SVNLOOK changed --revision $REV $REPOS`
SVN_DIFF=`$SVNLOOK diff --revision $REV $REPOS`
ZONE_ALL_CHANGED=`echo "$SVN_CHANGED" | $AWK '{print $NF}'` # Get deleted files
ZONE_CHANGED=`echo "$SVN_CHANGED" | $GREP -v "^D" | $AWK '{print $NF}'` # Do not get deleted files

# Define return code to NOK
MAJ_REPOS_BIND_RET="NOK"
RSYNC_SVN_RET="NOK"
REPLACE_SERIAL_RET="OK"
DNS_ALL_RET="NOK"


# Update bind zone files
# ----------------------

# Delete modified files inside bind repository
for zone in $ZONE_ALL_CHANGED
do
        $RM -f $BIND_REPOS/$zone
done

# "svn up" in bind repository
MAJ_REPOS_BIND=`$SVN update $BIND_REPOS -q 2>&1` && MAJ_REPOS_BIND_RET="OK"

echo "*Update Bind repository* [$MAJ_REPOS_BIND_RET]
$MAJ_REPOS_BIND"
>> $LOG_FILE


# Update serial for each file changed
# -----------------------------------
for zone in $ZONE_CHANGED
do
        insert=0
       
        # Verify serial file => we must have only one entry
        num=`$GREP -c "^$zone " $FILE_SERIAL`
        if [ "$num" != "1" ]
        then    
                REPLACE_SERIAL=$REPLACE_SERIAL" Zone $zone have $num entry in FILE_SERIAL"
                REPLACE_SERIAL_RET="NOK"
        fi
       
        # Get current serial from serial_file
        serial=`$GREP -E "^$zone [0-9]{10}$" $FILE_SERIAL | $AWK '{print $2}'`
       
        # If void, create new serial
        [ -z "$serial" ] && { serial=`$DATE +%Y%m%d00`; REPLACE_SERIAL=$REPLACE_SERIAL" Create new serial for zone $zone. "; insert=1; }
       
        # Replace serial on zone file
        export serial
        REPLACE_SERIAL=$REPLACE_SERIAL`$PERL -pi -e 'if ($SOA) { s/\d{10}/$ENV{serial}/; $SOA=0 } ; $SOA++ if /IN\s+SOA/' $BIND_REPOS/$zone 2>&1`
        [ $? -ne 0 ] && REPLACE_SERIAL_RET="NOK"
       
        # Update serial
        REPLACE_SERIAL=$REPLACE_SERIAL`$ZSU -f $BIND_REPOS/$zone 2>&1`
        [ $? -ne 0 ] && REPLACE_SERIAL_RET="NOK"
       
        # Replace serial on serial file
        #serial=`$GREP -E "^[[:blank:]]*[0-9]{10}($|[[:blank:]]*;.*$)" $BIND_REPOS/$zone | $AWK '{ print $1 }'`
        serial=`$PERL -n -e 'if ($SOA) { print $1 if /(\d{10})/; $SOA=0 } ; $SOA++ if /IN\s+SOA/' $BIND_REPOS/$zone 2>&1`
        [ -z "$serial" ] && REPLACE_SERIAL_RET="NOK"
        REPLACE_SERIAL=$REPLACE_SERIAL`$PERL -pi -e "s/^$zone [0-9]{10}$/$zone $serial/" $FILE_SERIAL 2>&1`
       
        # If zone do not exist on serial file, add it
        [ $insert -eq 1 ] && $ECHO "$zone $serial" >> $FILE_SERIAL
done

echo "*Serial replace* [$REPLACE_SERIAL_RET]
$REPLACE_SERIAL"
>> $LOG_FILE


# Apply changes
# -------------
DNS_ALL=`$SUDO -u $SUDO_USER $DNS_ALL $ZONE_CHANGED 2>&1` && DNS_ALL_RET="OK"

echo "*dns_all.sh* [$DNS_ALL_RET]
$DNS_ALL"
>> $LOG_FILE


# Create report
# -------------
{

/bin/cat <<EOF
Repository:     $REPOS
Revision:       $REV
Author:         $SVN_AUTHOR
Date:           $SVN_DATE
Log message:    $SVN_LOG
Modified paths:
$SVN_CHANGED

DNS Report:
===========

*Update Bind repository* [$MAJ_REPOS_BIND_RET]
$MAJ_REPOS_BIND
*Serial replace* [$REPLACE_SERIAL_RET]
$REPLACE_SERIAL
*Rsync* [$RSYNC_SVN_RET]
$RSYNC_SVN
*dns_all.sh* [$DNS_ALL_RET]
$DNS_ALL


$SVN_DIFF

EOF

} > $FILE

# Mail file and delete it
# -----------------------
if [ "$MAJ_REPOS_BIND_RET" == "OK" ] && [ "$REPLACE_SERIAL_RET" == "OK" ] && [ "$RSYNC_SVN_RET" == "OK" ] && [ "$DNS_ALL_RET" == "OK" ]
then
        STATUS="OK"
else
        STATUS="NOK"
fi
/bin/cat $FILE | /usr/bin/mail -s "DNS SVN update (rev. $REV): [$STATUS] $SVN_LOG" $MAIL_ADDR
rm -f $FILE
echo ">>> End POST-COMMIT ... (`$DATE '+%X %x'`)" >> $LOG_FILE



Script de déploiement: dns_all_ng.sh

Rôle:

L'écriture du script est laissée comme exercice au lecteur :)

3. Utilisation


Une fois les zones insérées dans le repository, les modifications de zones s'effectuent de la sorte:
$ svn up
$ vi <la zone DNS à modifier>
$ svn commit -m "<commentaire>"


Et voilà ! La zone sera vérifiée, le serial sera inséré dans le fichier de zone et celle-ci sera déployée sur les autoritaires. Rapide, efficace, que demande le peuple ? :)
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by WikkaWiki
Page was generated in 0.3175 seconds