Home > Net >  git/ssh - Having trouble with ssh authentication with multiple users
git/ssh - Having trouble with ssh authentication with multiple users

Time:06-09

I am having trouble getting git ssh authentication to work with multiple users. Initially, it would always try to authenticate with my home-key

~/.ssh/home-key,

untill I found this answer

https://gist.github.com/Jonalogy/54091c98946cfe4f8cdab2bea79430f9?permalink_comment_id=3700405#gistcomment-3700405

I ran that command and success. It worked, however now I have the opposite issue, and it always tries to autenticate with ~/.ssh/work-01 Despite having that and ~/.ssh/home-01

I know the git config file is correct because in my work repo, when I run

gitconfig user.email

I get

rob@Robs-MBP test % git config user.email
[email protected]

and likewise when in my home-repo

I get

rob@Robs-MacBook-Pro ~ % git config user.email
[email protected]

As far as I am aware, my ~/.ssh/config file is correct

#Default GitHub
Host github.com-home
  HostName github.com
  User git
  IdentityFile /Users/rob/.ssh/home-01
  IdentitiesOnly yes

#wearenv-git
Host github.com-work
  HostName github.com
  User git
  IdentityFile /Users/rob/.ssh/work-01
  IdentitiesOnly yes

and my global git config file is this

[user]
    name = home-username 
    email = [email protected] 
[includeIf "gitdir:~/work-repos"]
    path = /work-repos/.gitconfig
[init]
    defaultBranch = main
[color]
    ui = auto
[core]
    editor = code --wait

the includeIf points to this

[user]
    name = work-username
    email = [email protected]
[init]
    defaultBranch = main
[color]
    ui = auto
[core]
    editor = code --wait

and even setting a local config file

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = [email protected]:wearenv-digital/test.git
    fetch =  refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main 
[user]
    name = work-username
    email = [email protected]

I have checked, double checked and triple checked I have the correct key files uploaded to git.

Git can authenticate using work.key, as shown in this:

rob@Robs-MacBook-Pro ~ % ssh -i~/.ssh/work-01  [email protected] 
PTY allocation request failed on channel 0
Hi work-username! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
rob@Robs-MacBook-Pro ~ % 

It seems that when I only have work01 in ssh-agent, it always tries to authenticate with [email protected]

Vice versa with home-01

Then when both keys are in the ssh-agent, it always tries to use the first one added.

EDIT I can provide the verbose output of

ssh -i ~/.ssh/work-01 [email protected]

eg

ssh -i ~/.ssh/work-01 -v [email protected]

However StackOverflow detected it as spam in the original question :(

CodePudding user response:

This part:

#Default GitHub
Host github.com-home
  HostName github.com
  User git
  IdentityFile /Users/rob/.ssh/home-01
  IdentitiesOnly yes

#wearenv-git
Host github.com-work
  HostName github.com
  User git
  IdentityFile /Users/rob/.ssh/work-01
  IdentitiesOnly yes

is correct, assuming the identities are in the named files, i.e., .ssh/home-01 and .ssh/work-01 in your home directory which is /Users/rob. You can make this simpler by writing:

    IdentityFile ~/.ssh/home-01

for instance as ~ means "my home directory" and hence this is automatically the right ~/.ssh/ directory and all you have to get right is the file name.

But this part is wrong:

ssh -i~/.ssh/work-01 [email protected] 

Well, wrong is too strong: it works fine, it's just overkill. What you want is much simpler:

ssh github.com-home

to "log in" to [email protected] using your home identity, and

ssh github.com-work

to "log in" to [email protected] using your work identity. That is, instead of github.com we use the faked up "host name". I would spell this gh-work and gh-home for short myself:

Host gh-work
    User git

[etc] so that the "host name" is the unqualified string gh-work or gh-home, which is shorter and easier to type.

On your Mac, you may first need to run:

ssh-add ~/.ssh/work-01

and:

ssh-add ~/.ssh/home-01

(though just once after you've rebooted).1 Use ssh-add -l to list the IDs that your agent knows about.


1This makes use of the fact that macOS starts the ssh agent for you when you log in, providing the right environment variables to each shell opened in each terminal window. This way every terminal window opened from the time you log in shares a single agent process. There's no need to start one. Linux systems typically require you to start one as you log in, which in turn requires some fancy footwork in a .bashrc or .profile or other startup file. The macOS environment makes this much easier.


Making Git uses the right URL

Once the above works—you can easily test it with ssh -Tv github.com-home and so on, as you've written things—you simply need to convince Git to clone from, and push to, repositories stored on ssh://github.com-home/personal/repo and ssh://github.com-work/work/repo for instance.

This is where this kind of trick comes in:

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

(Note that I have added a ~ character that I think you dropped).

What we can do with includeIf is:

  • set user.name and user.email for work vs personal repos
  • make Git use an insteadOf rule for ssh://github.com/ URLs

and (this is the reason for the includeIf part) make the actual substitution conditional on whether this is a "work" or "home" repository based on where it lives in our home directories.

If you put your work repositories in ~/work-repos/* (as indicated here) and your personal ones elsewhere (perhaps ~/home-repos/? use whatever you like; as you've set this up only the ~/work-repos/ones get the work treatment), *and* add these lines to~/work-repos/.gitconfig`:

[url "ssh://github.com-work/"]
    insteadOf = ssh://github.com/

Now if you run:

git clone ssh://github.com/company/repo.git

Git will take that and change it to read:

git clone ssh://github.com-work/company/repo.git

This in turn will cause Git to run:

ssh github.com-work git-upload-...

That is, Git will ask ssh to connect to a host named github.com-work and run the smart protocol to access the company repository in company/repo.git.

We already know (and have tested) that ssh github.com-work actually connects to github.com, not github.com-work, and logs in as the work user using the work-user public-key so that your ssh command is correctly identified as "you-at-$company". This user therefore has access to the company repo and can clone it.

If you don't mind typing in the "wrong" URL (including the home/work distinction) in the first place, you don't need the insteadOf trick. The fact that you're using a fake host name will trigger ssh into using the desired identity on the real (github.com) host. But adding the insteadOf trick makes this even more convenient.

Since many people may use [email protected]:user/repo.git instead of ssh://github.com/user/repo.git, or add git@ in front of github.com to get ssh://[email protected]/user/repo.git, you may want multiple insteadOf rules here, e.g.:

[url "ssh://github.com-work/"]
    insteadOf = ssh://github.com/
    insteadOf = ssh://[email protected]/
    insteadOf = [email protected]:

There are many ways to work this, of course. Pick one that suits you best. Start by getting ssh to work the way you want, without adding Git into the mix at all. Then add Git, knowing that ssh is working the way you want.

  • Related