gloriphobia
gloriphobia

Reputation: 1493

How can you specify which ssh key `go get` will use

I'm using two different github accounts (personal and work) on the same laptop (running Ubuntu version 20). I need to be able to access private repos from work using the ssh key for my work github account.

I've made it all work using some neat git config controls, i.e. in my ~/.gitconfig file I've put:

[url "[email protected]:work_account/"]
    insteadOf = https://github.com/work_account/
[includeIf "gitdir:~/src/github.com/personal_account/"]
    path=~/.gitconfig_personal
[includeIf "gitdir:~/src/github.com/work_account/"]
    path=~/.gitconfig_work

The personal config contains:

[user]
name = Your Name
email = [email protected]
[core]
sshCommand = ssh -i ~/.ssh/id_rsa

The work config contains:

[user]
name = Your Name
email = [email protected]
signingkey = <ID of GPG key>
[core]
sshCommand = ssh -i ~/.ssh/id_ecdsa
[commit]
gpgsign = true
[gpg]
program = gpg

This all works great for pulling and pushing from github (and signing work commits with a gpg key), but it is failing for go get on private repos. For some bizarre reason go get is trying to use my personal ssh key (~/.ssh/id_rsa) instead of my work ssh key (~/.ssh/id_ecdsa). I've set the GOPRIVATE environment variable, i.e.

export GOPRIVATE=github.com/work_account/*

The output of go get is like:

$ go get github.com/work_account/private_repo
go get github.com/work_account/private_repo: module github.com/work_account/private_repo: git ls-remote -q origin in /home/marc/pkg/mod/cache/vcs/ff3efb332cb48232e5da90ff2073685cbdac4a86e3a47aa11663696f4943637a: exit status 128:
        ERROR: Repository not found.
        fatal: Could not read from remote repository.

        Please make sure you have the correct access rights
        and the repository exists.

I can see that my ssh agent has both keys:

$ ssh-add -l
521 SHA256:EKvhgg24_blah_bApjLSqX4J7l0 [email protected] (ECDSA)
4096 SHA256:r/qcO94F+ox_blah_JkTiVk+aERk [email protected] (RSA)

When I remove my personal ssh key (i.e. rm ~/.ssh/id_rsa*) then go get works just fine on the private repo, so I know it is definitely just trying to use the wrong ssh key. For some reason it is ignoring the git config core.sshCommand.

Upvotes: 6

Views: 5985

Answers (3)

aerth
aerth

Reputation: 557

You need this in your ~/.ssh/config file. If it doesn't exist, just create it. It specifies the ssh key to use for each host. You can add sort of aliases by adding invalid domains:

Host gitlab.com
IdentityFile ~/.ssh/id_ed25519

Host github.com
IdentityFile ~/.ssh/id_ed25519

Host github.invalid
HostName github.com
IdentityFile ~/.ssh/id_rsa

And then every time you use [email protected], you use the correct ssh key.

Related is this addition to ~/.gitconfig, which helps with importing private repositories. It uses ssh got all git operations with these hosts:


[url "[email protected]:"]
        insteadOf = https://github.com/
[url "[email protected]:"]
        insteadOf = https://gitlab.com/

Also see environmental variable GOPRIVATE which lists private repositories not to use proxy with. Example:

GOPRIVATE=*.corp.example.com,rsc.io/private

Upvotes: 1

gloriphobia
gloriphobia

Reputation: 1493

After a lot of trial and error and digging around, I've found a solution. If I set the environment variable GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ecdsa" in the private repo then go get uses the correct ssh key and then works for private repos. It seems that go get ignores the git config core.sshCommand but is taking into account the environment variable GIT_SSH_COMMAND.

To simplify my life I've used the program direnv to set this environment variable in the folder I keep my work repos in. The .envrc file in the top level folder looks like this:

export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ecdsa"

Upvotes: 11

Daniel Hornik
Daniel Hornik

Reputation: 2521

You can use the SSH-Agent. ssh-agent is part of the openssh. It also holds your keys and certificates unencrypted in memory. They are ready for use by ssh.

For example it is very helpful when you have ssh-key with a passphase. By default it will ask you to enter the key passphase every time, go is trying to clone/pull code from a upstream.

There are few commands, you can use:

  • echo $SSH_AGENT_PID - See if agent is assigned to the current session. the SSH_AGENT_PID variable should return pid of the ssh-agent.
  • eval $(ssh-agent) - start a new ssh-agent session.
  • ssh-add -l - List keys available in your ssh session
  • ssh-add ~/.ssh/tmp/id_rsa - Add the ~/.ssh/tmp/id_rsa key to current session.

Example session can be:

ip-192-168-200-63:tf-r0 daniel$ echo $SSH_AGENT_SOCK
ip-192-168-200-63:tf-r0 daniel ^C

ip-192-168-200-63:src daniel$ eval `ssh-agent`
Agent pid 50734
ip-192-168-200-63:src daniel$ echo $SSH_AGENT_PID 
50734
ip-192-168-200-63:src daniel$ ssh-add -l
The agent has no identities.
ip-192-168-200-63:src daniel$ ssh-add ~/.ssh/tmp/id_rsa
Enter passphrase for /Users/daniel/.ssh/tmp/id_rsa: 
Identity added: /Users/daniel/.ssh/tmp/id_rsa (/Users/daniel/.ssh/tmp/id_rsa)
ip-192-168-200-63:src daniel$ ssh-add -l
2048 SHA256:nm/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /Users/daniel/.ssh/tmp/id_rsa (RSA)
ip-192-168-200-63:src daniel$ 

After that I can pull remote code with ssh key protected by passphase without entering it every time, key is required.

Upvotes: 0

Related Questions