Tentukan kunci SSH untuk push git untuk domain yang diberikan


342

Saya memiliki kasus penggunaan berikut: Saya ingin dapat mendorong untuk git@git.company.com:gitolite-adminmenggunakan kunci pribadi pengguna gitolite-admin, sementara saya ingin mendorong untuk git@git.company.com:some_repomenggunakan kunci pribadi 'saya sendiri'. AFAIK, saya tidak bisa menyelesaikan ini menggunakan ~/.ssh/config, karena nama pengguna dan nama server identik dalam kedua kasus. Karena saya sebagian besar menggunakan kunci pribadi saya sendiri, saya mendefinisikannya ~/.ssh/configuntuk git@git.company.com. Adakah yang tahu cara menimpa kunci yang digunakan untuk satu gitdoa?

(Selain itu: gitolite membedakan siapa yang mendorong berdasarkan kunci, jadi itu bukan masalah, dalam hal akses, kepemilikan, dan audit, bahwa string pengguna @ server identik untuk pengguna yang berbeda.)


Jawaban:


597

Bahkan jika pengguna dan host sama, mereka masih dapat dibedakan ~/.ssh/config. Misalnya, jika konfigurasi Anda terlihat seperti ini:

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

Maka Anda cukup menggunakan gitolite-as-alicedan gitolite-as-bobalih-alih nama host di URL Anda:

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

Catatan

Anda ingin menyertakan opsi IdentitiesOnly yesuntuk mencegah penggunaan id default. Jika tidak, jika Anda juga memiliki file id yang cocok dengan nama default, mereka akan dicoba terlebih dahulu karena tidak seperti opsi konfigurasi lainnya (yang mematuhi "first in win") IdentityFileopsi ditambahkan ke daftar identitas untuk dicoba. Lihat: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807


9
Keren terima kasih. Saya tidak mengerti bahwa Anda dapat dengan bebas memilih 'alias' untuk spesifikasi Host di ~ / .ssh / config
Confusion

4
Terima kasih juga atas jawaban ini! Satu gotcha bagi saya adalah bahwa IdentityFile perlu path lengkap (saya hanya menempatkan id_rsa.rick sebagai argumen saya untuk IdentityFile, dan ini gagal). Lihat halaman manual ssh_config (5) untuk sintaksis lain untuk IdentityFile.
rickumali

1
Terima kasih banyak atas jawaban yang jelas dan sangat membantu. Saya telah mencoba untuk mendapatkan ini berfungsi untuk sementara waktu dan menyerah sebelumnya dengan asumsi bahwa pengguna yang sama harus menggunakan file kunci pribadi id_rsa yang sama.
DrCord

7
Bagian git@di remote tidak diperlukan karena diberikan di Userbaris konfigurasi.
dolmen

2
Saya berjuang dengan solusi ini sampai saya menambahkan baris lain yang berisi IdentitiesOnly yessegera setelah baris dengan IdentityFileuntuk tuan rumah. Tampaknya itu melewati beberapa identitas dan salah satunya diblokir dari mengakses host.
Fitter Man

57

Sebuah pendekatan alternatif yang ditawarkan di atas oleh Mark Longair adalah dengan menggunakan alias yang akan menjalankan setiap perintah git, pada setiap jarak jauh, dengan kunci SSH alternatif. Idenya pada dasarnya adalah untuk mengganti identitas SSH Anda ketika menjalankan perintah git.

Keuntungan relatif terhadap pendekatan alias host dalam jawaban lain:

  • Akan bekerja dengan setiap perintah git atau alias, bahkan jika Anda tidak dapat menentukan remotesecara eksplisit.
  • Lebih mudah bekerja dengan banyak repositori karena Anda hanya perlu mengaturnya sekali per mesin klien, tidak sekali per repositori pada setiap mesin klien.

Saya menggunakan beberapa skrip kecil dan alias git admin. Dengan begitu saya bisa melakukannya, misalnya:

git admin push 

Untuk mendorong ke remote standar menggunakan kunci SSH alternatif ("admin"). Sekali lagi, Anda bisa menggunakan perintah apa pun (tidak adil push) dengan alias ini. Anda bahkan dapat melakukannya git admin clone ...untuk mengkloning repositori yang hanya akan memiliki akses untuk menggunakan kunci "admin" Anda.

Langkah 1: Buat kunci SSH alternatif, secara opsional mengatur frasa sandi jika Anda melakukan ini pada mesin orang lain.

Langkah 2: Buat skrip yang disebut "ssh-as.sh" yang menjalankan hal-hal yang menggunakan SSH, tetapi menggunakan kunci SSH yang diberikan daripada default:

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

Langkah 3: Buat skrip yang disebut "git-as.sh" yang menjalankan perintah git menggunakan kunci SSH yang diberikan.

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

Langkah 4: Tambahkan alias (menggunakan sesuatu yang sesuai untuk "PATH_TO_SCRIPTS_DIR" di bawah):

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

Lebih detail di: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/


4
Jawaban yang sangat bagus Jangan lupa untuk menambahkan tanda kutip ganda di sekitar $@-> "$@"agar aman.
kevinarpe

@sinelaw Apakah ini masih berfungsi? Saya mendapat izin ditolak kesalahan sepanjang waktu
Alok Kumar

55

Anda dapat menggunakan variabel lingkungan git GIT_SSH_COMMAND. Jalankan ini di terminal Anda di bawah repositori git Anda:

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

Ganti ~/.ssh/your_private_keydengan jalur ssh private key yang ingin Anda gunakan. Dan Anda dapat mengubah perintah git berikutnya (dalam contoh ini git submodule update --init) kepada orang lain seperti git pull, git fetch, dll


1
Dok lengkap ada di git-scm.com/docs/git#git-codeGITSSHcode ; dibutuhkan recentish Git (> = 2.3. *) sekalipun.
Christian Ulbrich

2
Terima kasih atas solusi sederhana yang tidak memerlukan apa pun kecuali menetapkan satu variabel lingkungan.
Noah Sussman

4
Perhatikan bahwa ~ / .ssh / id_rsa Anda (atau apa pun kunci default Anda) akan diutamakan daripada yang Anda lewati melalui -i. Jadi Anda benar-benar ingin menggunakan GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes' untuk membuatnya mengabaikan kunci lain
staktrace

bagaimana Anda bisa memperbarui git push? Saya tidak dapat menemukannya di dokumentasi
lebed2045

Akan menyenangkan untuk membuat alias bash atau git - mirip dengan jawaban sinelaw tetapi menggunakan metode ini daripada harus membuat skrip di suatu tempat.
Inigo

14

Satu sistem berbasis Unix (Linux, BSD, Mac OS X), identitas default disimpan di direktori $ HOME / .ssh , dalam 2 file: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub Ketika Anda menggunakan sshtanpa opsi -i, ia menggunakan kunci pribadi default untuk mengotentikasi dengan sistem jarak jauh.

Jika Anda memiliki kunci pribadi lain yang ingin Anda gunakan, misalnya $ HOME / .ssh / deploy_key , Anda harus menggunakanssh -i ~/.ssh/deploy_key ...

Itu menjengkelkan. Anda dapat menambahkan baris berikut ke $ HOME / .bash_profile Anda : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Jadi setiap kali Anda menggunakan sshatau gitatau scp(pada dasarnya sshjuga), Anda tidak perlu menggunakan opsi -ilagi.

Anda dapat menambahkan kunci sebanyak yang Anda suka di file $ HOME / .bash_profile .


10

Alternatif lain adalah dengan menggunakan ssh-ident, untuk mengelola identitas ssh Anda .

Secara otomatis memuat dan menggunakan kunci berbeda berdasarkan direktori kerja Anda saat ini, opsi ssh, dan seterusnya ... yang berarti Anda dapat dengan mudah memiliki direktori kerja / pribadi dan direktori / yang secara transparan berakhir menggunakan kunci dan identitas berbeda dengan ssh.


9

Saya menggunakan Git Bash di Win7. Berikut ini bekerja untuk saya.

Buat file config di ~ / .ssh / config atau c: / users / [your_user_name] /. Ssh / config. Dalam file, masukkan:

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

Saya kira host harus berupa URL dan bukan hanya "nama" atau referensi untuk host Anda. Sebagai contoh,

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

Path juga dapat ditulis dalam format / c / users / [user_name] / ....

Solusi yang disediakan oleh Giordano Scalzo juga bagus. https://stackoverflow.com/a/9149518/1738546


9

Dari git 2.10 ke atas juga dimungkinkan untuk menggunakan pengaturan gitconfig sshCommand. Status dokumen :

Jika variabel ini disetel, git fetch dan git push akan menggunakan perintah yang ditentukan alih-alih ssh saat mereka perlu terhubung ke sistem jarak jauh. Perintah ini dalam bentuk yang sama dengan variabel lingkungan GIT_SSH_COMMAND dan diganti ketika variabel lingkungan diatur.

Contoh penggunaan adalah: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

Dalam beberapa kasus ini tidak berfungsi karena ssh_config mengesampingkan perintah, dalam hal ini cobalah ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nulluntuk tidak menggunakan ssh_config.


8

Saya telah merangkai dan menguji dengan github pendekatan berikut, berdasarkan membaca jawaban lain, yang menggabungkan beberapa teknik:

  • konfigurasi SSH yang benar
  • git URL menulis ulang

Keuntungan dari pendekatan ini adalah, sekali diatur, tidak memerlukan pekerjaan tambahan untuk memperbaikinya - misalnya, Anda tidak perlu mengubah URL jarak jauh atau ingat untuk mengkloning sesuatu secara berbeda - penulisan ulang URL membuat semuanya berfungsi .

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

Selama Anda menyimpan semua repo pekerjaan Anda di bawah ~ / dev / work dan barang-barang pribadi di tempat lain, git akan menggunakan kunci SSH yang benar ketika melakukan tarikan / klon / dorongan ke server, dan itu juga akan melampirkan alamat email yang benar ke semua komitmen Anda.

Referensi:


Bagaimana cara kerjanya dengan kloning? includeIfseharusnya hanya berfungsi jika ada hadiah .gitdirektori yang saya pikir?
detly

Tunggu saya mengerti, penulisan ulang URL-lah yang menangani itu. Jawaban ini sangat berguna!
detly

4

Jika menggunakan versi Git tentang ssh di windows, baris file identitas dalam konfigurasi ssh terlihat seperti

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

dimana /cuntukc:

Untuk memeriksa, di bash git lakukan

cd ~/.ssh
pwd 

3

Anda mungkin perlu menghapus (atau mengomentari) konfigurasi Host default .ssh / config


1

Anda paling ditentukan dalam file config key 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

Seperti orang lain yang disebutkan, core.sshCommandconfig dapat digunakan untuk mengganti kunci SSH dan parameter lainnya.

Berikut adalah exmaple tempat Anda memiliki kunci alternatif yang dinamai ~/.ssh/workrsadan ingin menggunakannya untuk semua repositori yang dikloning di bawah ~/work.

  1. Buat .gitconfigfile baru di bawah ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. Dalam konfigurasi global git Anda ~/.gitconfig, tambahkan:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig

0

Salah satu kemungkinan untuk digunakan ~/.ssh/configadalah menggunakan Matchpembatasan bukan Hostpembatasan. Secara khusus Match Execpanggilan perintah shell untuk memutuskan apakah akan menerapkan deklarasi atau tidak. Dalam bash Anda bisa menggunakan perintah berikut:

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

Ini menggunakan [perintah bash untuk memverifikasi apakah dua string sama. Dalam hal ini ia menguji apakah string git@git.company.com:gitolite-admincocok dengan output yang diperoleh dari $(git config --get remote.origin.url)''perintah.

Anda dapat menggunakan perintah lain yang mengidentifikasi repositori tempat shell aktif. Agar ini berfungsi, penting untuk memiliki $SHELLvariabel yang didefinisikan untuk shell Anda, dalam kasus saya /bin/bash. Contoh lengkapnya adalah sebagai berikut ~/.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

Dalam contoh ini saya berasumsi yang ~/.ssh/yourOwnPrivateKeyberisi kunci pribadi Anda dan yang ~/.ssh/gitolite-adminberisi kunci pribadi pengguna gitolite-admin. Saya menyertakan IdentitiesOnly yesdeklarasi untuk memastikan bahwa hanya satu kunci yang ditawarkan ke server git, yang disebutkan oleh Mark Longair . Deklarasi lain hanyalah opsi ssh standar untuk git.

Anda dapat menambahkan konfigurasi ini jika Anda memiliki beberapa some_repoyang ingin Anda gunakan dengan tombol yang berbeda. Jika Anda memiliki beberapa repositori git@git.company.comdan sebagian besar dari mereka menggunakannya, ~/.ssh/yourOwnPrivateKeylebih masuk akal untuk memasukkan kunci ini sebagai default untuk host. Dalam hal ini ~/.ssh/configadalah:

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

Perhatikan bahwa pesanan penting dan Host git.company.combatasannya akan muncul setelah Match Execsatu atau yang satu.


0

Konfigurasikan repositori Anda menggunakan git config. Sebagai contoh:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.