Кому интересно проверить свои знания, прочитайте задачку и попробуйте сначала сами ответить, а потом уже загляните под кат.
Итак: настроил я на работе git-сервер на базе gitolite. Доступ к репозиториям там осуществляется по ssh под юзером git, аутентификация только по ключам, пароли не работают. Я скопировал туда все нужные репозитории, занёс ssh-ключи всех сотрудников с jumpbox’а, руководитель разработчиков настроил своим сотрудникам права доступа к нужным репозиториям, написал им инструкцию, и они стали работать с этим сервером.
У большинства юзеров всё нормально, но один вдруг пожаловался, что он до репозитория достучаться не может, у него спрашивают пароль юзера git, а он его не знает..
Попросил его процитировать команду, которую он запускает, и последующие сообщения. Команда правильная: git clone git@gitserver:repository, но ssh сначала спрашивает пароль от ssh-ключа, а потом действительно пароль юзера git@gitserver.
Очевидно, это означает, что аутентифицикация по ключу почему-то не срабатывает. Я пошёл проверять. В gitolite-admin/keydir/ публичный ключ юзера есть, тот самый, что на jumpbox’е. Так чего ж он не работает? Посмотрел в security log на сервере, а там sshd: Invalid user \302\240git from 10.x.x.x
Загадка нумер раз: что это за чушь, и как её пофиксить?
Пофиксил. Дальше юзер скопировал свои ssh-ключи (приватный и публичный) с jumpbox’а на свой десктоп, где у него стоит Linux Mint, и попробовал достучаться до того же репозитория. Ан.. у него опять спрашивают пароль юзера git. Посмотрел в лог, а там опять ошибка, но уже другая: Postponed publickey for git from 10.x.x.x port ***** ssh2. Попросил юзера проверить совпадение ключей, и нет ли у него в ~/.ssh/ каких-нибудь других. Нет, говорит, старые ключи переложил в другую директорию, и вместо них положил новые. Итак, ключи те же самые, но не работают.
Загадка нумер два: а фигли ж одинаковые ключи с одной машины работают, а с другой нет?! Ну и это я довольно быстро отгадал и исправил.
Отгадки:
1) \302\240 – это два байта в восьмиричном виде. В шестнадцатиричном это C2 A0, что есть (non-breaking space) в UTF-8. То есть, второй пробел перед именем юзера git хоть и выглядит, как первый, но при разборе командной строки не воспринимается как пробел, что и приводит к передаче неправильного имени на сервер. А откуда там этот символ взялся? Вероятно, как-то попал в файл с инструкцией, и при копировании оттуда командной строки привёл к этой ошибке.
Я предложил юзеру не копировать строку, а набрать её вручную, и всё заработало.
2) В большинстве нынешних линуксов автоматически запускается ssh-agent, который подцепляет имеющиеся в ~/.ssh/ ключи, вот он старые ключи и подцепил, а про новые ничего и не знал. А ssh по умолчанию пользуется ssh-agent’ом, поэтому новые ключи он тоже игнорировал.
Лечится это путём перезапуска ssh-agent’а, но просто так его убить не получается. Придётся или перегрузить машину, чтобы ssh-agent при запуске уже не нашёл старых ключей, или руками запустить новый экземпляр ssh-agent’а, указать его сокет в environment и подсунуть ему новый ключ, ну или просто спрятать ненужный ssh-agent от ssh: unset SSH_AUTH_SOCK.
Оригинал этой записи в личном блоге.