feat: manage existing credential actions with audited replay

This commit is contained in:
2026-11-01 19:10:37 +08:00
parent baa81c4923
commit 98ad60c0b8
18 changed files with 1350 additions and 53 deletions

View File

@@ -3,6 +3,7 @@ package main
import (
"os"
"path/filepath"
"reflect"
"testing"
"time"
@@ -84,3 +85,42 @@ func TestPrivateOperationFileRejectsUnknownFieldsAndSymlinks(t *testing.T) {
t.Fatal("symlink operation file was accepted")
}
}
func TestPermissionActionList(t *testing.T) {
actions, err := parseCredentialActions("tasks:read, schedules:manage,schedules:read")
if err != nil || !reflect.DeepEqual(actions, []string{"schedules:manage", "schedules:read", "tasks:read"}) {
t.Fatalf("invalid canonical action list: %v %v", actions, err)
}
for _, value := range []string{"", " ", "*", "tasks:*", "tasks:read,tasks:read", "tasks:read, tasks:read", "tasks:read,", "schedules:admin"} {
if _, err := parseCredentialActions(value); err == nil {
t.Fatalf("accepted invalid action list %q", value)
}
}
}
func TestPermissionCommandRejectsLifetimeBeforeDatabaseAccess(t *testing.T) {
op := testOperation(t)
for _, flag := range []string{"--valid-for=0", "--grace=0"} {
err := runCredential([]string{"permissions", "--namespace-id=" + string(op.NamespaceID), "--credential-id=" + string(op.CredentialID), "--expected-revision=1", "--reason=test", "--output=" + filepath.Join(t.TempDir(), "op.json"), "--actions=tasks:read", flag})
if err == nil || err.Error() != "permission changes preserve validity and overlap; omit --valid-for and --grace" {
t.Fatalf("lifetime field not rejected: %v", err)
}
}
}
func TestPrivatePermissionOperationReplaysWithoutToken(t *testing.T) {
op := testOperation(t)
op.Version = 3
op.Action = "SET_PERMISSIONS"
op.Token = ""
op.ExpiresAt = nil
op.Actions = []string{"schedules:manage", "schedules:read", "tasks:read"}
path := filepath.Join(t.TempDir(), "permissions.json")
if err := writePrivateOperation(path, op); err != nil {
t.Fatal(err)
}
read, err := readPrivateOperation(path)
if err != nil || !reflect.DeepEqual(read, op) {
t.Fatalf("permission operation identity changed: %v", err)
}
}