ussh: configuration du multiplexage pour certains hôtes

This commit is contained in:
Jephté Clain 2016-01-27 11:23:13 +04:00
parent f40a3a240a
commit 5c75737a69
3 changed files with 154 additions and 24 deletions

View File

@ -6,8 +6,3 @@
# Le type d'analyse d'argument est spécifié avec un préfixe +auto (par défaut)
# ou +manual
#SHELL_TYPE=auto+auto
# Utilisateur par défaut pour la commande ussh
#USSH_USER=root
# Domaine par défaut pour la commande ussh
#USSH_DOMAIN=

40
lib/default/ussh Normal file
View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# Paramètres par défaut pour ussh. Pour compatibilité, les valeurs USSH_USER et
# USSH_DOMAIN sont valides aussi (elles sont chargées depuis le fichier de
# configuration 'nutools'), mais les valeurs disponibles ici ont la priorité.
# Utilisateur par défaut
#DEFAULT_USER=root
# Domaine par défaut
#DEFAULT_DOMAIN=
# Valeur par défaut de la valeur du paramètre ControlPersist
#DEFAULT_PERSIST=5m
# Hôtes pour lesquels ussh configure automatiquement un control master
# Chaque élément de ce tableau est une clé utilisée pour lire des valeurs par
# défaut dans des variables.
#CMHOSTS=(host)
## Exemple de valeurs pour la clé "host" dans le tableau CMHOSTS
# Faut-il multiplexer la connexion à l'hôte? C'est le cas par défaut puisque
# c'est l'objet de cette configuration.
#host_SHARED=1
# Nom d'hôtes associés à cette configuration. Typiquement, ce sont le nom
# pleinement qualifiés et les aliases de l'hôte. Par défaut, ce tableau contient
# (host.DEFAULT_DOMAIN host)
#host_HOSTS=(host.domain host)
# Fichier utilisé pour coordonner le multiplexage. Dans cette chaine, @user,
# @host et @port sont respectivement remplacé par le compte de connexion, l'hôte
# pleinement qualifié et le port de connexion.
#host_CONTROL="$HOME/.ssh/@user@@host:@port"
# Faut-il utiliser ControlPersist? Nécessite une version 5.6 ou ultérieure de
# OpenSSH. Avec auto, vérifier la version d'OpenSSH installée et choisir le cas
# échéant la valeur de la variable DEFAULT_PERSIST. Sinon passer la valeur sans
# modification
#host_PERSIST=auto

133
ussh
View File

@ -112,7 +112,9 @@ function __expand_braces() {
echo "$1"
fi
}
function __dot_is_localhost() { [ "$1" == "." ] && echo "localhost" || echo "$1"; }
function __dot_is_localhost() {
[ "$1" == "." ] && echo "localhost" || echo "$1"
}
function __fix_domain() {
local user host
splituserhost "$1" user host
@ -192,15 +194,15 @@ function remove_keys() {
eend
}
function __have_ssh_config() {
function __parse_ssh_config() {
local host="$1" config="$2"
[ -f "$config" ] || return 1
awkrun host="$host" '
BEGIN {
in_host = 0
ec = 1
found_user = 0
}
tolower($1) == "host" {
!found_user && tolower($1) == "host" {
in_host = 0
for (i = 2; i <= NF; i++) {
if ($i == host) {
@ -210,24 +212,111 @@ tolower($1) == "host" {
}
}
in_host && tolower($1) == "user" {
ec = 0
exit 0
print "SSH_USER=\"" $2 "\""
found_user = 1
}
in_host && tolower($1) == "port" {
print "SSH_PORT=\"" $2 "\""
}
END {
exit ec
if (found_user) print "true"
else print "false"
}
' -- "$config"
}
function __update_sshopts_l() {
# Ajouter l'option -l USSH_USER au tableau sshopts si aucune définition pour
# l'hôte $1 n'existe dans l'un des fichiers de configuration de ssh
if [ -n "$1" ]; then
__have_ssh_config "$1" ~/.ssh/config && return
__have_ssh_config "$1" /etc/ssh/ssh_config && return
function __update_sshopts_misc() {
# Déterminer l'utilisateur et le port de connexion et les placer dans les
# variables SSH_USER et SSH_PORT, respectivement. Analyser pour cela les
# arguments qui sont fournis dans les paramètres 2..@
# Ajouter l'option -l DEFAULT_USER au tableau sshopts si aucune définition
# pour l'hôte $1 n'existe dans l'un des fichiers de configuration de ssh et
# si l'utilisateur n'a pas déjà spécifié un compte utilisateur.
SSH_PORT=22
# L'utilisateur est peut-être fourni avec l'hôte
local user host
splituserhost "$1" user host; shift
if [ -n "$user" ]; then
SSH_USER="$user"
return
fi
# Rajouter l'option au début pour que l'utilisateur puisse la surcharger
sshopts=(${USSH_USER:+-l "$USSH_USER"} "${sshopts[@]}")
# Analyser les configuration de ssh
eval "$(__parse_ssh_config "$1" ~/.ssh/config)" && return
eval "$(__parse_ssh_config "$1" /etc/ssh/ssh_config)" && return
# Analyser les arguments
local i=1
while [ $i -le $# ]; do
if [ "${!i}" == -l ]; then
i=$(($i + 1))
SSH_USER="${!i}"
elif [ "${!i}" == -p ]; then
i=$(($i + 1))
SSH_PORT="${!i}"
fi
i=$(($i + 1))
done
[ -n "$SSH_USER" ] && return
# Rajouter l'option -l au début. De cette façon, on laisse la possibilité à
# l'utilisateur de surcharger cette option, dans le cas où nous n'avons pas
# pu analyser les arguments correctement
SSH_USER="${DEFAULT_USER:-$USER}"
sshopts=(${DEFAULT_USER:+-l "$DEFAULT_USER"} "${sshopts[@]}")
}
function __update_sshopts_cm() {
# Rajouter le cas échéant les options pour le multiplexage des connexions au
# tableau sshopts, pour l'hôte $1
# SSH_USER doit être défini
local user host
local found cmhost cmkey tmphost shared control persist
local -a hosts
splituserhost "$1" user host
for cmhost in "${CMHOSTS[@]}"; do
[ -n "$cmhost" ] || continue
cmkey="$cmhost"; cmkey="${cmkey//./_}"; cmkey="${cmkey//-/_}"
array_copy hosts "${cmkey}_HOSTS"
if [ -z "${hosts[0]}" ]; then
if [[ "$cmhost" == *.* ]]; then
hosts=("$cmhost" "${cmhost%%.*}")
else
hosts=("$cmhost${DEFAULT_DOMAIN:+.$DEFAULT_DOMAIN}" "$cmhost")
fi
fi
if array_contains hosts "$host"; then
found=1
break
fi
done
[ -n "$found" ] || return
shared="${cmkey}_SHARED"; shared="${!shared}"
[ -n "$shared" ] || shared=1 # connexion multiplexée par défaut
is_yes "$shared" || return
control="${cmkey}_CONTROL"; control="${!control}"
[ -n "$control" ] || control="$HOME/.ssh/@user@@host:@port"
control="${control//@user/$SSH_USER}"
control="${control//@port/$SSH_PORT}"
control="${control//@host/${hosts[0]}}"
persist="${cmkey}_PERSIST"; persist="${!persist}"
[ -n "$persist" ] || persist=auto
sshopts=("${sshopts[@]}" -o ControlPath="$control" -o ControlMaster=auto)
if [ "$persist" == auto ]; then
local version major minor
version="$(ssh -V 2>&1)"
version="${version#OpenSSH_}"; major="${version%%.*}"
minor="${version#$major.}"; minor="${minor:0:1}"
if [ $major -ge 6 ]; then
persist="$DEFAULT_PERSIST"
elif [ $major -eq 5 ]; then
if [ "$minor" -ge 6 ]; then
persist="$DEFAULT_PERSIST"
else
persist=
fi
elif [ $major -le 4 ]; then
persist=
fi
fi
[ -n "$persist" ] && sshopts=("${sshopts[@]}" -o ControlPersist="$persist")
}
function show_vars() {
@ -235,7 +324,8 @@ function show_vars() {
local -a sshopts
array_copy sshopts SSHOPTS
__update_sshopts_l "${hosts[0]}"
__update_sshopts_misc "${hosts[0]}" "$@"
__update_sshopts_cm "${hosts[0]}"
set_var_cmd ssh "$SSH"
set_var_cmd exec "$exec"
@ -257,7 +347,8 @@ function do_ssh() {
[ -z "$onehost" ] && etitle "$host"
array_copy sshopts SSHOPTS
__update_sshopts_l "$host"
__update_sshopts_misc "$host" "$@"
__update_sshopts_cm "$host"
${exec:+exec} "$SSH" "${sshopts[@]}" "$host" "$@" || r=$?
[ -z "$onehost" ] && eend
@ -267,10 +358,14 @@ function do_ssh() {
function __update_SSHOPTS() { SSHOPTS=("${SSHOPTS[@]}" "$@"); }
# charger USSH_DOMAIN et USSH_USER
# charger la configuration
set_defaults nutools
set_defaults ussh
[ -n "$DEFAULT_USER" ] || DEFAULT_USER="${USSH_USER:-root}"
[ -n "$DEFAULT_DOMAIN" ] || DEFAULT_DOMAIN="$USSH_DOMAIN"
[ -n "$DEFAULT_PERSIST" ] || DEFAULT_PERSIST=5m
DOMAIN="$USSH_DOMAIN"
DOMAIN="$DEFAULT_DOMAIN"
SSH=
remove=
remove_only=