[feature request] Support different upstream keys (and maybe upstream hosts) based on the connection key
callumgare opened this issue · 13 comments
Sorry if this has already been requested and I missed it. Also this might not be possible, I don't know enough about how ssh works, but I thought I may as well ask :) I'd love to be able to use a different key for connecting to the upstream server based on what key was used to connect to sshpiper.
One use case for this is with GitLab. I have sshpiper in front of a GitLab instance and way ssh authentication works in GitLab is that each user uploads their public key in the GitLab UI and GitLab uses the connection key to tell which user has connected rather than the connecting username (the same username is used for all users, by default "git"). Since sshpiper can currently only be configured to use one upstream ssh key per username it's currently not possible to support multiple users in GitLab with sshpiper in a way that is constant with the GitLab UI.
Another use case where this would be useful is with borg backup which uses an ssh connection for a client to connect to a borg server, typically running under a user account named "borg". To ensure the connection can't be abused for other things it is highly recommended to append command="borg serve --restrict-to-path /repos/name-of-repo",restrict
to each authorized_keys entry for the borg user on the borg server. Ideally you'd have multiple authorized keys for each client that are each restrict to their own repo (specified by the /repos/name-of-repo
part of the above key prefix). At the moment since sshpiper currently only lets you configure one upstream key per user I have to use /repos
instead which means all connecting borg clients can read all available repos (a term borg uses to refer to as a set of backups for a client). An alternative is to have muliple sshpiper users per borg client (e.g. "borg-client1", "borg-client2", etc) which each maps to a different authorized_key entry on the borg server. This works but it would be nice to have sshpiper be "transparent" and just setup borg in the standard way, connecting via the borg username.
I'm using the working Working Directory and the way I'm imaging this might work is by supporting sub-directories inside each user directory, inside of which would be all the normal config that's available at the top-level of a username config directory. E.g.
├── gitlab
│ └── user1
│ │ └── authorized_keys
│ │ └── id_ed25519
│ │ └── id_ed25519.pub
│ │ └── sshpiper_upstream
│ └── user2
│ │ └── authorized_keys
│ │ └── id_ed25519
│ │ └── id_ed25519.pub
│ │ └── sshpiper_upstream
│ └── authorized_keys
│ └── id_ed25519
│ └── id_ed25519.pub
│ └── sshpiper_upstream
└── linode
└── authorized_keys
└── id_ed25519
└── id_ed25519.pub
└── sshpiper_upstream
sshpiper would look into any available sub-directories under the connecting username directory and would check to see if any of them have a match in their authorized_keys. If there are no matching sub-directories any config at the top level of the username directory would be used as a fallback/behave as it currently does today. This should hopefully be fairly backwards comparable. The names of the sub-directories (in the example above, "user1" and "user2") would be arbitrary as far as sshpiper is concerned, just named by whatever makes the most sense for the person managing the config to keep track of the different sets of configurations. sshpiper would purely use the authorized_keys file to find a matching config set.
Thanks for your consideration!
is grpc upstream
good for you? it can be fully customized
Where would I find the documentation for that? The link in the readme is 404’d
here is a grpc example https://github.com/tg123/sshpiper/blob/master/sshpiperd/upstream/grpcupstream/simpleserver/impl.go
but I noticed findupstream
does not support routing by key
at the moment.
I revamp it and add this feature.
please allow me some weekends
Thanks for that! To be honest grpc probably seems a lot more complex than I'm looking for with my setup. The file based driver is easy for me to maintain so I'll probably stick with that.
If you're not interested in supporting key based routing with the file driver that's completely understandable though. Just thought I'd ask. Thanks for making such a great project! 😊
still working on this
need few more weekends, a big code refactor
hi @callumgare
here is preview version at https://github.com/tg123/sshpiper/tree/v1
you can build and test, looking forward to see your feedback
note: only yaml and working dir works in preview version
start with --upstream-workingdir-matchpublickeyinsubdir
here is my test folder structure
├── git
│ ├── bitbucket
│ │ └── sshpiper_upstream
│ ├── github
│ │ ├── authorized_keys
│ │ ├── id_rsa
│ │ └── sshpiper_upstream
│ └── gitlab
│ └── sshpiper_upstream
ssh git@sshpiper will search across all sub
the reforge took couple weekends and rewrite most of code to support even more flexible scenerio.
Thanks for the idea
Amazing! Thanks for your had work with that!
Are there instructions for building the docker image (I run sshpiper using the docker image from https://hub.docker.com/r/farmer1992/sshpiperd)? When I try just running docker build .
on my x86 home server running proxmox (basically Debian) I get errors:
git clone https://github.com/tg123/sshpiper
cd sshpiper
git submodule update --init --recursive
docker build .
Ta. It looks like it's now checking for config in subdirectories which is great but it also seems to be ignoring the top level directory now. Rather than matching the username that is used when connecting to sshpiper with the name of a directory in the top-level, it now seems to ignore the username and check all directories.
For example if I'm connecting to sshpiper from a computer who's ssh public key is in both authorized_keys files in the below example then even if I'm connecting with ssh borg@sshpiper-server
the borg
username appears to be ignored so if sshpiper checks /git/github/authorized_keys before it checks /borg/backup-server/authorized_keys then it'll connect to /git/github/sshpiper_upstream.
├── git
│ └── github
│ ├── authorized_keys
│ ├── id_rsa
│ └── sshpiper_upstream
└── borg
└── backup-server
├── authorized_keys
├── id_rsa
└── sshpiper_upstream
I'm using /sshpiperd daemon --upstream-workingdir-matchpublickeyinsubdir
as the command for the docker container running that uses the image build from the v1 branch.
good to know it works
anyway seems a bug, I am working on rewriting the plugin system to fit new api
allow me some time to fix it
No worries! Thanks :)
fixed your bug in https://github.com/tg123/sshpiper/tree/v1plugin/plugin/workingdirbykey
note I am not still not finishing the doc of v1,
but you can test the new plugin based system
here is your plugin
# build plugin/workingdirbykey
cd plugin/workingdirbykey
go build
# in cmd/sshpiperd
go build
./sshpiperd --log-level trace -i ssh_host_rsa_key ../../plugin/workingdirbykey/workingdirbykey --root <your dir>
I am working on more plugins
Sorry I'm just replying to this now. Looks like it works perfectly! Thanks again ❤️