I would like to do access control based on committer's IP. I.e., allow pushing from development IPs and deny pushing from staging/production IPs. I am using Git Essentials/Git Stash and my git pushes are via the ssh protocol.
Without finding a better approach with Git Stash, I am trying to add a pre-receive hook (perl script) suggested by the following:
http://search.cpan.org/~mschilli/SVN-Utils-ClientIP-0.02/ClientIP.pm
Since it is based on lsof I have to run stash as root by setting the STASH_USER variable as root, which is not good from security stand point. Long story short, I got the pre-receive perl script to detect committer's IP correctly on a plain Git server, but in the Git Essential context, the script is not able to detect IP, likely due to the difference in inter-process mechanisms.
Is there better approaches and plugins that allows one to do IP-based access control?
Thank you very much for your comments.
The best way to intercept hosting operations is through the use of an ScmRequestCheck
. You could
component-import
in your atlassian-plugin.xml for RequestManagerscm-request-check
module in your atlassian-plugin.xmlcheck
, call requestManager.getRequestContext().getRemoteAddress() to get the callers IPI've created a small plugin to help you on your way: https://bitbucket.org/mheemskerk/stash-scm-ip-check-example
Thank you so much Michale. It's working as a charm -- exactly the way I want it to be! -- Hanxi
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Edit: this solution does not work because the request context isn't available in a repository hook. See the other answer for an alternative.
An alternative is to write a small plugin that provides a PreReceiveRepositoryHook that checks the remote IP and allows or rejects the push.
component-import
in your atlassian-plugin.xml for RequestManageronReceive
, call requestManager.getRequestContext().getRemoteAddress() to get the callers IP.Please note that if you have a proxy server in the mix and that proxy server sets X-Forwarded-For
headers, the remote address may be a comma separated list of ip addresses. In that case, you'd want the first IP in the list.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Michael, I like the solution you suggested very much, however I am fighting a classloading issue: In my atlassian-plugin.xml I have: <component-import key="reqManager" interface="com.atlassian.stash.request.RequestManager" /> And my custom RepositoryHook looks like: public class MyRepositoryHook implements PreReceiveRepositoryHook { private com.atlassian.stash.request.RequestManager reqManager; public MyRepositoryHook(RequestManager reqManager) { this.reqManager = reqManager; } public boolean onReceive(...) { String ip = this.reqManager.getRequestContext().getRemoteAddress(); //do some ip checking and return true/false accordingly return true; } } I don't know if the above is the correct way to inject RequestManger to the PreReceiveHook. In my case upon a test push, the plugin throws null pointer exceptions because reqManager is null, which tells me it's not injected properly. The small custom plugin installs correctly and shows up in the "manage add-ons" admin page, with all modules loaded including the PreReceiveHook and the component-import for Request Manager. Thanks again for your comments!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, The problem isn't that the RequestManager isn't being injected. The problem is that there is no current request context because the hooks get processed on a separate thread which doesn't inherit the request context state. There is an alternative however using `ScmRequestCheck`. I'll write a separate answer describing that option.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Presumably if you want the staging/production machines to only be able to pull, you could add the SSH key for those machines in as Read Only Access tokens which would mean that they'd be able to pull and not push?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.