fix(auth): tighten bridge claim protocol

This commit is contained in:
2026-08-16 22:44:44 +02:00
parent 7d9ca13f1d
commit 8477a69a29
7 changed files with 333 additions and 40 deletions
+44 -1
View File
@@ -35,7 +35,7 @@ func TestProtocolCreatesReadsReplacesListsAndRemovesPrivateRecord(t *testing.T)
t.Fatal("replace did not report success")
}
listed := runRequest(t, request{Version: 1, Operation: "list", Root: root, Directory: "sessions"})
if len(listed.Entries) != 1 || listed.Entries[0].Name != filename {
if listed.Entries == nil || len(*listed.Entries) != 1 || (*listed.Entries)[0].Name != filename {
t.Fatalf("list = %#v, want exactly %q", listed.Entries, filename)
}
removed := runRequest(t, request{Version: 1, Operation: "remove", Root: root, Directory: "sessions", Filename: filename})
@@ -61,6 +61,49 @@ func TestProtocolListSerializesLowerCamelBridgeDTO(t *testing.T) {
}
}
func TestProtocolListAlwaysSerializesAnEmptyEntriesArray(t *testing.T) {
root := filepath.Join(privateTestRoot(t), "auth")
input, err := json.Marshal(request{Version: 1, Operation: "list", Root: root, Directory: "sessions"})
if err != nil {
t.Fatal(err)
}
var stdout, stderr bytes.Buffer
if code := Run(context.Background(), nil, bytes.NewReader(input), &stdout, &stderr); code != 0 {
t.Fatalf("Run() code = %d stderr = %q", code, stderr.String())
}
if !strings.Contains(stdout.String(), `"entries":[]`) {
t.Fatalf("empty list bridge JSON = %q, want entries array", stdout.String())
}
}
func TestProtocolPermitsClaimNamesOnlyForOIDCRemove(t *testing.T) {
root := filepath.Join(privateTestRoot(t), "auth")
digest := "abababababababababababababababababababababababababababababababab.json"
claim := strings.TrimSuffix(digest, ".json") + ".claim"
for _, directory := range []string{"sessions", "oidc"} {
runRequest(t, request{Version: 1, Operation: "list", Root: root, Directory: directory})
}
if err := safeio.WriteCanonicalNewPrivateFile(filepath.Join(root, "sessions", claim), []byte("orphan"), 0o600); err != nil {
t.Fatal(err)
}
if err := safeio.WriteCanonicalNewPrivateFile(filepath.Join(root, "oidc", claim), []byte("orphan"), 0o600); err != nil {
t.Fatal(err)
}
runRejected(t, request{Version: 1, Operation: "remove", Root: root, Directory: "sessions", Filename: claim})
runRejected(t, request{Version: 1, Operation: "list", Root: root, Directory: "sessions", Filename: claim})
runRejected(t, request{Version: 1, Operation: "read", Root: root, Directory: "oidc", Filename: claim})
runRejected(t, request{Version: 1, Operation: "create", Root: root, Directory: "oidc", Filename: claim, ContentBase64: base64.StdEncoding.EncodeToString([]byte("record"))})
runRejected(t, request{Version: 1, Operation: "replace", Root: root, Directory: "oidc", Filename: claim, ContentBase64: base64.StdEncoding.EncodeToString([]byte("record"))})
runRejected(t, request{Version: 1, Operation: "remove", Root: root, Directory: "oidc", Filename: "../" + claim})
runRejected(t, request{Version: 1, Operation: "remove", Root: root, Directory: "oidc", Filename: strings.TrimSuffix(claim, ".claim") + ".claim.bak"})
removed := runRequest(t, request{Version: 1, Operation: "remove", Root: root, Directory: "oidc", Filename: claim})
if !removed.Removed {
t.Fatal("OIDC orphan claim removal did not report success")
}
}
func TestRunRejectsProtocolOverflowAndTrailingJSONValues(t *testing.T) {
root := filepath.Join(privateTestRoot(t), "auth")
valid, err := json.Marshal(request{Version: 1, Operation: "list", Root: root, Directory: "sessions"})