Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4fe5c1d75 |
@@ -30,20 +30,15 @@ P2: security: referer blacklist
|
|||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
- 2026-10-04 the metrics basic auth, CORS preflight, request logging and
|
- 2026-10-04 the metrics basic auth, CORS preflight, request logging and
|
||||||
metrics recording have tests (closes #79): `MetricsAuth` on its own answers
|
metrics recording have tests (closes #79): the basic auth in front of
|
||||||
401 with a challenge without credentials or with a wrong username or password
|
`/metrics` answers 401 with a challenge without credentials or with a wrong
|
||||||
and lets the configured ones through; a preflight request gets `*` for any
|
username or password and lets the configured ones through; a preflight
|
||||||
origin when `access_control_allow_origin` is `*` and no
|
request gets `*` for any origin when `access_control_allow_origin` is `*` and
|
||||||
`Access-Control-Allow-Origin` from another origin than the configured one; a
|
no `Access-Control-Allow-Origin` from another origin than the configured
|
||||||
`POST /` carrying the signing key leaves no trace of it in the request log
|
one; a `POST /` carrying the signing key leaves no trace of it in the log
|
||||||
line, and the login handler's own log lines leave out the submitted key; the
|
line; the metrics middleware records a request it served, and the router
|
||||||
metrics middleware on its own records a request it served, and the router
|
records nothing while no metrics username is set. Tests only; the basic auth
|
||||||
records nothing while no metrics username is set. Not tested: that the router
|
library already compares the password in constant time.
|
||||||
puts the basic auth in front of `/metrics` and records requests when a
|
|
||||||
metrics username is set. Only one test per package can set up `/metrics`, and
|
|
||||||
in `internal/server` that is `TestMaintenanceModeKeepsOtherRoutes`, which
|
|
||||||
needs the owner's approval to change; #180 holds it. Tests only; the basic
|
|
||||||
auth library already compares the password in constant time.
|
|
||||||
- 2026-10-04 routes, encrypted URLs and config file documented (closes #75):
|
- 2026-10-04 routes, encrypted URLs and config file documented (closes #75):
|
||||||
"Routes" in `README.md` lists every route with its method, purpose, what it
|
"Routes" in `README.md` lists every route with its method, purpose, what it
|
||||||
needs and the status codes it answers with, and says `q` and `fit` are part
|
needs and the status codes it answers with, and says `q` and `fit` are part
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log/slog"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"sneak.berlin/go/pixa/internal/config"
|
|
||||||
"sneak.berlin/go/pixa/internal/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestLoginLogLeavesOutSubmittedKey verifies that the log lines for a
|
|
||||||
// failed and for a successful login do not contain the submitted key.
|
|
||||||
func TestLoginLogLeavesOutSubmittedKey(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
const wrongKey = "wrong-signing-key-fedcba9876543210"
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
sessMgr, err := session.NewManager(testSigningKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("session.NewManager() error = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h := &Handlers{
|
|
||||||
log: slog.New(slog.NewJSONHandler(&buf, nil)),
|
|
||||||
config: &config.Config{SigningKey: testSigningKey},
|
|
||||||
sessMgr: sessMgr,
|
|
||||||
}
|
|
||||||
|
|
||||||
submittedKeys := []string{wrongKey, testSigningKey}
|
|
||||||
|
|
||||||
for _, key := range submittedKeys {
|
|
||||||
form := url.Values{loginKeyField: {key}}
|
|
||||||
req := httptest.NewRequestWithContext(
|
|
||||||
t.Context(), http.MethodPost, "/",
|
|
||||||
strings.NewReader(form.Encode()))
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
|
|
||||||
h.handleLoginPost(httptest.NewRecorder(), req)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, msg := range []string{"failed login attempt", "successful login"} {
|
|
||||||
if !strings.Contains(buf.String(), msg) {
|
|
||||||
t.Fatalf("log missing %q; got %q", msg, buf.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range submittedKeys {
|
|
||||||
if strings.Contains(buf.String(), key) {
|
|
||||||
t.Errorf("log contains submitted key %q; got %q", key, buf.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -112,11 +112,10 @@ func TestCORSAnswersPreflightWithConfiguredOrigin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMetricsAuthRequiresConfiguredCredentials checks that MetricsAuth on
|
// TestMetricsAuthRequiresConfiguredCredentials checks that the basic auth
|
||||||
// its own answers 401 with a challenge to a request without credentials or
|
// in front of /metrics answers 401 with a challenge to a request without
|
||||||
// with a wrong username or password, and lets a request with the configured
|
// credentials or with a wrong username or password, and lets a request with
|
||||||
// username and password through. That the router puts it in front of
|
// the configured username and password through.
|
||||||
// /metrics is not tested.
|
|
||||||
func TestMetricsAuthRequiresConfiguredCredentials(t *testing.T) {
|
func TestMetricsAuthRequiresConfiguredCredentials(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user