Você pode especificar o git-shell em .ssh / allowed_keys para restringir o acesso apenas aos comandos git via ssh?

37

Eu gostaria de poder usar uma chave ssh para autenticação, mas ainda assim restringir os comandos que podem ser executados no túnel ssh.

Com o Subversion, consegui isso usando um arquivo .ssh / allowed_keys como:

command="/usr/local/bin/svnserve -t --tunnel-user matt -r /path/to/repository",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAABIetc...

Eu tentei isso com "/ usr / bin / git-shell" no comando, mas recebo apenas a antiga fatal: What do you think I am? A shell?mensagem de erro antiga .

Matt Connolly
fonte

Respostas:

30

O seguinte funciona para mim.

Em ~/.ssh/authorized_keys:

command="./gitserve",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-dss AAAAB…

No ~/gitservescript:

#!/bin/sh
exec git-shell -c "$SSH_ORIGINAL_COMMAND"

Note que se você colocar gitservealgum lugar diferente do diretório home, você terá que ajustar o command="./gitserve"parâmetro authorized_keys.

Neil Mayhew
fonte
Bingo! Isso funciona exatamente como o que eu esperava alcançar! Obrigado.
Matt Connolly
Neste post relacionado no SO stackoverflow.com/questions/5871652/... eles apontam para uma outra solução aqui: joey.kitenet.net/blog/entry/locking_down_ssh_authorized_keys
Tim
11
@ Tim Esta é essencialmente a mesma solução, mas comprime o conteúdo do meu script ~ / gitserve em chaves autorizadas usando perl. Pessoalmente, prefiro mantê-lo em um script separado.
Neil Mayhew
11
Entendo, apenas o adicionei como referência.
Tim
Em qual shell você definiu o usuário nesta configuração? /bin/bash?
M-Pixel
33

Eu poderia usar o git-shell com sucesso diretamente no arquivo allowedKeys sem usar um script adicional.

A chave é adicionar em \"torno da variável env.

Testado em rhel6 openssh-server-5.3p1-70.el6.x86_64:

no-port-forwarding,no-agent-forwarding,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-dss AAAA...
sophana
fonte
+1 é a resposta correta, consulte svnweb.freebsd.org/base/head/crypto/openssh/…
Tino
2
Pessoalmente, eu daria o caminho completo git-shell, mas isso pode ser apenas paranóia.
Ulrich Schwarz
Alguém encontrou uma maneira de restringir o diretório ao qual ele tem acesso? Eu descobri que posso cd em um diretório antes de executar o git-shell, mas o git-shell permite ".." e caminhos absolutos.
yokto
5

A solução da Grawity pode ser facilmente modificada para funcionar, substituindo a linha

        exec $SSH_ORIGINAL_COMMAND

com a linha

        git-shell -c "$SSH_ORIGINAL_COMMAND"

As aspas resolvem os problemas relatados acima e a substituição de exec por git-shell parece um pouco mais segura.

dschwen
fonte
4

git-shellfoi projetado para ser usado como um shell de logon, para receber -c "originalcommand"como argumentos. Isso não acontece com "comandos forçados" no OpenSSH; em vez disso, o comando forçado é passado para o shell configurado.

O que você pode fazer é escrever um script que o verifique $SSH_ORIGINAL_COMMANDe execute. Exemplo no bash :

#!/bin/bash

SSH_ORIGINAL_COMMAND=${SSH_ORIGINAL_COMMAND/#git /git-}

case $SSH_ORIGINAL_COMMAND in
    "git-receive-pack"*|"git-upload-pack"*|"git-upload-archive"*)
        eval exec $SSH_ORIGINAL_COMMAND
        ;;
    *)
        echo "Go away." >&2
        exit 1
        ;;
esac
gravidade
fonte
@ Matt: git-shell (1) diz que os comandos git <cmd>não são git-<cmd>?
grawity
Hmm ... fiz essa alteração de acordo com o que vi quando a executei. Com o script bash e o ruby, vi "git-receive-pack" como o comando. Citação de my man git-shell(git 1.7.3.4): Atualmente, apenas quatro comandos podem ser chamados, git-receive-pack git-upload-pack e git-upload-archive com um único argumento necessário ou servidor cvs (para chamar o git -cvsserver).
Matt Connolly
formatação não funciona nos comentários :(
Matt Connolly
11
Isso não funciona para mim, porque meu cliente git (1.7.5.4) envia o nome do repo entre aspas simples, presumivelmente porque espera ter toda a linha de comando interpretada por um shell. O exec $ SSH_ORIGINAL_COMMAND passa as aspas simples para o git-receive-pack etc. que, portanto, não encontram o repositório.
Neil Mayhew
Obrigado pela solução, grawity, mas não funciona para mim, pelo mesmo motivo relatado por Neil Mayhew ... minha versão 1.7.x do git também envia o nome do repo entre aspas simples, fazendo $SSH_ORIGINAL_COMMANDcom que seja inválido, e causando git-shellbum out :-(
pvandenberk
1

Para garantir a integridade, e como a pergunta original não especificou que a mesma conta deveria ser usada para coisas que não são do git, a resposta óbvia é usar git-shellcomo foi projetada para ser usada: defina-a como o shell de login (ou seja usermod, com , in /etc/passwd) para esse usuário ssh.

Se você possui uma única conta de usuário que deseja usar de duas maneiras:

  • ao conectar com autenticação de chave, use apenas para git
  • ao conectar-se com autenticação por senha ou usar uma chave privada diferente, forneça um shell completo

... então as outras respostas neste tópico se aplicam. Mas se você puder alocar um usuário separado para o git, definir seu shell como git-shella maneira mais simples de restringi-lo e é um pouco mais seguro, pois não requer scripts de shell adicionais.

Felix
fonte