package httpapi import ( "net/http/httptest" "os" "regexp" "testing" ) // HTTP LAN/tailnet origins may omit Fetch Metadata. nginx must preserve the // external authority including its port so Origin can be checked without it. func TestQAProxyPreservesBrowserAuthority(t *testing.T) { config, err := os.ReadFile("../../deploy/nginx.conf") if err != nil { t.Fatal(err) } hosts := regexp.MustCompile(`(?m)^\s*proxy_set_header\s+Host\s+([^;]+);`).FindAllStringSubmatch(string(config), -1) if len(hosts) < 2 { t.Fatal("API and health proxy Host directives must both be explicit") } for _, host := range hosts { if host[1] != "$http_host" { t.Fatalf("proxy drops browser authority/port: got %q, want $http_host", host[1]) } } } func TestQAIntentWithoutFetchMetadataChecksExactAuthority(t *testing.T) { for _, tc := range []struct { name, host, origin, forwarded, site, intent string allowed bool }{ {"LAN same authority", "192.168.50.134:8088", "http://192.168.50.134:8088", "", "", "qa-quality", true}, {"tailnet same authority", "100.92.49.78:8088", "http://100.92.49.78:8088", "", "", "qa-quality", true}, {"proxy stripped port", "192.168.50.134", "http://192.168.50.134:8088", "", "", "qa-quality", false}, {"foreign origin", "192.168.50.134:8088", "http://foreign.invalid:8088", "", "", "qa-quality", false}, {"different port", "192.168.50.134:8088", "http://192.168.50.134:8089", "", "", "qa-quality", false}, {"forwarded header cannot grant", "192.168.50.134:8088", "http://foreign.invalid:8088", "foreign.invalid:8088", "", "qa-quality", false}, {"opaque origin", "192.168.50.134:8088", "null", "", "", "qa-quality", false}, {"explicit cross site", "192.168.50.134:8088", "http://192.168.50.134:8088", "", "cross-site", "qa-quality", false}, {"missing intent", "192.168.50.134:8088", "http://192.168.50.134:8088", "", "", "", false}, } { t.Run(tc.name, func(t *testing.T) { req := httptest.NewRequest("POST", "http://"+tc.host+"/api/v1/qa-ops/quality/query", nil) req.Header.Set("Origin", tc.origin) req.Header.Set("X-Governance-Action", tc.intent) if tc.forwarded != "" { req.Header.Set("X-Forwarded-Host", tc.forwarded) } if tc.site != "" { req.Header.Set("Sec-Fetch-Site", tc.site) } rec := httptest.NewRecorder() if got := authorizeQAIntent(rec, req, "qa-quality"); got != tc.allowed { t.Fatalf("authorized=%v want %v, HTTP=%d", got, tc.allowed, rec.Code) } if !tc.allowed && rec.Code != 403 { t.Fatalf("rejected authority should be 403, got %d", rec.Code) } }) } }