Skip to content

Commit

Permalink
Merge pull request ContentSquare#78 from lalex/header_auth
Browse files Browse the repository at this point in the history
Allow to auth with the X-ClickHouse-User header
  • Loading branch information
hagen1778 authored Feb 1, 2020
2 parents 7c9a04c + 28a883e commit ea4d066
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
36 changes: 36 additions & 0 deletions proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,42 @@ func TestReverseProxy_ServeHTTP1(t *testing.T) {
return makeCustomRequest(p, req)
},
},
{
cfg: authCfg,
name: "headers auth ok",
expResponse: okResponse,
expStatusCode: http.StatusOK,
f: func(p *reverseProxy) *http.Response {
req := httptest.NewRequest("POST", fakeServer.URL, nil)
req.Header.Set("X-ClickHouse-User", "foo")
req.Header.Set("X-ClickHouse-Key", "bar")
return makeCustomRequest(p, req)
},
},
{
cfg: authCfg,
name: "header auth wrong name",
expResponse: "invalid username or password for user \"fooo\"",
expStatusCode: http.StatusUnauthorized,
f: func(p *reverseProxy) *http.Response {
req := httptest.NewRequest("POST", fakeServer.URL, nil)
req.Header.Set("X-ClickHouse-User", "fooo")
req.Header.Set("X-ClickHouse-Key", "bar")
return makeCustomRequest(p, req)
},
},
{
cfg: authCfg,
name: "header auth wrong name",
expResponse: "invalid username or password for user \"foo\"",
expStatusCode: http.StatusUnauthorized,
f: func(p *reverseProxy) *http.Response {
req := httptest.NewRequest("POST", fakeServer.URL, nil)
req.Header.Set("X-ClickHouse-User", "foo")
req.Header.Set("X-ClickHouse-Key", "baar")
return makeCustomRequest(p, req)
},
},
}

for _, tc := range testCases {
Expand Down
4 changes: 4 additions & 0 deletions scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ func (s *scope) decorateRequest(req *http.Request) (*http.Request, url.Values) {
// Rewrite possible previous Basic Auth and send request
// as cluster user.
req.SetBasicAuth(s.clusterUser.name, s.clusterUser.password)
// Delete possible X-ClickHouse headers,
// it is not allowed to use X-ClickHouse HTTP headers and other authentication methods simultaneously
req.Header.Del("X-ClickHouse-User")
req.Header.Del("X-ClickHouse-Key")

// Send request to the chosen host from cluster.
req.URL.Scheme = s.host.addr.Scheme
Expand Down
9 changes: 8 additions & 1 deletion utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ func respondWith(rw http.ResponseWriter, err error, status int) {
}

// getAuth retrieves auth credentials from request
// according to CH documentation @see "http://clickhouse.readthedocs.io/en/latest/reference_en.html#HTTP interface"
// according to CH documentation @see "https://clickhouse.yandex/docs/en/interfaces/http/"
func getAuth(req *http.Request) (string, string) {
// check X-ClickHouse- headers
name := req.Header.Get("X-ClickHouse-User")
pass := req.Header.Get("X-ClickHouse-Key")
if name != "" {
return name, pass
}
// if header is empty - check basicAuth
if name, pass, ok := req.BasicAuth(); ok {
return name, pass
}
Expand Down

0 comments on commit ea4d066

Please sign in to comment.