forked from docker-archive/golem
/
main.go
124 lines (107 loc) · 3.3 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"flag"
"net/http"
"net/http/httputil"
"net/url"
"path"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/api/v2"
"github.com/docker/libtrust"
"github.com/gorilla/mux"
)
var listenAddr string
var registryAddr string
var notaryAddr string
var cert string
var certKey string
var key libtrust.PrivateKey
func init() {
flag.StringVar(&listenAddr, "l", "localhost:6000", "Address to listen on")
flag.StringVar(®istryAddr, "r", "http://localhost:5000", "Upstream registry to connect to")
flag.StringVar(¬aryAddr, "n", "http://localhost:4443", "Upstream notary server to connect to")
flag.StringVar(&cert, "c", "", "TLS certificate")
flag.StringVar(&certKey, "k", "", "TLS certificate key")
var err error
key, err = libtrust.GenerateECP256PrivateKey()
if err != nil {
logrus.Fatalf("Error generating key: %s", err)
}
}
func main() {
flag.Parse()
r, err := url.Parse(registryAddr)
if err != nil {
logrus.Fatalf("Error parsing registry address: %s", err)
}
n, err := url.Parse(notaryAddr)
if err != nil {
logrus.Fatalf("Error parsing notary address: %s", err)
}
rHandler := hostProxy(r)
nHandler := hostProxy(n)
router := v2.RouterWithPrefix("")
router.GetRoute(v2.RouteNameBase).Handler(rHandler)
// Configure notary routes
router.Methods("POST").Path("/v2/{imageName:.*}/_trust/tuf/").Handler(nHandler)
router.Methods("GET").Path("/v2/{imageName:.*}/_trust/tuf/{tufRole:(root|targets|snapshot)}.json").Handler(nHandler)
router.Methods("GET").Path("/v2/{imageName:.*}/_trust/tuf/timestamp.json").Handler(nHandler)
router.Methods("GET").Path("/v2/{imageName:.*}/_trust/tuf/timestamp.key").Handler(nHandler)
router.Methods("DELETE").Path("/v2/{imageName:.*}/_trust/tuf/").Handler(nHandler)
// Configure registry routes
router.GetRoute(v2.RouteNameManifest).Handler(manifestChanger{rHandler})
router.GetRoute(v2.RouteNameTags).Handler(rHandler)
router.GetRoute(v2.RouteNameBlob).Handler(blobChanger{rHandler})
router.GetRoute(v2.RouteNameBlobUpload).Handler(rHandler)
router.GetRoute(v2.RouteNameBlobUploadChunk).Handler(rHandler)
if cert != "" && certKey != "" {
http.ListenAndServeTLS(listenAddr, cert, certKey, logWrapper{router})
} else {
http.ListenAndServe(listenAddr, logWrapper{router})
}
}
func hostProxy(target *url.URL) http.Handler {
proxy := httputil.NewSingleHostReverseProxy(target)
director := proxy.Director
proxy.Director = func(req *http.Request) {
addr := req.RemoteAddr
if i := strings.Index(addr, ":"); i > 0 {
addr = addr[:i]
}
xff := req.Header.Get("X-Forwarded-For")
if xff == "" {
xff = addr
} else {
xff = xff + ", " + addr
}
proto := "http"
if req.TLS != nil && req.TLS.HandshakeComplete {
proto = "https"
}
director(req)
req.Header.Set("X-Real-IP", addr)
req.Header.Set("X-Forwarded-Proto", proto)
req.Header.Set("X-Forwarded-For", xff)
}
return proxy
}
type logWrapper struct {
http.Handler
}
func (l logWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
logrus.Infof("Called %s: %s", r.Method, r.URL.String())
l.Handler.ServeHTTP(rw, r)
}
func extractOperation(r *http.Request) string {
vars := mux.Vars(r)
name := vars["name"]
return path.Base(name)
}
func copyHeader(dst, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}