-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for gitea #187
Conversation
src/main/java/svnserver/ext/gitea/mapping/GiteaMappingConfig.java
Outdated
Show resolved
Hide resolved
@NotNull | ||
private static final String PREFIX_USER = "user-"; | ||
@NotNull | ||
private static final ThreadLocal<ApiClient> threadLocal = new ThreadLocal<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really doubt this will end up well. We reuse threads for subsequent connections, so this threadlocal will have completely unrelated stuff. Did you investigate where code that uses this is called? Maybe that functionality could just be claimed unsupported for Gitea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK,
An ApiClient is actually just a holder for a username and password so it's really light and doesn't waste too much memory. Collecting the ApiClient is checked on username - so another user of the thread won't be able to get the ApiClient unless it's for the same username. This is because User is final and can't be extended to keep the password around for the remainder of the request.
It's unfortunately needed because at present there is no way to ask the Gitea API what permissions a random user has and lacks a Sudo feature - I wrote a pull-request for a sudo go-gitea/gitea#4809 and to change the collaborator api go-gitea/gitea#4814 but neither particularly seem to be gaining traction.
If there's a better way to keep the session around I'd be happy to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
go-gitea/gitea#4809 has been merged now in to the Gitea mainline so once Gitea v1.6 or a release is made with this patch in I will release java-gitea-api v1.6 (as appropriate) and change this patch to use the sudo. (If go-gitea/gitea#4814 is pulled we could even drop the sudo.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I think we can merge this PR when you get rid of threadLocal. Download of all users is weird, but since it is only used for LFS (that most likely doesn't work for different reasons), we can live with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it appears that LFS works on the svn:https:// protocol with the default config-gitea.example and doesn't use the lookupByExternal function.
2e40832
to
07f59be
Compare
81df01b
to
1b1cbd4
Compare
Signed-Off: Andrew Thornton <[email protected]>
OK, so I've made some more changes - I noticed that there was a problem with adding repositories from the DirectoryWatcher which required a few changes. I've also done more testing and discovered that the LFS works out of the box when using the svn:https:// protocol - lookupByExternal isn't used in this. Is there another way of connecting to the svn repositories? |
No, git-as-svn only exposes svn:https:// to users. We cannot do svn+ssh because in svn+ssh user connects to server via ssh and runs Have you tried both uploading and downloading LFS files via git-as-svn? Are they available from git side after that? |
Yah it works both ways. I don't think there's a clear way to install git lfs from within svn, but once it's installed it works. |
Okay, I've released 1.6.0 with your changes! |
In fact, We can implement a SSH Server and Parse svn handshake, then proxy to git-as-svn. git-as-svn should use Go use https://github.com/gliderlabs/ssh Java can use https://github.com/apache/mina-sshd |
Hmm I suspect implementing one's own SSH server could be risky and could conflict with the SSH requirements for gitlab and gitea. I personally wouldn't be too happy running a SSH server from a small project like this - the attack surface is too large. However, looking at what SVN does for svn+ssh it appears that after the SSH handshake it simply executes
From http:https://coderazzi.net/howto/security/ssh_svn.html) This would require some way of listening for new public keys and sudoing as the user. It might be possible to set up the |
Yep, implementing a custom executable for svn+ssh is much more preferred than creatiing a full-blown SSH server. |
I really wish there was a "svns:https://" protocol - svn over ssl, i.e. encrypted channel with ordinary svn:https:// traffic inside. Unfortunately, svn devs went http/https route and never implemented this. svn+ssh is problematic wrt identifying the user (we no longer have username but instead have ssh key that needs to be mapped to username somehow) and user access permissions on server. Afaik, when running native svn+ssh, svnserve is run on behalf of connected user so user technically has full write access to repo files and can do whatever he wants with them, including deletion. Also, svn+ssh has terrible performance due to svn client opening multiple connections for various operations. And unless you're running persistent ssh connections, you spend 0.2-0.3s to establish an ssh connection. |
Yes it seems insane that there is no "svns:https://" protocol. It's somewhat ludicrous that this was never implemented. There was something about the cyrus SASL but I think authentication wasn't protected on this. OK, well, in terms of getting secure access to the server - and one that doesn't involve passing passwords over the network in plain text I think there are two options:
|
This should be easier, both in terms of implementation in git-as-svn and server setup. |
So just looking at "svn+ssh:https://" it seems that putting the following in
works with the caveat that git-as-svn then asks you to login again... |
@zeripath @slonopotamus NO. In fact gitea and gogs use golang.org/x/crypto/ssh. See: https://github.com/go-gitea/gitea/blob/master/modules/ssh/ssh.go gogs: https://github.com/gogs/gogs/blob/master/pkg/ssh/ssh.go You only need to add support for We use github.com/gliderlabs/ssh provider git ssh and svn+ssh feature. |
@fcharlie "no" what? |
@slonopotamus
|
To be more precise gitea and gogs let the admin choose to use internal ssh or the standard sshd deamon by editing the authorized_keys file of user. So the admin can choose what suit best his case. |
I don't see how that's related to git-a-svn. If git-as-svn implements its own ssh (I hope not), it will obviously use a separate port. |
@fcharlie I think I understand what you're saying. Yes, we can use the gitea ssh. The implementation would have to be:
|
If i understand how things work, when user connects via ssh, they explicitly tell server what command they want to execute (git-receive-pack, svnserve, git-lfs-authenticate, etc). You don't need to separate gitea users from svn users. We just need a small svnserve-like executable that will get ssh key from env, connect to git-as-svn via protected port (pipe, preferrably), pretend it is using a different authentication mechanism (we already have CRAM-MD5 and LOGIN auths) and give ssh key to git-as-svn. Now, on git-as-svn side we ask gitea "what user has this ssh key" and authenticate that way. After that, svnserve just proxies all traffic between remote client and git-as-svn. So:
So yes, you can pre-communicate by implementing custom auth mechanism. https://github.com/bozaro/git-as-svn/blob/master/src/main/java/svnserver/server/SvnServer.java#L280 (sorry for comments in RU). Possibly traffic between our 'svnserve' and git-as-svn doesn't need to be proper svn traffic and instead can be something simpler. |
Ah you'd be right about The way gitea works is that you always log in to the git user. On a successful ssh connection the command specified in Here's an example:
The Now if you don't want to touch the Regarding the way to communicate with The A possible shadow would look like: #!/bin/bash
REAL_GITEA_PATH="/the_real_unshadowed_gitea
SSH_ORIGINAL_COMMANDS=($SSH_ORIGINAL_COMMAND)
SUBCOMMAND="$1"
if [ "$1" = "serv" ] && [ -n "$SSH_ORIGINAL_COMMAND" ] && [ "${SSH_ORIGINAL_COMMANDS[0]}" = "svnserve" ] ; then
## DO THE MAGIC ##
# but I think here's an easy working test
exec nc localhost 3690
else
exec "$REAL_GITEA_PATH" "$@"
fi |
OK, so if I move #!/bin/bash
REAL_GITEA_PATH="/app/gitea/gitea-shadowed"
SSH_ORIGINAL_COMMANDS=($SSH_ORIGINAL_COMMAND)
SUBCOMMAND="$1"
if [ "$1" = "serv" ] && [ -n "$SSH_ORIGINAL_COMMAND" ] && [ "${SSH_ORIGINAL_COMMANDS[0]}" = "svnserve" ] ; then
## DO THE MAGIC ##
# but I think here's an easy working test
exec nc localhost 3690
else
exec -a "/app/gitea/gitea" "$REAL_GITEA_PATH" "$@"
fi This will work although it will ask for the password... |
Look at this: http:https://svn.apache.org/repos/asf/subversion/trunk/notes/ssh-tricks If we can add custom entries to gitea Also, you do not need to move |
Also, WRT pipe. Not pipe but named socket! We can create named sockets from git-as-svn (see https://github.com/bozaro/git-as-svn/blob/master/src/main/java/svnserver/ext/socket/config/SocketConfig.java#L33 ). And here is client side: https://github.com/bozaro/git-as-svn/blob/master/tools/git-lfs-authenticate#L67 That particular thing is overcomplicated and setups protobuf on top of that socket, ignore that. |
Ah but then you're back to parsing |
We do not need to parse |
hmm... were you intending to make every user of svn a real user on the machine? |
BTW If moving around gitea isn't right then, munging/parsing the |
Uff. Let's try again. SSH gives us a key via environment. We (fake svnserve) can take this key, pass key to git-as-svn, which in turn calls gitea api and asks "hey, gitea, tell us what user has this key". Gitea gives us username/email, authentication done, svnserve just proxies traffic between client and git-as-svn. This route will work if we use the same keys as Gitea uses. But this way we either need to shadow gitea shell or teach it that invoking Option numba two: we use separate keys (from gitea) for svn+ssh, but still same ssh account. This way, we can (via command=... in authorized_keys) tell ssh to invoke us the way we want to be invoked. Users connecting with keys that are made for svn+ssh simply cannot invoke any different command. And the command we force them to invoke is either the same as in option 1 (that still takes key out of env variables, passes it to git-as-svn, which uses gitea api to lookup user data) or In both options, no authentication is performed by git-as-svn, it assumes that user was already authenticated and needs to blindly trust user identifier that our |
This pull-request implements basic support for Gitea.
Still to-do: