From: Mark Wooding Date: Sun, 4 Dec 2011 22:00:27 +0000 (+0000) Subject: bin/zoneconf: Reload zones after signing them. X-Git-Tag: 1.0.0~1 X-Git-Url: https://git.distorted.org.uk/~mdw/zoneconf/commitdiff_plain/400655ac5d4a70661b9b8cfe7ade317347d11c40 bin/zoneconf: Reload zones after signing them. There are some other changes, too. * Move the program-running, output printing logic into `build-program' (rename it `run') because it's in too many places. * Avoid resigning a zone if we've done it already. --- diff --git a/bin/zoneconf b/bin/zoneconf index aad3ac3..772088a 100755 --- a/bin/zoneconf +++ b/bin/zoneconf @@ -164,6 +164,40 @@ proc set* {names values} { } } +proc run {what command args} { + ## Run a command, reporting the result. WHAT is shown in the output; + ## COMMAND are the command and arguments as a list; these are substituted + ## according to the string map ARGS. Return true if the command succeeded, + ## false if it failed. + + global QUIS + + ## Substitute tokens in the command. + set cmd {} + set subst [concat [list "%%" "%"] $args] + foreach item $command { lappend cmd [string map $subst $item] } + + ## Run the command. + set rc [catch { + set out [eval exec -ignorestderr $cmd 2>@1] + } msg] + + ## Sort out the report. + if {$rc} { set out $msg } + set out "| [string map [list "\n" "\n| "] $out]" + + ## Announce the result. + if {$rc} { + puts stderr "$QUIS: $what failed..." + puts stderr $out + return false + } else { + puts "$QUIS: $what output..." + puts $out + return true + } +} + ###-------------------------------------------------------------------------- ### Configuration spaces. ### @@ -1055,17 +1089,6 @@ define-configuration-space toplevel ZONECFG { ###-------------------------------------------------------------------------- ### Processing the results. -proc build-command {command args} { - ## Return the COMMAND list, after applying the string map ARGS to each item - ## in turn. - - set cmd {} - foreach item $command { - lappend cmd [string map $args $item] - } - return $cmd -} - proc zone-file-name {view config} { ## Return the relative file name for the zone described by CONFIG, relative ## to the given VIEW. An absolute filename may be derived later, depending @@ -1195,26 +1218,12 @@ proc sign-zone-file {info input soafmt} { global QUIS array set zone $info - set cmd [build-command $zone(signzone-command) \ - "%z" $zone(name) \ - "%f" $zone(file-name) \ - "%o" $zone(server-file-name) \ - "%q" $soafmt] - set rc [catch { - set out [eval exec -ignorestderr $cmd] - } msg] - if {$rc} { set out $msg } - set out "| [string map [list "\n" "\n| "] $out]" - set ident "zone `$zone(name)' in view `$zone(mapped-view)'" - if {$rc} { - puts stderr "$QUIS: signing zone $ident failed..." - puts stderr $out - return false - } else { - puts "$QUIS: signing zone $ident output..." - puts $out - return true - } + return [run "zone `$zone(name)' in view `$zone(mapped-view)'" \ + $zone(signzone-command) \ + "%z" $zone(name) \ + "%f" $zone(file-name) \ + "%o" $zone(server-file-name) \ + "%q" $soafmt] } proc write-zone-stanza {view chan config} { @@ -1391,23 +1400,12 @@ provided by the named USER" close $chan ## Check the zone for sanity. - set cmd [build-command $zone(checkzone-command) \ - "%z" $name \ - "%v" $view \ - "%f" $tmp] - set rc [catch { - set out [eval exec $cmd] - } msg] - if {$rc} { set out $msg } - set out "| [string map [list "\n" "\n| "] $out]" - if {$rc} { - puts stderr "$QUIS: zone check failed..." - puts stderr $out + if {![run "zone check" $zone(checkzone-command) \ + "%z" $name \ + "%v" $view \ + "%f" $tmp]} { eval $cleanup exit 1 - } else { - puts "$QUIS: zone check output..." - puts $out } ## If the zone wants signing, better to do that now. @@ -1421,9 +1419,12 @@ provided by the named USER" file rename -force -- $tmp $zone(file-name) set cleanup {} foreach view $matchview { - eval exec $cmd [build-command $zone(reload-command) \ - "%v" $view \ - "%z" $zone(name)] + if {![run "reload zone `$zone(name) in view `$view'" \ + $zone(reload-command) \ + "%v" $view \ + "%z" $zone(name)]} { + exit 3 + } } } { eval $cleanup @@ -1441,24 +1442,49 @@ defcmd sign {} { confspc-eval toplevel [list source $CONFFILE] ## Grind through all of the zones. - foreach iview $ZONECFG(all-views) { + array unset seen + foreach view $ZONECFG(all-views) { foreach info $ZONES { + + ## Fetch the zone information. array unset zone - set compinfo [compute-zone-properties $iview $info] + set compinfo [compute-zone-properties $view $info] array set zone $compinfo if {![string equal $zone(config-type) master]} { continue } + if {[string equal $zone(type) static] && $zone(sign)} { - if {![sign-zone-file $compinfo $zone(file-name) $zone(soa-format)]} { - set rc 2 + ## Static zone: re-sign it if we haven't seen this user view before, + ## and then reload. + + ## Sign the zone file if we haven't tried before. + set id [list $zone(name) $zone(mapped-view)] + if {![info exists seen($id)]} { + if {[sign-zone-file $compinfo \ + $zone(file-name) $zone(soa-format)]} { + set seen($id) true + } else { + set rc 2 + set seen($id) failed + } + } + + ## If we succeeded, reload the zone in this server view. + if {[string equal $seen($id) true]} { + if {![run "reload zone `$zone(name) in server view `$view'" \ + $zone(reload-command) \ + "%z" $zone(name) \ + "%v" $view]} { + set rc 2 + } } } elseif {[string equal $zone(type) dynamic] && ![string equal $zone(auto-dnssec) off]} { - set cmd [build-command $zone(autosign-command) \ - "%z" $zone(name) \ - "%v" $iview] - if {[catch { exec $cmd } msg]} { - puts stderr "$QUIS: failed to reload `$zone(name)'" - puts stderr "| [string map [list "\n" "\n| "] $msg]" + ## Dynamic zone: get BIND to re-sign it. + + if {![run "re-sign zone `$zone(name) in server view `$view'" \ + $zone(autosign-command) \ + "%z" $zone(name) \ + "%v" $view]} { set rc 2 } }