Skip to content

Commit f57a015

Browse files
Merge 0655331 into 6dbb40e
2 parents 6dbb40e + 0655331 commit f57a015

File tree

6 files changed

+1127
-5
lines changed

6 files changed

+1127
-5
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
language: go
22

33
go:
4-
- 1.15
4+
- 1.18
55

66
install:
77
- go get -v -t ./...
8-
- go get github.com/mattn/goveralls
8+
- go install github.com/mattn/goveralls@latest
99

1010
script:
1111
- go vet ./...

Dockerfile.envelope

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Built the command using a golang base image.
2-
FROM golang:1.14.4-alpine3.12 AS build
2+
FROM golang:1.18-alpine3.16 AS build
33
RUN apk add git
44
ADD . /go/src/github.com/m-lab/access
5-
RUN go get -v github.com/m-lab/access/cmd/envelope
5+
RUN go get -v github.com/m-lab/access/cmd/envelope && \
6+
go install github.com/m-lab/access/cmd/envelope
67

78
# Now copy the resulting command into the minimal base image.
8-
FROM alpine:3.12
9+
FROM alpine:3.16
910
COPY --from=build /go/bin/envelope /
1011
WORKDIR /
1112
RUN apk add --no-cache iptables ip6tables ca-certificates && update-ca-certificates

Dockerfile.proxy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Built the command using a golang base image.
2+
FROM golang:1.18-alpine3.16 AS build
3+
RUN apk add git
4+
ADD . /go/src/github.com/m-lab/access
5+
WORKDIR /go/src/github.com/m-lab/access
6+
RUN go get -v github.com/m-lab/access/cmd/proxy && \
7+
go install github.com/m-lab/access/cmd/proxy
8+
9+
# Now copy the resulting command into the minimal base image.
10+
FROM alpine:3.16
11+
COPY --from=build /go/bin/proxy /
12+
WORKDIR /
13+
RUN apk add --no-cache iptables ip6tables ca-certificates && update-ca-certificates
14+
ENTRYPOINT ["/proxy"]

cmd/proxy/main.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Create a forwarding NewSingleHostReverseProxy for local services that
2+
// supports admission control, including access token validation and utilization
3+
// based "tx controller".
4+
package main
5+
6+
import (
7+
"context"
8+
"crypto/tls"
9+
"errors"
10+
"flag"
11+
"log"
12+
"net/http"
13+
"net/http/httputil"
14+
"net/url"
15+
"os"
16+
"strings"
17+
"time"
18+
19+
"github.com/gorilla/handlers"
20+
21+
"github.com/m-lab/access/controller"
22+
"github.com/m-lab/access/token"
23+
24+
"github.com/m-lab/go/flagx"
25+
"github.com/m-lab/go/httpx"
26+
"github.com/m-lab/go/rtx"
27+
)
28+
29+
var (
30+
tokenVerifyKey = flagx.FileBytesArray{}
31+
tokenRequired bool
32+
tokenMachine string
33+
certFile string
34+
keyFile string
35+
forward = forwardURLs{}
36+
)
37+
38+
type ForwardURL struct {
39+
From *url.URL
40+
Target *url.URL
41+
}
42+
43+
type forwardURLs []ForwardURL
44+
45+
func (f forwardURLs) String() string {
46+
s := ""
47+
for i := range f {
48+
s += f[i].From.String() + "@" + f[i].Target.String()
49+
}
50+
return s
51+
}
52+
53+
func (f *forwardURLs) Get() string {
54+
return f.String()
55+
}
56+
57+
func (f *forwardURLs) Set(s string) error {
58+
fields := strings.Split(s, "@")
59+
if len(fields) != 2 {
60+
return errors.New("from-url@target-url")
61+
}
62+
from, err := url.Parse(fields[0])
63+
if err != nil {
64+
return err
65+
}
66+
target, err := url.Parse(fields[1])
67+
if err != nil {
68+
return err
69+
}
70+
x := ForwardURL{
71+
From: from,
72+
Target: target,
73+
}
74+
*f = append(*f, x)
75+
return nil
76+
}
77+
78+
func init() {
79+
flag.Var(&forward, "forward", "listen on from and forward to target url")
80+
flag.Var(&tokenVerifyKey, "token.verify-key", "Public key for verifying access tokens")
81+
flag.BoolVar(&tokenRequired, "token.required", false, "Require access token for requests")
82+
flag.StringVar(&tokenMachine, "token.machine", "", "Use given machine name to verify token claims")
83+
flag.StringVar(&certFile, "cert", "", "TLS certificate for envelope server")
84+
flag.StringVar(&keyFile, "key", "", "TLS key for envelope server")
85+
}
86+
87+
var mainCtx, mainCancel = context.WithCancel(context.Background())
88+
89+
func EarlyRequestLogger(next http.Handler) http.Handler {
90+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
91+
log.Println(r.RemoteAddr, time.Now(), r.Method, r.URL, r.Proto, r.RequestURI)
92+
// Clone the request with the context provided by isVerified.
93+
next.ServeHTTP(w, r)
94+
})
95+
}
96+
97+
func main() {
98+
defer mainCancel()
99+
flag.Parse()
100+
101+
v, err := token.NewVerifier(tokenVerifyKey.Get()...)
102+
if tokenRequired && err != nil {
103+
rtx.Must(err, "Failed to load verifier for when tokens are required")
104+
}
105+
ac, _ := controller.Setup(mainCtx, v, tokenRequired, tokenMachine)
106+
ac = ac.Append(EarlyRequestLogger)
107+
108+
for i := range forward {
109+
rp := httputil.NewSingleHostReverseProxy(forward[i].Target)
110+
rp.Transport = &http.Transport{
111+
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
112+
}
113+
h := handlers.LoggingHandler(os.Stderr, rp)
114+
smx := http.NewServeMux()
115+
smx.Handle("/", ac.Then(h))
116+
117+
listenAddr := forward[i].From.Host
118+
s := &http.Server{
119+
Addr: listenAddr,
120+
Handler: smx,
121+
// NOTE: set absolute read and write timeouts for server connections.
122+
ReadTimeout: time.Minute, // TODO: make configurable.
123+
WriteTimeout: time.Minute, // TODO: make configurable.
124+
}
125+
126+
switch forward[i].From.Scheme {
127+
case "https":
128+
log.Println("Listening for secure access requests on " + listenAddr + " to " + forward[i].Target.String())
129+
rtx.Must(httpx.ListenAndServeTLSAsync(s, certFile, keyFile), "Could not start envelop server")
130+
case "http":
131+
log.Println("Listening for INSECURE access requests on " + listenAddr + " to " + forward[i].Target.String())
132+
rtx.Must(httpx.ListenAndServeAsync(s), "Could not start envelop server")
133+
default:
134+
panic("unknown forward scheme")
135+
}
136+
defer s.Close()
137+
}
138+
<-mainCtx.Done()
139+
}

go.mod

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module github.com/m-lab/access
2+
3+
go 1.18
4+
5+
require (
6+
github.com/go-test/deep v1.0.8
7+
github.com/gorilla/handlers v1.5.1
8+
github.com/gorilla/websocket v1.4.2
9+
github.com/justinas/alice v1.2.0
10+
github.com/kr/pretty v0.3.0
11+
github.com/m-lab/go v0.1.45
12+
github.com/m-lab/locate v0.8.3
13+
github.com/prometheus/client_golang v1.8.0
14+
github.com/prometheus/procfs v0.2.0
15+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
16+
gopkg.in/m-lab/pipe.v3 v3.0.0-20180108231244-604e84f43ee0
17+
gopkg.in/square/go-jose.v2 v2.6.0
18+
)
19+
20+
require (
21+
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 // indirect
22+
github.com/beorn7/perks v1.0.1 // indirect
23+
github.com/cespare/xxhash/v2 v2.1.1 // indirect
24+
github.com/felixge/httpsnoop v1.0.1 // indirect
25+
github.com/golang/protobuf v1.5.2 // indirect
26+
github.com/kr/text v0.2.0 // indirect
27+
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
28+
github.com/prometheus/client_model v0.2.0 // indirect
29+
github.com/prometheus/common v0.14.0 // indirect
30+
github.com/rogpeppe/go-internal v1.6.1 // indirect
31+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
32+
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
33+
google.golang.org/protobuf v1.27.1 // indirect
34+
)

0 commit comments

Comments
 (0)