root / doc / examples / hooks / ipsec.in @ f7b769b1
History | View | Annotate | Download (7.4 kB)
1 | d1e95dde | Luca Bigliardi | #!/bin/bash |
---|---|---|---|
2 | d1e95dde | Luca Bigliardi | |
3 | d1e95dde | Luca Bigliardi | # Copyright (C) 2009 Google Inc. |
4 | d1e95dde | Luca Bigliardi | # |
5 | d1e95dde | Luca Bigliardi | # This program is free software; you can redistribute it and/or modify |
6 | d1e95dde | Luca Bigliardi | # it under the terms of the GNU General Public License as published by |
7 | d1e95dde | Luca Bigliardi | # the Free Software Foundation; either version 2 of the License, or |
8 | d1e95dde | Luca Bigliardi | # (at your option) any later version. |
9 | d1e95dde | Luca Bigliardi | # |
10 | d1e95dde | Luca Bigliardi | # This program is distributed in the hope that it will be useful, but |
11 | d1e95dde | Luca Bigliardi | # WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | d1e95dde | Luca Bigliardi | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | d1e95dde | Luca Bigliardi | # General Public License for more details. |
14 | d1e95dde | Luca Bigliardi | # |
15 | d1e95dde | Luca Bigliardi | # You should have received a copy of the GNU General Public License |
16 | d1e95dde | Luca Bigliardi | # along with this program; if not, write to the Free Software |
17 | d1e95dde | Luca Bigliardi | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | d1e95dde | Luca Bigliardi | # 02110-1301, USA. |
19 | d1e95dde | Luca Bigliardi | |
20 | d1e95dde | Luca Bigliardi | |
21 | d1e95dde | Luca Bigliardi | # This is an example ganeti hook that sets up an IPsec ESP link between all the |
22 | d1e95dde | Luca Bigliardi | # nodes of a cluster for a given list of protocols. |
23 | d1e95dde | Luca Bigliardi | |
24 | d1e95dde | Luca Bigliardi | # When run on cluster initialization it will create the shared key to be used |
25 | d1e95dde | Luca Bigliardi | # for all the links. When run on node add/removal it will reconfigure IPsec |
26 | d1e95dde | Luca Bigliardi | # on each node of the cluster. |
27 | d1e95dde | Luca Bigliardi | |
28 | d1e95dde | Luca Bigliardi | set -e |
29 | d1e95dde | Luca Bigliardi | |
30 | d1e95dde | Luca Bigliardi | LOCALSTATEDIR=@LOCALSTATEDIR@ |
31 | d1e95dde | Luca Bigliardi | SYSCONFDIR=@SYSCONFDIR@ |
32 | d1e95dde | Luca Bigliardi | |
33 | d1e95dde | Luca Bigliardi | GNTDATA=${LOCALSTATEDIR}/lib/ganeti |
34 | d1e95dde | Luca Bigliardi | |
35 | d1e95dde | Luca Bigliardi | LOCKFILE=${LOCALSTATEDIR}/lock/ganeti_ipsec |
36 | d1e95dde | Luca Bigliardi | CRYPTALGO=rijndael-cbc |
37 | d1e95dde | Luca Bigliardi | KEYPATH=${GNTDATA}/ipsec.key |
38 | d1e95dde | Luca Bigliardi | KEYSIZE=24 |
39 | d1e95dde | Luca Bigliardi | PROTOSTOSEC="icmp tcp" |
40 | d1e95dde | Luca Bigliardi | TCPTOIGNORE="22 1811" |
41 | d1e95dde | Luca Bigliardi | # On debian/ubuntu this file is automatically reloaded on boot |
42 | d1e95dde | Luca Bigliardi | SETKEYCONF=${SYSCONFDIR}/ipsec-tools.conf |
43 | d1e95dde | Luca Bigliardi | SETKEYCUSTOMCONF=${SYSCONFDIR}/ipsec-tools-custom.conf |
44 | d1e95dde | Luca Bigliardi | AUTOMATIC_MARKER="# Automatically generated rules" |
45 | d1e95dde | Luca Bigliardi | REGEN_KEY_WAIT=2 |
46 | d1e95dde | Luca Bigliardi | |
47 | d1e95dde | Luca Bigliardi | NODES=${GNTDATA}/ssconf_node_secondary_ips |
48 | d1e95dde | Luca Bigliardi | MASTERNAME_FILE=${GNTDATA}/ssconf_master_node |
49 | d1e95dde | Luca Bigliardi | MASTERIP_FILE=${GNTDATA}/ssconf_master_ip |
50 | d1e95dde | Luca Bigliardi | |
51 | d1e95dde | Luca Bigliardi | SSHOPTS="-q -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no \ |
52 | d1e95dde | Luca Bigliardi | -oGlobalKnownHostsFile=${GNTDATA}/known_hosts" |
53 | d1e95dde | Luca Bigliardi | SCPOPTS="-p $SSHOPTS" |
54 | d1e95dde | Luca Bigliardi | |
55 | d1e95dde | Luca Bigliardi | CLEANUP=( ) |
56 | d1e95dde | Luca Bigliardi | |
57 | d1e95dde | Luca Bigliardi | cleanup() { |
58 | d1e95dde | Luca Bigliardi | # Perform all registered cleanup operation |
59 | d1e95dde | Luca Bigliardi | local i |
60 | d1e95dde | Luca Bigliardi | for (( i=${#CLEANUP[@]}; i >= 0 ; --i )); do |
61 | d1e95dde | Luca Bigliardi | ${CLEANUP[$i]} |
62 | d1e95dde | Luca Bigliardi | done |
63 | d1e95dde | Luca Bigliardi | } |
64 | d1e95dde | Luca Bigliardi | |
65 | d1e95dde | Luca Bigliardi | acquire_lockfile() { |
66 | d1e95dde | Luca Bigliardi | # Acquire the lockfile associated with system ipsec configuration. |
67 | d1e95dde | Luca Bigliardi | lockfile-create "$LOCKFILE" || exit 1 |
68 | d1e95dde | Luca Bigliardi | CLEANUP+=("lockfile-remove $LOCKFILE") |
69 | d1e95dde | Luca Bigliardi | } |
70 | d1e95dde | Luca Bigliardi | |
71 | d1e95dde | Luca Bigliardi | update_system_ipsec() { |
72 | d1e95dde | Luca Bigliardi | # Update system ipsec configuration. |
73 | d1e95dde | Luca Bigliardi | # $1 : temporary location of a working configuration |
74 | d1e95dde | Luca Bigliardi | local TMPCONF="$1" |
75 | d1e95dde | Luca Bigliardi | acquire_lockfile |
76 | d1e95dde | Luca Bigliardi | mv "$TMPCONF" "$SETKEYCONF" |
77 | d1e95dde | Luca Bigliardi | setkey -f "$SETKEYCONF" |
78 | d1e95dde | Luca Bigliardi | } |
79 | d1e95dde | Luca Bigliardi | |
80 | d1e95dde | Luca Bigliardi | update_keyfile() { |
81 | d1e95dde | Luca Bigliardi | # Obtain the IPsec keyfile from the master. |
82 | d1e95dde | Luca Bigliardi | local MASTERIP=$(< "$MASTERIP_FILE") |
83 | d1e95dde | Luca Bigliardi | scp $SCPOPTS "$MASTERIP":"$KEYPATH" "$KEYPATH" |
84 | d1e95dde | Luca Bigliardi | } |
85 | d1e95dde | Luca Bigliardi | |
86 | d1e95dde | Luca Bigliardi | gather_key() { |
87 | d1e95dde | Luca Bigliardi | # Output IPsec key, if no key is present on the node |
88 | d1e95dde | Luca Bigliardi | # obtain it from master. |
89 | d1e95dde | Luca Bigliardi | if [[ ! -f "$KEYPATH" ]]; then |
90 | d1e95dde | Luca Bigliardi | update_keyfile |
91 | d1e95dde | Luca Bigliardi | fi |
92 | d1e95dde | Luca Bigliardi | cut -d ' ' -f2 "$KEYPATH" |
93 | d1e95dde | Luca Bigliardi | } |
94 | d1e95dde | Luca Bigliardi | |
95 | d1e95dde | Luca Bigliardi | gather_key_seqno() { |
96 | d1e95dde | Luca Bigliardi | # Output IPsec key sequence number, if no key is present |
97 | d1e95dde | Luca Bigliardi | # on the node exit with error. |
98 | d1e95dde | Luca Bigliardi | if [[ ! -f "$KEYPATH" ]]; then |
99 | d1e95dde | Luca Bigliardi | echo 'Cannot obtain key timestamp, no key file.' >&2 |
100 | d1e95dde | Luca Bigliardi | exit 1 |
101 | d1e95dde | Luca Bigliardi | fi |
102 | d1e95dde | Luca Bigliardi | cut -d ' ' -f1 "$KEYPATH" |
103 | d1e95dde | Luca Bigliardi | } |
104 | d1e95dde | Luca Bigliardi | |
105 | d1e95dde | Luca Bigliardi | update_ipsec_conf() { |
106 | d1e95dde | Luca Bigliardi | # Generate a new IPsec configuration and update the system. |
107 | d1e95dde | Luca Bigliardi | local TMPCONF=$(mktemp) |
108 | d1e95dde | Luca Bigliardi | CLEANUP+=("rm -f $TMPCONF") |
109 | d1e95dde | Luca Bigliardi | ESCAPED_HOSTNAME=$(sed 's/\./\\./g' <<< "$HOSTNAME") |
110 | d1e95dde | Luca Bigliardi | local MYADDR=$(grep -E "^$ESCAPED_HOSTNAME\\>" "$NODES" | cut -d ' ' -f2) |
111 | d1e95dde | Luca Bigliardi | local KEY=$(gather_key) |
112 | d1e95dde | Luca Bigliardi | local SETKEYPATH=$(which setkey) |
113 | d1e95dde | Luca Bigliardi | |
114 | d1e95dde | Luca Bigliardi | { |
115 | d1e95dde | Luca Bigliardi | echo "#!$SETKEYPATH -f" |
116 | d1e95dde | Luca Bigliardi | echo |
117 | d1e95dde | Luca Bigliardi | echo "# Configuration for $MYADDR" |
118 | d1e95dde | Luca Bigliardi | echo |
119 | d1e95dde | Luca Bigliardi | echo '# This file has been automatically generated. Do not modify by hand,' |
120 | d1e95dde | Luca Bigliardi | echo "# add your own rules to $SETKEYCUSTOMCONF instead." |
121 | d1e95dde | Luca Bigliardi | echo |
122 | d1e95dde | Luca Bigliardi | echo '# Flush SAD and SPD' |
123 | d1e95dde | Luca Bigliardi | echo 'flush;' |
124 | d1e95dde | Luca Bigliardi | echo 'spdflush;' |
125 | d1e95dde | Luca Bigliardi | echo |
126 | d1e95dde | Luca Bigliardi | if [[ -f "$SETKEYCUSTOMCONF" ]]; then |
127 | d1e95dde | Luca Bigliardi | echo "# Begin custom rules from $SETKEYCUSTOMCONF" |
128 | d1e95dde | Luca Bigliardi | cat "$SETKEYCUSTOMCONF" |
129 | d1e95dde | Luca Bigliardi | echo "# End custom rules from $SETKEYCUSTOMCONF" |
130 | d1e95dde | Luca Bigliardi | echo |
131 | d1e95dde | Luca Bigliardi | fi |
132 | d1e95dde | Luca Bigliardi | echo "$AUTOMATIC_MARKER" |
133 | d1e95dde | Luca Bigliardi | for node in $(cut -d ' ' -f2 "$NODES") ; do |
134 | d1e95dde | Luca Bigliardi | if [[ "$node" != "$MYADDR" ]]; then |
135 | d1e95dde | Luca Bigliardi | # Traffic to ignore |
136 | d1e95dde | Luca Bigliardi | for port in $TCPTOIGNORE ; do |
137 | d1e95dde | Luca Bigliardi | echo "spdadd $MYADDR[$port] $node tcp -P out none;" |
138 | d1e95dde | Luca Bigliardi | echo "spdadd $node $MYADDR[$port] tcp -P in none;" |
139 | d1e95dde | Luca Bigliardi | echo "spdadd $MYADDR $node[$port] tcp -P out none;" |
140 | d1e95dde | Luca Bigliardi | echo "spdadd $node[$port] $MYADDR tcp -P in none;" |
141 | d1e95dde | Luca Bigliardi | done |
142 | d1e95dde | Luca Bigliardi | # IPsec ESP rules |
143 | d1e95dde | Luca Bigliardi | echo "add $MYADDR $node esp 0x201 -E $CRYPTALGO $KEY;" |
144 | d1e95dde | Luca Bigliardi | echo "add $node $MYADDR esp 0x201 -E $CRYPTALGO $KEY;" |
145 | d1e95dde | Luca Bigliardi | for proto in $PROTOSTOSEC ; do |
146 | d1e95dde | Luca Bigliardi | echo "spdadd $MYADDR $node $proto -P out ipsec esp/transport//require;" |
147 | d1e95dde | Luca Bigliardi | echo "spdadd $node $MYADDR $proto -P in ipsec esp/transport//require;" |
148 | d1e95dde | Luca Bigliardi | done |
149 | d1e95dde | Luca Bigliardi | echo |
150 | d1e95dde | Luca Bigliardi | fi |
151 | d1e95dde | Luca Bigliardi | done |
152 | d1e95dde | Luca Bigliardi | } > "$TMPCONF" |
153 | d1e95dde | Luca Bigliardi | |
154 | d1e95dde | Luca Bigliardi | chmod 400 "$TMPCONF" |
155 | d1e95dde | Luca Bigliardi | update_system_ipsec "$TMPCONF" |
156 | d1e95dde | Luca Bigliardi | } |
157 | d1e95dde | Luca Bigliardi | |
158 | d1e95dde | Luca Bigliardi | regen_ipsec_conf() { |
159 | d1e95dde | Luca Bigliardi | # Reconfigure IPsec on the system when a new key is generated |
160 | d1e95dde | Luca Bigliardi | # on the master (assuming the current configuration is working |
161 | d1e95dde | Luca Bigliardi | # and a new key is about to be generated on the master). |
162 | d1e95dde | Luca Bigliardi | if [[ ! -f "$KEYPATH" ]]; then |
163 | d1e95dde | Luca Bigliardi | echo 'Asking to regenerate with new key, but no old key.' >&2 |
164 | d1e95dde | Luca Bigliardi | exit 1 |
165 | d1e95dde | Luca Bigliardi | fi |
166 | d1e95dde | Luca Bigliardi | local CURSEQNO=$(gather_key_seqno) |
167 | d1e95dde | Luca Bigliardi | update_keyfile |
168 | d1e95dde | Luca Bigliardi | local NEWSEQNO=$(gather_key_seqno) |
169 | d1e95dde | Luca Bigliardi | while [[ $NEWSEQNO -le $CURSEQNO ]]; do |
170 | d1e95dde | Luca Bigliardi | # Master did not update yet, wait.. |
171 | d1e95dde | Luca Bigliardi | sleep $REGEN_KEY_WAIT |
172 | d1e95dde | Luca Bigliardi | update_keyfile |
173 | d1e95dde | Luca Bigliardi | NEWSEQNO=$(gather_key_seqno) |
174 | d1e95dde | Luca Bigliardi | done |
175 | d1e95dde | Luca Bigliardi | update_ipsec_conf |
176 | d1e95dde | Luca Bigliardi | } |
177 | d1e95dde | Luca Bigliardi | |
178 | d1e95dde | Luca Bigliardi | clean_ipsec_conf() { |
179 | d1e95dde | Luca Bigliardi | # Unconfigure IPsec on the system, removing the key and |
180 | d1e95dde | Luca Bigliardi | # the rules previously generated. |
181 | d1e95dde | Luca Bigliardi | rm -f "$KEYPATH" |
182 | d1e95dde | Luca Bigliardi | |
183 | d1e95dde | Luca Bigliardi | local TMPCONF=$(mktemp) |
184 | d1e95dde | Luca Bigliardi | CLEANUP+=("rm -f $TMPCONF") |
185 | d1e95dde | Luca Bigliardi | # Remove all auto-generated rules |
186 | d1e95dde | Luca Bigliardi | sed "/$AUTOMATIC_MARKER/q" "$SETKEYCONF" > "$TMPCONF" |
187 | d1e95dde | Luca Bigliardi | chmod 400 "$TMPCONF" |
188 | d1e95dde | Luca Bigliardi | update_system_ipsec "$TMPCONF" |
189 | d1e95dde | Luca Bigliardi | } |
190 | d1e95dde | Luca Bigliardi | |
191 | d1e95dde | Luca Bigliardi | generate_secret() { |
192 | d1e95dde | Luca Bigliardi | # Generate a random HEX string (length specified by global variable KEYSIZE) |
193 | d1e95dde | Luca Bigliardi | python -c "from ganeti import utils; print utils.GenerateSecret($KEYSIZE)" |
194 | d1e95dde | Luca Bigliardi | } |
195 | d1e95dde | Luca Bigliardi | |
196 | d1e95dde | Luca Bigliardi | gen_key() { |
197 | d1e95dde | Luca Bigliardi | # Generate a new random key to be used for IPsec, the key is associated with |
198 | d1e95dde | Luca Bigliardi | # a sequence number. |
199 | d1e95dde | Luca Bigliardi | local KEY=$(generate_secret) |
200 | d1e95dde | Luca Bigliardi | if [[ ! -f "$KEYPATH" ]]; then |
201 | d1e95dde | Luca Bigliardi | # New environment/cluster, let's start from scratch |
202 | d1e95dde | Luca Bigliardi | local SEQNO="0" |
203 | d1e95dde | Luca Bigliardi | else |
204 | d1e95dde | Luca Bigliardi | local SEQNO=$(( $(gather_key_seqno) + 1 )) |
205 | d1e95dde | Luca Bigliardi | fi |
206 | d1e95dde | Luca Bigliardi | local TMPKEYPATH=$(mktemp) |
207 | d1e95dde | Luca Bigliardi | CLEANUP+=("rm -f $TMPKEYPATH") |
208 | d1e95dde | Luca Bigliardi | echo -n "$SEQNO 0x$KEY" > "$TMPKEYPATH" |
209 | d1e95dde | Luca Bigliardi | chmod 400 "$TMPKEYPATH" |
210 | d1e95dde | Luca Bigliardi | mv "$TMPKEYPATH" "$KEYPATH" |
211 | d1e95dde | Luca Bigliardi | } |
212 | d1e95dde | Luca Bigliardi | |
213 | d1e95dde | Luca Bigliardi | trap cleanup EXIT |
214 | d1e95dde | Luca Bigliardi | |
215 | d1e95dde | Luca Bigliardi | hooks_path="$GANETI_HOOKS_PATH" |
216 | d1e95dde | Luca Bigliardi | if [[ ! -n "$hooks_path" ]]; then |
217 | d1e95dde | Luca Bigliardi | echo '\$GANETI_HOOKS_PATH not specified.' >&2 |
218 | d1e95dde | Luca Bigliardi | exit 1 |
219 | d1e95dde | Luca Bigliardi | fi |
220 | d1e95dde | Luca Bigliardi | hooks_phase="$GANETI_HOOKS_PHASE" |
221 | d1e95dde | Luca Bigliardi | if [[ ! -n "$hooks_phase" ]]; then |
222 | d1e95dde | Luca Bigliardi | echo '\$GANETI_HOOKS_PHASE not specified.' >&2 |
223 | d1e95dde | Luca Bigliardi | exit 1 |
224 | d1e95dde | Luca Bigliardi | fi |
225 | d1e95dde | Luca Bigliardi | |
226 | d1e95dde | Luca Bigliardi | if [[ "$hooks_phase" = post ]]; then |
227 | d1e95dde | Luca Bigliardi | case "$hooks_path" in |
228 | d1e95dde | Luca Bigliardi | cluster-init) |
229 | d1e95dde | Luca Bigliardi | gen_key |
230 | d1e95dde | Luca Bigliardi | ;; |
231 | d1e95dde | Luca Bigliardi | cluster-destroy) |
232 | d1e95dde | Luca Bigliardi | clean_ipsec_conf |
233 | d1e95dde | Luca Bigliardi | ;; |
234 | d1e95dde | Luca Bigliardi | cluster-regenkey) |
235 | d1e95dde | Luca Bigliardi | # This hook path is not yet implemented in Ganeti, here we suppose it |
236 | d1e95dde | Luca Bigliardi | # runs on all the nodes. |
237 | d1e95dde | Luca Bigliardi | MASTERNAME=$(< "$MASTERNAME_FILE") |
238 | d1e95dde | Luca Bigliardi | if [[ "$MASTERNAME" = "$HOSTNAME" ]]; then |
239 | d1e95dde | Luca Bigliardi | gen_key |
240 | d1e95dde | Luca Bigliardi | update_ipsec_conf |
241 | d1e95dde | Luca Bigliardi | else |
242 | d1e95dde | Luca Bigliardi | regen_ipsec_conf |
243 | d1e95dde | Luca Bigliardi | fi |
244 | d1e95dde | Luca Bigliardi | ;; |
245 | d1e95dde | Luca Bigliardi | node-add) |
246 | d1e95dde | Luca Bigliardi | update_ipsec_conf |
247 | d1e95dde | Luca Bigliardi | ;; |
248 | d1e95dde | Luca Bigliardi | node-remove) |
249 | d1e95dde | Luca Bigliardi | node_name="$GANETI_NODE_NAME" |
250 | d1e95dde | Luca Bigliardi | if [[ ! -n "$node_name" ]]; then |
251 | d1e95dde | Luca Bigliardi | echo '\$GANETI_NODE_NAME not specified.' >&2 |
252 | d1e95dde | Luca Bigliardi | exit 1 |
253 | d1e95dde | Luca Bigliardi | fi |
254 | d1e95dde | Luca Bigliardi | if [[ "$node_name" = "$HOSTNAME" ]]; then |
255 | d1e95dde | Luca Bigliardi | clean_ipsec_conf |
256 | d1e95dde | Luca Bigliardi | else |
257 | d1e95dde | Luca Bigliardi | update_ipsec_conf |
258 | d1e95dde | Luca Bigliardi | fi |
259 | d1e95dde | Luca Bigliardi | ;; |
260 | d1e95dde | Luca Bigliardi | *) |
261 | d1e95dde | Luca Bigliardi | echo "Hooks path $hooks_path is not for us." >&2 |
262 | d1e95dde | Luca Bigliardi | ;; |
263 | d1e95dde | Luca Bigliardi | esac |
264 | d1e95dde | Luca Bigliardi | else |
265 | d1e95dde | Luca Bigliardi | echo "Hooks phase $hooks_phase is not for us." >&2 |
266 | d1e95dde | Luca Bigliardi | fi |
267 | d1e95dde | Luca Bigliardi |