Виберіть приватний ключ для використання з Git


84

У мене є 2 сервери Git, яким потрібні 2 різні ключі SSH.

git clone user1@server1:blahblahblahвикористовує ~/.ssh/id_rsa, але мені потрібно вказати, який ключ використовувати залежно від сервера, до якого я підключаюся.

Який параметр командного рядка Git виконує цю роботу? (Я працюю під Linux.)


2
Відповідь на це запитання надано на superuser.com/questions/232373/… .
Daira Hopwood


Відповіді:


60

Якщо ви підключаєтеся за допомогою SSH, тоді ключем керуватиме параметр SSH, а не параметр git.

SSH шукає у ~/.ssh/configфайлі параметри конфігурації. Змініть цей файл і додайте записи IdentityFile для двох серверів Git, як це:

Host server1.whatever.com
  IdentityFile /path/to/key_1
Host server2.whatever.com
  IdentityFile /path/to/key_2

У цій статті є кілька деталей.


13
Це не відповіло на запитання. Питання в тому, як мені надати git цей параметр, коли ssh обробляє авторизацію?
keks

@Keks: Ви не можете передавати аргументи ssh через командний рядок git. Ця відповідь дає обхідний шлях. Можливі й інші обхідні шляхи, наприклад git.wiki.kernel.org/index.php/… . Зверніть увагу, що цей підхід також не використовує аргументи командного рядка для зміни поведінки ssh.
Cameron Skinner

12
Це правда, однак ваша оригінальна відповідь не відповіла на запитання. Ви також можете використовувати ssh-agentі використовувати, ssh-addа потім просто використовувати git. Коли git підключається через ssh, ключ уже ввімкнено. Розумієте, є кілька способів, і ваша оригінальна відповідь просто не допомогла.
keks

Це відповідь лише на посилання. Не могли б ви узагальнити відповідні фрагменти статті у своїй відповіді?
Флімм

@Flimm: Підсумок додано.
Cameron Skinner

105

Є й інша можливість. Це встановити core.sshCommand, наприклад

git config --local core.sshCommand "/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo"

Існує один конкретний сценарій, коли ця стратегія є особливо корисною: це коли у вас є кілька облікових записів на Github, як і всі облікові записи sshGithub as, git@github.comі він використовує sshключ, щоб визначити, яким користувачем Github ви є. У цьому випадку ні, .ssh/configні ssh-agentробитиме те, що ти хочеш.

Оновлення - Ви не можете запустити вищезазначене, поки у вас не буде локального сховища, тому, якщо ви намагаєтеся клонувати віддалене сховище, вам потрібно буде вказати ключ вручну відповідно до відповіді drewbie18:

git clone -c core.sshCommand="/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo" git@github.com:me/repo.git

Після клонування сховища ви можете скористатися git configкомандою, щоб встановити це остаточно.


8
Це має бути обрана відповідь. Необхідна конфігурація гарно локалізована у сховищі, яке має використовувати інший ключ ssh для доступу до різних серверів git. Не потрібно змінювати ~ / .ssh / config (і навіть / etc / hosts, у випадку кількох облікових записів на GitHub).
mr.b

1
Однак є одна проблема: ви не можете клонувати репо перед тим, як його налаштувати, і для того, щоб його налаштувати, потрібно спершу клонувати його. АБО, ви можете git initзробити репо, налаштувати його локально, щоб використовувати правильну команду ssh, а потім додати віддалений (3 кроки, порівняно лише з 1 з "git clone").
mr.b

3
Щоб клонувати репо, я б використав рішення @ Guss нижче, встановивши змінну середовища GIT_SSH_COMMAND. Але при звичайному використанні я віддаю перевагу своєму рішенню, оскільки воно уникає необхідності повторного експорту цієї змінної кожного разу, коли я запускаю нову оболонку.
Річард Сміт,

рятівник! є маса людей, які показують, як використовувати ./ssh/config, щоб налаштувати це, та використовують ssh-agent / ssh-add -K для mac. Користувався ним рік, але він раптово перестав працювати в High Sierra з останніми патчами. core.sshCommand працював, коли все інше не спрацьовувало. Дякую!
Стів

2
Дякуємо за це елегантне рішення. Однак я просто хочу уточнити, що core.sshCommand доступний лише для git> = 2.10.0
slonepi

32

Як правило, ви хочете використовувати ~/.ssh/configдля цього. Просто з'єднайте адреси сервера з ключами, які ви хочете використовувати для них, наступним чином:

Host github.com
  IdentityFile ~/.ssh/id_rsa.github
Host heroku.com
  IdentityFile ~/.ssh/id_rsa.heroku
Host *
  IdentityFile ~/.ssh/id_rsa

Host *позначає будь-який сервер, тому я використовую його для встановлення ~/.ssh/id_rsaв якості ключа за замовчуванням для використання.


9
Ця ідея не працює, якщо у вас є кілька облікових записів на одному сервері, як-от GitHub, і вам потрібен інший приватний ключ для кожного.
Флімм

Для кількох облікових записів на одному сервері см ця відповідь stackoverflow.com/questions/3225862 / ...
lexicalscope

23

У моєму сценарії, подібному до сценарію @Richard Smith (рішення якого, BTW, для мене не працювало), мені потрібно використовувати різні ключі для одного сервера в різних сховищах.

Обхідним шляхом для мене було правильно налаштувати сеанс із змінною середовища GIT_SSH_COMMAND, наприклад:

export GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/my-secret-identitiy"

Оновлення :

Ще одне, на що слід звернути увагу, це те, що правильне встановлення змінної середовища може бути суєтою, тому я використовую засоби модифікації командного рядка, що надаються такими речами, як Liquid Prompt або Fish Shell, щоб зачепити оболонку і продовжувати оновлювати змінні середовища відповідно до поточний каталог та деякі правила. Наприклад, усі мої особисті проекти, які потребують мого персонального ключа SSH з Gitlab, знаходяться, ~/Documents/Projects/personalтому, коли хук оболонки запускається pwdі виявляє, що поточний каталог знаходиться під цим шляхом, він автоматично встановлює GIT_SSH_COMMANDзмінні за необхідності.


15

Використовуйте ssh-add path-to-private-keyце працює нестандартно.


5
Ні, якщо у вас є два ключі розгортання, і вони працюють лише з певними сховищами. У цьому випадку він може використовувати неправильний ключ і сказати, що у вас немає доступу.
cdmckay

У мене проблема cdmckay сказав
Suge

7

Ви можете встановити --global або --local конфігурацію, глобальний оновить ~/.gitconfigфайл, локальний оновить конфігурацію у сховищі .git/configта замінить глобальну конфігурацію (~ / .gitconfig)

git config --local --add core.sshCommand 'ssh -i ~ / .ssh / my_key'


2
працював як шарм, це було саме те, що мені потрібно, рішення для конкретного репо.
Quaestor Lucem

6

Користувач Windows тут, я щойно зіткнувся з цією проблемою і маю дещо інше рішення, ніж я читав тут до цього часу. Проблема, з якою я зіткнувся, полягає в тому, що я просто хотів клонувати репо за допомогою певного приватного ключа ssh і не мусив глобально налаштовувати конфігурацію git або додавати конкретні налаштування git bash, оскільки я роблю свою роботу в PowerShell. По суті, я просто хочу, щоб деякі приватні ключі сиділи в моїй папці .ssh, і я посилаюся на них у певних репозиторіях, якщо потрібно.

Для цього працює наступна команда:

git clone -c core.sshCommand="ssh -i ~/.ssh/<PRIVATE KEY NAME>" <CLONE URL>

По суті, це робиться після ініціалізації репозиторію git, він встановлює опцію core.sshCommand перед запуском клону. Тож конкретна клавіша ssh, яку ви хочете використовувати для цього репо, встановлюється ТІЛЬКИ для цього репо. Це може бути не ідеальним рішенням для всіх випадків, але для того, що я хочу, воно є.


Дякую. Я не знав про -cваріант git clone. Це краще, ніж встановлення середовища, як я пропоную при клонуванні.
Richard Smith

1

Інші відповіді надихнули мене на написання невеликого сценарію, який вибирає ключ ssh залежно від параметрів командного рядка або (якщо є) значень git remote -v. Сподіваюся, це допоможе!

Щоб насправді відповісти на питання: Використовуйте gat.

Див. Також https://bitbucket.org/eikerobert/gat/src/master/

#!/bin/bash

usegat=false

for VAR in "$@"
do
    if [ "$VAR" != "${VAR/git@bitbucket.org:myaccount/}" ]; then
        usegat=true
    fi
done

if [ $usegat=false ]; then
   /usr/bin/git rev-parse --is-inside-work-tree >/dev/null 2>&1
   isinsidegitrepo=$?
    #echo $isinsidegitrepo
   if [ $isinsidegitrepo = 0 ]; then
       remote=`/usr/bin/git remote -v`
       if [ "$remote" != "${remote/git@bitbucket.org:myaccount/}" ]; then
           usegat=true
       fi
   fi
fi


if [ $usegat = true ]; then
    # echo "TRUE"
    /usr/bin/git -c core.sshCommand="/usr/bin/ssh -i /home/myaccount/.ssh/mykey" "$@"
else
     #echo "FALSE"
    /usr/bin/git "$@"
fi

1

Інший варіант - написати невеликий скрипт, щоб зробити core.sshCommandтрохи розумнішим - перевірте, чи в поточному робочому каталозі налаштований певний ключ SSH, і якщо так, використовуйте його, інакше - покладайтеся на стандартну роздільну здатність ключа SSH.

Ось моя перша версія:

#!/bin/bash
key="$(git config ssh.key)"
if [ -n "$key" ]; then
        ssh -o IdentitiesOnly=yes -i "$key" "$@"
else
        ssh "$@"
fi

Потім встановіть його як глобальну команду git SSH:

chmod 755 ~/.local/bin/git-ssh-command
git config --global core.sshCommand ~/.local/bin/git-ssh-command

( ~/.local/binце поточний стандарт "розміщувати тут скрипти користувачів" в операційних системах SystemD )

Після цього ви можете налаштувати будь-яке сховище на використання певного ключа SSH, встановивши параметр конфігурації ssh.key:

git config --local ssh.key ~/.ssh/my-non-default-private-key

Додаткові необов’язкові хитрощі

  • Встановіть для глобального ssh.keyзначення "резервний резервний ключ до SSH-ключа, який не є типовим" або щось інше.
  • Коли git виконується core.sshCommandв кореневому каталозі сховища, ви git-ssh-commandможете переглядати це та мати певну евристику щодо імен каталогів. Це можна зробити в elseрозділі, тому евристика вводиться лише в тому випадку, якщо немає конкретного ключа ssh.key.
  • Ви можете додати git remote -vгалочку, щоб додати евристику на основі пультів дистанційного керування, як у сценарії Ейке
  • Якщо ви хочете переглянути пульти сховища, але маєте кілька пультів дистанційного керування, які потребують різних ключів, ви можете додати remote="$1:$(sed "s,.* ,,;s,',,g"<<<"$2")"на початку сценарію, щоб вирішити проблему, на якій експлуатується пульт - і перевірити це (це $remoteбуде виглядати як середній стовпець на git remote -vвиході).

Оновлення:

Ось версія користувацької команди SSH, яка переглядає віддалену URL-адресу та виконує певні евристики - у моєму випадку у мене є кілька різних ідентифікаційних даних з однією і тією ж публічною службою хостингу git (одна для роботи, одна для особистого тощо), і я можу вибрати правильну ідентифікацію, переглянувши віддалену URL-адресу (вивчаючи групу Gitlab або організацію Github тощо):

#!/bin/bash
if [[ "$2" =~ ^git-lfs-authenticate.* ]]; then # reconstruct url for git-lfs
        remote="$1:$(awk '{print$2}'<<<"$2")"
else # reconstruct url for standard git commands
        remote="$1:$(sed "s,.* ,,;s,',,g"<<<"$2")"
fi
#echo "Detected $remote from $@" >&2 # optional debug log
key="$(git config ssh.key)"
if [ -n "$key" ]; then # use specified SSH key, if set
        ssh -o IdentitiesOnly=yes -i "$key" "$@"
elif [[ "$remote" == git@gitlab.com:my-company* ]]; then # use company id
        ssh -o IdentitiesOnly=yes -i ~/.ssh/company-id "$@"
elif [[ "$remote" =~ git@bitbucket.org:.*other-org.* ]]; then # bitbucket has weird urls
        ssh -o IdentitiesOnly=yes -i ~/.ssh/custom-org-key "$@"
else # otherwise use whatever the agent has (my personal key)
        ssh "$@"
fi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.