Skip to content

Commit 2f7a8c1

Browse files
committed
cmd/coordinator: add authenticated proxy to internal module proxy
So builders outside of GCE (Macs, etc) can use a module proxy. It will be exposed to them via an unauthenticated localhost:3000 server that adds the necessary authentication to this server. This is a follow-up of work started in CL 157438. Updates golang/go#14594 Change-Id: Id824b0ad3a0274048023cc72f8adad23d5f0ea29 Reviewed-on: https://go-review.googlesource.com/c/build/+/165779 Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent f3f1951 commit 2f7a8c1

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

cmd/coordinator/coordinator.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,25 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
211211
return tc, nil
212212
}
213213

214+
// httpRouter is the coordinator's mux, routing traffic to one of
215+
// three locations:
216+
// 1) a buildlet, from gomote clients (if X-Buildlet-Proxy is set)
217+
// 2) our module proxy cache on GKE (if X-Proxy-Service == module-cache)
218+
// 3) traffic to the coordinator itself (the default)
219+
type httpRouter struct{}
220+
221+
func (httpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
222+
if r.Header.Get("X-Buildlet-Proxy") != "" {
223+
requireBuildletProxyAuth(http.HandlerFunc(proxyBuildletHTTP)).ServeHTTP(w, r)
224+
return
225+
}
226+
if r.Header.Get("X-Proxy-Service") == "module-cache" {
227+
requireBuildletProxyAuth(http.HandlerFunc(proxyModuleCache)).ServeHTTP(w, r)
228+
return
229+
}
230+
http.DefaultServeMux.ServeHTTP(w, r)
231+
}
232+
214233
type loggerFunc func(event string, optText ...string)
215234

216235
func (fn loggerFunc) LogEventTime(event string, optText ...string) {

cmd/coordinator/modproxy.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"net/http"
9+
"net/http/httputil"
10+
"net/url"
11+
"strings"
12+
)
13+
14+
// proxyModuleCache proxies from https://farmer.golang.org (with Auth
15+
// & a magic header, as handled by coordinator.go's httpRouter type)
16+
// to Go's private module proxy server running on GKE. The module proxy protocol
17+
// does not define authentication, so we do it ourselves.
18+
//
19+
// The complete path is the buildlet listens on localhost:3000 to run
20+
// an unauthenticated module proxy server for the cmd/go binary to use
21+
// via GOPROXY=http://localhost:3000. That localhost:3000 server
22+
// proxies it to https://farmer.golang.org with auth headers and a
23+
// sentinel X-Proxy-Service:module-cache header. Then coordinator.go's
24+
// httpRouter sends it here after the auth has been checked.
25+
//
26+
// This code then does the final reverse proxy, sent without auth.
27+
//
28+
// In summary:
29+
//
30+
// cmd/go -> localhost:3000 -> buildlet -> coordinator --> GKE server
31+
func proxyModuleCache(w http.ResponseWriter, r *http.Request) {
32+
target := moduleProxy()
33+
if !strings.HasPrefix(target, "http") {
34+
http.Error(w, "module proxy not configured", 500)
35+
return
36+
}
37+
backend, err := url.Parse(target)
38+
if err != nil {
39+
http.Error(w, "module proxy misconfigured", 500)
40+
return
41+
}
42+
// TODO: maybe only create this once early. But probably doesn't matter.
43+
rp := httputil.NewSingleHostReverseProxy(backend)
44+
r.Header.Del("Authorization")
45+
r.Header.Del("X-Proxy-Service")
46+
rp.ServeHTTP(w, r)
47+
}

cmd/coordinator/remote.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -265,19 +265,6 @@ func remoteBuildletStatus() string {
265265
return buf.String()
266266
}
267267

268-
// httpRouter separates out HTTP traffic being proxied
269-
// to buildlets on behalf of remote clients from traffic
270-
// destined for the coordinator itself (the default).
271-
type httpRouter struct{}
272-
273-
func (httpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
274-
if r.Header.Get("X-Buildlet-Proxy") != "" {
275-
requireBuildletProxyAuth(http.HandlerFunc(proxyBuildletHTTP)).ServeHTTP(w, r)
276-
} else {
277-
http.DefaultServeMux.ServeHTTP(w, r)
278-
}
279-
}
280-
281268
func proxyBuildletHTTP(w http.ResponseWriter, r *http.Request) {
282269
if r.TLS == nil {
283270
http.Error(w, "https required", http.StatusBadRequest)

0 commit comments

Comments
 (0)