Укажите ключ SSH для git push для данного домена

342

У меня есть следующий вариант использования: я хотел бы иметь возможность git@git.company.com:gitolite-adminиспользовать личный ключ пользователя gitolite-admin, в то время как я хочу git@git.company.com:some_repoиспользовать собственный ключ. AFAIK, я не могу решить это с помощью ~/.ssh/config, потому что имя пользователя и имя сервера идентичны в обоих случаях. Поскольку я в основном использую свой собственный закрытый ключ, я определил его в ~/.ssh/configfor git@git.company.com. Кто-нибудь знает способ переопределить ключ, который используется для одного gitвызова?

(Кроме того, gitolite различает, кто выполняет нажатие на основе ключа, поэтому с точки зрения доступа, владения и аудита не проблема, что строка user @ server одинакова для разных пользователей.)

Спутанность сознания
источник
Тесно связаны: stackoverflow.com/questions/4565700/…
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

597

Даже если пользователь и хост совпадают, их все равно можно различить ~/.ssh/config. Например, если ваша конфигурация выглядит следующим образом:

Host gitolite-as-alice
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_rsa.alice
  IdentitiesOnly yes

Host gitolite-as-bob
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_dsa.bob
  IdentitiesOnly yes

Тогда вы просто используете gitolite-as-aliceи gitolite-as-bobвместо имени хоста в вашем URL:

git remote add alice git@gitolite-as-alice:whatever.git
git remote add bob git@gitolite-as-bob:whatever.git

Заметка

Вы хотите включить опцию, IdentitiesOnly yesчтобы предотвратить использование идентификаторов по умолчанию. В противном случае, если у вас также есть идентификаторы, совпадающие с именами по умолчанию, они будут опробованы в первую очередь, потому что в отличие от других параметров конфигурации (которые учитывают «сначала в выигрышах»), IdentityFileопция добавляется в список идентификаторов, которые нужно попробовать. См .: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Марк Лонгэйр
источник
9
Здорово, спасибо. Я не понял, что вы можете свободно выбрать «псевдоним» для спецификации хоста в ~ / .ssh / config
Confusion
4
Спасибо за этот ответ! Одна проблема для меня заключалась в том, что IdentityFile должен быть полным путем (я только указал id_rsa.rick в качестве аргумента IdentityFile, и это не удалось). См. Справочную страницу ssh_config (5) для другого синтаксиса для IdentityFile.
Рикумали
1
Большое спасибо за ясный и очень полезный ответ. Я пытался заставить это работать некоторое время и отказывался раньше, предполагая, что один и тот же пользователь должен был использовать тот же файл закрытого ключа id_rsa.
DrCord
7
git@Часть в пульте дистанционного управления не является необходимой , как оно дано в Userстроке конфигурации.
Дольмен
2
Я боролся с этим решением, пока не добавил еще одну строку, содержащую IdentitiesOnly yesсразу после строки IdentityFileдля хоста. Кажется, он передавал несколько идентификаторов, и один из них был заблокирован от доступа к хосту.
Установщик
57

Альтернативный подход, предложенный Марком Лонгэйром выше, заключается в использовании псевдонима, который будет запускать любую команду git на любом удаленном компьютере с альтернативным ключом SSH. Идея в основном состоит в том, чтобы переключать вашу личность SSH при запуске команд git.

Преимущества относительно подхода псевдонима хоста в другом ответе:

  • Будет работать с любыми командами или псевдонимами git, даже если вы не можете указать remoteявно.
  • Проще работать со многими репозиториями, потому что вам нужно настроить его только один раз для каждого клиентского компьютера, а не один раз для каждого репозитория на каждом клиентском компьютере.

Я использую несколько небольших скриптов и псевдоним git admin. Таким образом, я могу сделать, например:

git admin push 

Чтобы нажать на пульт по умолчанию, используя альтернативный ("admin") ключ SSH. Опять же, вы можете использовать любую команду (не только push) с этим псевдонимом. Вы могли бы даже сделать git admin clone ...клонирование хранилища, к которому у вас был бы доступ только с помощью вашего ключа «admin».

Шаг 1: Создайте альтернативные ключи SSH, при желании установите пароль, если вы делаете это на чужой машине.

Шаг 2: Создайте скрипт с именем «ssh-as.sh», который запускает материал, который использует SSH, но использует заданный ключ SSH, а не по умолчанию:

#!/bin/bash
exec ssh ${SSH_KEYFILE+-i "$SSH_KEYFILE"} "$@"

Шаг 3: Создайте скрипт с именем «git-as.sh», который запускает команды git с использованием данного ключа SSH.

#!/bin/bash
SSH_KEYFILE=$1 GIT_SSH=${BASH_SOURCE%/*}/ssh-as.sh exec git "${@:2}"

Шаг 4: Добавьте псевдоним (используя что-то подходящее для «PATH_TO_SCRIPTS_DIR» ниже):

# Run git commands as the SSH identity provided by the keyfile ~/.ssh/admin
git config --global alias.admin \!"PATH_TO_SCRIPTS_DIR/git-as.sh ~/.ssh/admin"

Более подробная информация на: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

sinelaw
источник
4
Очень хороший ответ. Не забудьте добавить двойные кавычки вокруг $@-> "$@"чтобы быть в безопасности.
Кевинарпе
@sinelaw Это все еще работает? Я все время получаю сообщение об ошибке «
Alok Kumar
56

Вы можете использовать переменную окружения git GIT_SSH_COMMAND. Запустите это в своем терминале под своим репозиторием git:

GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key' git submodule update --init

Замените ~/.ssh/your_private_keyпуть к секретному ключу ssh, который вы хотите использовать. И вы можете изменить последующую команду git (в примере есть git submodule update --init) на другие, например git pull, git fetchи т. Д.

Hustlion
источник
1
Полный документ находится по адресу git-scm.com/docs/git#git-codeGITSSHcode ; ему нужен недавний Git (> = 2.3. *).
Кристиан Ульбрих
2
Спасибо за простое решение, которое не требует ничего, кроме установки одной переменной среды.
Ноа Суссман
4
Обратите внимание, что ваш ~ / .ssh / id_rsa (или любой другой ключ по умолчанию) будет иметь приоритет над тем, который вы передаете через -i. Поэтому вы действительно хотите использовать GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes', чтобы игнорировать другие ключи
staktrace
как вы можете обновить git push? Я не смог найти это в документации
lebed2045
Было бы неплохо создать псевдонимы bash или git - по аналогии с ответом sinelaw, но с использованием этого метода вместо необходимости где-то создавать скрипты.
Иниго
14

В системах на основе Unix (Linux, BSD, Mac OS X) идентификатор по умолчанию хранится в каталоге $ HOME / .ssh в 2 файлах: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub при использовании sshбез параметра -iиспользуется закрытый ключ по умолчанию для аутентификации на удаленной системе.

Если у вас есть другой закрытый ключ, который вы хотите использовать, например, $ HOME / .ssh / deploy_key , вы должны использоватьssh -i ~/.ssh/deploy_key ...

Это раздражает. Вы можете добавить следующие строки в ваш $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Поэтому каждый раз, когда вы используете sshили gitили scp(в основном sshтоже), вам больше не нужно использовать опцию -i.

Вы можете добавить столько ключей, сколько захотите, в файле $ HOME / .bash_profile .

Châu Hồng Lĩnh
источник
10

Другой альтернативой является использование ssh-идент для управления вашими ssh-идентичностями .

Он автоматически загружает и использует различные ключи в зависимости от вашего текущего рабочего каталога, параметров ssh и т. Д. ... это означает, что вы можете легко иметь каталог work / directory и private /, который прозрачно в конечном итоге использует различные ключи и идентификаторы с ssh.

rabexc
источник
9

Я использую Git Bash на Win7. Следующее сработало для меня.

Создайте файл конфигурации в ~ / .ssh / config или в c: / users / [your_user_name] /. Ssh / config. В файле введите:

Host your_host.com
     IdentityFile [absolute_path_to_your_.ssh]\id_rsa

Я думаю, что хост должен быть URL-адресом, а не просто именем или ссылкой для вашего хоста. Например,

Host github.com
     IdentityFile c:/users/[user_name]/.ssh/id_rsa

Путь также может быть записан в формате / c / users / [user_name] / ....

Решение, предоставленное Джордано Скальцо, также великолепно. https://stackoverflow.com/a/9149518/1738546

user1738546
источник
9

Начиная с git 2.10 и выше, также можно использовать настройку gitconfig sshCommand. Документы утверждают :

Если эта переменная установлена, git fetch и git push будут использовать указанную команду вместо ssh, когда им необходимо подключиться к удаленной системе. Команда находится в той же форме, что и переменная среды GIT_SSH_COMMAND, и переопределяется при установке переменной среды.

Пример использования будет: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

В некоторых случаях это не работает, потому что ssh_config переопределяет команду, в этом случае старайтесь ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nullне использовать ssh_config.

firfin
источник
8

Я собрал вместе и протестировал с github следующий подход, основанный на чтении других ответов, который сочетает в себе несколько приемов:

  • правильная конфигурация SSH
  • переписывание git URL

Преимущество этого подхода в том, что после настройки он не требует дополнительной работы для правильной настройки - например, вам не нужно менять удаленные URL-адреса или помнить, что нужно клонировать объекты по-другому - перезапись URL-адреса делает все это работоспособным ,

~/.ssh/config

# Personal GitHub
Host github.com
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/github_id_rsa

# Work GitHub
Host github-work
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/work_github_id_rsa

Host *
  IdentitiesOnly yes

~/.gitconfig

[user]
    name = My Name
    email = personal@personal.email

[includeIf "gitdir:~/dev/work/"]
    path = ~/dev/work/.gitconfig

[url "github-work:work-github-org/"]
    insteadOf = git@github.com:work-github-org/

~/dev/work/.gitconfig

[user]
    email = work@work.email

Пока вы храните все свои рабочие репозитории в ~ / dev / work и личные вещи в других местах, git будет использовать правильный SSH-ключ при выполнении команды pull / clones / pushes на сервере, а также будет прикреплять правильный адрес электронной почты ко всем ваши коммиты.

Ссылки:

Karlos
источник
Как это работает с клонированием? includeIfдолжен работать, только если есть .gitкаталог, который я подумал?
detly
Подождите, я понял, это перезапись URL, который заботится об этом. Этот ответ невероятно полезен!
детально
4

При использовании sit-версии Git для Windows строка файла идентификации в конфигурации ssh выглядит так:

IdentityFile /c/Users/Whoever/.ssh/id_rsa.alice

где /cдляc:

Чтобы проверить, в Git's Bash сделать

cd ~/.ssh
pwd 
Эндрю Мерфи
источник
3

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

ViliusK
источник
1

Вы больше всего указали в файле конфигурации ключ ssh:

# Default GitHub user
Host one
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-one
 IdentitiesOnly yes

#two user
Host two
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-two
 IdentitiesOnly yes
Диего Санта Круз Мендесу
источник
0

Как уже упоминалось, core.sshCommandconfig может использоваться для переопределения ключа SSH и других параметров.

Вот пример, где у вас есть альтернативный ключ с именем ~/.ssh/workrsaи вы хотите использовать его для всех клонированных репозиториев ~/work.

  1. Создайте новый .gitconfigфайл в разделе ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. В вашей глобальной конфигурации git ~/.gitconfigдобавьте:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Mansour
источник
0

Одной из возможностей использования ~/.ssh/configявляется использование Matchограничения вместо Hostограничения. В частности, Match Execвызывает команду оболочки, чтобы решить, применять ли объявления или нет. В bash вы можете использовать следующую команду:

[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]

Это использует команду bash, [чтобы проверить, равны ли две строки. В этом случае он проверяет, соответствует ли строка git@git.company.com:gitolite-adminвыводу, полученному из $(git config --get remote.origin.url)''команды.

Вы можете использовать любую другую команду, которая идентифицирует хранилище, в котором находится оболочка. Для этого важно, чтобы $SHELLв моем случае была определена переменная для вашей оболочки /bin/bash. Полный пример будет следующим ~/.ssh/config:

Match Exec "[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Match Exec "[ git@git.company.com:some_repo = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

В этом примере я предположил, что он ~/.ssh/yourOwnPrivateKeyсодержит ваш собственный закрытый ключ и который ~/.ssh/gitolite-adminсодержит закрытый ключ пользователя gitolite-admin. Я включил IdentitiesOnly yesдекларацию, чтобы убедиться, что на git-сервер предлагается только один ключ, упомянутый Марком Лонгэйром . Другие объявления - это просто стандартные опции ssh для git.

Вы можете добавить эту конфигурацию, если у вас есть несколько, some_repoкоторые вы хотите использовать с разными ключами. Если у вас есть несколько репозиториев, git@git.company.comи большинство из них используют, ~/.ssh/yourOwnPrivateKeyимеет смысл включить этот ключ по умолчанию для хоста. В этом случае ~/.ssh/configбудет:

Match Exec "[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes

Host git.company.com
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Обратите внимание, что порядок имеет значение, и Host git.company.comограничение должно появиться после Match Execодного или одного.

LuisR
источник
0

Настройте свой репозиторий, используя git config. Например:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
episage
источник