Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-workhorse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gitlab-workhorse
Commits
4b3b9a15
Commit
4b3b9a15
authored
Dec 04, 2015
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
a462b6e9
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
85 additions
and
14 deletions
+85
-14
blob.go
blob.go
+15
-13
main_test.go
main_test.go
+69
-0
upstream.go
upstream.go
+1
-1
No files found.
blob.go
View file @
4b3b9a15
...
@@ -51,7 +51,7 @@ type AuthCacheEntry struct {
...
@@ -51,7 +51,7 @@ type AuthCacheEntry struct {
// Authorization reply cache
// Authorization reply cache
// {} project -> AuthCacheEntry
// {} project -> AuthCacheEntry
//
//
// XXX should be not only project (private
T
oken etc...)
// XXX should be not only project (private
_t
oken etc...)
type
AuthCache
struct
{
type
AuthCache
struct
{
mu
sync
.
RWMutex
// guards .cached
mu
sync
.
RWMutex
// guards .cached
cached
map
[
string
]
*
AuthCacheEntry
cached
map
[
string
]
*
AuthCacheEntry
...
@@ -166,7 +166,8 @@ func askAuthBackend(u *upstream, project string) AuthReply {
...
@@ -166,7 +166,8 @@ func askAuthBackend(u *upstream, project string) AuthReply {
// Request to auth backend to verify whether download is possible via
// Request to auth backend to verify whether download is possible via
// asking as `git fetch` would do.
// asking as `git fetch` would do.
// XXX privateToken not propagated, etc ...
// XXX private_token not propagated, etc ...
// XXX PRIVATE-TOKEN (if header)
reqDownloadAccess
,
err
:=
http
.
NewRequest
(
"GET"
,
project
+
".git/info/refs?service=git-upload-pack"
,
nil
)
reqDownloadAccess
,
err
:=
http
.
NewRequest
(
"GET"
,
project
+
".git/info/refs?service=git-upload-pack"
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
fail500
(
authReply
.
RawReply
,
"GET git-upload-pack"
,
err
)
fail500
(
authReply
.
RawReply
,
"GET git-upload-pack"
,
err
)
...
@@ -196,23 +197,18 @@ func verifyDownloadAccess(u *upstream, project string) AuthReply {
...
@@ -196,23 +197,18 @@ func verifyDownloadAccess(u *upstream, project string) AuthReply {
}
}
// HTTP handler for `.../raw/<ref>/path`
// HTTP handler for `.../raw/<ref>/path`
var
projectRe
=
regexp
.
MustCompile
(
`^/[\w\.-]+/[\w\.-]+
/`
)
var
rawRe
=
regexp
.
MustCompile
(
`/raw
/`
)
func
handleGetBlobRaw
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
func
handleGetBlobRaw
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
// Extract project & refpath
// Extract project & refpath
// <project>/raw/branch/file -> <project>, branch/file
// <project>/raw/branch/file -> <project>, branch/file
project
:=
projectRe
.
FindString
(
r
.
Request
.
URL
.
Path
)
rawLoc
:=
rawRe
.
FindStringIndex
(
r
.
Request
.
URL
.
Path
)
if
project
==
""
||
project
[
len
(
project
)
-
1
]
!=
'/'
{
if
rawLoc
==
nil
{
fail500
(
w
,
"extract project name"
,
nil
)
// XXX err=nil
fail500
(
w
,
"extract project name"
,
nil
)
// XXX err=nil
return
return
}
}
refpath
:=
r
.
Request
.
URL
.
Path
[
len
(
project
)
:
]
project
:=
r
.
Request
.
URL
.
Path
[
:
rawLoc
[
0
]]
if
refpath
[
:
4
]
!=
"raw/"
{
refpath
:=
r
.
Request
.
URL
.
Path
[
rawLoc
[
1
]
:
]
fail500
(
w
,
"refpath != raw/..."
,
nil
)
// XXX err=nil
return
}
project
=
project
[
:
len
(
project
)
-
1
]
// strip '.../'
refpath
=
refpath
[
4
:
]
// strip 'raw/...'
// Query download access auth for this project
// Query download access auth for this project
authReply
:=
verifyDownloadAccess
(
r
.
u
,
project
)
authReply
:=
verifyDownloadAccess
(
r
.
u
,
project
)
...
@@ -224,7 +220,13 @@ func handleGetBlobRaw(w http.ResponseWriter, r *gitRequest) {
...
@@ -224,7 +220,13 @@ func handleGetBlobRaw(w http.ResponseWriter, r *gitRequest) {
w
.
Header
()[
k
]
=
v
w
.
Header
()[
k
]
=
v
}
}
w
.
WriteHeader
(
authReply
.
RawReply
.
Code
)
w
.
WriteHeader
(
authReply
.
RawReply
.
Code
)
io
.
Copy
(
w
,
authReply
.
RawReply
.
Body
)
// NOTE do not consume authReply.RawReply.Body with io.Copy -
// this way it will be read one time only and next reads will
// be empty.
_
,
err
:=
w
.
Write
(
authReply
.
RawReply
.
Body
.
Bytes
())
if
err
!=
nil
{
logContext
(
"writing authReply.RawReply.Body"
,
err
)
}
return
return
}
}
...
...
main_test.go
View file @
4b3b9a15
...
@@ -2,6 +2,7 @@ package main
...
@@ -2,6 +2,7 @@ package main
import
(
import
(
"bytes"
"bytes"
"crypto/sha1"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
...
@@ -453,3 +454,71 @@ func deniedXSendfileDownload(t *testing.T, contentFilename string, filePath stri
...
@@ -453,3 +454,71 @@ func deniedXSendfileDownload(t *testing.T, contentFilename string, filePath stri
t
.
Fatal
(
"Unexpected file contents in download"
)
t
.
Fatal
(
"Unexpected file contents in download"
)
}
}
}
}
// sha1(data) as human-readable string
func
sha1s
(
data
[]
byte
)
string
{
return
fmt
.
Sprintf
(
"%x"
,
sha1
.
Sum
(
data
))
}
func
download
(
t
*
testing
.
T
,
url
string
)
(
*
http
.
Response
,
[]
byte
)
{
resp
,
err
:=
http
.
Get
(
url
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
resp
.
Body
.
Close
()
body
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
resp
,
body
}
func
TestAllowedBlobDownload
(
t
*
testing
.
T
)
{
// Prepare test server and backend
ts
:=
testAuthServer
(
nil
,
200
,
gitOkBody
(
t
))
defer
ts
.
Close
()
ws
:=
startWorkhorseServer
(
ts
.
URL
)
defer
ws
.
Close
()
downloadRaw
:=
func
(
refpath
string
)
(
*
http
.
Response
,
[]
byte
)
{
return
download
(
t
,
fmt
.
Sprintf
(
"%s/%s/raw/%s"
,
ws
.
URL
,
testProject
,
refpath
))
}
downloadAndExpectSha1
:=
func
(
refpath
,
expectSha1
string
)
{
_
,
out
:=
downloadRaw
(
refpath
)
outSha1
:=
sha1s
(
out
)
if
outSha1
!=
expectSha1
{
t
.
Fatal
(
"Unexpected content in blob download"
)
}
}
downloadAndExpect
:=
func
(
refpath
,
expect
string
)
{
downloadAndExpectSha1
(
refpath
,
sha1s
([]
byte
(
expect
)))
}
downloadAndExpect
(
"5f923865/README.md"
,
"testme
\n
======
\n\n
Sample repo for testing gitlab features
\n
"
)
downloadAndExpectSha1
(
"5f923865/files/ruby/popen.rb"
,
"68990cc20fa74383358797a27967fa2b45d7d8f6"
)
downloadAndExpectSha1
(
"874797c3/files/ruby/popen.rb"
,
"4c266708f2bfd7ca3fed3f7ec74253f92ff3fe73"
)
resp
,
_
:=
downloadRaw
(
"master/non-existing-file"
)
if
resp
.
StatusCode
!=
404
{
t
.
Fatalf
(
"Unexpected status code (expected 404, got %v)"
,
resp
.
StatusCode
)
}
}
func
TestDeniedBlobDownload
(
t
*
testing
.
T
)
{
// Prepare test server and backend
ts
:=
testAuthServer
(
nil
,
403
,
"Access denied"
)
defer
ts
.
Close
()
ws
:=
startWorkhorseServer
(
ts
.
URL
)
defer
ws
.
Close
()
downloadAndExpect
:=
func
(
refpath
string
,
code
int
)
{
resp
,
_
:=
download
(
t
,
fmt
.
Sprintf
(
"%s/%s/raw/%s"
,
ws
.
URL
,
testProject
,
refpath
))
if
resp
.
StatusCode
!=
code
{
t
.
Fatalf
(
"Unexpected status code (expected %v, got %v)"
,
code
,
resp
.
StatusCode
)
}
}
downloadAndExpect
(
"5f923865/README.md"
,
403
)
downloadAndExpect
(
"5f923865/files/ruby/popen.rb"
,
403
)
downloadAndExpect
(
"874797c3/files/ruby/popen.rb"
,
403
)
downloadAndExpect
(
"master/non-existing-file"
,
403
)
}
upstream.go
View file @
4b3b9a15
...
@@ -75,7 +75,7 @@ var gitServices = [...]gitService{
...
@@ -75,7 +75,7 @@ var gitServices = [...]gitService{
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/uploads/`
),
handleSendFile
},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/uploads/`
),
handleSendFile
},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/raw/
.+\z
`
),
handleGetBlobRaw
},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/raw/`
),
handleGetBlobRaw
},
// Git LFS
// Git LFS
gitService
{
"PUT"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
)},
gitService
{
"PUT"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
)},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment