Podaj klucz SSH dla git push dla danej domeny

342

Mam następujący przypadek użycia: Chciałbym móc naciskać na [email protected]:gitolite-adminużywanie klucza prywatnego użytkownika gitolite-admin, natomiast chcę naciskać na [email protected]:some_repoużywanie „własnego” klucza prywatnego. AFAIK, nie mogę rozwiązać tego za pomocą ~/.ssh/config, ponieważ nazwa użytkownika i nazwa serwera są identyczne w obu przypadkach. Ponieważ w większości używam własnego klucza prywatnego, zdefiniowałem go ~/.ssh/configdla [email protected]. Czy ktoś zna sposób na zastąpienie klucza używanego do pojedynczego gitwywołania?

(Poza tym: gitolite rozróżnia, kto wykonuje wypychanie na podstawie klucza, więc pod względem dostępu, własności i audytu nie ma problemu, że ciąg user @ server jest identyczny dla różnych użytkowników.)

Dezorientacja
źródło
Ściśle związane: stackoverflow.com/questions/4565700/…
Ciro Santilli 16 冠状 病 六四 事件 法轮功

Odpowiedzi:

597

Nawet jeśli użytkownik i host są tacy sami, nadal można je rozróżnić ~/.ssh/config. Na przykład, jeśli twoja konfiguracja wygląda następująco:

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

Następnie po prostu użyj gitolite-as-alicei gitolite-as-bobzamiast nazwy hosta w swoim adresie URL:

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

Uwaga

Chcesz dołączyć opcję IdentitiesOnly yeszapobiegania domyślnym identyfikatorom. W przeciwnym razie, jeśli masz również pliki id pasujące do domyślnych nazw, zostaną one wypróbowane jako pierwsze, ponieważ w przeciwieństwie do innych opcji konfiguracji (które są zgodne z „pierwszymi wygranymi”), IdentityFileopcja dołącza się do listy tożsamości do wypróbowania. Zobacz: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Mark Longair
źródło
9
Wielkie dzieki. Nie zrozumiałem, że można swobodnie wybrać „alias” dla specyfikacji hosta w ~ / .ssh / config
Confusion
4
Dziękuję też za tę odpowiedź! Jedną z rzeczy dla mnie było to, że IdentityFile musi być pełną ścieżką (wstawiłem tylko id_rsa.rick jako mój argument do IdentityFile, a to się nie udało). Zobacz stronę podręcznika ssh_config (5), aby uzyskać inną składnię dla IdentityFile.
rickumali
1
Dziękuję bardzo za jasną i bardzo pomocną odpowiedź. Próbowałem uruchomić to przez jakiś czas i poddałem się wcześniej, zakładając, że ten sam użytkownik musi użyć tego samego pliku klucza prywatnego id_rsa.
DrCord,
7
git@Część w pilocie nie jest konieczne, ponieważ jest ona podana w Userwierszu config.
dolmen
2
Walczyłem z tym rozwiązaniem, dopóki nie dodałem kolejnej linii zawierającej IdentitiesOnly yesbezpośrednio po linii IdentityFiledla hosta. Wygląda na to, że przekazywał wiele tożsamości, a jedna z nich nie miała dostępu do hosta.
Fitter Man
57

Alternatywnym podejściem do powyższego oferowanego przez Marka Longaira jest użycie aliasu, który uruchomi dowolne polecenie git na dowolnym pilocie z alternatywnym kluczem SSH. Chodzi przede wszystkim o zmianę tożsamości SSH podczas uruchamiania poleceń git.

Zalety w stosunku do aliasu hosta w innej odpowiedzi:

  • Będzie działał z dowolnymi poleceniami lub aliasami git, nawet jeśli nie możesz podać ich remotewprost.
  • Łatwiejsza praca z wieloma repozytoriami, ponieważ wystarczy skonfigurować go tylko raz na komputerze klienckim, a nie raz na repozytorium na każdym komputerze klienckim.

Używam kilku małych skryptów i aliasu git admin. W ten sposób mogę na przykład:

git admin push 

Aby przekazać do domyślnego pilota przy użyciu alternatywnego („admin”) klucza SSH. Ponownie możesz użyć dowolnego polecenia (nie tylko push) z tym aliasem. Możesz nawet git admin clone ...sklonować repozytorium, do którego miałbyś dostęp tylko przy użyciu klucza „admin”.

Krok 1: Utwórz alternatywne klucze SSH, opcjonalnie ustaw hasło w przypadku, gdy robisz to na czyimś komputerze.

Krok 2: Utwórz skrypt o nazwie „ssh-as.sh”, który uruchamia rzeczy korzystające z SSH, ale używa danego klucza SSH zamiast domyślnego:

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

Krok 3: Utwórz skrypt o nazwie „git-as.sh”, który uruchamia polecenia git przy użyciu podanego klucza SSH.

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

Krok 4: Dodaj alias (używając czegoś odpowiedniego dla „PATH_TO_SCRIPTS_DIR” poniżej):

# 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"

Więcej informacji: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

sinelaw
źródło
4
Bardzo miła odpowiedź. Nie zapomnij dodać podwójnych cudzysłowów wokół $@-> "$@"dla bezpieczeństwa.
kevinarpe
@sinelaw Czy to nadal działa? Cały czas dostaję błąd odmowy uprawnień
Alok Kumar,
55

Możesz użyć zmiennej środowiskowej git GIT_SSH_COMMAND. Uruchom to w swoim terminalu pod repozytorium git:

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

Zastąp ~/.ssh/your_private_keyścieżkę prywatnego klucza ssh, którego chcesz użyć. I można zmienić późniejsze polecenia git (w przykładzie jest git submodule update --init), aby inni lubią git pull, git fetchitp

Hustlion
źródło
1
Pełny dokument znajduje się na stronie git-scm.com/docs/git#git-codeGITSSHcode ; potrzebuje jednak nowszego Gita (> = 2.3. *).
Christian Ulbrich,
2
Dziękujemy za proste rozwiązanie, które nie wymaga niczego poza ustawieniem jednej zmiennej środowiskowej.
Noah Sussman
4
Zauważ, że twój ~ / .ssh / id_rsa (lub cokolwiek to jest domyślny klucz) będzie miał pierwszeństwo przed tym, który przekazujesz przez -i. Tak naprawdę chcesz użyć GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes', aby ignorować inne klawisze
staktrace
jak możesz zaktualizować git push? Nie mogłem tego znaleźć w dokumentacji
lebed2045
Byłoby miło stworzyć aliasy bash lub git - podobnie jak odpowiedź sinelaw, ale używając tej metody zamiast konieczności tworzenia skryptów.
Inigo
14

Jeden system uniksowy (Linux, BSD, Mac OS X), domyślna tożsamość jest przechowywana w katalogu $ HOME / .ssh , w 2 plikach: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub Gdy używasz sshbez opcji -i, używa domyślnego klucza prywatnego do uwierzytelnienia w systemie zdalnym.

Jeśli masz inny klucz prywatny, którego chcesz użyć, na przykład $ HOME / .ssh / deploy_key , musisz użyćssh -i ~/.ssh/deploy_key ...

To jest denerwujące. Możesz dodać następujące wiersze do swojego $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Więc za każdym razem używasz sshlub gitlub scp(w zasadzie sshteż), nie trzeba korzystać z opcji -iwięcej.

Możesz dodać dowolną liczbę kluczy w pliku $ HOME / .bash_profile .

Châu Hồng Lĩnh
źródło
10

Inną alternatywą jest użycie ssh-ident do zarządzania tożsamością ssh .

Automatycznie ładuje i używa różnych kluczy w oparciu o bieżący katalog roboczy, opcje ssh itd., Co oznacza, że ​​możesz łatwo mieć katalog roboczy / katalog prywatny / katalog, który w przejrzysty sposób używa różnych kluczy i tożsamości z ssh.

rabexc
źródło
9

Używam Git Bash na Win7. Poniższe działało dla mnie.

Utwórz plik konfiguracyjny w ~ / .ssh / config lub c: / users / [twoja_nazwa_użytkownika] / .ssh / config. W pliku wpisz:

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

Wydaje mi się, że host musi być adresem URL, a nie tylko „nazwą” lub referencją dla twojego hosta. Na przykład,

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

Ścieżkę można również zapisać w formacie / c / users / [nazwa_użytkownika] / ....

Świetne jest również rozwiązanie dostarczone przez Giordano Scalzo. https://stackoverflow.com/a/9149518/1738546

użytkownik1738546
źródło
9

Od gita 2.10 w górę można również użyć ustawienia sshCommand gitconfig. Stan dokumentów :

Jeśli ta zmienna jest ustawiona, git fetch i git push użyją podanego polecenia zamiast ssh, gdy będą musiały połączyć się ze zdalnym systemem. Polecenie ma taką samą formę jak zmienna środowiskowa GIT_SSH_COMMAND i jest zastępowane, gdy zmienna środowiskowa jest ustawiona.

Przykładem użycia może być: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

W niektórych przypadkach nie działa to, ponieważ ssh_config przesłania polecenie, w tym przypadku spróbuj ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nullnie używać ssh_config.

firfin
źródło
8

Skopałem razem i przetestowałem z github następujące podejście, oparte na czytaniu innych odpowiedzi, które łączy kilka technik:

  • poprawna konfiguracja SSH
  • ponowne pisanie adresu URL git

Zaletą tego podejścia jest to, że po skonfigurowaniu nie wymaga żadnej dodatkowej pracy, aby uzyskać prawidłowe działanie - na przykład nie trzeba zmieniać zdalnych adresów URL ani pamiętać o klonowaniu różnych elementów - przepisywanie adresów URL sprawia, że ​​wszystko działa .

~/.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 = [email protected]

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

[url "github-work:work-github-org/"]
    insteadOf = [email protected]:work-github-org/

~/dev/work/.gitconfig

[user]
    email = [email protected]

Tak długo, jak trzymasz wszystkie repozytoria pracy w ~ / dev / work i rzeczy osobiste gdzie indziej, git będzie używał poprawnego klucza SSH podczas wykonywania pull / clones / pushów na serwerze, a także dołącza poprawny adres e-mail do wszystkich twoje zobowiązania.

Bibliografia:

Karlos
źródło
Jak to działa z klonowaniem? includeIfpowinien działać tylko wtedy, gdy istnieje .gitkatalog, o którym myślałem?
detly
Poczekaj, rozumiem, zajmuje się tym przepisywanie adresów URL. Ta odpowiedź jest niezwykle przydatna!
detly
4

Jeśli używasz wersji ssh Gita w systemie Windows, wygląda linia pliku tożsamości w konfiguracji ssh

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

gdzie /cjestc:

Aby to sprawdzić, w git's bash wykonaj

cd ~/.ssh
pwd 
Andrew Murphy
źródło
3

Może być konieczne usunięcie (lub skomentowanie) domyślnej konfiguracji hosta .ssh / config

ViliusK
źródło
1

najbardziej określony w kluczu konfiguracji pliku 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
Diego Santa Cruz Mendezú
źródło
0

Jak ktoś wspomniał, core.sshCommandconfig może zostać użyty do zastąpienia klucza SSH i innych parametrów.

Oto przykład, w którym masz alternatywny klucz o nazwie ~/.ssh/workrsai chcesz go użyć dla wszystkich sklonowanych repozytoriów ~/work.

  1. Utwórz nowy .gitconfigplik w ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. W globalnej konfiguracji git ~/.gitconfigdodaj:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Mansour
źródło
0

Jedną z możliwości wykorzystania ~/.ssh/configjest użycie Matchograniczenia zamiast Hostograniczenia. W szczególności Match Execwywołuje polecenie powłoki, aby zdecydować, czy zastosować deklaracje, czy nie. W bashu możesz użyć następującego polecenia:

[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]

Używa [polecenia bash do sprawdzenia, czy dwa ciągi są równe. W tym przypadku sprawdza się, czy ciąg znaków [email protected]:gitolite-adminpasuje do wyniku uzyskanego z $(git config --get remote.origin.url)''polecenia.

Możesz użyć dowolnego innego polecenia identyfikującego repozytorium, w którym znajduje się powłoka. Aby to zadziałało, ważne jest, aby mieć $SHELLzmienną zdefiniowaną dla twojej powłoki, w moim przypadku /bin/bash. Pełny przykład byłby następujący ~/.ssh/config:

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

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

W tym przykładzie założyłem, że ~/.ssh/yourOwnPrivateKeyzawiera Twój prywatny klucz i że ~/.ssh/gitolite-adminzawiera prywatny klucz użytkownika gitolite-admin. I obejmował IdentitiesOnly yesdeklarację, aby upewnić się, że tylko jeden klucz jest przeznaczona do serwera git, wspomnianej przez Mark Longair . Pozostałe deklaracje są tylko standardowymi opcjami ssh dla git.

Możesz dodać tę konfigurację, jeśli masz kilka some_repo, których chcesz używać z różnymi kluczami. Jeśli masz kilka repozytoriów [email protected]i większość z nich korzysta z ~/.ssh/yourOwnPrivateKeytego, bardziej sensowne jest włączenie tego klucza jako domyślnego dla hosta. W takim przypadku ~/.ssh/configbyłoby to:

Match Exec "[ [email protected]: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

Pamiętaj, że kolejność ma znaczenie, a Host git.company.comograniczenie powinno pojawić się po Match Execjednym lub jednym.

LuisR
źródło
0

Skonfiguruj swoje repozytorium za pomocą git config. Na przykład:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
odcinek
źródło