From d559b903d5a02e360f6faa467e743c80e37d9038 Mon Sep 17 00:00:00 2001 From: B Stack Date: Sat, 27 May 2017 15:33:04 -0400 Subject: initial commit --- usr/share/updatezone/docs/README.txt | 20 ++ usr/share/updatezone/docs/files-for-versioning.txt | 3 + usr/share/updatezone/docs/packaging.txt | 1 + usr/share/updatezone/docs/updatezone.spec | 56 ++++ .../examples/ipa.smith122.com.conf.example | 7 + usr/share/updatezone/inc/get-files | 40 +++ usr/share/updatezone/inc/pack | 116 ++++++++ usr/share/updatezone/updatezone.sh | 327 +++++++++++++++++++++ 8 files changed, 570 insertions(+) create mode 100644 usr/share/updatezone/docs/README.txt create mode 100644 usr/share/updatezone/docs/files-for-versioning.txt create mode 100644 usr/share/updatezone/docs/packaging.txt create mode 100644 usr/share/updatezone/docs/updatezone.spec create mode 100644 usr/share/updatezone/examples/ipa.smith122.com.conf.example create mode 100755 usr/share/updatezone/inc/get-files create mode 100755 usr/share/updatezone/inc/pack create mode 100755 usr/share/updatezone/updatezone.sh (limited to 'usr') diff --git a/usr/share/updatezone/docs/README.txt b/usr/share/updatezone/docs/README.txt new file mode 100644 index 0000000..0e9ac28 --- /dev/null +++ b/usr/share/updatezone/docs/README.txt @@ -0,0 +1,20 @@ +File: usr/share/updatezone/docs/README.txt +Package: updatezone +Author: bgstack15 +Startdate: 2017-05-26 +Title: Readme file for updatezone +Purpose: All packages should come with a readme +Usage: Read it. +Reference: README.txt +Improve: +Document: Below this line + +### WELCOME + +### NOTES + +### REFERENCE + +### CHANGELOG +2017-05-26 B Stack 0.0-1 +- Initial package construction diff --git a/usr/share/updatezone/docs/files-for-versioning.txt b/usr/share/updatezone/docs/files-for-versioning.txt new file mode 100644 index 0000000..c08c65a --- /dev/null +++ b/usr/share/updatezone/docs/files-for-versioning.txt @@ -0,0 +1,3 @@ +docs/README.txt +docs/updatezone.spec +docs/debian-updatezone/control diff --git a/usr/share/updatezone/docs/packaging.txt b/usr/share/updatezone/docs/packaging.txt new file mode 100644 index 0000000..beb1ccb --- /dev/null +++ b/usr/share/updatezone/docs/packaging.txt @@ -0,0 +1 @@ +delete this file please. diff --git a/usr/share/updatezone/docs/updatezone.spec b/usr/share/updatezone/docs/updatezone.spec new file mode 100644 index 0000000..4907d10 --- /dev/null +++ b/usr/share/updatezone/docs/updatezone.spec @@ -0,0 +1,56 @@ +# ref: http://www.rpm.org/max-rpm/s1-rpm-build-creating-spec-file.html +Summary: update dns zone files easily +Name: updatezone +Version: 0.0 +Release: 1 +License: CC BY-SA 4.0 +Group: Applications/System +Source: updatezone.tgz +URL: https://bgstack15.wordpress.com/ +#Distribution: +#Vendor: +Packager: B Stack +Requires: bgscripts >= 1.2-11 +Buildarch: noarch + +%description +updatezone provides updatezone.sh which takes a simple config file for selecting the dns zone files to edit. Bind is the only supported dns server right now, but experimentation is encouraged. + +#%global _python_bytecompile_errors_terminate_build 0 + +%prep +%setup + +%build + +%install +rm -rf %{buildroot} +rsync -a . %{buildroot}/ --exclude='**/.*.swp' --exclude='**/.git' + +%post +exit 0 + +%preun +exit 0 + +%postun +exit 0 + +%files +%dir /etc/updatezone +%dir /usr/share/updatezone +%dir /usr/share/updatezone/inc +%dir /usr/share/updatezone/examples +%dir /usr/share/updatezone/docs +/usr/share/updatezone/inc/pack +/usr/share/updatezone/inc/get-files +%config %attr(666, -, -) /usr/share/updatezone/examples/ipa.smith122.com.conf.example +%doc %attr(444, -, -) /usr/share/updatezone/docs/files-for-versioning.txt +%doc %attr(444, -, -) /usr/share/updatezone/docs/packaging.txt +%doc %attr(444, -, -) /usr/share/updatezone/docs/README.txt +/usr/share/updatezone/docs/updatezone.spec +/usr/share/updatezone/updatezone.sh + +%changelog +* Fri May 26 2017 B Stack 0.0-1 +- Initial rpm release diff --git a/usr/share/updatezone/examples/ipa.smith122.com.conf.example b/usr/share/updatezone/examples/ipa.smith122.com.conf.example new file mode 100644 index 0000000..9f74dd8 --- /dev/null +++ b/usr/share/updatezone/examples/ipa.smith122.com.conf.example @@ -0,0 +1,7 @@ +UZ_ZONE_NAME=ipa.smith122.com +UZ_FORWARD_ZONE=ipa.smith122.com +UZ_FORWARD_FILE=/var/named/data/db.ipa.smith122.com +UZ_REVERSE_ZONE=1.168.192.in-addr.arpa +UZ_REVERSE_FILE=/var/named/data/db.192.168.1 +UZ_SLAVE_COUNT=1 +UZ_SLAVE_1=dns2 diff --git a/usr/share/updatezone/inc/get-files b/usr/share/updatezone/inc/get-files new file mode 100755 index 0000000..fd3e45a --- /dev/null +++ b/usr/share/updatezone/inc/get-files @@ -0,0 +1,40 @@ +#!/bin/sh +# File: get-files +case "${1}" in + rpm) +if test -n "${package}"; then cd ${rpmbuilddir}/SOURCES/"${package}-${version}"; else cd $( pwd | sed -r -e 's/(SOURCES\/[^\/]+\/).*/\1/;' ); fi + +### for rpm +find * -type d -regextype grep \ + \( -regex 'usr\/share\/updatezone.*' -o -regex 'etc\/updatezone.*' \) \ + ! -regex '.*gui.*' \ + | sed -e 's/^/%dir \//;' +find * -mindepth 1 ! -name "${package}.spec.$$.swp" \ + ! -type d -regextype grep \ + ! -regex '.*.swp' \ + ! -regex '.*DEBIAN.*' \ + | sed -r -e ' +s/^/\//; +s/(.*\.txt)/%doc %attr(444, -, -) \1/; +s/(.*bin.*)/%verify(link) \1/; +s/(.*)\.py$/\1\.py\n\1\.pyc\n\1\.pyo/; +s/(.*\.conf)/%config %attr(666, -, -) \1/; +s/(\/usr)?\/lib\/systemd\/system\/(.*)/%{_unitdir}\/\2/; +' + + ;; + deb) + +### for deb +find . -mindepth 1 ! -name "${package}.spec\.$$\.swp" \ + ! -type d -regextype grep \ + ! -regex '.*hg.*' ! -regex '.*?debian-binary.*' \ + ! -regex '.*DEBIAN.*' ! -regex '.*\.swp' ! -regex '.*\.git.*' ! -name 'README.md' \ + -printf '%P ' + + ;; + *) + echo "FATAL ERROR: check ./pack or get-files-core. Please use [ rpm | deb ] option. Aborted." 1>&2 + exit 1 + ;; +esac diff --git a/usr/share/updatezone/inc/pack b/usr/share/updatezone/inc/pack new file mode 100755 index 0000000..6c5d72f --- /dev/null +++ b/usr/share/updatezone/inc/pack @@ -0,0 +1,116 @@ +#!/bin/bash + +# DETERMINE LOCATION OF FRAMEWORK +while read flocation; do if test -x ${flocation} && test "$( ${flocation} --fcheck )" -ge 20170111; then frameworkscript="${flocation}"; break; fi; done <&2 && exit 4 + +. ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2 + +type=""; + +case "${thisflavor}" in + redhat|rhel|centos|fedora|korora) type=rpm;; + debian|ubuntu) type=dpkg;; + *) type=targz;; +esac + +echo " $@ " | grep -qiE -- "help|usage|\s-h\s|\s-\?" 1>/dev/null 2>&1 && { + # display help and exit + less -F </dev/null 2>&1 && type=rpm +echo " $@ " | grep -qiE -- "debian|ubuntu|deb\s|dpkg" 1>/dev/null 2>&1 && type=dpkg +echo " $@ " | grep -qiE -- "tar|tgz|gz" 1>/dev/null 2>&1 && type=targz +echo " $@ " | grep -qiE -- "scrub" 1>/dev/null 2>&1 && type=scrub + +# Display information +echo "packaging ${package}-${version} as ${type}" +echo " $@ " | grep -qiE -- "debug|\s-d[ 0-9]{0,3}\s" 1>/dev/null 2>&1 && exit 0 + +case "${type}" in + rpm) + +########## PACKAGING for rhel/centos +# if you copy-paste this, be sure to define package, version, shortversion +rpmbuilddir=~/rpmbuild/ +packagespecfile="${package}-${version}/usr/share/${package}/docs/${package}.spec" +sed -n -e '1,/^\%files$/p;' "${rpmbuilddir}/SOURCES/${packagespecfile}" > "${rpmbuilddir}/SOURCES/${packagespecfile}.$$.swp" # removes files and changelog +cd ${rpmbuilddir}/SOURCES/"${package}-${version}" +"${rpmbuilddir}/SOURCES/${package}-${version}/usr/share/${package}/inc/get-files" rpm >> "${rpmbuilddir}/SOURCES/${packagespecfile}.$$.swp" +{ printf '\n'; sed -n -e '/^\%changelog/,$p' "${rpmbuilddir}/SOURCES/${packagespecfile}"; } >> "${rpmbuilddir}/SOURCES/${packagespecfile}.$$.swp" +mv -f "${rpmbuilddir}/SOURCES/${packagespecfile}.$$.swp" "${rpmbuilddir}/SOURCES/${packagespecfile}" +rm -rf "${rpmbuilddir}/SOURCES/${package}-${shortversion}"; cp -prf "${rpmbuilddir}/SOURCES/${package}-${version}" "${rpmbuilddir}/SOURCES/${package}-${shortversion}" +rm -rf "${rpmbuilddir}/SOURCES/${package}-${shortversion}/DEBIAN" +cd "${rpmbuilddir}/SOURCES" +rm -rf "${package}.tgz"; tar -zc --exclude='.git*' --exclude='README.md' -f "${package}.tgz" "${package}-${shortversion}" +cp -p "${rpmbuilddir}/SOURCES/${packagespecfile}" "${rpmbuilddir}/SPECS" +mkdir -p "${rpmbuilddir}/RPMS/noarch"; cd "${rpmbuilddir}/RPMS/noarch" +rpmbuild -bb "${rpmbuilddir}/SPECS/${package}.spec" +rm -rf "${rpmbuilddir}/SOURCES/${package}-${shortversion}/" "${rpmbuilddir}/SOURCES/${package}.tgz" + + ;; + dpkg) + +########## PACKAGING for ubuntu +# You need package dpkg-dev to build packages. +# if you copy-paste this, be sure to define package, version +debdir=~/deb +debiandirmain="${package}-${version}/usr/share/${package}/docs/debian-${package}" +cd "${debdir}/${package}-${version}" +"${debdir}/${package}-${version}/usr/share/${package}/inc/get-files" deb | xargs md5sum > "${debdir}/${debiandirmain}/md5sums" +#mkdir -p "${debdir}/$$"; mv "${debdir}/${package}-${version}/.git" "${debdir}/${package}-${version}/README.md" "${debdir}/$$/" +cd "${debdir}" + +# main +rm -rf "${debdir}/${package}-${version}/DEBIAN/" 2>/dev/null; mkdir -p "${debdir}/${package}-${version}/DEBIAN/" +cp -pf "${debdir}/${debiandirmain}"/* "${debdir}/${package}-${version}/DEBIAN/" +mkdir "${debdir}/${package}" 2>/dev/null; rm -rf "${debdir}/${package}-${version}-work.tgz" +tar -zc --exclude='.git*' --exclude='README.md' -f "${debdir}/${package}-${version}-work.tgz" -C "${debdir}/${package}-${version}" $( awk '{print $2}' "${debdir}/${package}-${version}/DEBIAN/md5sums" ) DEBIAN +tar -zx -C "${debdir}/${package}" -f "${debdir}/${package}-${version}-work.tgz" +fakeroot dpkg-deb -b "${debdir}/${package}" +mv -f "${debdir}/${package}.deb" "${debdir}/${package}-${version}.deb" +rm -rf "${debdir}/${package}-${version}-work.tgz" "${debdir}/${package}" + +#mv "${debdir}/$$/.git" "${debdir}/$$/"* "${debdir}/${package}-${version}/"; rmdir "${debdir}/$$" + + ;; + targz) + +########## PACKAGING in a master.tgz +# if you copy-paste this, be sure to define package, version +cd ~/deb 2>/dev/null || cd ~/rpmbuild/SOURCES +rm -rf ./"${package}-${version}".master.tgz +tar -zcf "${package}-${version}".master.tgz "${package}-${version}"/ + + ;; + scrub) + +########## SCRUB for publication +# if you copy-paste this, be sure to define package, version +cd ~/deb 2>/dev/null || cd ~/rpmbuild/SOURCES +cd "$( find . -name "*scrub.txt" | grep -iE "${package}-${version}\/" | xargs dirname )" +/usr/share/bgscripts/scrub.py + + ;; + unknown) + echo "error: check $0 for errors on type ${type}." 1>&2 + ;; +esac diff --git a/usr/share/updatezone/updatezone.sh b/usr/share/updatezone/updatezone.sh new file mode 100755 index 0000000..40e644a --- /dev/null +++ b/usr/share/updatezone/updatezone.sh @@ -0,0 +1,327 @@ +#!/bin/sh +# Filename: updatezone.sh +# Location: +# Author: bgstack15@gmail.com +# Startdate: 2017-05-26 07:02:47 +# Title: Script that Updates a DNS Zone +# Purpose: Provides a single command to update dns zones +# Package: updatezone +# History: +# Usage: +# Primarily intended for updating forward and reverse zones for bind9. +# Reference: ftemplate.sh 2017-05-24a; framework.sh 2017-05-24a +# Improve: +# Dependencies: +# rndc +# ssh with password-less authentication to slave servers +# each zone file has only a single zone +fiversion="2017-05-24a" +updatezoneversion="2017-05-27a" + +usage() { + less -F >&2 <> "${zones_to_thaw_file}" + + # prepare temp file + cp -p "${zone_real_file}" "${zone_temp_file}" + fi + fi +} + +zone_action() { + # call: zone_action ${forwardzone} + debuglev 9 && ferror "zone_action $@" + local action="$1" + local zone="$2" + case "${action}" in + freeze|thaw) + rndc "${action}" "${zone}" 2>&1 | grep -viE "a zone reload and thaw|Check the logs to see" + ;; + *) + ferror "${scriptfile} minor error: ignoring unknown zone_action $@" + ;; + esac +} + +update_real_zone_if_updated() { + # call: update_real_zone_if_updated "${UZ_REVERSE_ZONE}" "${UZ_REVERSE_FILE}" "${temp_rev_file}" + debuglev 9 && ferror "update_real_zone_if_updated $@" + local zone_name="$1" + local zone_real_file="$2" + local zone_temp_file="$3" + if test -n "${zone_temp_file}" && test -f "${zone_temp_file}"; + then + if ! cmp -s "${zone_real_file}" "${zone_temp_file}"; + then + # a change occurred, so increment the serial number and replace the original zone file + increment_serial_in_zone_file "${zone_temp_file}" + cat "${zone_temp_file}" > "${zone_real_file}" + + # plan to notify the dns slaves + echo "${zone_name}" >> "${zones_to_update_file}" + fi + fi + + # If the temp file does not exist, it was deleted because the real file was invalid for whatever reason. +} + +increment_serial_in_zone_file() { + # call: increment_serial_in_zone_file "${zone_temp_file}" + # dependencies: a single zone in the zone file, with the ";serial" comment after the number. + debuglev 9 && ferror "increment_serial_in_zone_file $@" + local infile="$1" + currentnum="$( grep -iE "[0-9]+\s*;\s*serial" "${infile}" | grep -oIE "[0-9]+" )" + nextnum=$(( currentnum + 1 )) + sed -i -r -e "s/${currentnum}(\s*;\s*serial)/${nextnum}\1/" "${infile}" +} + +# DEFINE TRAPS + +clean_updatezone() { + rm -rf ${tempdir} > /dev/null 2>&1 + [ ] #use at end of entire script if you need to clean up tmpfiles +} + +CTRLC() { + #trap "CTRLC" 2 + [ ] #useful for controlling the ctrl+c keystroke + exit 0 +} + +CTRLZ() { + #trap "CTRLZ" 18 + [ ] #useful for controlling the ctrl+z keystroke +} + +parseFlag() { + flag="$1" + hasval=0 + case ${flag} in + # INSERT FLAGS HERE + "d" | "debug" | "DEBUG" | "dd" ) setdebug; ferror "debug level ${debug}";; + "u" | "usage" | "help" | "h" ) usage; exit 1;; + "V" | "fcheck" | "version" ) ferror "${scriptfile} version ${updatezoneversion}"; exit 1;; + #"i" | "infile" | "inputfile" ) getval;infile1=${tempval};; + "c" | "conf" | "config" | "conffile" ) getval;conffile=${tempval};; + esac + + debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}"; } +} + +# DETERMINE LOCATION OF FRAMEWORK +while read flocation; do if test -x ${flocation} && test "$( ${flocation} --fcheck )" -ge 20170524; then frameworkscript="${flocation}"; break; fi; done <&2 && exit 4 + +# INITIALIZE VARIABLES +# variables set in framework: +# today server thistty scriptdir scriptfile scripttrim +# is_cronjob stdin_piped stdout_piped stderr_piped sendsh sendopts +. ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2 +infile1= +outfile1= +logfile=${scriptdir}/${scripttrim}.${today}.out +define_if_new interestedparties "bgstack15@gmail.com" +# SIMPLECONF +define_if_new default_conffile "/etc/updatezone/updatezone.conf" +#define_if_new defuser_conffile ~/.config/updatezone/updatezone.conf +define_if_new EDITOR vi + +# REACT TO OPERATING SYSTEM TYPE +case $( uname -s ) in + Linux) [ ];; + FreeBSD) [ ];; + *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 3;; +esac + +## REACT TO ROOT STATUS +#case ${is_root} in +# 1) # proper root +# [ ] ;; +# sudo) # sudo to root +# [ ] ;; +# "") # not root at all +# #ferror "${scriptfile}: 5. Please run as root or sudo. Aborted." +# #exit 5 +# [ ] +# ;; +#esac + +# VALIDATE PARAMETERS +# objects before the dash are options, which get filled with the optvals +# to debug flags, use option DEBUG. Variables set in framework: fallopts +validateparams - "$@" + +# CONFIGURE VARIABLES AFTER PARAMETERS + +## LOAD CONFIG FROM SIMPLECONF +## This section follows a simple hierarchy of precedence, with first being used: +## 1. parameters and flags +## 2. environment +## 3. config file +## 4. default user config: ~/.config/script/script.conf +## 5. default config: /etc/script/script.conf +if test -f "${conffile}"; +then + get_conf "${conffile}" +else + if test "${conffile}" = "${default_conffile}" || test "${conffile}" = "${defuser_conffile}"; then :; else ferror "${scriptfile}: Ignoring conf file which is not found: ${conffile}."; fi +fi +#test -f "${defuser_conffile}" && get_conf "${defuser_conffile}" +test -f "${default_conffile}" && get_conf "${default_conffile}" + +## REACT TO BEING A CRONJOB +#if test ${is_cronjob} -eq 1; +#then +# [ ] +#else +# [ ] +#fi + +# SET TRAPS +trap "CTRLC" 2 +#trap "CTRLZ" 18 +trap "clean_updatezone" 0 + +# DEBUG SIMPLECONF +debuglev 5 && { + ferror "Using values" + # used values: EX_(OPT1|OPT2|VERBOSE) + set | grep -iE "^UZ_" 1>&2 +} + +# MAKE TEMP LOCATIONS +tempdir=/tmp/updatezone/ +if ! mkdir -p "${tempdir}"; +then + ferror "${scriptfile}: 4. Unable to make temp directory ${tempdir}. Aborted." + exit 4 +fi + +temp_for_file="$( mktemp -p "${tempdir}" forward.XXXX 2>/dev/null )" +temp_rev_file="$( mktemp -p "${tempdir}" reverse.XXXX 2>/dev/null )" +zones_to_thaw_file="$( mktemp -p "${tempdir}" thaw.XXXX )" +zones_to_update_file="$( mktemp -p "${tempdir}" update.XXXX )" +for word in "${temp_for_file}" "${temp_rev_file}"; +do + if test ! -f "${word}"; + then + ferror "${scriptfile}: 4. Unable to make temp file ${word}. Aborted." + exit 4 + fi +done + +# MAIN LOOP +#{ + pause_to_show_error=0 + # Check forward zone file and freeze + check_zone_file forward "${UZ_FORWARD_ZONE}" "${UZ_FORWARD_FILE}" "${temp_for_file}" + + # Check reverse zone file and freeze + check_zone_file reverse "${UZ_REVERSE_ZONE}" "${UZ_REVERSE_FILE}" "${temp_rev_file}" + + # Slow down to show errors if any + fistruthy "${pause_to_show_error}" && sleep 1.3 + + # Allow user to edit files that exist + $EDITOR $( find "${temp_for_file}" "${temp_rev_file}" 2>/dev/null | xargs ) + + # Update the real zone if the temp file was updated + update_real_zone_if_updated "${UZ_FORWARD_ZONE}" "${UZ_FORWARD_FILE}" "${temp_for_file}" + update_real_zone_if_updated "${UZ_REVERSE_ZONE}" "${UZ_REVERSE_FILE}" "${temp_rev_file}" + # Thaw zones that need it + while read thiszone; + do + zone_action thaw "${thiszone}" + done < "${zones_to_thaw_file}" + + # Transfer zones that need it + # This section exists because my automatic zone transfers/updates do not work. + + # Build list of commands to run on each dns slave server + transfercommand="" + while read thiszone; + do + transfercommand="${transfercommand}rndc retransfer ${thiszone}; " + done < "${zones_to_update_file}" + + # Execute command on each slave server + x=0 + while test ${x} -lt ${UZ_SLAVE_COUNT}; + do + x=$(( x + 1 )) + eval this_dns_slave=\"\${UZ_SLAVE_${x}}\" + debuglev 5 && ferror "ssh ${this_dns_slave} ${transfercommand}" + ssh ${this_dns_slave} ${transfercommand} + done + +#} | tee -a ${logfile} + +# EMAIL LOGFILE +#${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties} + +## STOP THE READ CONFIG FILE +#exit 0 +#fi; done; } -- cgit