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
015c6f5f
Commit
015c6f5f
authored
Mar 11, 2016
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
86b2a17f
Pipeline
#563
failed with stage
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
51 additions
and
12 deletions
+51
-12
internal/api/auth.go
internal/api/auth.go
+34
-10
internal/git/xblob.go
internal/git/xblob.go
+1
-1
main_test.go
main_test.go
+16
-1
No files found.
internal/api/auth.go
View file @
015c6f5f
...
...
@@ -42,9 +42,10 @@ type AuthCacheEntry struct {
// Entries are keyed by project + credentials
type
AuthCacheKey
struct
{
project
string
query
string
// e.g. with passing in private_token=...
header
string
// request header url-encoded, e.g. PRIVATE-TOKEN=...
project
string
userinfo
string
// user[:password] or ""
query
string
// e.g. with passing in private_token=...
header
string
// request header url-encoded, e.g. PRIVATE-TOKEN=...
}
// Authorization reply cache
...
...
@@ -63,7 +64,13 @@ func NewAuthCache(a *API) *AuthCache {
// Verify that download access is ok or not.
// first we try to use the cache; if information is not there -> ask auth backend
// download is ok if AuthReply.RepoPath != ""
func
(
c
*
AuthCache
)
VerifyDownloadAccess
(
project
string
,
query
string
,
header
http
.
Header
)
AuthReply
{
func
(
c
*
AuthCache
)
VerifyDownloadAccess
(
project
string
,
userinfo
*
url
.
Userinfo
,
query
string
,
header
http
.
Header
)
AuthReply
{
// In addition to userinfo:
u
:=
""
if
userinfo
!=
nil
{
u
=
userinfo
.
String
()
}
// Use only tokens from query/header and selected cookies to minimize cache and avoid
// creating redundant cache entries because of e.g. unrelated headers.
queryValues
,
_
:=
url
.
ParseQuery
(
query
)
// this is what URL.Query() does
...
...
@@ -95,7 +102,7 @@ func (c *AuthCache) VerifyDownloadAccess(project string, query string, header ht
h
[
"Cookie"
]
=
[]
string
{
hc
}
}
key
:=
AuthCacheKey
{
project
,
q
.
Encode
(),
h
.
Encode
()}
key
:=
AuthCacheKey
{
project
,
u
,
q
.
Encode
(),
h
.
Encode
()}
return
c
.
verifyDownloadAccess
(
key
)
}
...
...
@@ -194,6 +201,18 @@ func (c *AuthCache) refreshEntry(auth *AuthCacheEntry, key AuthCacheKey) {
// Ask auth backend about cache key
func
(
c
*
AuthCache
)
askAuthBackend
(
key
AuthCacheKey
)
AuthReply
{
// key.userinfo -> url.Userinfo
var
user
*
url
.
Userinfo
if
key
.
userinfo
!=
""
{
u
,
err
:=
url
.
Parse
(
key
.
userinfo
+
"@/"
)
// url prepared-to-parse userinfo must be valid
panic
(
err
)
if
(
u
.
User
==
nil
)
{
panic
(
fmt
.
Errorf
(
"userinfo parse: `%s` -> empty"
,
key
.
userinfo
))
}
user
=
u
.
User
}
// key.header -> url.Values -> http.Header
hv
,
err
:=
url
.
ParseQuery
(
key
.
header
)
if
err
!=
nil
{
...
...
@@ -206,7 +225,7 @@ func (c *AuthCache) askAuthBackend(key AuthCacheKey) AuthReply {
header
[
k
]
=
v
}
return
c
.
a
.
verifyDownloadAccess
(
key
.
project
,
key
.
query
,
header
)
return
c
.
a
.
verifyDownloadAccess
(
key
.
project
,
user
,
key
.
query
,
header
)
}
// Ask auth backend about whether download is ok for a project.
...
...
@@ -215,11 +234,11 @@ func (c *AuthCache) askAuthBackend(key AuthCacheKey) AuthReply {
//
// Replies from authentication backend are cached for 30 seconds as each
// request to Rails code is heavy and slow.
func
(
a
*
API
)
VerifyDownloadAccess
(
project
,
query
string
,
header
http
.
Header
)
AuthReply
{
return
a
.
authCache
.
VerifyDownloadAccess
(
project
,
query
,
header
)
func
(
a
*
API
)
VerifyDownloadAccess
(
project
string
,
user
*
url
.
Userinfo
,
query
string
,
header
http
.
Header
)
AuthReply
{
return
a
.
authCache
.
VerifyDownloadAccess
(
project
,
user
,
query
,
header
)
}
func
(
a
*
API
)
verifyDownloadAccess
(
project
,
query
string
,
header
http
.
Header
)
AuthReply
{
func
(
a
*
API
)
verifyDownloadAccess
(
project
string
,
user
*
url
.
Userinfo
,
query
string
,
header
http
.
Header
)
AuthReply
{
authReply
:=
AuthReply
{
RawReply
:
httptest
.
NewRecorder
(),
}
...
...
@@ -230,7 +249,12 @@ func (a *API) verifyDownloadAccess(project, query string, header http.Header) Au
// - that's why we auth backend to authenticate as if it was request to
// get repo archive and propagate request query and header.
// url := project + ".git/info/refs?service=git-upload-pack"
url
:=
project
+
"/repository/archive.zip"
url
:=
""
if
user
!=
nil
{
url
+=
fmt
.
Sprintf
(
"%s@"
,
user
)
}
url
+=
project
+
"/repository/archive.zip"
if
query
!=
""
{
url
+=
"?"
+
query
}
...
...
internal/git/xblob.go
View file @
015c6f5f
...
...
@@ -40,7 +40,7 @@ func handleGetBlobRaw(a *api.API, w http.ResponseWriter, r *http.Request) {
refpath
:=
u
.
Path
[
rawLoc
[
1
]
:
]
// Query download access auth for this project
authReply
:=
a
.
VerifyDownloadAccess
(
project
,
u
.
RawQuery
,
r
.
Header
)
authReply
:=
a
.
VerifyDownloadAccess
(
project
,
u
.
User
,
u
.
RawQuery
,
r
.
Header
)
if
authReply
.
RepoPath
==
""
{
// access denied - copy auth reply to client in full -
// there are HTTP code and other headers / body relevant for
...
...
main_test.go
View file @
015c6f5f
...
...
@@ -815,7 +815,13 @@ func TestPrivateBlobDownload(t *testing.T) {
token_ok2
:=
r
.
Header
.
Get
(
"BBB-TOKEN"
)
==
"TOKEN-4BBB"
cookie
,
_
:=
r
.
Cookie
(
"_gitlab_session"
)
cookie_ok3
:=
(
cookie
!=
nil
&&
cookie
.
Value
==
"COOKIE-CCC"
)
if
!
(
token_ok1
||
token_ok2
||
cookie_ok3
)
{
user
:=
r
.
URL
.
User
user_ok4
:=
false
if
user
!=
nil
{
password
,
_
:=
user
.
Password
()
user_ok4
=
(
user
.
Username
()
==
"user-ddd"
&&
password
==
"password-eee"
)
}
if
!
(
token_ok1
||
token_ok2
||
cookie_ok3
||
user_ok4
)
{
w
.
WriteHeader
(
403
)
fmt
.
Fprintf
(
w
,
"Access denied"
)
return
...
...
@@ -854,4 +860,13 @@ func TestPrivateBlobDownload(t *testing.T) {
dl
.
Header
.
Set
(
"Cookie"
,
"alpha=1; _gitlab_session=COOKIE-CCC; beta=2"
)
dl
.
ExpectCode
(
"/5f923865/README.md"
,
200
)
dl
.
ExpectSha1
(
"/5f923865/README.md"
,
"5f7af35c185a9e5face2f4afb6d7c4f00328d04c"
)
dl
.
Header
=
make
(
http
.
Header
)
// clear
dl
.
ExpectCode
(
"/5f923865/README.md"
,
403
)
dlBaseUrl
:=
dl
.
urlPrefix
dl
.
urlPrefix
=
"user-aaa:password-bbb@"
+
dlBaseUrl
dl
.
ExpectCode
(
"/5f923865/README.md"
,
403
)
dl
.
urlPrefix
=
"user-ddd:password-eee@"
+
dlBaseUrl
dl
.
ExpectCode
(
"/5f923865/README.md"
,
200
)
dl
.
ExpectSha1
(
"/5f923865/README.md"
,
"5f7af35c185a9e5face2f4afb6d7c4f00328d04c"
)
}
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