PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

blog-libre : sshrc, utiliser vos fichiers de configuration dans des sessions SSH

jeudi 14 septembre 2017 à 11:00

sshrc apporte une réponse à 2 problématiques :

Alors sshrc est fait pour vous. Sur votre poste vous allez créer un fichier ~/.sshrc dans lequel vous allez exporter/sourcer votre configuration personnalisée et un dossier ~./sshrc.d où vous allez placer vos fichiers de configuration (.bashrc, .vimrc, .inputrc, etc.). Au lieu de vous connecter sur ces pc/serveurs avec la commande ssh, vous allez vous connecter avec la commande sshrc (no stress c’est propre). Un dossier /tmp/.cascador.sshrc.XXXX unique (XXXX généré aléatoirement) sera créé sur l’hôte distant, votre configuration personnalisée sera envoyée dedans (avec openssl) puis chargée. A la déconnexion ce dossier sera supprimé.

sshrc est un script shell sous licence MIT aisément maintenable, compréhensible et lisible. Il nécessite comme prérequis openssl sur l’hôte local et distant. Il existe également moshrc pour Mosh. Voici le code source.

#!/usr/bin/env bash
function sshrc() {
    local SSHHOME=${SSHHOME:=~}
    if [ -f $SSHHOME/.sshrc ]; then
        local files=.sshrc
        if [ -d $SSHHOME/.sshrc.d ]; then
            files="$files .sshrc.d"
        fi
        SIZE=$(tar cfz - -h -C $SSHHOME $files | wc -c)
        if [ $SIZE -gt 65536 ]; then
            echo >&2 $'.sshrc.d and .sshrc files must be less than 64kb\\ncurrent size: '$SIZE' bytes'
            exit 1
        fi
        if [ -z "$CMDARG" -a ! -e ~/.sshrc.d/.hushlogin ]; then
            WELCOME_MSG="
                if [ ! -e ~/.hushlogin ]; then
                    if [ -e /etc/motd ]; then cat /etc/motd; fi
                    if [ -e /etc/update-motd.d ]; then run-parts /etc/update-motd.d/ 2>/dev/null; fi
                    last -F \\$USER 2>/dev/null | grep -v 'still logged in' | head -n1 | awk '{print \\"Last login:\\",\\$4,\\$5,\\$6,\\$7,\\$8,\\"from\\",\\$3;}'
                fi
                "
        else
            WELCOME_MSG=""
        fi
        ssh -t "$DOMAIN" $SSHARGS "
            command -v openssl >/dev/null 2>&1 || { echo >&2 \\"sshrc requires openssl to be installed on the server, but it's not. Aborting.\\"; exit 1; }
            $WELCOME_MSG
            export SSHHOME=\\$(mktemp -d -t .$(whoami).sshrc.XXXX)
            export SSHRCCLEANUP=\\$SSHHOME
            trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0
            echo $'"$(cat "$0" | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc
            chmod +x \\$SSHHOME/sshrc

            echo $'"$( cat << 'EOF' | openssl enc -base64
                if [ -r /etc/profile ]; then source /etc/profile; fi
                if [ -r ~/.bash_profile ]; then source ~/.bash_profile
                elif [ -r ~/.bash_login ]; then source ~/.bash_login
                elif [ -r ~/.profile ]; then source ~/.profile
                fi
                export PATH=$PATH:$SSHHOME
                source $SSHHOME/.sshrc;
EOF
                )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc.bashrc

            echo $'"$( cat << 'EOF' | openssl enc -base64
#!/usr/bin/env bash
                exec bash --rcfile <(echo '
                [ -r /etc/profile ] && source /etc/profile
                if [ -r ~/.bash_profile ]; then source ~/.bash_profile
                elif [ -r ~/.bash_login ]; then source ~/.bash_login
                elif [ -r ~/.profile ]; then source ~/.profile
                fi
                source '$SSHHOME'/.sshrc;
                export PATH=$PATH:'$SSHHOME'
                ') "$@"
EOF
                )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/bashsshrc
            chmod +x \\$SSHHOME/bashsshrc

            echo $'"$(tar czf - -h -C $SSHHOME $files | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d | tar mxzf - -C \\$SSHHOME
            export SSHHOME=\\$SSHHOME
            echo \\"$CMDARG\\" >> \\$SSHHOME/sshrc.bashrc
            bash --rcfile \\$SSHHOME/sshrc.bashrc
            "
    else
        echo "No such file: $SSHHOME/.sshrc" >&2
        exit 1
    fi
}

function sshrc_parse() {
  while [[ -n $1 ]]; do
    case $1 in
      -b | -c | -D | -E | -e | -F | -I | -i | -L | -l | -m | -O | -o | -p | -Q | -R | -S | -W | -w )
        SSHARGS="$SSHARGS $1 $2"; shift ;;
      -* )
        SSHARGS="$SSHARGS $1" ;;
      *)
        if [ -z "$DOMAIN" ]; then
         DOMAIN="$1"
        else
          local SEMICOLON=$([[ "$@" = *[![:space:]]* ]] && echo '; ')
          CMDARG="$@$SEMICOLON exit"
          return;
        fi
        ;;
    esac
    shift
  done
  if [ -z $DOMAIN ]; then
    ssh $SSHARGS; exit 1;
  fi
}

command -v openssl >/dev/null 2>&1 || { echo >&2 "sshrc requires openssl to be installed locally, but it's not. Aborting."; exit 1; }
sshrc_parse "$@"
sshrc

Prise en main

On ne s’embête pas avec Git, on se contente de copier sshrc et le placer dans /usr/local/bin.

wget https://raw.githubusercontent.com/Russell91/sshrc/master/sshrc && chmod +x sshrc && sudo mv sshrc /usr/local/bin/
touch ~/.sshrc && mkdir -p ~/.sshrc.d

Voici mon fichier ~/.sshrc actuel. Dans le dossier ~/.sshrc.d j’ai mes .bashrc, .inputrc, .vimrc.

export EDITOR=vim
export INPUTRC=$SSHHOME/.sshrc.d/.inputrc
export LESS='-FRXi'
export LESS_TERMCAP_mb=$'\\E[01;31m'
export LESS_TERMCAP_md=$'\\E[01;31m'
export LESS_TERMCAP_me=$'\\E[0m'
export LESS_TERMCAP_so=$'\\E[01;44;33m'
export LESS_TERMCAP_se=$'\\E[0m'
export LESS_TERMCAP_us=$'\\E[01;32m'
export LESS_TERMCAP_ue=$'\\E[0m'
export VIMINIT="let \\$MYVIMRC='$SSHHOME/.sshrc.d/.vimrc' | source \\$MYVIMRC"

source $SSHHOME/.sshrc.d/.bashrc
if [[ -f ${SSHHOME}/.sshrc.d/.bash_aliases ]]; then source ${SSHHOME}/.sshrc.d/.bash_aliases ; fi
if [[ -f ${SSHHOME}/.sshrc.d/.bash_functions ]]; then source ${SSHHOME}/.sshrc.d/.bash_functions ; fi

On se connecte ensuite à un serveur comme ceci sshrc root@blog-libre.org. Pour retrouver le répertoire sshrc echo $SSHHOME et s’y déplacer cd $SSHHOME; ls -a.

Je vous invite à taper « dotfile sshrc » dans votre moteur de recherche préféré pour avoir d’autres exemples : 1, 2, 3, 4, 5.

Deux points négatifs

Il n’est pas possible d’envoyer plus de 64 Ko de fichiers de configuration compressés avec sshrc. Première réaction la peur puis après quelques tests, j’arrive à passer 1 Mo sans problème, le mot important à retenir : compressés. Cependant ça reste un problème important pour certains, on peut citer les plugins Vim par exemple. Dans ce cas l’auteur conseille de copier les fichiers dans un obscur dossier sur le serveur et d’utiliser sshrc pour automatiquement sourcer ces configurations au login.

On a vu que sshrc était bien conçu et propre, il crée un dossier /tmp/.cascador.sshrc.XXXX unique qu’il supprime à la déconnexion. Cependant pour certains cas, vous serez obligés de « sortir » de ce dossier. Pour nano il n’est pas possible d’exporter un fichier de configuration, il lit seulement /etc/nanorc et ~/.nanorc, il ne possède pas d’option permettant de préciser où se situe (ailleurs) nanorc. On est donc obligé d’aller placer .nanorc dans ~/. Certains font une copie, d’autres créent un lien symbolique, c’est plus propre. Il faut gérer la suppression de ce fichier (on peut modifier trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0 entre autres solutions) mais si une autre personne se connecte sous le même compte que vous, il va charger ce fichier de configuration… et puis vous touchez aux fichiers de configuration du pc/serveur (/root/.nanorc pourrait déjà exister par exemple).

Quelques conseils

N’oubliez pas que les fichiers de configuration de votre pc sont probablement différents de ceux de vos serveurs. Typiquement je suis sur Xubuntu et j’administre des serveurs Debian, les versions des paquets sont différentes, les fichiers de configuration également. Je vous invite à copier les fichiers de configuration à partir de vos serveurs dans ~/.sshrc.d puis les modifier.

N’hésitez pas à abuser de if [ "$(hostname)" == "jessie1" ]; then source ${SSHHOME}/.sshrc.d/.bashrc_jessie1 ; fi afin de gérer finement vos dotfiles par serveur.

Vous pouvez créer des liens symboliques au lieu de copier certains fichiers de configuration dans ~/.sshrc.d. Personnellement j’ai fait ln -s ~/.inputrc ~/.sshrc.d/.inputrc pour inputrc. Ça me permet ainsi d’avoir mes raccourcis claviers personnalisés en fonction du poste sur lequel je suis (touches utilisées différentes si je suis sur mon pc portable).

Je vous invite à lire ce fil sur Hacker News autour de sshrc, il y a des réflexions intéressantes. Je me demande notamment dans quelle mesure on peut charger des fichiers de configuration (rendus disponibles par un serveur web) avec wget/curl. A noter le reddit dotfiles, the unofficial guide to doing dotfiles on GitHub, awesome-shell et tant qu’à faire awesome.

Gravatar de blog-libre
Original post of blog-libre.Votez pour ce billet sur Planet Libre.

Articles similaires