Checkpoint: fix all lint warnings
- errorlint: use errors.Is for ErrSealed comparisons in vault_test.go - gofmt: reformat config, config_test, middleware_test with goimports - govet/fieldalignment: reorder struct fields in vault.go, csrf.go, detail_test.go, middleware_test.go for optimal alignment - unused: remove unused newCSRFManager in csrf.go (superseded by newCSRFManagerFromVault) - revive/early-return: invert sealed-vault condition in main.go Security: no auth/crypto logic changed; struct reordering and error comparison fixes only. newCSRFManager removal is safe — it was never called; all CSRF construction goes through newCSRFManagerFromVault. Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
func TestJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
verify func(t *testing.T, result string)
|
||||
name string
|
||||
pairs []string
|
||||
verify func(t *testing.T, result string)
|
||||
}{
|
||||
{
|
||||
name: "single pair",
|
||||
@@ -109,9 +109,9 @@ func TestJSON(t *testing.T) {
|
||||
|
||||
func TestJSONWithRoles(t *testing.T) {
|
||||
tests := []struct {
|
||||
verify func(t *testing.T, result string)
|
||||
name string
|
||||
roles []string
|
||||
verify func(t *testing.T, result string)
|
||||
}{
|
||||
{
|
||||
name: "multiple roles",
|
||||
|
||||
@@ -174,8 +174,8 @@ func (c *Config) validate() error {
|
||||
// generous to accommodate a range of legitimate deployments while
|
||||
// catching obvious typos (e.g. "876000h" instead of "8760h").
|
||||
const (
|
||||
maxDefaultExpiry = 30 * 24 * time.Hour // 30 days
|
||||
maxAdminExpiry = 24 * time.Hour // 24 hours
|
||||
maxDefaultExpiry = 30 * 24 * time.Hour // 30 days
|
||||
maxAdminExpiry = 24 * time.Hour // 24 hours
|
||||
maxServiceExpiry = 5 * 365 * 24 * time.Hour // 5 years
|
||||
)
|
||||
if c.Tokens.DefaultExpiry.Duration <= 0 {
|
||||
|
||||
@@ -213,9 +213,9 @@ threads = 4
|
||||
// TestTrustedProxyValidation verifies that trusted_proxy must be a valid IP.
|
||||
func TestTrustedProxyValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
proxy string
|
||||
wantErr bool
|
||||
name string
|
||||
proxy string
|
||||
wantErr bool
|
||||
}{
|
||||
{"empty is valid (disabled)", "", false},
|
||||
{"valid IPv4", "127.0.0.1", false},
|
||||
|
||||
@@ -361,8 +361,8 @@ func TestClientIP(t *testing.T) {
|
||||
remoteAddr string
|
||||
xForwardedFor string
|
||||
xRealIP string
|
||||
trustedProxy net.IP
|
||||
want string
|
||||
trustedProxy net.IP
|
||||
}{
|
||||
{
|
||||
name: "no proxy configured: uses RemoteAddr",
|
||||
@@ -377,11 +377,11 @@ func TestClientIP(t *testing.T) {
|
||||
want: "198.51.100.9",
|
||||
},
|
||||
{
|
||||
name: "request from trusted proxy with X-Real-IP: uses X-Real-IP",
|
||||
remoteAddr: "10.0.0.1:8080",
|
||||
xRealIP: "203.0.113.42",
|
||||
trustedProxy: proxy,
|
||||
want: "203.0.113.42",
|
||||
name: "request from trusted proxy with X-Real-IP: uses X-Real-IP",
|
||||
remoteAddr: "10.0.0.1:8080",
|
||||
xRealIP: "203.0.113.42",
|
||||
trustedProxy: proxy,
|
||||
want: "203.0.113.42",
|
||||
},
|
||||
{
|
||||
name: "request from trusted proxy with X-Forwarded-For: uses first entry",
|
||||
@@ -407,10 +407,10 @@ func TestClientIP(t *testing.T) {
|
||||
want: "203.0.113.55",
|
||||
},
|
||||
{
|
||||
name: "proxy request with no forwarding headers falls back to RemoteAddr host",
|
||||
remoteAddr: "10.0.0.1:8080",
|
||||
trustedProxy: proxy,
|
||||
want: "10.0.0.1",
|
||||
name: "proxy request with no forwarding headers falls back to RemoteAddr host",
|
||||
remoteAddr: "10.0.0.1:8080",
|
||||
trustedProxy: proxy,
|
||||
want: "10.0.0.1",
|
||||
},
|
||||
{
|
||||
// Security: attacker fakes X-Forwarded-For but connects directly.
|
||||
|
||||
@@ -29,15 +29,9 @@ import (
|
||||
// on the next unseal. This is safe because sealed middleware prevents
|
||||
// reaching CSRF-protected routes.
|
||||
type CSRFManager struct {
|
||||
mu sync.Mutex
|
||||
key []byte
|
||||
vault *vault.Vault
|
||||
}
|
||||
|
||||
// newCSRFManager creates a CSRFManager with a static key derived from masterKey.
|
||||
// Key derivation: SHA-256("mcias-ui-csrf-v1" || masterKey)
|
||||
func newCSRFManager(masterKey []byte) *CSRFManager {
|
||||
return &CSRFManager{key: deriveCSRFKey(masterKey)}
|
||||
key []byte
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// newCSRFManagerFromVault creates a CSRFManager that derives its key lazily
|
||||
|
||||
@@ -24,10 +24,10 @@ var ErrSealed = errors.New("vault is sealed")
|
||||
// Vault holds the server's cryptographic key material behind a mutex.
|
||||
// All three servers (REST, UI, gRPC) share a single Vault by pointer.
|
||||
type Vault struct {
|
||||
mu sync.RWMutex
|
||||
masterKey []byte
|
||||
privKey ed25519.PrivateKey
|
||||
pubKey ed25519.PublicKey
|
||||
mu sync.RWMutex
|
||||
sealed bool
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package vault
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
@@ -25,13 +26,13 @@ func TestNewSealed(t *testing.T) {
|
||||
if !v.IsSealed() {
|
||||
t.Fatal("NewSealed() should be sealed")
|
||||
}
|
||||
if _, err := v.MasterKey(); err != ErrSealed {
|
||||
if _, err := v.MasterKey(); !errors.Is(err, ErrSealed) {
|
||||
t.Fatalf("MasterKey() error = %v, want ErrSealed", err)
|
||||
}
|
||||
if _, err := v.PrivKey(); err != ErrSealed {
|
||||
if _, err := v.PrivKey(); !errors.Is(err, ErrSealed) {
|
||||
t.Fatalf("PrivKey() error = %v, want ErrSealed", err)
|
||||
}
|
||||
if _, err := v.PubKey(); err != ErrSealed {
|
||||
if _, err := v.PubKey(); !errors.Is(err, ErrSealed) {
|
||||
t.Fatalf("PubKey() error = %v, want ErrSealed", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user