threads / discuss / 30968

git clone fails "with error: RPC failed; result=22, HTTP code = 401

Subject: git clone fails "with error: RPC failed; result=22, HTTP code = 401

## tl;dr

2 messages between Jul 6, 2012 and Jul 10, 2012.

replies: 1people: 2as markdown or json

Ilya Ruprecht· Jul 6, 2012, 12:04 UTC · lore
Hi all,
following enviroment:

stock debian squeeze + apache2 + gitweb. Apache handles user authentication over ldap.

the apache git-related config is:

--- (taken from the http://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html)

[...] SetEnv GIT_PROJECT_ROOT /mnt/system/git

AliasMatch ^/git/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$
/mnt/system/git/$1
AliasMatch ^/git/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$
/mnt/system/git/$1
ScriptAliasMatch \
        "(?x)^/git/(.*/(HEAD | \
                        info/refs | \
                        objects/info/[^/]+ | \
                        git-(upload|receive)-pack))$" \
        /usr/lib/git-core/git-http-backend/$1
ScriptAlias /git/ /usr/lib/cgi-bin/gitweb.cgi/
[...]
        <Location "/git/repo1.git">
                # read access
                <Limit GET>
                        require ldap-group repo.writers
                        require ldap-group repo.readers
                </Limit>
                # write access
                <Limit GET PUT POST DELETE PROPPATCH MKCOL COPY MOVE
LOCK UNLOCK>
                        require ldap-group repo.writers
                </Limit>
        </Location>
----------

The ldap group "repo.writers" has "repo.writer" user in it. The ldap group "repo.readers" has "repo.reader" user in it.

Using the "repo.writer" User, i can successfully clone the repo / push into the repo. The appropriate apache-log entries are:

---------------------------------------------------- 10.13.99.59 - - [06/Jul/2012:13:28:57 +0200] "GET /git/repo1.git/info/refs?service=git-receive-pack HTTP/1.1" 401 2427 "-" "git/1.7.2.5" 10.13.99.59 - repo.writer [06/Jul/2012:13:28:57 +0200] "GET /git/repo1.git/info/refs?service=git-receive-pack HTTP/1.1" 200 728 "-" "git/1.7.2.5" 10.13.99.59 - repo.writer [06/Jul/2012:13:28:57 +0200] "POST /git/repo1.git/git-receive-pack HTTP/1.1" 200 754 "-" "git/1.7.2.5" ----------------------------------------------------

But if i try to use the "repo.reader" account to CLONE the repo, then it fails:

output@shell: ---------------------------------------------------- ilya@brick:/tmp $ git clone https://repo.reader@git-host/git/repo1.git Cloning into repo1... Password: error: RPC failed; result=22, HTTP code = 401 fatal: The remote end hung up unexpectedly ilya@brick: ----------------------------------------------------

output@apache-logs ---------------------------------------------------- 10.13.99.59 - - [06/Jul/2012:13:28:13 +0200] "GET /git/repo1.git/info/refs?service=git-upload-pack HTTP/1.1" 401 2427 "-" "git/1.7.2.5" 10.13.99.59 - repo.reader [06/Jul/2012:13:28:13 +0200] "GET /git/repo1.git/info/refs?service=git-upload-pack HTTP/1.1" 200 935 "-" "git/1.7.2.5" 10.13.99.59 - repo.reader [06/Jul/2012:13:28:13 +0200] "POST /git/repo1.git/git-upload-pack HTTP/1.1" 401 894 "-" "git/1.7.2.5" ----------------------------------------------------

The reason why the cloning fails is pretty clear
1. the repo.reader is trying to "POST /git/repo1.git/git-upload-pack",
2. accordingly the rule "<Limit POST>" for "writers" is matching,
3. apache makes a lookup into LDAP and OF COURSE cannot fint the
"repo.reader"-User in the group "repo.writers"
4. as a result the 401 is replied by apache.

When i put the "repo.reader" user into the "repo.writers"-group, then, of course, he can clone the repo. But then he also can push into the repo...

The question is now - why, damn, the git client is trying to post something on CLONE!??!

And the second question - how do i solve it?
I need the authenticated read / authenticated writes separation.
Thanks in advance!
Ilya
Jeff King· Jul 10, 2012, 20:51 UTC · re: Ilya Ruprecht · lore

Re: git clone fails "with error: RPC failed; result=22, HTTP code = 401

On Fri, Jul 06, 2012 at 02:04:10PM +0200, Ilya Ruprecht wrote:
Show 12 quoted lines
>         <Location "/git/repo1.git">
>                 # read access
>                 <Limit GET>
>                         require ldap-group repo.writers
>                         require ldap-group repo.readers
>                 </Limit>
> 
>                 # write access
>                 <Limit GET PUT POST DELETE PROPPATCH MKCOL COPY MOVE
> LOCK UNLOCK>
>                         require ldap-group repo.writers
>                 </Limit>

As you noticed, this will not do what you want. Git's smart-http protocol uses POST requests to send the list of heads during ref negotiation. So even a fetch request will require both GETs and POSTs.

The right way to restrict reading versus writing over smart-http is to check which git service is being requested (confusingly, "git-upload-pack" is for clones and fetches, and "git-receive-pack" is for pushes; the names are based on what the _server_ is doing). There is an example in the git-http-backend documentation, which uses a LocationMatch along with a "require" directive.

-Peff

← back to recent threads