comparison tests/test-lfs-serve-access.t @ 37766:925707ac2855

lfs: add the 'Authorization' property to the Batch API response, if present The client copies all of these properties under 'header' to the HTTP Headers of the subsequent GET or PUT request that it performs. That allows the Basic HTTP authentication used to authorize the Batch API request to also authorize the upload/download action. There's likely further work to do here. There's an 'authenticated' boolean key in the Batch API response that can be set, and there is an 'LFS-Authenticate' header that is used instead of 'WWW-Authenticate'[1]. (We likely need to support both, since some hosting solutions are likely to only respond with the latter.) In any event, this works with SCM Manager, so there is real world benefit. I'm limiting the headers returned to 'Basic', because that's all the lfs spec calls out. In practice, I've seen gitbucket emit custom header content[2]. [1] https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#response-errors [2] https://github.com/gitbucket/gitbucket/blob/35655f33c7713f08515ed640ece0948acd6d6168/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala#L119
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 06 Apr 2018 11:13:47 -0400
parents ab04972a33ef
children 326b174c6a47 538e850ae737
comparison
equal deleted inserted replaced
37765:ab04972a33ef 37766:925707ac2855
329 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob) 329 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob)
330 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, 'dummy content') (glob) 330 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, 'dummy content') (glob)
331 $LOCALIP - - [$ERRDATE$] HG error: hint=_('run hg verify')) (glob) 331 $LOCALIP - - [$ERRDATE$] HG error: hint=_('run hg verify')) (glob)
332 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (glob) 332 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (glob)
333 $LOCALIP - - [$ERRDATE$] HG error: (glob) 333 $LOCALIP - - [$ERRDATE$] HG error: (glob)
334
335 Basic Authorization headers are returned by the Batch API, and sent back with
336 the GET/PUT request.
337
338 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
339
340 $ cat >> $HGRCPATH << EOF
341 > [experimental]
342 > lfs.disableusercache = True
343 > [auth]
344 > l.schemes=http
345 > l.prefix=lo
346 > l.username=user
347 > l.password=pass
348 > EOF
349
350 $ cat << EOF > userpass.py
351 > import base64
352 > from mercurial.hgweb import common
353 > def perform_authentication(hgweb, req, op):
354 > auth = req.headers.get(b'Authorization')
355 > if not auth:
356 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, b'who',
357 > [(b'WWW-Authenticate', b'Basic Realm="mercurial"')])
358 > if base64.b64decode(auth.split()[1]).split(b':', 1) != [b'user',
359 > b'pass']:
360 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, b'no')
361 > def extsetup():
362 > common.permhooks.insert(0, perform_authentication)
363 > EOF
364
365 $ hg --config extensions.x=$TESTTMP/userpass.py \
366 > -R server serve -d -p $HGPORT1 --pid-file=hg.pid \
367 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
368 $ mv hg.pid $DAEMON_PIDS
369
370 $ hg clone --debug http://localhost:$HGPORT1 auth_clone | egrep '^[{}]| '
371 {
372 "objects": [
373 {
374 "actions": {
375 "download": {
376 "expires_at": "$ISO_8601_DATE_TIME$"
377 "header": {
378 "Accept": "application/vnd.git-lfs"
379 "Authorization": "Basic dXNlcjpwYXNz"
380 }
381 "href": "http://localhost:$HGPORT1/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d"
382 }
383 }
384 "oid": "276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d"
385 "size": 14
386 }
387 ]
388 "transfer": "basic"
389 }
390
391 $ echo 'another blob' > auth_clone/lfs.blob
392 $ hg -R auth_clone ci -Aqm 'add blob'
393 $ hg -R auth_clone --debug push | egrep '^[{}]| '
394 {
395 "objects": [
396 {
397 "actions": {
398 "upload": {
399 "expires_at": "$ISO_8601_DATE_TIME$"
400 "header": {
401 "Accept": "application/vnd.git-lfs"
402 "Authorization": "Basic dXNlcjpwYXNz"
403 }
404 "href": "http://localhost:$HGPORT1/.hg/lfs/objects/df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3"
405 }
406 }
407 "oid": "df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3"
408 "size": 13
409 }
410 ]
411 "transfer": "basic"
412 }
413
414 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
415
416 $ cat $TESTTMP/access.log $TESTTMP/errors.log
417 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
418 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
419 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
420 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
421 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - (glob)
422 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
423 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 200 - (glob)
424 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
425 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
426 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e+4d9397055dc0c205f3132f331f36353ab1a525a3 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
427 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
428 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
429 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
430 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
431 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - (glob)
432 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
433 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3 HTTP/1.1" 201 - (glob)
434 $LOCALIP - - [$LOGDATE$] "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
435 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)