Migrer une zone signée par dnssec

Comment faire lorsqu’on change de machine pour qu’une zone signée par dnssec fonctionne toujours correctement ?
La façon logique de faire serait de prévenir la zone parent qu’on a une nouvelle clé publique KSK, celle qui signe les clés qui signent les champs d’une zone, en lui soumettant une nouvelle empreinte DS. Il faudrait ensuite après avoir mis en place tout ce qu’il faut sur la nouvelle machine attendre deux TTLs avant de modifier l’enregistrement NS, après s’être assuré que les serveurs secondaires prennent bien les modifications depuis ce nouveau serveur.
L’option plus simple consiste à désactiver dnssec en supprimant la clé DS de la zone parent, attendre toujours deux TTLs, et basculer sur le nouveau serveur. On peut alors remettre en place dnssec. Evidemment, dans l’intervalle il n’y a plus de dnssec du tout. Si on utilise opendnssec, repartir de zéro plutôt que d’importer l’existant semble également une bonne idée. Sur Debian 8, j’ai constaté que parfois systemd se prend les pieds dans le tapis et crois avoir redémarré opendnssec-enforcerd (vous pouvez s/opendnssec-enforcerd/n’importe quoi) et systemctl status machin renvoiera Ok. Le truc marrant, c’est qu’en plus systemctl restart ne fonctionne pas non plus, il faut faire systemctl stop puis systemctl start. Alors forcément dans le cas de opendnssec, le rollover des clés ne se passe pas très bien.

Une dernière chose, si vous utilisez le programme de notification suggéré par Stéphane Borztmeyer, la commande /usr/sbin/nsdc a été remplacée par /usr/sbin/nsd-control et le paramètre rebuild n’est plus nécéssaire dans la version 4.1 de NSD fournie avec Debian 8. On peut donc utiliser le code modifié suivant :

/*
 * This program is useful for opendnssec's NotifyCommand when using nsd.
 * It should be setuid root.
 * 
 * Authored by Russell Harmon <russ@eatnumber1.com>
 */

#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

static void spawn( char * const argv[] ) {
	pid_t pid = fork();
	if( pid == -1 ) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if( pid == 0 ) {
		// Child
		execv(argv[0], argv);
		perror("execvp");
		exit(EXIT_FAILURE);
	} else {
		// Parent
		siginfo_t siginfo;
		if( waitid(P_PID, pid, &siginfo, WEXITED) == -1 ) {
			perror("waitid");
			exit(EXIT_FAILURE);
		}
		if( siginfo.si_code != CLD_EXITED || siginfo.si_status != EXIT_SUCCESS ) {
			fprintf(stderr, "Abnormal child exit\n");
			exit(EXIT_FAILURE);
		}
	}
}

int main() {
	if( setuid(0) == -1 ) {
		perror("setuid");
		exit(EXIT_FAILURE);
	}
	char *args[3] = { [2] = NULL };
	char **command = &args[1], **binary = &args[0];
	*binary = "/usr/sbin/nsd-control";

/*
	*command = "rebuild";
	spawn(args);
*/
	*command = "reload";
	spawn(args);
	*command = "notify";
	spawn(args);
	return EXIT_SUCCESS;
}