Можете ли вы указать git-shell в .ssh / authorized_keys, чтобы ограничить доступ только к командам git через ssh?

37

Я хотел бы иметь возможность использовать ключ ssh для аутентификации, но все же ограничить команды, которые могут быть выполнены через туннель ssh.

С Subversion я достиг этого, используя файл .ssh / authorized_keys, например:

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...

Я пробовал это с "/ usr / bin / git-shell" в команде, но я просто получаю старое fatal: What do you think I am? A shell?сообщение об ошибке.

Мэтт Коннолли
источник

Ответы:

30

Следующее работает для меня.

В ~/.ssh/authorized_keys:

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

В ~/gitserveсценарии:

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

Обратите внимание, что если вы поместите что- gitserveто другое, чем домашний каталог, вам придется настроить command="./gitserve"параметр в authorized_keys.

Нил Мэйхью
источник
Бинго! Это работает так же, как то, что я надеялся достичь! Спасибо.
Мэтт Коннолли
В этом сообщении на SO stackoverflow.com/questions/5871652/… они указывают на другое решение здесь: joey.kitenet.net/blog/entry/locking_down_ssh_authorized_keys
Тим
1
@Tim Это по сути то же самое решение, но сжимает содержимое моего скрипта ~ / gitserve в авторизованные ключи с помощью perl. Лично я предпочитаю держать это в отдельном сценарии.
Нил Мэйхью
1
Я понимаю, я просто добавил это как ссылку.
Тим
На какую оболочку у вас настроен пользователь в этой конфигурации? /bin/bash?
M-Pixel
33

Я мог бы успешно использовать git-shell непосредственно в файле авторизованных ключах без использования дополнительного скрипта.

Ключ должен добавить \"вокруг переменной env.

Протестировано в 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
источник
+1 это правильный ответ, см. Svnweb.freebsd.org/base/head/crypto/openssh/…
Тино
2
Лично я бы дал полный путь git-shell, но это может быть просто паранойя.
Ульрих Шварц
Кто-нибудь нашел способ ограничения каталога, к которому у него есть доступ? Я обнаружил, что могу выполнить переход в каталог до запуска git-shell, но git-shell допускает ".." и абсолютные пути.
yokto
5

Решение Grawity можно легко модифицировать для работы, заменив линию

        exec $SSH_ORIGINAL_COMMAND

с линией

        git-shell -c "$SSH_ORIGINAL_COMMAND"

Кавычки решают проблемы, о которых говорилось выше, и замена exec на git-shell кажется более безопасной.

dschwen
источник
4

git-shellпредназначен для использования в качестве оболочки входа в систему, чтобы он мог получать в -c "originalcommand"качестве аргументов. Этого не происходит с «принудительными командами» в OpenSSH; вместо этого принудительная команда передается в настроенную оболочку.

Что вы можете сделать, это написать скрипт, который проверяет $SSH_ORIGINAL_COMMANDи выполняет его. Пример в 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
grawity
источник
@Matt: git-shell (1) говорит, что команды есть git <cmd>, не так git-<cmd>ли?
Гравитация
Хм ... Я сделал это изменение в соответствии с тем, что я увидел, когда запустил его. Как с bash-скриптом, так и с ruby-скриптом я увидел команду git-receive-pack. Цитата из моего man git-shell(git 1.7.3.4): В настоящее время разрешено вызывать только четыре команды: git-receive-pack, git-upload-pack и git-upload-archive с одним обязательным аргументом, или сервер cvs (для вызова git -cvsserver).
Мэтт Коннолли
форматирование не работает в комментариях :(
Мэтт Коннолли
1
Это не работает для меня, потому что мой клиент git (1.7.5.4) отправляет имя репо в одинарных кавычках, предположительно потому, что он ожидает, что вся командная строка интерпретируется оболочкой. Затем exec $ SSH_ORIGINAL_COMMAND передает одинарные кавычки в git-receive-pack и т. Д., Которые поэтому не находят хранилище.
Нил Мэйхью
Спасибо за решение, спасибо, но оно не работает для меня, по той же причине, о которой сообщил Нил Мэйхью ... Моя версия git 1.7.x также отправляет имя репо в одинарных кавычках, что в конечном итоге приводит к $SSH_ORIGINAL_COMMANDтому, что недействительным и вызывающим git-shellзадницу :-(
pvandenberk
1

Я не смог заставить работать решение grawity по той же причине, о которой сообщил Нил Мэйхью (т.е. одинарные кавычки, отправленные git-клиентом, вызвали недействительность $SSH_ORIGINAL_COMMAND- я использую git v1.7.x)

Однако следующее решение, реализованное @moocode, просто работает:

https://moocode.com/posts/6-code-your-own-multi-user-private-git-server-in-5-minutes

Руби FTW! :-)

pvandenberk
источник
1

Для полноты картины , а так как исходный вопрос не указать , что та же учетная запись должна была быть полезной для не GIT вещей, очевидный ответ заключается в использовании , git-shellкак он был разработан для использования: установить его в качестве регистрационной оболочки (т.е. usermod, в /etc/passwd) для этого пользователя SSH.

Если у вас есть одна учетная запись, которую вы хотите использовать двумя способами:

  • при соединении с ключом аутентификации используйте только для git
  • при подключении с аутентификацией по паролю или с использованием другого закрытого ключа предоставьте полную оболочку

... тогда применяются другие ответы в этой теме. Но если вы можете позволить себе выделить отдельного пользователя для git, то установка его оболочки git-shell- это самый простой способ ограничить его, и он немного более безопасен, так как не требует дополнительных сценариев оболочки.

Феликс
источник