Allow only specific keys in agent forwarding?

Solution 1:

I'm not aware of any agents that allow for the selective forwarding of keys as you've diagramed. Once a key is forwarded to a host, it's as if it were locally stored and can be used to authenticate against any host from there.

Looking at your question on another level, I have two ideas about what you might be trying to do:

  • Prevent somebody from authenticating to certain hosts without physical presence at a location.

If this is your goal, you cannot achieve it through control of authentication keys. You must control access through architecture and host restrictions such that no host which can be accessed remotely is capable of accessing a "safe" host.

  • "Protect" certain keys so they're not exposed.

If this is your goal, it's a misunderstanding of how to protect keys. Keys themselves are never forwarded. The ability to access the ssh agent to authenticate against a key is forwarded. However, that forwarding can only be taken advantage of while the forwarding is in place and only if the machine you've forwarded your agent to is run by an untrustworthy admin (voluntarily or through compromise). Thus in your diagram, unless you successfully log from machine B -> D and export forwarding from A -> B -> D, you are not at risk of exposing your credentials. You can forward from A -> B safely if you trust B.

I suggest you read a very verbose explanation of how forwarding works with diagrams if you're still unclear about the concept.

Solution 2:

A feature like the one requested would belong in the ssh client.

It would be too difficult for the ssh-agent to figure out when it was communicating through a forwarding and when it was communicating with a local ssh client. Letting the server apply the restriction would be a security flaw. This leaves the ssh client as the only place such a feature could reasonably exist.

A quick look through the openssh source lead me to the client_request_agent function in clientloop.c. From what I see there I get the impression the ssh client simply forwards the raw byte stream without trying to understand which keys are being used. This means it would require a significant effort to add this feature to the client.

Another related feature, which could be added with less work would be an option to use two different agents. One agent could be used for authenticating with the server while another agent could be forwarded to the server.

Both would be useful features which I would make use of as well, but alas appears to not exist in openssh (yet).

Solution 3:

If this problem comes up solely for app deployment using various private repos that require different keys:

You can skip agent forwarding altogether. Copy the files onto the machine containing the various keys, then rsync the cloned repos over to the server where deployment occurs.

Client A
    |
* private keys
* `git clone ...` private repos 
* /tmp/repos
      | 
      |  ------------> rsync/scp -----------> Server B

You could automate the process with alias, shell scripts, etc. Capistrano even has this built in. It's called the copy strategy: http://rubydoc.info/github/capistrano/capistrano/master/Capistrano/Deploy/Strategy/Copy