Especifique uma chave SSH para git push para um determinado domínio

342

Eu tenho o seguinte caso de uso: Eu gostaria de poder [email protected]:gitolite-adminusar a chave privada do usuário gitolite-admin, enquanto desejo usar a chave privada [email protected]:some_repo'minha própria'. AFAIK, não consigo resolver isso usando ~/.ssh/config, porque o nome de usuário e o nome do servidor são idênticos nos dois casos. Como Eu use a própria chave privada, eu tenho que definiu no ~/.ssh/configpara [email protected]. Alguém sabe uma maneira de substituir a chave usada para uma única gitinvocação?

(Além disso: gitolite distingue quem está fazendo o push com base na chave, portanto, não é um problema, em termos de acesso, propriedade e auditoria, que a sequência user @ server seja idêntica para usuários diferentes.)

Confusão
fonte
Intimamente relacionado: stackoverflow.com/questions/4565700/…
Ciro Santilli escreveu:

Respostas:

597

Mesmo se o usuário e o host forem iguais, eles ainda poderão ser distinguidos ~/.ssh/config. Por exemplo, se sua configuração estiver assim:

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

Então você apenas usa gitolite-as-alicee, em gitolite-as-bobvez do nome do host no seu URL:

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

Nota

Você deseja incluir a opção IdentitiesOnly yespara impedir o uso de IDs padrão. Caso contrário, se você também tiver arquivos de identificação que correspondam aos nomes padrão, eles serão tentados primeiro porque, diferentemente de outras opções de configuração (que atendem ao "primeiro ganho"), a IdentityFileopção anexa à lista de identidades a serem tentadas. Consulte: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Mark Longair
fonte
9
Incrível, obrigado. Eu não tinha entendido que você poderia escolher livremente um 'pseudônimo' para a especificação Host no ~ / .ssh / config
Confusion
4
Obrigado também por esta resposta! Um problema para mim foi que o IdentityFile precisa ser um caminho completo (eu apenas coloquei id_rsa.rick como argumento para o IdentityFile, e isso falhou). Consulte a página do manual ssh_config (5) para obter outra sintaxe para o IdentityFile.
Rickumali
11
Muito obrigado pela resposta clara e muito útil. Eu tentei fazer isso funcionar por um tempo e desisti antes, supondo que o mesmo usuário tivesse que usar o mesmo arquivo de chave privada id_rsa.
precisa saber é
7
A git@parte no controle remoto não é necessária, pois é fornecida na Userlinha da configuração.
anta
2
Eu estava lutando com essa solução até adicionar outra linha contendo IdentitiesOnly yesimediatamente após a linha IdentityFilepara o host. Parece que estava passando várias identidades e uma delas foi impedida de acessar o host.
Fitter Man
57

Uma abordagem alternativa à oferecida acima por Mark Longair é usar um alias que execute qualquer comando git, em qualquer controle remoto, com uma chave SSH alternativa. A idéia é basicamente mudar sua identidade SSH ao executar os comandos git.

Vantagens em relação à abordagem do alias do host na outra resposta:

  • Funcionará com quaisquer comandos ou aliases git, mesmo que você não possa especificar o remoteexplicitamente.
  • É mais fácil trabalhar com muitos repositórios porque você só precisa configurá-lo uma vez por máquina cliente, não uma vez por repositório em cada máquina cliente.

Eu uso alguns scripts pequenos e um alias do git admin. Dessa forma, eu posso fazer, por exemplo:

git admin push 

Para enviar para o controle remoto padrão usando a chave SSH alternativa ("admin"). Novamente, você pode usar qualquer comando (não apenas push) com esse alias. Você pode fazer o mesmo git admin clone ...para clonar um repositório ao qual você só teria acesso usando sua chave "admin".

Etapa 1: crie as chaves SSH alternativas e, opcionalmente, defina uma senha, caso esteja fazendo isso na máquina de outra pessoa.

Etapa 2: Crie um script chamado “ssh-as.sh” que execute coisas que usem SSH, mas use uma determinada chave SSH em vez da padrão:

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

Etapa 3: Crie um script chamado "git-as.sh" que execute os comandos git usando a chave SSH fornecida.

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

Etapa 4: adicione um alias (usando algo apropriado para "PATH_TO_SCRIPTS_DIR" abaixo):

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

Mais detalhes em: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

sinelaw
fonte
4
Resposta muito boa. Não se esqueça de adicionar aspas duplas em torno de $@-> "$@"para ser seguro.
Kevinarpe
@sinelaw Isso ainda funciona? Recebo Permissão negada erro o tempo todo
Alok Kumar
55

Você pode utilizar a variável de ambiente git GIT_SSH_COMMAND. Execute isso no seu terminal no seu repositório git:

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

Substitua ~/.ssh/your_private_keypelo caminho da chave privada ssh que você deseja usar. E você pode mudar o comando posterior git (no exemplo, é git submodule update --init) a outros como git pull, git fetch, etc.

Hustlion
fonte
11
O documento completo está em git-scm.com/docs/git#git-codeGITSSHcode ; ele precisa de um Git recente (> = 2.3. *).
Christian Ulbrich
2
Obrigado por uma solução simples que não requer nada, exceto a configuração de uma variável de ambiente.
Noah Sussman
4
Note que o seu ~ / .ssh / id_rsa (ou qualquer que seja sua chave padrão) terá precedência sobre o que você passa via -i. Então, você realmente quiser usar GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes' para torná-lo ignorar outras teclas
staktrace
como você pode atualizar o git push? Não consegui encontrá-lo na documentação
lebed2045 28/01
Seria bom criar aliases bash ou git - semelhante à resposta do sinelaw, mas usando esse método em vez de ter que criar scripts em algum lugar.
Inigo
14

Em sistemas baseados em Unix (Linux, BSD, Mac OS X), a identidade padrão é armazenada no diretório $ HOME / .ssh , em 2 arquivos: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub Quando você usa sshsem opção -i, ele usa a chave privada padrão para autenticar no sistema remoto.

Se você tiver outra chave privada que deseja usar, por exemplo $ HOME / .ssh / deploy_key , precisará usarssh -i ~/.ssh/deploy_key ...

É irritante. Você pode adicionar as seguintes linhas ao seu $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Portanto, toda vez que você usa sshou gitou scp(basicamente sshtambém), não precisa -imais usar a opção

Você pode adicionar quantas chaves quiser no arquivo $ HOME / .bash_profile .

Châu Hồng Lĩnh
fonte
10

Outra alternativa é usar o ssh-ident, para gerenciar suas identidades ssh .

Ele carrega e usa automaticamente chaves diferentes com base no seu diretório de trabalho atual, nas opções ssh e assim por diante ... o que significa que você pode facilmente ter um diretório de trabalho / privado e diretório / privado que acabem de forma transparente usando diferentes chaves e identidades com o ssh.

rabexc
fonte
9

Estou usando o Git Bash no Win7. O seguinte funcionou para mim.

Crie um arquivo de configuração em ~ / .ssh / config ou c: / users / [your_user_name] /. Ssh / config. No arquivo, digite:

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

Eu acho que o host deve ser um URL e não apenas um "nome" ou referência para o seu host. Por exemplo,

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

O caminho também pode ser gravado no formato / c / users / [nome_do_usuário] / ....

A solução fornecida por Giordano Scalzo também é ótima. https://stackoverflow.com/a/9149518/1738546

user1738546
fonte
9

A partir do git 2.10, também é possível usar a configuração gitconfig sshCommand. Documentos :

Se essa variável estiver definida, o git fetch e o git push usarão o comando especificado em vez do ssh quando eles precisarem se conectar a um sistema remoto. O comando está no mesmo formato que a variável de ambiente GIT_SSH_COMMAND e é substituído quando a variável de ambiente é configurada.

Um exemplo de uso seria: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

Em alguns casos, isso não funciona porque o ssh_config substitui o comando; nesse caso, tente ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nullnão usar o ssh_config.

firfin
fonte
8

Criei e testei com o github a seguinte abordagem, com base na leitura de outras respostas, que combina algumas técnicas:

  • configuração SSH correta
  • reescrita de URL do git

A vantagem dessa abordagem é que, uma vez configurada, ela não requer nenhum trabalho adicional para corrigi-la - por exemplo, você não precisa alterar URLs remotas ou lembre-se de clonar as coisas de maneira diferente - a reescrita da URL faz com que tudo funcione .

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

Contanto que você mantenha todos os seus repositórios de trabalho em ~ / dev / work e coisas pessoais em outro lugar, o git usará a chave SSH correta ao executar pull / clones / push no servidor e também anexará o endereço de email correto a todos os seus commits.

Referências:

karlos
fonte
Como isso funciona com a clonagem? includeIfsó deve funcionar se houver um .gitdiretório presente, pensei?
detly
Espere, entendi, é a reescrita de URL que cuida disso. Esta resposta é incrivelmente útil!
detly
4

Se estiver usando a versão do ssh do Git no Windows, a linha do arquivo de identidade na configuração do ssh será semelhante a

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

onde /cé parac:

Para verificar, no git's bash, faça

cd ~/.ssh
pwd 
Andrew Murphy
fonte
3

Pode ser necessário remover (ou comentar) a configuração padrão do host .ssh / config

ViliusK
fonte
1

você mais especificou na chave de configuração do arquivo 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ú
fonte
0

Como outra pessoa mencionou, a core.sshCommandconfiguração pode ser usada para substituir a chave SSH e outros parâmetros.

Aqui está um exemplo em que você tem uma chave alternativa nomeada ~/.ssh/workrsae deseja usá-la para todos os repositórios clonados em ~/work.

  1. Crie um novo .gitconfigarquivo em ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. Na sua configuração global do git ~/.gitconfig, adicione:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Mansour
fonte
0

Uma possibilidade de usar ~/.ssh/configé usar a Matchrestrição em vez da Hostrestrição. Em particular, Match Execchama um comando shell para decidir se deve aplicar as declarações ou não. No bash, você pode usar o seguinte comando:

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

Isso usa o [comando bash para verificar se duas cadeias são iguais. Nesse caso, ele está testando se a sequência [email protected]:gitolite-admincorresponde à saída obtida do $(git config --get remote.origin.url)''comando.

Você pode usar qualquer outro comando que identifique o repositório no qual o shell está. Para que isso funcione, é importante ter a $SHELLvariável definida para o seu shell, no meu caso /bin/bash. O exemplo completo seria o seguinte ~/.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

Neste exemplo, presumi que ~/.ssh/yourOwnPrivateKeycontenha sua própria chave privada e que ~/.ssh/gitolite-admincontenha a chave privada do usuário gitolite-admin. Incluí a IdentitiesOnly yesdeclaração para garantir que apenas uma chave seja oferecida ao servidor git, mencionada por Mark Longair . As outras declarações são apenas opções ssh padrão para o git.

Você pode adicionar essa configuração se tiver várias some_repoque deseja usar com chaves diferentes. Se você possui vários repositórios [email protected]e a maioria deles usa ~/.ssh/yourOwnPrivateKey, faz mais sentido incluir essa chave como padrão para o host. Nesse caso, ~/.ssh/configseria:

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

Observe que o pedido é importante e a Host git.company.comrestrição deve aparecer após o pedido Match Exec.

LuisR
fonte
0

Configure seu repositório usando git config. Por exemplo:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
episódio
fonte