221 votes

Comment copier des fichiers nécessitant un accès root avec scp?

J'ai un serveur Ubuntu auquel je me connecte en utilisant SSH.

J'ai besoin de téléverser des fichiers depuis mon ordinateur dans /var/www/ sur le serveur, les fichiers dans /var/www/ sont possédés par root.

En utilisant PuTTY, après m'être connecté, je dois taper sudo su et mon mot de passe d'abord pour pouvoir modifier les fichiers dans /var/www/.

Mais lorsque je copie des fichiers en utilisant WinSCP, je ne peux pas créer/modifier des fichiers dans /var/www/, car l'utilisateur avec lequel je me connecte n'a pas les permissions sur les fichiers dans /var/www/ et je ne peux pas taper sudo su comme je le fais en cas de session ssh.

Sais-tu comment je pourrais gérer cela ?

Si je travaillais sur mon ordinateur local, je lancerais gksudo nautilus mais dans ce cas, j'ai seulement accès au terminal de la machine.

12voto

Michael Kelley Points 1153

Lorsque vous exécutez sudo su, tous les fichiers que vous créez seront la propriété de root, mais il n'est pas possible par défaut de se connecter directement en tant que root avec ssh ou scp. Il n'est également pas possible d'utiliser sudo avec scp, donc les fichiers ne sont pas utilisables. Corrigez cela en réclamant la propriété de vos fichiers :

En supposant que votre nom d'utilisateur était dimitri, vous pourriez utiliser cette commande.

sudo chown -R dimitri:dimitri /home/dimitri

À partir de ce moment-là, comme mentionné dans d'autres réponses, la méthode "Ubuntu" consiste à utiliser sudo et non les connexions en tant que root. C'est un paradigme utile, avec de grands avantages en matière de sécurité.

6voto

bergoid Points 61

Si vous utilisez les outils OpenSSH au lieu de PuTTY, vous pouvez accomplir cela en lançant le transfert de fichier scp sur le serveur avec sudo. Assurez-vous d'avoir un démon sshd en cours d'exécution sur votre machine locale. Avec ssh -R, vous pouvez donner au serveur un moyen de contacter votre machine.

Sur votre machine :

ssh -R 11111:localhost:22 NOM_UTILISATEUR_DISTANT@NOM_SERVEUR

En plus de vous connecter sur le serveur, cela redirigera chaque connexion effectuée sur le port 11111 du serveur vers le port 22 de votre machine : le port sur lequel votre sshd écoute.

Sur le serveur, lancez le transfert de fichier de cette manière :

cd /var/www/
sudo scp -P 11111 -r NOM_UTILISATEUR_LOCAL@localhost:NOM_DOSSIER .

2voto

Bruce Points 171

Voici une version modifiée de la réponse de Willie Wheeler qui transfère le(s) fichier(s) via tar mais prend également en charge le passage d'un mot de passe à sudo sur l'hôte distant.

(stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) \
 | ssh remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""

Le petit supplément de magie ici est l'option -S pour sudo. Selon la page de manuel de sudo :

-S, --stdin Écrire l'invite dans la sortie d'erreur standard et lire le mot de passe depuis l'entrée standard au lieu d'utiliser le périphérique terminal. Le mot de passe doit être suivi d'un caractère de nouvelle ligne.

Nous voulons en fait que la sortie de tar soit redirigée vers ssh, ce qui redirige ensuite l'entrée standard de ssh vers la sortie de tar, supprimant ainsi tout moyen de transmettre le mot de passe à sudo depuis le terminal interactif. (Nous pourrions utiliser la fonction ASKPASS de sudo à l'autre bout, mais c'est une autre histoire). Nous pouvons toutefois transmettre le mot de passe à sudo en le capturant à l'avance et en le préfixant à la sortie de tar en effectuant ces opérations dans un sous-shell et en passant la sortie du sous-shell à travers ssh. Cela présente également l'avantage supplémentaire de ne pas laisser une variable d'environnement contenant notre mot de passe traîner dans notre shell interactif.

Vous remarquerez que je n'ai pas exécuté 'read' avec l'option -p pour afficher une invite. C'est parce que l'invite du mot de passe de sudo est commodément renvoyée vers la sortie d'erreur standard de notre shell interactif via ssh. Vous pourriez vous demander "comment sudo est-il exécuté alors qu'il s'exécute à l'intérieur de ssh à droite de notre pipe ?" Lorsque nous exécutons plusieurs commandes et redirigeons la sortie de l'une vers l'autre, le shell parent (le shell interactif dans ce cas) exécute chaque commande dans la séquence immédiatement après avoir exécuté la précédente. À chaque commande derrière un pipe qui est exécutée, le shell parent attache (redirige) la sortie standard du côté gauche vers l'entrée standard du côté droit. La sortie devient alors une entrée au fur et à mesure qu'elle passe par les processus. Nous pouvons voir cela en action en exécutant la commande entière et en mettant le groupe de processus en arrière-plan (Ctrl-z) avant de taper notre mot de passe, puis en regardant l'arbre des processus.

$ (stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) | ssh 
remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
[sudo] password for bruce: 
[1]+  Stopped                 ( stty -echo; read passwd; stty echo; echo 
$passwd; tar -cz foo.* ) | ssh remote_host "sudo -S bash -c \"tar -C 
/var/www/ -xz; echo\""

$ pstree -lap $$
bash,7168
  bash,7969
  pstree,7972 -lap 7168
  ssh,7970 remote_host sudo -S bash -c "tar -C /var/www/ -xz; echo"`

Notre shell interactif est PID 7168, notre sous-shell est PID 7969 et notre processus ssh est PID 7970.

Le seul inconvénient est que read acceptera l'entrée avant que sudo n'ait le temps de renvoyer son invite. Sur une connexion rapide et un hôte distant rapide, vous ne remarquerez pas cela, mais vous pourriez le remarquer si l'un ou l'autre est lent. Tout retard n'affectera pas la capacité à entrer l'invite ; elle pourrait simplement apparaître après que vous ayez commencé à taper.

Notez simplement que j'ai ajouté une entrée de fichier host pour "remote_Host" sur ma machine locale pour la démo.

1voto

test30 Points 517

Vous pouvez utiliser le script que j'ai écrit en m'inspirant de ce sujet:

touch /tmp/justtest && scpassudo /tmp/justtest remoteuser@ssh.superserver.com:/tmp/

mais cela nécessite quelques trucs fous (qui d'ailleurs sont automatiquement faits par le script)

  1. le serveur auquel le fichier est envoyé ne demandera plus de mot de passe lors de l'établissement de la connexion ssh avec l'ordinateur source
  2. en raison de la nécessité de ne pas avoir de invite de sudo sur le serveur, sudo ne demandera plus de mot de passe sur la machine distante, pour l'utilisateur

Voici le script:

interface=wlan0
if [[ $# -ge 3 ]]; then interface=$3; fi
thisIP=$(ifconfig | grep $interface -b1 | tail -n1 | egrep -o '[0-9.]{4,}' -m1 | head -n 1)
thisUser=$(whoami)
localFilePath=/tmp/justfortest
destIP=192.168.0.2
destUser=silesia
#dest 
#destFolderOnRemoteMachine=/opt/glassfish/glassfish/
#destFolderOnRemoteMachine=/tmp/

if [[ $# -eq 0 ]]; then 
echo -e "Envoyer le fichier vers le serveur distant à l'emplacement où les autorisations root sont nécessaires.\n\tutilisation: $0 nom_fichier_local [nom_utilisateur@](ip|hôte):(dossier_distant/|nom_fichier_distant) [interfaceOptionnelle=wlan0]"
echo -e "Exemple: \n\ttouch /tmp/justtest &&\n\t $0 /tmp/justtest remoteuser@ssh.superserver.com:/tmp/ "
exit 1
fi

localFilePath=$1

test -e $localFilePath 

destString=$2
usernameAndHost=$(echo $destString | cut -f1 -d':')

if [[ "$usernameAndHost" == *"@"* ]]; then
destUser=$(echo $usernameAndHost | cut -f1 -d'@')
destIP=$(echo $usernameAndHost | cut -f2 -d'@')
else
destIP=$usernameAndHost
destUser=$thisUser
fi

destFolderOnRemoteMachine=$(echo $destString | cut -f2 -d':')

set -e #arrêter le script s'il y a même une seule erreur

echo 'Première étape: nous devons pouvoir exécuter scp sans aucune interaction utilisateur'
echo 'générer la clé publique sur la machine qui recevra le fichier'
ssh $destUser@$destIP 'test -e ~/.ssh/id_rsa.pub -a -e ~/.ssh/id_rsa || ssh-keygen -t rsa'
echo 'Terminé'

echo 'Deuxième étape: télécharger la clé publique de la machine distante vers cette machine afin que cette machine autorise la machine distante (celle qui reçoit le fichier) à se connecter sans demander de mot de passe'

key=$(ssh $destUser@$destIP 'cat ~/.ssh/id_rsa.pub')
if ! grep "$key" ~/.ssh/authorized_keys; then
echo $key >> ~/.ssh/authorized_keys
echo 'Clé ajoutée aux hôtes autorisés'
else
echo "La clé existe déjà dans les clés autorisées"
fi

echo "Nous voulons exécuter la commande sudo à distance, ce qui signifie désactiver la demande de mot de passe"
echo 'Cela peut être fait en suivant ce tutoriel http://stackoverflow.com/a/10310407/781312'
echo 'Vous devrez le faire manuellement: '
echo -e "exécuter dans un nouveau terminal: \n\tssh $destUser:$destIP\nAppuyez sur Entrée lorsque vous êtes prêt"
read 
echo 'exécutez sudo visudo là-bas'
read
echo 'change '
echo '    %sudo   ALL=(ALL:ALL) ALL'
echo 'à'
echo '    %sudo   ALL=(ALL:ALL) NOPASSWD: ALL'
echo "Après cette étape, vous aurez terminé."
read

listOfFiles=$(ssh $destUser@$destIP "sudo ls -a")

if [[ "$listOfFiles" != "" ]]; then 
echo "Envoi en exécutant la commande, en fait, récupération, du fichier sur la machine distante"
echo 'Notez que cette commande (en raison de "" au lieu de '', voir man bash | less -p''quotes'') est remplie avec des valeurs de la machine locale'
echo -e "Exécution \n\t"identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"" \sur la machine distante"
ssh $destUser@$destIP "identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"
ssh $destUser@$destIP "ls ${destFolderOnRemoteMachine%\\\\n}/$(basename $localFilePath)"
if [[ ! "$?" -eq 0 ]]; then echo "erreur de validation"; else echo -e "SUCCÈS! Envoyé avec succès\n\t$localFilePath \nà \n\t$destString\nTrouvez-en plus sur http://arzoxadi.tk"; fi
else
echo "quelque chose s'est mal passé avec l'exécution de sudo sur l'hôte distant, échec"

fi
ENDOFSCRIPT
) | sudo tee /usr/bin/scpassudo && chmod +x /usr/bin/scpassudo

1voto

sigmunda Points 11

Vous pouvez combiner ssh, sudo et par exemple tar pour transférer des fichiers entre les serveurs sans pouvoir vous connecter en tant que root et sans avoir la permission d'accéder aux fichiers avec votre utilisateur. C'est un peu compliqué, c'est pourquoi j'ai écrit un script pour vous aider. Vous pouvez trouver le script ici : https://github.com/sigmunau/sudoscp

ou ici:

#! /bin/bash
res=0
from=$1
to=$2
shift
shift
files="$@"
if test -z "$from" -o -z "$to" -o -z "$files"
then
    echo "Utilisation: $0    (fichier)\*"
    echo "exemple: $0 serveur1 serveur2 /usr/bin/myapp"
    exit 1
fi

read -s -p "Entrez le mot de passe : " sudopassword
echo ""
temp1=$(mktemp)
temp2=$(mktemp)
(echo "$sudopassword";echo "$sudopassword"|ssh $from sudo -S tar c -P -C / $files 2>$temp1)|ssh $to sudo -S tar x -v -P -C / 2>$temp2
sourceres=${PIPESTATUS\[0\]}
if \[ $? -ne 0 -o $sourceres -ne 0 \]
then
    echo "Échec !" >&2
    echo "Sortie de $from :" >&2
    cat $temp1 >&2
    echo "" >&2
    echo "Sortie de $to :" >&2
    cat $temp2 >&2
    res=1
fi

rm $temp1 $temp2
exit $res

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X