]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Adding scripts/create-pdns-zones-from-files
authorFrank Brehm <frank.brehm@pixelpark.com>
Wed, 30 Nov 2022 09:17:28 +0000 (10:17 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Wed, 30 Nov 2022 09:17:28 +0000 (10:17 +0100)
scripts/create-pdns-zones-from-files [new file with mode: 0755]

diff --git a/scripts/create-pdns-zones-from-files b/scripts/create-pdns-zones-from-files
new file mode 100755 (executable)
index 0000000..d158aa4
--- /dev/null
@@ -0,0 +1,265 @@
+#!/bin/bash
+
+set -e
+set -u
+
+BASE_NAME="$( basename ${0} )"
+MY_REAL_NAME=$( readlink -f $0 )
+BIN_DIR=$( dirname "${MY_REAL_NAME}" )
+
+RC_FILE='/usr/libexec/pixelpark/functions.rc'
+
+if [[ -f "${RC_FILE}" ]] ; then
+    . "${RC_FILE}"
+else
+    echo "Bash resource file '${RC_FILE}' not found" >&2
+    exit 5
+fi
+
+detect_color
+
+CUSTOMER='DNS:NET'
+TSIG_KEY='pp-dns.com'
+ERRORS="0"
+
+declare -a ZONE_FILES=()
+
+DESCRIPTION=$( cat <<-EOF
+       Creating zones from zone files on the local PowerDNS service.
+
+       EOF
+)
+
+#------------------------------------------------------------------------------
+usage() {
+    cat <<-EOF
+       Usage: ${BASE_NAME} [-C|--customer CUSTOMER] [--tsig-key KEY] [Common Options] ZONE_FILE [ZONE_FILE ...]
+              ${BASE_NAME} [-h|--help]
+              ${BASE_NAME} [-V|--version]
+
+           Zone options:
+               -C|--customer CUSTOMER
+                               The name of the customer or registrar of the zone.
+                               Use 'local' or 'private' to create a private zone, which is
+                               not mirrored at the authoritative name servers.
+                               Default: '${CUSTOMER}'.
+               --tsig-key KEY  The name of the TSIG key, which has to be used by secondary
+                               servers on transfering the zone. Defaut: '${TSIG_KEY}'.
+
+           Common Options:
+       ${STD_USAGE_MSG}
+       EOF
+
+}
+
+#------------------------------------------------------------------------------
+get_options() {
+
+    local tmp=
+    local base_dir=
+
+    set +e
+    tmp=$( getopt -o ${STD_SHORT_OPTIONS}C: \
+                  --long ${STD_LONG_OPTIONS},customer:,tsig-key: \
+                  -n "${BASE_NAME}" -- "$@" )
+    if [[ $? != 0 ]] ; then
+        echo "" >&2
+        usage >&2
+        exit 1
+    fi
+    set -e
+
+    # Note the quotes around `$TEMP': they are essential!
+    eval set -- "${tmp}"
+    eval_common_options "$@"
+    if [[ "${DEBUG}" == 'y' ]] ; then
+        declare -p REMAINING_OPTS
+        declare -p REMAINING_ARGS
+    fi
+
+    local len="${#REMAINING_OPTS[*]}"
+    local i="0"
+    local j=
+    local arg=
+
+    while [[ "$i" -lt "${len}" ]] ; do
+
+        j=$(( $i + 1 ))
+        arg="${REMAINING_OPTS[$i]}"
+
+        case "${arg}" in
+            -C|--customer)
+                CUSTOMER="${REMAINING_OPTS[$j]}"
+                i=$(( $i + 2 ))
+                ;;
+            --tsig-key)
+                TSIG_KEY="${REMAINING_OPTS[$j]}"
+                i=$(( $i + 2 ))
+                ;;
+            *)  echo -e "Internal error - option '${RED}${arg}${NORMAL} was wrong!"
+                exit 1
+                ;;
+        esac
+
+    done
+
+    if [[ "${#REMAINING_OPTS[@]}" -gt 0 ]] ; then
+        error "Unknown options: ${REMAINING_OPTS[*]}"
+        echo >&2
+        usage >&2
+        exit 1
+    fi
+
+    if [[ "${#REMAINING_ARGS[@]}" == "0" ]] ; then
+        error "No zone files for loading into PowerDNS given."
+        echo >&2
+        usage >&2
+        exit 1
+    fi
+
+    i="0"
+    for arg in "${REMAINING_ARGS[@]}" ; do
+        if [[ "${i}" == "0" && "${arg}" == '--' ]] ; then
+            continue
+        fi
+        i=$(( $i + 1 ))
+        ZONE_FILES+=( "${arg}" )
+    done
+
+    if [[ "${#ZONE_FILES[@]}" == "0" ]] ; then
+        error "No zone files for loading into PowerDNS given."
+        echo >&2
+        usage >&2
+        exit 1
+    fi
+
+    if [[ $(id -u -n) != "root" ]] ; then
+        error "You must ${RED}be root${NORMAL} to execute this script!" >&2
+        exit 1
+    fi
+
+    local zone_file=
+    local found=y
+    for zone_file in "${ZONE_FILES[@]}" ; do
+        if [[ ! -f "${zone_file}" ]] ; then
+            error "Zone file '${RED}${zone_file}${NORMAL}' not found."
+            found=n
+        fi
+    done
+    if [[ "${found}" == 'n' ]] ; then
+        exit 1
+    fi
+
+    local cmd=
+    for cmd in pdns_control pdnsutil; do
+        if [[ -z $( type -p "${cmd}" ) ]] ; then
+            error "Command '${RED}${cmd}${NORMAL}' not found."
+            exit 5
+        fi
+    done
+
+    local pong=$( pdns_control rping | tr '[:upper:]' '[:lower:]' || true )
+    if [[ "${pong}" != 'pong' ]] ; then
+        error "The PowerDNS server service seems not to be active and running."
+        exit 2
+    fi
+
+}
+
+#------------------------------------------------------------------------------
+create_zone() {
+
+    local zone_file="$1"
+
+    local zone=$( grep -P -i '^\S+\s+\d+\s+IN\s+SOA\s' "${zone_file}" | \
+                  grep -P -o '^(\S+)' | \
+                  sed -e 's/\.*$//' )
+
+    if [[ -z "${zone}" ]] ; then
+        error "Did not found a valid SOA record in zone file '${RED}${zone_file}${NORMAL}'."
+        ERRORS=$(( $ERRORS + 1 ))
+        return
+    fi
+
+    local existing=$( pdnsutil list-zone "${zone}" 2>/dev/null || true )
+    if [[ -n "${existing}" ]] ; then
+        error "Zone '${RED}${zone}${NORMAL}' is already existing in PowerDNS."
+        ERRORS=$(( $ERRORS + 1 ))
+        return
+    fi
+
+    empty_line
+    line
+    info "Creating zone '${GREEN}${zone}${NORMAL}' from file '${CYAN}${zone_file}${NORMAL}' ..."
+    empty_line
+
+    local cmd=
+
+    cmd="pdnsutil load-zone \"${zone}\" \"${zone_file}\""
+    if [[ "${SIMULATE}" == "y" ]] ; then
+        info "Executing: ${cmd}"
+    else
+        debug "Executing: ${cmd}"
+    fi
+
+    cmd="pdnsutil set-account \"${zone}\" \"${CUSTOMER}\""
+    if [[ "${SIMULATE}" == "y" ]] ; then
+        info "Executing: ${cmd}"
+    else
+        debug "Executing: ${cmd}"
+    fi
+
+    cmd="pdnsutil set-kind \"${zone}\" \"master\""
+    if [[ "${SIMULATE}" == "y" ]] ; then
+        info "Executing: ${cmd}"
+    else
+        debug "Executing: ${cmd}"
+    fi
+
+    cmd="pdnsutil set-meta \"${zone}\" \"SOA-EDIT-API\" \"DEFAULT\""
+    if [[ "${SIMULATE}" == "y" ]] ; then
+        info "Executing: ${cmd}"
+    else
+        debug "Executing: ${cmd}"
+    fi
+
+    cmd="pdnsutil set-meta \"${zone}\" \"TSIG-ALLOW-AXFR\" \"${TSIG_KEY}\""
+    if [[ "${SIMULATE}" == "y" ]] ; then
+        info "Executing: ${cmd}"
+    else
+        debug "Executing: ${cmd}"
+    fi
+
+}
+
+################################################################################
+##
+## Main
+##
+################################################################################
+
+#------------------------------------------------------------------------------
+main() {
+
+    get_options "$@"
+
+    set_locale 'en_US.utf8'
+
+    local zone_file=
+    for zone_file in "${ZONE_FILES[@]}" ; do
+        create_zone "${zone_file}"
+    done
+
+    empty_line
+    info "Finished."
+
+}
+
+main "$@"
+
+if [[ "${ERRORS}" != "0" ]] ; then
+    exit 6
+fi
+exit 0
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list