Some checks failed
Docker image builds / build (push) Waiting to run
Asset Build Verification / asset_verification (push) Has been cancelled
Docs deploy / build (push) Has been cancelled
Go Mod Tidy Check / go_mod_tidy_check (push) Has been cancelled
Go / go_tests (push) Has been cancelled
Package builds (unstable) / package_builds (push) Has been cancelled
Smoke tests / smoke-test (default-config-macro) (push) Has been cancelled
Smoke tests / smoke-test (docker-registry) (push) Has been cancelled
Smoke tests / smoke-test (double_slash) (push) Has been cancelled
Smoke tests / smoke-test (forced-language) (push) Has been cancelled
Smoke tests / smoke-test (git-clone) (push) Has been cancelled
Smoke tests / smoke-test (git-push) (push) Has been cancelled
Smoke tests / smoke-test (healthcheck) (push) Has been cancelled
Smoke tests / smoke-test (i18n) (push) Has been cancelled
Smoke tests / smoke-test (log-file) (push) Has been cancelled
Smoke tests / smoke-test (nginx) (push) Has been cancelled
Smoke tests / smoke-test (palemoon/amd64) (push) Has been cancelled
Smoke tests / smoke-test (robots_txt) (push) Has been cancelled
Check Spelling / Check Spelling (push) Has been cancelled
SSH CI / ssh (aarch64-16k) (push) Has been cancelled
SSH CI / ssh (aarch64-4k) (push) Has been cancelled
SSH CI / ssh (ppc64le) (push) Has been cancelled
SSH CI / ssh (riscv64) (push) Has been cancelled
zizmor / zizmor latest via PyPI (push) Has been cancelled
124 lines
2.6 KiB
Go
124 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"log"
|
|
"log/slog"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.sad.ovh/sophie/nuke/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,
|
|
),
|
|
)
|
|
}
|