aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/.gitignore2
-rw-r--r--test/cmd/relayd/main.go124
-rw-r--r--test/cmd/unixhttpd/main.go75
-rw-r--r--test/go.mod41
-rw-r--r--test/go.sum55
-rwxr-xr-xtest/unix-socket-xff/start.sh54
6 files changed, 351 insertions, 0 deletions
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..f3324c6
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,2 @@
+*.sock
+*.pem
diff --git a/test/cmd/relayd/main.go b/test/cmd/relayd/main.go
new file mode 100644
index 0000000..26700d7
--- /dev/null
+++ b/test/cmd/relayd/main.go
@@ -0,0 +1,124 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "log"
+ "log/slog"
+ "net"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/TecharoHQ/anubis/internal"
+ "github.com/facebookgo/flagenv"
+ "github.com/google/uuid"
+)
+
+var (
+ bind = flag.String("bind", ":3004", "port to listen on")
+ certDir = flag.String("cert-dir", "/xe/pki", "where to read mounted certificates from")
+ certFname = flag.String("cert-fname", "cert.pem", "certificate filename")
+ keyFname = flag.String("key-fname", "key.pem", "key filename")
+ proxyTo = flag.String("proxy-to", "http://localhost:5000", "where to reverse proxy to")
+ slogLevel = flag.String("slog-level", "info", "logging level")
+)
+
+func main() {
+ flagenv.Parse()
+ flag.Parse()
+
+ internal.InitSlog(*slogLevel)
+
+ slog.Info("starting",
+ "bind", *bind,
+ "cert-dir", *certDir,
+ "cert-fname", *certFname,
+ "key-fname", *keyFname,
+ "proxy-to", *proxyTo,
+ )
+
+ cert := filepath.Join(*certDir, *certFname)
+ key := filepath.Join(*certDir, *keyFname)
+
+ st, err := os.Stat(cert)
+
+ if err != nil {
+ slog.Error("can't stat cert file", "certFname", cert)
+ os.Exit(1)
+ }
+
+ lastModified := st.ModTime()
+
+ go func(lm time.Time) {
+ t := time.NewTicker(time.Hour)
+ defer t.Stop()
+
+ for range t.C {
+ st, err := os.Stat(cert)
+ if err != nil {
+ slog.Error("can't stat file", "fname", cert, "err", err)
+ continue
+ }
+
+ if st.ModTime().After(lm) {
+ slog.Info("new cert detected", "oldTime", lm.Format(time.RFC3339), "newTime", st.ModTime().Format(time.RFC3339))
+ os.Exit(0)
+ }
+ }
+ }(lastModified)
+
+ u, err := url.Parse(*proxyTo)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ h := httputil.NewSingleHostReverseProxy(u)
+
+ if u.Scheme == "unix" {
+ slog.Info("using unix socket proxy")
+
+ h = &httputil.ReverseProxy{
+ Director: func(r *http.Request) {
+ r.URL.Scheme = "http"
+ r.URL.Host = r.Host
+
+ r.Header.Set("X-Forwarded-Proto", "https")
+ r.Header.Set("X-Forwarded-Scheme", "https")
+ r.Header.Set("X-Request-Id", uuid.NewString())
+ r.Header.Set("X-Scheme", "https")
+
+ remoteHost, remotePort, err := net.SplitHostPort(r.Host)
+ if err == nil {
+ r.Header.Set("X-Forwarded-Host", remoteHost)
+ r.Header.Set("X-Forwarded-Port", remotePort)
+ } else {
+ r.Header.Set("X-Forwarded-Host", r.Host)
+ }
+
+ host, _, err := net.SplitHostPort(r.RemoteAddr)
+ if err == nil {
+ r.Header.Set("X-Real-Ip", host)
+ }
+ },
+ Transport: &http.Transport{
+ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
+ return net.Dial("unix", strings.TrimPrefix(*proxyTo, "unix://"))
+ },
+ },
+ }
+ }
+
+ log.Fatal(
+ http.ListenAndServeTLS(
+ *bind,
+ cert,
+ key,
+ h,
+ ),
+ )
+}
diff --git a/test/cmd/unixhttpd/main.go b/test/cmd/unixhttpd/main.go
new file mode 100644
index 0000000..a57c202
--- /dev/null
+++ b/test/cmd/unixhttpd/main.go
@@ -0,0 +1,75 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "log/slog"
+ "net"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/TecharoHQ/anubis/internal"
+ "github.com/facebookgo/flagenv"
+)
+
+var (
+ dir = flag.String("dir", ".", "directory to serve")
+ slogLevel = flag.String("slog-level", "info", "logging level")
+ socketPath = flag.String("socket-path", "./unixhttpd.sock", "unix socket path to use")
+)
+
+func init() {
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0]))
+ fmt.Fprintf(os.Stderr, " %s [--dir=.] [--socket-path=./unixhttpd.sock]\n\n", filepath.Base(os.Args[0]))
+ flag.PrintDefaults()
+ os.Exit(2)
+ }
+}
+
+func main() {
+ flagenv.Parse()
+ flag.Parse()
+
+ internal.InitSlog(*slogLevel)
+
+ if *dir == "" && *socketPath == "" {
+ flag.Usage()
+ }
+
+ slog.Info("starting up", "dir", *dir, "socketPath", *socketPath)
+
+ os.Remove(*socketPath)
+
+ mux := http.NewServeMux()
+
+ mux.HandleFunc("/reqmeta", func(w http.ResponseWriter, r *http.Request) {
+ contains := strings.Contains(r.Header.Get("Accept"), "text/html")
+
+ if contains {
+ w.Header().Add("Content-Type", "text/html")
+ fmt.Fprint(w, "<pre id=\"main\"><code>")
+ }
+
+ r.Write(w)
+
+ if contains {
+ fmt.Fprintln(w, "</pre></code>")
+ }
+ })
+
+ mux.Handle("/", http.FileServer(http.Dir(*dir)))
+
+ server := http.Server{
+ Handler: mux,
+ }
+
+ unixListener, err := net.Listen("unix", *socketPath)
+ if err != nil {
+ panic(err)
+ }
+ log.Fatal(server.Serve(unixListener))
+}
diff --git a/test/go.mod b/test/go.mod
new file mode 100644
index 0000000..ca08313
--- /dev/null
+++ b/test/go.mod
@@ -0,0 +1,41 @@
+module github.com/TecharoHQ/anubis/test
+
+go 1.24.2
+
+replace github.com/TecharoHQ/anubis => ..
+
+require (
+ github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456
+ github.com/google/uuid v1.6.0
+)
+
+require (
+ github.com/TecharoHQ/anubis v1.16.0 // indirect
+ github.com/a-h/templ v0.3.857 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
+ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
+ github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
+ github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
+ github.com/jsha/minica v1.1.0 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_model v0.6.1 // indirect
+ github.com/prometheus/common v0.62.0 // indirect
+ github.com/prometheus/procfs v0.15.1 // indirect
+ github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a // indirect
+ github.com/yl2chen/cidranger v1.0.2 // indirect
+ golang.org/x/net v0.39.0 // indirect
+ golang.org/x/sys v0.32.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
+ k8s.io/apimachinery v0.32.3 // indirect
+ sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+ sigs.k8s.io/yaml v1.4.0 // indirect
+)
+
+tool (
+ github.com/TecharoHQ/anubis/cmd/anubis
+ github.com/jsha/minica
+)
diff --git a/test/go.sum b/test/go.sum
new file mode 100644
index 0000000..f7914fa
--- /dev/null
+++ b/test/go.sum
@@ -0,0 +1,55 @@
+github.com/a-h/templ v0.3.857 h1:6EqcJuGZW4OL+2iZ3MD+NnIcG7nGkaQeF2Zq5kf9ZGg=
+github.com/a-h/templ v0.3.857/go.mod h1:qhrhAkRFubE7khxLZHsBFHfX+gWwVNKbzKeF9GlPV4M=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
+github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
+github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456 h1:CkmB2l68uhvRlwOTPrwnuitSxi/S3Cg4L5QYOcL9MBc=
+github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456/go.mod h1:zFhibDvPDWmtk4dAQ05sRobtyoffEHygEt3wSNuAzz8=
+github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
+github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
+github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
+github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
+github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
+github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jsha/minica v1.1.0 h1:O2ZbzAN75w4RTB+5+HfjIEvY5nxRqDlwj3ZlLVG5JD8=
+github.com/jsha/minica v1.1.0/go.mod h1:dxC3wNmD+gU1ewXo/R8jB2ihB6wNpyXrG8aUk5Iuf/k=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
+github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
+github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
+github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
+github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM=
+github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
+github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
+k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/test/unix-socket-xff/start.sh b/test/unix-socket-xff/start.sh
new file mode 100755
index 0000000..2d13fba
--- /dev/null
+++ b/test/unix-socket-xff/start.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# Remove lingering .sock files, relayd and unixhttpd will do that too but
+# measure twice, cut once.
+rm *.sock ||:
+
+# If the transient local TLS certificate doesn't exist, mint a new one
+if [ ! -f ../pki/relayd.local.cetacean.club/cert.pem ]; then
+ # Subshell to contain the directory change
+ (
+ cd ../pki \
+ && mkdir -p relayd.local.cetacean.club \
+ && \
+ # Try using https://github.com/FiloSottile/mkcert for better DevEx,
+ # but fall back to using https://github.com/jsha/minica in case
+ # you don't have that installed.
+ (
+ mkcert \
+ --cert-file ./relayd.local.cetacean.club/cert.pem \
+ --key-file ./relayd.local.cetacean.club/key.pem relayd.local.cetacean.club \
+ || go tool minica -domains relayd.local.cetacean.club
+ )
+ )
+fi
+
+# Build static assets
+(cd ../.. && npm ci && npm run assets)
+
+# Spawn three jobs:
+
+# HTTP daemon that listens over a unix socket (implicitly ./unixhttpd.sock)
+go run ../cmd/unixhttpd &
+
+# A copy of Anubis, specifically for the current Git checkout
+go tool anubis \
+ --bind=./anubis.sock \
+ --bind-network=unix \
+ --target=unix://$(pwd)/unixhttpd.sock &
+
+# A simple TLS terminator that forwards to Anubis, which will forward to
+# unixhttpd
+go run ../cmd/relayd \
+ --proxy-to=unix://./anubis.sock \
+ --cert-dir=../pki/relayd.local.cetacean.club &
+
+# When you press control c, kill all the child processes to clean things up
+trap 'echo signal received!; kill $(jobs -p); wait' SIGINT SIGTERM
+
+echo "open https://relayd.local.cetacean.club:3004/reqmeta"
+
+# Wait for all child processes to exit
+wait