X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=modules%2Fstaticsync%2Ffiles%2Fstaticsync-ssh-wrap;fp=modules%2Fstaticsync%2Ffiles%2Fstaticsync-ssh-wrap;h=959b4f8f0df84dd186c8ed3e4b0654836cd38050;hb=0c067639ec7d7050b69249b85e6aa83ab91820b5;hp=0000000000000000000000000000000000000000;hpb=168aa3f05f914802698b8db5fdde823c4e992913;p=mirror%2Fdsa-puppet.git diff --git a/modules/staticsync/files/staticsync-ssh-wrap b/modules/staticsync/files/staticsync-ssh-wrap new file mode 100755 index 000000000..959b4f8f0 --- /dev/null +++ b/modules/staticsync/files/staticsync-ssh-wrap @@ -0,0 +1,225 @@ +#!/bin/bash + +# Copyright (c) 2009, 2010, 2012 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +set -e +set -u + +. /etc/staticsync.conf +if ! [ -n "$base" ]; then + echo >&2 "base not configured!" + exit 1 +fi +BASEDIR="$base" + +MYLOGNAME="`basename "$0"`[$$]" +COMPONENTLIST=/etc/static-components.conf + +usage() { + echo "local Usage: $0 " + echo "via ssh orig command:" + echo " mirror " + echo " rsync " + echo " static-master-update-component " +} + +one_more_arg() { + if [ "$#" -lt 1 ]; then + usage >&2 + exit 1 + fi +} + +info() { + logger -p daemon.info -t "$MYLOGNAME" "$1" +} + +croak() { + logger -s -p daemon.warn -t "$MYLOGNAME" "$1" + exit 1 +} + +do_mirror() { + local remote_host="$1"; shift + one_more_arg "$@" + local component="$1"; shift + one_more_arg "$@" + local serial="$1"; shift + + masterhost="$(awk -v component="$component" '!/^ *(#|$)/ && $2 == component {print $1; exit}' "$COMPONENTLIST")" + if [ -z "$masterhost" ]; then + croak "Did not find master for component $component." + elif [ "$masterhost" != "$remote_host" ]; then + croak "$remote_host is not master for $component." + else + info "Host $remote_host triggered a mirror run for $component, serial $serial" + exec /usr/local/bin/static-mirror-run "$BASEDIR/mirrors/$component" "$remote_host:$component/-new-" "$serial" + echo >&2 "Exec failed" + croak "exec failed" + fi +} + +do_rsync_on_master() { + local remote_host="$1"; shift + local allowed_rsyncs + allowed_rsyncs=() + allowed_rsyncs+=("--server --sender -vlHtrze.iLsf --safe-links .") # wheezy + allowed_rsyncs+=("--server --sender -vlHtrze.iLsfx --safe-links .") # jessie + allowed_rsyncs+=("--server --sender -vlHtrze.iLsfxC --safe-links .") # stretch + + for cmd_idx in ${!allowed_rsyncs[*]}; do + args="${allowed_rsyncs[$cmd_idx]}" + for component in $(awk -v this_host="$(hostname -f)" '!/^ *(#|$)/ && $1 == this_host {print $2}' $COMPONENTLIST); do + if [ "$*" = "$args $component/-new-/" ] || [ "$*" = "$args ./$component/-new-/" ] ; then + local path="$BASEDIR/master/$component-current-push" + info "serving $remote_host with $path" + exec rsync $args "$path/." + croak "Exec failed" + elif [ "$*" = "$args $component/-live-/" ] || [ "$*" = "$args ./$component/-live-/" ] ; then + local path="$BASEDIR/master/$component-current-live" + info "host $remote_host wants $path, acquiring lock" + tgtlock="$BASEDIR/master/$component.lock" + if ! [ -e "$tgtlock" ]; then + touch "$tgtlock" + fi + exec 200< "$tgtlock" + if ! flock -s -w 0 200; then + echo >&2 "Cannot acquire shared lock on $tgtlock covering $path - this should mean an update is already underway anyway." + exit 1 + fi + exec rsync $args "$path/." + croak "Exec failed" + fi + done + done +} + +do_rsync_on_source() { + local remote_host="$1" + shift + + local allowed_rsyncs + allowed_rsyncs=() + + if [ -e "$COMPONENTLIST" ]; then + for path in $(awk -v host="$(hostname -f)" '!/^ *(#|$)/ && $3 == host {print $4}' $COMPONENTLIST); do + allowed_rsyncs+=("--server --sender -lHtrze.iLsf --safe-links . $path/.") # wheezy + allowed_rsyncs+=("--server --sender -lHtrze.iLsfx --safe-links . $path/.") # jessie + allowed_rsyncs+=("--server --sender -lHtrze.iLsfxC --safe-links . $path/.") # stretch + done + fi + for cmd_idx in ${!allowed_rsyncs[*]}; do + allowed="${allowed_rsyncs[$cmd_idx]}" + if [ "$*" = "$allowed" ]; then + info "Running for host $remote_host: rsync $*" + exec rsync "$@" + croak "Exec failed" + fi + done +} + +do_rsync() { + do_rsync_on_master "$@" + do_rsync_on_source "$@" + + info "NOT allowed for $remote_host: rsync $*" + echo >&2 "This rsync command ($@) not allowed." + exit 1 +} + +do_update_component() { + local remote_host="$1"; shift + + one_more_arg "$@" + component="$1" + shift + + hit="$( + awk -v this_host="$(hostname -f)" -v component="$component" -v host="$remote_host" ' + !/^ *(#|$)/ && $1 == this_host && $2 == component { + if ($3 == host) { + print $4 + exit + } + split($5,extra,",") + for (i in extra) { + if (host == extra[i]) { + printf "%s:%s\n", $3, $4 + exit + } + } + exit + }' "$COMPONENTLIST" + )" + if [ -n "$hit" ]; then + exec static-master-update-component "$component" + echo >&2 "Exec failed" + croak "exec failed" + else + info "Not whitelisted: $remote_host update $component" + echo >&2 "Not whitelisted: $remote_host update $component" + exit 1 + fi +} + + +if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then + usage + exit 0 +fi + +one_more_arg "$@" +remote_host="$1" +shift + + +# check/parse remote command line +if [ -z "${SSH_ORIGINAL_COMMAND:-}" ] ; then + croak "Did not find SSH_ORIGINAL_COMMAND" +fi +set "dummy" ${SSH_ORIGINAL_COMMAND} +shift + +info "host $remote_host called with $*" + +one_more_arg "$@" +action="$1" +shift + +case "$action" in + # on a static mirror, update a component from its master + mirror) + do_mirror "$remote_host" "$@" + ;; + # on a static source, allow fetching from the master, + # on a master, allow fetching from a component's mirrors + rsync) + do_rsync "$remote_host" "$@" + ;; + # on a master, initiate an update of a component + static-master-update-component) + do_update_component "$remote_host" "$@" + ;; + *) + croak "Invalid operation '$action'" + ;; +esac