Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
language: go

go:
- 1.15
- 1.18

install:
- go get -v -t ./...
- go get github.com/mattn/goveralls
- go install github.com/mattn/goveralls@latest

script:
- go vet ./...
Expand Down
7 changes: 4 additions & 3 deletions Dockerfile.envelope
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Built the command using a golang base image.
FROM golang:1.14.4-alpine3.12 AS build
FROM golang:1.18-alpine3.16 AS build
RUN apk add git
ADD . /go/src/github.com/m-lab/access
RUN go get -v github.com/m-lab/access/cmd/envelope
RUN go get -v github.com/m-lab/access/cmd/envelope && \
go install github.com/m-lab/access/cmd/envelope

# Now copy the resulting command into the minimal base image.
FROM alpine:3.12
FROM alpine:3.16
COPY --from=build /go/bin/envelope /
WORKDIR /
RUN apk add --no-cache iptables ip6tables ca-certificates && update-ca-certificates
Expand Down
14 changes: 14 additions & 0 deletions Dockerfile.proxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Built the command using a golang base image.
FROM golang:1.18-alpine3.16 AS build
RUN apk add git
ADD . /go/src/github.com/m-lab/access
WORKDIR /go/src/github.com/m-lab/access
RUN go get -v github.com/m-lab/access/cmd/proxy && \
go install github.com/m-lab/access/cmd/proxy

# Now copy the resulting command into the minimal base image.
FROM alpine:3.16
COPY --from=build /go/bin/proxy /
WORKDIR /
RUN apk add --no-cache iptables ip6tables ca-certificates && update-ca-certificates
ENTRYPOINT ["/proxy"]
139 changes: 139 additions & 0 deletions cmd/proxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Create a forwarding NewSingleHostReverseProxy for local services that
// supports admission control, including access token validation and utilization
// based "tx controller".
package main

import (
"context"
"crypto/tls"
"errors"
"flag"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strings"
"time"

"github.com/gorilla/handlers"

"github.com/m-lab/access/controller"
"github.com/m-lab/access/token"

"github.com/m-lab/go/flagx"
"github.com/m-lab/go/httpx"
"github.com/m-lab/go/rtx"
)

var (
tokenVerifyKey = flagx.FileBytesArray{}
tokenRequired bool
tokenMachine string
certFile string
keyFile string
forward = forwardURLs{}
)

type ForwardURL struct {
From *url.URL
Target *url.URL
}

type forwardURLs []ForwardURL

func (f forwardURLs) String() string {
s := ""
for i := range f {
s += f[i].From.String() + "@" + f[i].Target.String()
}
return s
}

func (f *forwardURLs) Get() string {
return f.String()
}

func (f *forwardURLs) Set(s string) error {
fields := strings.Split(s, "@")
if len(fields) != 2 {
return errors.New("from-url@target-url")
}
from, err := url.Parse(fields[0])
if err != nil {
return err
}
target, err := url.Parse(fields[1])
if err != nil {
return err
}
x := ForwardURL{
From: from,
Target: target,
}
*f = append(*f, x)
return nil
}

func init() {
flag.Var(&forward, "forward", "listen on from and forward to target url")
flag.Var(&tokenVerifyKey, "token.verify-key", "Public key for verifying access tokens")
flag.BoolVar(&tokenRequired, "token.required", false, "Require access token for requests")
flag.StringVar(&tokenMachine, "token.machine", "", "Use given machine name to verify token claims")
flag.StringVar(&certFile, "cert", "", "TLS certificate for envelope server")
flag.StringVar(&keyFile, "key", "", "TLS key for envelope server")
}

var mainCtx, mainCancel = context.WithCancel(context.Background())

func EarlyRequestLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println(r.RemoteAddr, time.Now(), r.Method, r.URL, r.Proto, r.RequestURI)
// Clone the request with the context provided by isVerified.
next.ServeHTTP(w, r)
})
}

func main() {
defer mainCancel()
flag.Parse()

v, err := token.NewVerifier(tokenVerifyKey.Get()...)
if tokenRequired && err != nil {
rtx.Must(err, "Failed to load verifier for when tokens are required")
}
ac, _ := controller.Setup(mainCtx, v, tokenRequired, tokenMachine)
ac = ac.Append(EarlyRequestLogger)

for i := range forward {
rp := httputil.NewSingleHostReverseProxy(forward[i].Target)
rp.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
h := handlers.LoggingHandler(os.Stderr, rp)
smx := http.NewServeMux()
smx.Handle("/", ac.Then(h))

listenAddr := forward[i].From.Host
s := &http.Server{
Addr: listenAddr,
Handler: smx,
// NOTE: set absolute read and write timeouts for server connections.
ReadTimeout: time.Minute, // TODO: make configurable.
WriteTimeout: time.Minute, // TODO: make configurable.
}

switch forward[i].From.Scheme {
case "https":
log.Println("Listening for secure access requests on " + listenAddr + " to " + forward[i].Target.String())
rtx.Must(httpx.ListenAndServeTLSAsync(s, certFile, keyFile), "Could not start envelop server")
case "http":
log.Println("Listening for INSECURE access requests on " + listenAddr + " to " + forward[i].Target.String())
rtx.Must(httpx.ListenAndServeAsync(s), "Could not start envelop server")
default:
panic("unknown forward scheme")
}
defer s.Close()
}
<-mainCtx.Done()
}
34 changes: 34 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module github.com/m-lab/access

go 1.18

require (
github.com/go-test/deep v1.0.8
github.com/gorilla/handlers v1.5.1
github.com/gorilla/websocket v1.4.2
github.com/justinas/alice v1.2.0
github.com/kr/pretty v0.3.0
github.com/m-lab/go v0.1.45
github.com/m-lab/locate v0.8.3
github.com/prometheus/client_golang v1.8.0
github.com/prometheus/procfs v0.2.0
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
gopkg.in/m-lab/pipe.v3 v3.0.0-20180108231244-604e84f43ee0
gopkg.in/square/go-jose.v2 v2.6.0
)

require (
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.14.0 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
Loading