Statistics
| Branch: | Tag: | Revision:

root / doc / examples / hooks / ipsec.in @ 98028e5d

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