p2.5: redact reason/err for permit_restricted logs
Guard messages embed the hostname (resolve <host>, no addresses for <host>). Restricted callers now log a coarse reason class and err=-. Test dumps slog records and forbids the hostname anywhere in them. docs: P3 review — fail-closed search, cache class, public dialer
This commit is contained in:
@@ -284,7 +284,7 @@ func recHost(r slog.Record) string {
|
||||
var host string
|
||||
r.Attrs(func(a slog.Attr) bool {
|
||||
if a.Key == "host" {
|
||||
host = fmtString(a.Value)
|
||||
host = a.Value.String()
|
||||
}
|
||||
return true
|
||||
})
|
||||
@@ -293,11 +293,17 @@ func recHost(r slog.Record) string {
|
||||
|
||||
func recMsg(r slog.Record) string { return r.Message }
|
||||
|
||||
func fmtString(v slog.Value) string {
|
||||
if v.Kind() == slog.KindString {
|
||||
return v.String()
|
||||
}
|
||||
return v.Any().(string)
|
||||
func recDump(r slog.Record) string {
|
||||
var b strings.Builder
|
||||
b.WriteString(r.Message)
|
||||
r.Attrs(func(a slog.Attr) bool {
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(a.Key)
|
||||
b.WriteByte('=')
|
||||
b.WriteString(a.Value.String())
|
||||
return true
|
||||
})
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func TestRestrictedCallerLogsBlankHost(t *testing.T) {
|
||||
@@ -345,7 +351,7 @@ func TestRestrictedCallerLogsBlankHost(t *testing.T) {
|
||||
src, _ := env["source"].(map[string]any)
|
||||
final, _ := src["final_url"].(string)
|
||||
if !strings.Contains(final, hostOf(ts.URL)) {
|
||||
t.Fatalf("final_url still in body, got %q", final)
|
||||
t.Fatalf("final_url missing from body, got %q", final)
|
||||
}
|
||||
|
||||
rec = postJSON(t, s, "/v1/fetch", strings.TrimSpace(string(gsKey)), map[string]any{"url": "http://10.0.0.5/", "mode": "clean"})
|
||||
@@ -353,6 +359,12 @@ func TestRestrictedCallerLogsBlankHost(t *testing.T) {
|
||||
t.Fatalf("gs refused: %d %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
|
||||
const badHost = "this-host-does-not-exist-sift-p25.invalid"
|
||||
rec = postJSON(t, s, "/v1/fetch", strings.TrimSpace(string(gsKey)), map[string]any{"url": "http://" + badHost + "/", "mode": "clean"})
|
||||
if rec.Code != 403 {
|
||||
t.Fatalf("gs nxdomain: %d %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
|
||||
rec = postJSON(t, s, "/v1/fetch", strings.TrimSpace(string(fleetKey)), map[string]any{"url": ts.URL, "mode": "clean"})
|
||||
if rec.Code != 200 {
|
||||
t.Fatalf("fleet fetch: %d %s", rec.Code, rec.Body.String())
|
||||
@@ -386,6 +398,18 @@ func TestRestrictedCallerLogsBlankHost(t *testing.T) {
|
||||
if fleetFetch != wantHost {
|
||||
t.Fatalf("fleet fetch host=%q want %q", fleetFetch, wantHost)
|
||||
}
|
||||
|
||||
h.mu.Lock()
|
||||
for _, r := range h.recs {
|
||||
if attrCaller(r) != "straylight-gs" {
|
||||
continue
|
||||
}
|
||||
dump := recDump(r)
|
||||
if strings.Contains(dump, badHost) || strings.Contains(dump, "10.0.0.5") {
|
||||
t.Fatalf("restricted log leaked host: %s", dump)
|
||||
}
|
||||
}
|
||||
h.mu.Unlock()
|
||||
}
|
||||
|
||||
func attrCaller(r slog.Record) string {
|
||||
|
||||
Reference in New Issue
Block a user