aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2023-01-03 23:49:41 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2023-01-03 23:49:41 -0500
commitc71b37eb23d4c8af7ab983de34c6da5be9363f3a (patch)
treefa699de5d31008b17529d799df00a9a3290c52bf
parent61612c8e1861ac704bbe592a623a41f12ebc9c11 (diff)
downloadpaste-c71b37eb23d4c8af7ab983de34c6da5be9363f3a.tar.gz
paste-c71b37eb23d4c8af7ab983de34c6da5be9363f3a.tar.xz
Tweak index handler to always load the frontend.HEADv0.0.1masterdev
Also add Nginx testing script, logging options and some docs.
-rw-r--r--.gitignore3
-rw-r--r--LICENSE2
-rw-r--r--main.go56
-rw-r--r--nginx.conf46
-rwxr-xr-xnginx.sh10
5 files changed, 109 insertions, 8 deletions
diff --git a/.gitignore b/.gitignore
index 333aca1..50783c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
bpaste
paste
.idea/*
+*.pem
+storage/*
+ses.vim
diff --git a/LICENSE b/LICENSE
index 2e0cf78..34de18b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2021 Mitchell Riedstra
+Copyright (c) 2023 Mitchell Riedstra
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/main.go b/main.go
index 2e55100..d61be41 100644
--- a/main.go
+++ b/main.go
@@ -73,6 +73,8 @@ func main() {
var (
listen = ":6130"
idBytes = "8"
+ logRequestsF = "false"
+ logRequests bool
debugF = "false"
debug bool
genhash = false
@@ -105,9 +107,13 @@ func main() {
EnvFlagString(fl, &proxyURL, "sp", "STATIC_PROXY",
"What server do we proxy to for static content?")
EnvFlagString(fl, &jwtKey, "jwt", "JWT_KEY",
- "If supplied use the value as the JWT key instead of a random value")
+ "If supplied use the value as the JWT key instead of a random value\n"+
+ "Please understand this is not a good idea. Use a random key if "+
+ "possible\n")
EnvFlagString(fl, &sessionHours, "hours", "SESSION_HOURS",
"How many hours should login sessions last?")
+ EnvFlagString(fl, &logRequestsF, "log", "LOG_REQUESTS",
+ "Do we do full request logs, or are we quiet?")
fl.BoolVar(&genhash, "genhash", genhash,
"Interactively prompt for a password and spit out a hash\n")
version := fl.Bool("v", false, "Print version then exit")
@@ -129,6 +135,11 @@ func main() {
logger.Println("Warning invalid value for debug: ", debugF)
}
+ logRequests, err = strconv.ParseBool(logRequestsF)
+ if err != nil {
+ logger.Println("Warning invalid value for logRequests: ", logRequestsF)
+ }
+
if debug {
logger.SetFlags(log.LstdFlags | log.Llongfile)
}
@@ -184,8 +195,14 @@ func main() {
logger.Println("listening on: ", listen)
+ handler := app.Handler()
+
+ if logRequests {
+ handler = httpRequestLogger(handler)
+ }
+
srv := &http.Server{
- Handler: logRequests(app.Handler()),
+ Handler: handler,
Addr: listen,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
@@ -220,7 +237,7 @@ func getProxyHandler(proxyURL string) (http.Handler, error) {
return rp, nil
}
-func logRequests(next http.Handler) http.Handler {
+func httpRequestLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logger.Printf("%s %s %s \"%s\" \"%s\"\n",
r.RemoteAddr, r.Method, r.URL.Path, r.UserAgent(), r.Referer())
@@ -283,10 +300,12 @@ func (a *App) Handler() http.Handler {
"/api/v1/login": loginHandler(a.users, a.jwtKey, a.sessionHours),
"/api/v1/logout": logoutHandler(),
- "/": http.FileServer(http.FS(a.static)),
+ "/_app/": http.FileServer(http.FS(a.static)),
+ "/": a.HandleIndex(a.static),
}
if a.staticHandler != nil {
+ delete(handlers, "/_app")
handlers["/"] = a.staticHandler
}
@@ -317,6 +336,13 @@ func (a *App) Handler() http.Handler {
return mux
}
+// LoadUsersFromEnviron lets you build a very basic user store from scraping
+// the environment variables alone. Environment variables are in the form of
+// `USER_<username>=<hash>` For example in a shell script:
+//
+// export USER_mitch='$2a$10$MdpHOxqyaxVwX7tBmch/MOnuq5jgcy7ciCUGwixVR43SchyDtxLVW'
+//
+// Will then be picked up and put into the map as mitch: <hash_above>
func LoadUsersFromEnviron() UsersMap {
users := map[string]string{}
for _, entry := range os.Environ() {
@@ -335,6 +361,22 @@ func LoadUsersFromEnviron() UsersMap {
return users
}
+func (a *App) HandleIndex(f fs.FS) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ pth := filepath.Clean(r.URL.Path)
+ fh, err := f.Open(pth)
+ if err != nil {
+ fh, err = f.Open("index.html")
+ if err != nil {
+ sendPlain(Response{w, http.StatusInternalServerError,
+ "Internal server error", nil}, nil)
+ }
+ }
+
+ _, _ = io.Copy(w, fh)
+ })
+}
+
func genTokenKey() string {
r := make([]byte, 16) // 128 bits
_, err := rand.Read(r)
@@ -453,12 +495,11 @@ func (users UsersMap) HasValidPlainAuth(r *http.Request) bool {
// it's invalid or there are any errors.
func getCookie(r *http.Request, name string) string {
c, err := r.Cookie(name)
- // Normally I'd also check c.Valid()... Expires is optional, but
- // apparently makes it invalid?
+ // Normally I'd also check c.Valid()... Expires is optional, but apparently
+ // makes it invalid? Either way duration is handled by the JWT
if err != nil {
return ""
}
- fmt.Printf("Cookie value: '%s'\n", c.Value)
return c.Value
}
@@ -534,6 +575,7 @@ func loginHandler(users UsersMap, jwtKey string, sessionHours int,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Value: ss,
+ Secure: true,
})
http.Redirect(w, r, "/", http.StatusFound)
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..07995ad
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,46 @@
+user nginx;
+worker_processes auto;
+
+error_log /var/log/nginx/error.log notice;
+pid /var/run/nginx.pid;
+
+
+events {
+ worker_connections 1024;
+}
+
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ keepalive_timeout 65;
+
+ #gzip on;
+
+ # include /etc/nginx/conf.d/*.conf;
+
+
+ server {
+ listen [::1]:8443 ssl http2;
+ listen 127.0.0.1:8443 ssl http2;
+
+ ssl_certificate /crt.pem;
+ ssl_certificate_key /key.pem;
+
+ location / {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_pass http://localhost:6130/;
+ }
+ }
+}
diff --git a/nginx.sh b/nginx.sh
new file mode 100755
index 0000000..31ff236
--- /dev/null
+++ b/nginx.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -ex
+# Testing script to run behind a local https proxy
+# `mkcert` can be useful to generate valid certs
+# for testing
+podman run --rm --network=host \
+ -v "$(pwd)/nginx.conf":/etc/nginx/nginx.conf \
+ -v "$(pwd)/key.pem":/key.pem \
+ -v "$(pwd)/crt.pem":/crt.pem \
+ docker.io/nginx:alpine