]> git.sven.stormbind.net Git - sven/scripts.git/blob - stormbind/dkim/dkim-key-rotation.sh
first take on dkim update script
[sven/scripts.git] / stormbind / dkim / dkim-key-rotation.sh
1 #!/bin/bash
2 # helper script to update dkim keys in bind9 and dkimpy-milter
3
4 DOMAINS="stormbind.net raspe-box.de fusspflege-rita.de honig-aus-schlebusch.de"
5 KEYFOLDER="/etc/dkimpy-milter/keys"
6 CURKEYFILE="${KEYFOLDER}/curkey"
7 OLDKEYFILE="${KEYFOLDER}/oldkey"
8 SIGNTABLE="/etc/dkimpy-milter/signtable"
9 KEYTABLE="/etc/dkimpy-milter/keytable"
10 ZONEDIR="/etc/bind/zones"
11 ZONEFILE="${ZONEDIR}/dkim.inc"
12
13 # generate a bind9 compatible TXT record based on the dkimpy generated .dns file
14 function genTXTrecord {
15     local keyname="$1"
16     local key="$2"
17     echo "${keyname}._domainkey IN TXT ( "
18     echo "${key}" | \
19         fold | \
20         sed -e 's/^/"/' -e 's/$/"/'
21     echo ") ;"
22 }
23
24 # ensure keyfolder exist
25 test -d "${KEYFOLDER}" || mkdir "${KEYFOLDER}"
26
27 # get current key name
28 if [ -f ${CURKEYFILE} ]; then
29     CURKEY="$(cat ${CURKEYFILE})"
30 else
31     # if there is no current key we still have to initialize the variable
32     echo "W: No current keyfile found - looked for ${CURKEYFILE}"
33     CURKEY=""
34 fi
35
36 # check for old key file name
37 if [ -f ${OLDKEYFILE} ]; then
38     OLDKEY="$(cat ${OLDKEYFILE})"
39 else
40     echo "W: No old keyfile found - looked for ${OLDKEYFILE}"
41     OLDKEY=""
42 fi
43
44 # make our execution idempotent and do not regenerate keys all the time
45 # check if the NEWKEY value differs by less than 7 - a week
46 NEWKEY="s$(date +%Y%m%d)"
47 if [[ $(( ${CURKEY#s} + 7 )) -le ${NEWKEY#s} ]]; then
48     # full blown invocation when we have a current and old key
49     DELETEKEY="${OLDKEY}"
50     OLDKEY="${CURKEY}"
51     echo "I: generating new keys with the name of ${NEWKEY} in folder ${KEYFOLDER}"
52     cd "${KEYFOLDER}" && dknewkey --ktype rsa "${NEWKEY}"
53     cd -
54 else
55     NEWKEY="${CURKEY}"
56     echo "W: NEWKEY date ${NEWKEY#s} is less than 7 days before OLDKEY ${OLDKEY#s}"
57     echo "W: No new key generated"
58 fi
59
60 # generate bind dkim include with pub key
61 echo "I: writing DNS pubkey include"
62 genTXTrecord "${NEWKEY}" "$(cat ${KEYFOLDER}/${NEWKEY}.dns)" > "${ZONEFILE}"
63 if [ -n "${OLDKEY}" ]; then
64     genTXTrecord "${OLDKEY}" "$(cat ${KEYFOLDER}/${OLDKEY}.dns)" >> "${ZONEFILE}"
65 fi
66
67 # recreate dkimpy-milter tables
68 > ${KEYTABLE}
69 > ${SIGNTABLE}
70 for x in ${DOMAINS}; do
71     echo "*@${x} ${x%.*}" >> ${SIGNTABLE}
72     echo "${x%.*} ${x}:${NEWKEY}:${KEYFOLDER}/${NEWKEY}.key" >> ${KEYTABLE}
73 done
74
75 # update state files
76 echo "${NEWKEY}" > "${CURKEYFILE}"
77 echo "${OLDKEY}" > "${OLDKEYFILE}"
78
79 # clean up prior old key
80 if [ -n "${DELETEKEY}" ]; then
81     rm "${KEYFOLDER}/${DELETEKEY}".{key,dns}
82 fi
83
84 # update zone timestamps, verify zone
85 for x in ${DOMAINS}; do
86     SERIAL="$(sed -n '3p' ${x} | grep -Eo '[0-9]+')"
87     let SERIAL++
88     sed -i -re "3s/[0-9]{10}/${SERIAL}/" "${ZONEDIR}/${x}"
89     named-checkzone "${x}" "${ZONEDIR}/${x}" || \
90         ( echo "E: could not validate zone ${x} - exiting"; exit 23; )
91 done
92
93 # store changes in etckeeper
94 etckeeper commit "automatic commit by dkim key update script called as $0"
95
96 # restart dkimpy-milter and reload bind9
97 systemctl reload named.service && \
98     systemctl reload dkimpy-milter.service