mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-21 04:57:48 +00:00
test: add R-round regression and security suite
- fail-on-old regression tests for every shipped fix (R-rounds) - fuzz targets (parseJWT, bearer), concurrency-stress, shuffle-flake guards - coverage-closing contract tests (health-check backend, TLS-posture reuse) - r154 ID-token fixture built from parts to avoid false-positive secret scan
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package traefikoidc
|
||||
|
||||
// R132 regression: saveCombined must read token/main-session fields under
|
||||
// sessionMutex.RLock so a concurrent Set* (which writes under the write
|
||||
// side) cannot tear the combined payload. Previously only the extra-map
|
||||
// walk took the Read side; the token field reads (getAccessTokenUnsafe &
|
||||
// friends) were unlocked, a latent data race on the refresh-rotation
|
||||
// path (a concurrently-rotated refresh token could be read half-consistently
|
||||
// and re-encoded into the cookie, clobbering the fresh one). Run with -race.
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
func TestSaveCombined_NoDataRaceWithConcurrentSet(t *testing.T) {
|
||||
sm := createTestSessionManager(t)
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
sd, err := sm.GetSession(req)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSession: %v", err)
|
||||
}
|
||||
sd.useCombinedStorage = true
|
||||
|
||||
options := &sessions.Options{Path: "/", MaxAge: 86400, HttpOnly: true, Secure: true}
|
||||
|
||||
// Seed the refresh/access tokens so the concurrent save has something
|
||||
// to read; SetAccessToken requires >=20-char tokens.
|
||||
sd.SetAccessToken("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") // must be >= 20 chars
|
||||
sd.refreshSession.Values["token"] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
|
||||
// One reader goroutine calls saveCombined (payload build reads under
|
||||
// RLock after R132) while many writers call SetAccessToken (writes
|
||||
// under Lock). Before R132 the companion payload reads were unlocked,
|
||||
// so -race flagged the torn read here.
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
rw := httptest.NewRecorder()
|
||||
for j := 0; j < 500; j++ {
|
||||
_ = sd.saveCombined(req, rw, options) // ignore cookie-write errors; testing the read race
|
||||
}
|
||||
}()
|
||||
for i := 0; i < 8; i++ {
|
||||
wg.Add(1)
|
||||
go func(seed int) {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 500; j++ {
|
||||
sd.SetAccessToken("tok-%d-%d-abcdefghijklmnopqrstuvwxyz")
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user