From 0321a3210ef6bb42ef8b536d0964bef081294d1d Mon Sep 17 00:00:00 2001 From: Jerome Date: Fri, 25 Dec 2009 04:11:25 -0500 Subject: Define autossh::tunnel resource and improve initscript --- README | 42 +++++++++++ manifests/init.pp | 16 ---- manifests/tunnel.pp | 70 ++++++++++++++++++ templates/autossh-tunnel.erb | 171 +++++++++++++++++++++++++++++++++++++++++++ templates/tunnel-autossh.erb | 30 -------- 5 files changed, 283 insertions(+), 46 deletions(-) create mode 100644 manifests/tunnel.pp create mode 100644 templates/autossh-tunnel.erb delete mode 100644 templates/tunnel-autossh.erb diff --git a/README b/README index e69de29..4143856 100644 --- a/README +++ b/README @@ -0,0 +1,42 @@ +This module manages autossh tunnels between hosts. + + +Prerequisites +============= + +* The user has to be able to log in to the remote ssh system automatically, + ssh-agent and/or authorized_keys can be used to accomplish this + +* SSH port forwarding must be enabled on the remote host + + +Example +======= + +autossh::tunnel { 'mysql': + ensure => present, + user => 'tunnel', + port => 3307, + hostport => 3306, + remote_host => 'mysql.example.org', +} + +This will establish an ssh connection as user 'tunnel', to remote server +'mysql.example.org' with port forwarding enabled. Connections on localhost to +port '3307' with be forwarded through the tunnel to 'localhost', port 3306. + +Only connections originating from 'localhost' will be accepted into the tunnel. +If you wish to allow other hosts on the network to use this tunnel, you may +specify an explicit interface to bind the connection to using 'bind_address'. +A value of '*' will bind to all interfaces. + +Furthermore, if you wish to use the remote host as a gateway to another host on +the network, you may specify it using the 'host' parameter. + + +More info +========= + +* AutoSSH README : http://www.harding.motd.ca/autossh/README + +* SSH manual : http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&sektion=1 diff --git a/manifests/init.pp b/manifests/init.pp index 6915a44..0fb316a 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -2,20 +2,4 @@ class autossh { package { "autossh": ensure => installed, } - - file { - "/etc/init.d/tunnel-autossh": - owner => root, - group => root, - mode => 755, - require => Package["autossh"], - content => template("autossh/tunnel-autossh.erb"); - } - - exec { "autossh_update_rcd": - command => "update-rc.d tunnel-autossh start 18 2 3 4 5 . stop 81 0 1 6 .", - creates => "/etc/rc2.d/S18tunnel-autossh", - path => "/bin:/sbin:/usr/sbin:/usr/bin", - require => [ Package["autossh"], File["/etc/init.d/tunnel-autossh"]], - } } diff --git a/manifests/tunnel.pp b/manifests/tunnel.pp new file mode 100644 index 0000000..6d9c9d1 --- /dev/null +++ b/manifests/tunnel.pp @@ -0,0 +1,70 @@ +define autossh::tunnel ( + $ensure = present, + $user, + $bind_address = 'localhost', + $port, + $host = 'localhost', + $hostport, + $remote_host, + $monitor_port = 0, + $gatetime = 'absent', + $first_poll = 'absent', + $poll = 'absent', + $maxstart = 'absent', + $maxlifetime = 'absent', + $logfile = 'absent' +) { + + include autossh + + if ($ensure == 'present') { + + file { "/etc/init.d/autossh-tunnel-${name}": + content => template("autossh/autossh-tunnel.erb"), + owner => root, + group => root, + mode => 755, + require => Package["autossh"], + notify => Service["autossh-tunnel-${name}"], + } + + exec { "autossh-tunnel-${name}_update_rcd": + command => "update-rc.d autossh-tunnel-${name} start 18 2 3 4 5 . stop 81 0 1 6 .", + creates => "/etc/rc2.d/S18autossh-tunnel-${name}", + path => "/bin:/sbin:/usr/sbin:/usr/bin", + require => [ Package["autossh"], File["/etc/init.d/autossh-tunnel-${name}"]], + } + + service { "autossh-tunnel-${name}": + ensure => running, + hasrestart => true, + hasstatus => true, + require => File["/etc/init.d/autossh-tunnel-${name}"], + } + + } + else { + + exec { "autossh-tunnel-${name}_stop": + command => "/etc/init.d/autossh-tunnel-${name} stop", + path => "/bin:/sbin:/usr/sbin:/usr/bin", + onlyif => "test -x /etc/init.d/autossh-tunnel-${name} && test -e /var/run/autossh-tunnel-${name}.pid", + } + + file { "/etc/init.d/autossh-tunnel-${name}": + ensure => absent, + require => Exec["autossh-tunnel-${name}_stop"], + } + + exec { "autossh-tunnel-${name}_update_rcd_remove": + command => "update-rc.d autossh-tunnel-${name} remove", + path => "/bin:/sbin:/usr/sbin:/usr/bin", + onlyif => "test -L /etc/rc2.d/S18autossh-tunnel-${name}", + require => File["/etc/init.d/autossh-tunnel-${name}"], + } + + } + +} + + diff --git a/templates/autossh-tunnel.erb b/templates/autossh-tunnel.erb new file mode 100644 index 0000000..3302f5a --- /dev/null +++ b/templates/autossh-tunnel.erb @@ -0,0 +1,171 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: autossh-tunnel-<%= name %> +# Required-Start: $local_fs $remote_fs $network +# Required-Stop: $local_fs $remote_fs $network +# Should-Start: $syslog +# Should-Stop: $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Autossh tunnel <%= name %> +# Description: Maintain an SSH tunnel between two hosts. +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +USERNAME=<%= user %> + +DESC="secure tunnel" +NAME=autossh-tunnel-<%= name %> +REAL_NAME=autossh +DAEMON=$(which $REAL_NAME) +PIDFILE="/var/run/autossh-tunnel-<%= name %>.pid" +SCRIPTNAME=/etc/init.d/$NAME + +. /lib/lsb/init-functions + +# +# AutoSSH configuration +# +AUTOSSH_ARGS="-M <%= monitor_port %> -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -L <%= bind_address %>:<%= port %>:<%= host %>:<%= hostport %> <%= remote_host %>" +<% if gatetime != 'absent' -%> +AUTOSSH_GATETIME=<%= gatetime %> +<% end -%> +<% if first_poll != 'absent' -%> +AUTOSSH_FIRST_POLL=<%= first_poll %> +<% end -%> +<% if poll != 'absent' -%> +AUTOSSH_POLL=<%= poll %> +<% end -%> +<% if maxstart != 'absent' -%> +AUTOSSH_MAXSTART=<%= maxstart %> +<% end -%> +<% if maxlifetime != 'absent' -%> +AUTOSSH_MAXLIFETIME=<%= maxlifetime %> +<% end -%> +<% if logfile != 'absent' -%> +AUTOSSH_LOGFILE=<%= logfile %> +<% end -%> + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# +# Function that starts the daemon/service +# +do_start() +{ + # Export the autossh configuration + if [ -n "$AUTOSSH_GATETIME" ]; then + export AUTOSSH_GATETIME + fi + if [ -n "$AUTOSSH_FIRST_POLL" ]; then + export AUTOSSH_FIRST_POLL + fi + if [ -n "$AUTOSSH_POLL" ]; then + export AUTOSSH_POLL + fi + if [ -n "$AUTOSSH_MAXSTART" ]; then + export AUTOSSH_MAXSTART + fi + if [ -n "$AUTOSSH_MAXLIFETIME" ]; then + export AUTOSSH_MAXLIFETIME + fi + if [ -n "$AUTOSSH_LOGFILE" ]; then + export AUTOSSH_LOGFILE + fi + + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + pidofproc -p "$PIDFILE" "$DAEMON" >/dev/null && return 1 + start-stop-daemon --chuid $USERNAME --start --pidfile $PIDFILE --make-pidfile \ + --exec $DAEMON --background -- $AUTOSSH_ARGS \ + || return 2 + + # if autossh was started but bad arguments were passed to ssh, autossh will + # return 0 but exit after a few seconds, so we wait just a bit to make sure + # everything is ok + sleep 5 + pidofproc -p "$PIDFILE" "$DAEMON" >/dev/null || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/10/KILL/5 --pidfile $PIDFILE --name $REAL_NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + + return "$RETVAL" +} + +case "$1" in + start) + log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_progress_msg "was already running" && log_end_msg 0 ;; + *) log_end_msg 1 ;; # Failed to start + esac + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0) log_end_msg 0 ;; + 1) log_progress_msg "was already stopped" && log_end_msg 0 ;; + *) log_end_msg 1 ;; # Failed to stop + esac + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_progress_msg "was already running" && log_end_msg 0 ;; + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + log_end_msg 1 ;; + esac + ;; + status) + status_of_proc -p "$PIDFILE" "$DAEMON" $NAME && exit 0 || exit $? + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 + exit 3 + ;; +esac + + diff --git a/templates/tunnel-autossh.erb b/templates/tunnel-autossh.erb deleted file mode 100644 index 0e38c3a..0000000 --- a/templates/tunnel-autossh.erb +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# port forwarding with ssh -# installed with: update-rc.d tunnel-autossh start 18 2 3 4 5 . stop 81 0 1 6 . - -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - -if ! [ -x /usr/bin/autossh ]; then - echo "Where is autossh?" - exit 0 -fi - -case "$1" in - start) - # same as above for the collector - # here we are binding to a host with an common internal interface (127.0.0.1) - /bin/su <%= autossh_tunneluser %> -c '/usr/bin/autossh -f -N -L <%= autossh_localport %>:<%= autossh_localip %>:<%= autossh_localportservice %> <%= autossh_remotehost %> -M <%= autossh_moniport %>' - echo "adding tunnel for ldap replication" - ;; - stop) - echo -n "destroying tunnel ..." - killall autossh - echo "destroyed!" - ;; - - *) - echo "Usage: /etc/init.d/tunnel-autossh {start|stop}" - exit 1 - ;; -esac - -- cgit v1.2.3