Why can't I use one ssh key on more than one github repo?

kramer65 picture kramer65 · Nov 9, 2016 · Viewed 7.6k times · Source

I've got a server which needs to be set up with the contents of two git repos which I host at github. I now want to add the ssh key of the server as deployment key to both the projects on github.

Unfortunately I'm getting an error saying Key is already in use, which according to this github page is because I can't add a deploy key to more than one repo.

I really wonder though; why is this a problem? Why can't one server have access to several repo's? What's the risk they're trying mitigate here?

Answer

torek picture torek · Nov 9, 2016

That's not quite the right characterization of what it says on the GitHub page you linked. In fact, you can use the same ssh key for many different GitHub repositories. What you can't do is use one ssh key for many repositories and as what they call a "deploy key", nor use the same ssh key as some other user.

What's going on here is that GitHub's ssh server classifies incoming keys into one of two types:

  • An account key, which authenticates an incoming connection as you. You then have permissions on some wide (or narrow) swath of repositories, as controlled by each repository's "accounts that have access" settings. That is, the key itself is how they know you are kramer65 (or whatever your account name actually is there).
  • A deploy key, which authenticates an incoming connection as having access to one particular repository. That is, there's no "account" involved: it's just one key, attached to one specific repository.

There are also "machine users", but those are a form of account; I'm not sure whether GitHub even distinguishes those internally from regular account-keys. Because these are account-like rather than deploy-key-like, you can give them access to many different repositories. (This is probably what you want.)

I really wonder though; why is this a problem? Why can't one server have access to several repo's? What's the risk they're trying mitigate here?

They are not really protecting anything here. They are just letting you save, on GitHub, this one extra key, and for (your) convenience, do it without bothering to create an account. For (their) convenience, they then attach this one extra key to exactly one repository, which lets their ssh server—or really, what's right behind it after the key authenticates, i.e., the "login shell"—look up the one allowed repository without having to indirect through an "account" table first. When the incoming key is an account (or machine user) key, their ssh server, or what's right behind it, must look in this secondary table, to find the set of allowed repositories.

See https://developer.github.com/guides/managing-deploy-keys/#deploy-keys for details.

(There is no theoretical reason they could not allow a deploy key to automatically create an otherwise-anonymous "machine user" that is then automatically added to each repository, or removed from it, as you would like. However, that buys them nothing, since machine users already exist, and perform this same function. They can try to spin it as a security feature because it lets you know "hey, that key already means something to me" ... but if you have that key and aren't supposed to have that key, you can now find out what that one key actually unlocks, which if anything is somewhat anti-security. On the other hand, if you are supposed to have that key, and have simply forgotten which of your repositories it unlocks, that makes the system very difficult for you. This is typical of any security system though: the more secure you make it, the more inconvenient it is to actually use.)