Admit review acts for the three T03 version-3 memos (v11).
Assistant: grok Assistant-Session: 01a106a5-fc07-78c2-b64f-8e04cea25daf
This commit is contained in:
parent
f32a1d4dc6
commit
1aae59feb6
4 changed files with 172 additions and 7 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"policy_id": "informed-decision.compact-sitting",
|
||||
"policy_version": "v10",
|
||||
"policy_version": "v11",
|
||||
"note": "Offline request/response fixtures. Shipped admitted sets are empty, so attribute_eligible is not in this file. An allow here is an exact-record pin, not proof of a live approval.",
|
||||
"cases": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
id: informed-decision.compact-sitting
|
||||
name: Compact sitting exact-record human review
|
||||
namespace: informed-decision:decision-memo
|
||||
version: v10
|
||||
version: v11
|
||||
status: ready
|
||||
package: flexauth.informed_decision.compact_sitting
|
||||
allow_ttl: 30s
|
||||
|
|
@ -99,6 +99,14 @@ approvals `974eae4d-782d-41ed-93be-e34433b5fe59`,
|
|||
and `b75752d1-bab6-4cf3-9308-5368c1d5aa91`. Existing exact records, including
|
||||
v9's, stay. The v8 attribute branch still admits nobody.
|
||||
|
||||
v11 (2026-10-04, IR-WP-0005-T02) lets the three `list_only_records` be
|
||||
reviewed. `read`, `acknowledge`, `accept`, `return`, `discuss` and
|
||||
`decline` allow when the memo id, memo version 3, approval id and binding
|
||||
digest match those records, with the same 900-second KeyCape bar as the
|
||||
version-1 act rule. `list` is unchanged. A version other than 3, a foreign
|
||||
approval id, or a different digest is refused. The version-1 `records` set
|
||||
is unchanged, and these three ids stay out of it.
|
||||
|
||||
`admitted_submitters` and `admitted_classes` are generated from
|
||||
informed-decision `deploy/intake-submitters.json`. The shipped registry is
|
||||
empty, so both sets are empty and this branch admits nobody. Regenerate with
|
||||
|
|
@ -225,8 +233,8 @@ list_only_records := {
|
|||
}
|
||||
}
|
||||
|
||||
# listable is the union list may range over. Sitting records are memo version 1,
|
||||
# as the act rule pins; T03 records carry their own version (3).
|
||||
# listable is the union list may range over. Sitting records are memo version 1.
|
||||
# T03 records carry memo version 3 and are acted on only through list_only_records.
|
||||
listable := object.union(
|
||||
{id: object.union(r, {"memo_version": 1}) | some id, r in records},
|
||||
list_only_records,
|
||||
|
|
@ -356,6 +364,33 @@ decision := {"effect": "allow", "reason": "operator_admitted_compact_sitting"} i
|
|||
input.context.approval_id == record.approval_id
|
||||
input.context.approval_binding_digest == record.binding_digest
|
||||
input.action in {"read", "acknowledge", "accept", "return", "discuss", "decline"}
|
||||
} else := {"effect": "allow", "reason": "operator_admitted_t03_review_act"} if {
|
||||
input.action in {"read", "acknowledge", "accept", "return", "discuss", "decline"}
|
||||
input.tenant == "tenant:platform"
|
||||
input.subject.tenant == "tenant:platform"
|
||||
input.subject.type == "human"
|
||||
is_string(input.subject.id)
|
||||
input.subject.id != ""
|
||||
input.subject.attributes.principal_type_source == "authentication-derived"
|
||||
input.subject.attributes.tenant_source in {"registration-supplied", "directory-asserted"}
|
||||
"net-kingdom-admins" in input.subject.attributes.groups
|
||||
assurance := input.subject.attributes.assurance
|
||||
assurance.level == "aal2"
|
||||
assurance.mfa == true
|
||||
assurance.source == "key-cape"
|
||||
assurance.methods == ["pwd", "otp"]
|
||||
is_number(assurance.at)
|
||||
assurance.at > 0
|
||||
age := time.now_ns() / 1000000000 - assurance.at
|
||||
age >= -30
|
||||
age <= 900
|
||||
input.resource.tenant == "tenant:platform"
|
||||
input.resource.system == "informed-decision"
|
||||
input.resource.type == "decision-memo"
|
||||
record := list_only_records[input.resource.id]
|
||||
input.context.memo_version == record.memo_version
|
||||
input.context.approval_id == record.approval_id
|
||||
input.context.approval_binding_digest == record.binding_digest
|
||||
} else := {"effect": "allow", "reason": "operator_admitted_overview_list"} if {
|
||||
input.action == "list"
|
||||
input.tenant == "tenant:platform"
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ func TestInformedDecisionAttributeAdmission(t *testing.T) {
|
|||
if !pkg.Valid {
|
||||
t.Fatalf("package invalid: %+v", pkg.Validation)
|
||||
}
|
||||
if pkg.Metadata.Version != "v10" {
|
||||
t.Fatalf("version = %s; want v10", pkg.Metadata.Version)
|
||||
if pkg.Metadata.Version != "v11" {
|
||||
t.Fatalf("version = %s; want v11", pkg.Metadata.Version)
|
||||
}
|
||||
if strings.Contains(pkg.RegoModule, "view_hash") {
|
||||
t.Fatal("rule module reads view_hash")
|
||||
|
|
@ -50,7 +50,7 @@ func TestInformedDecisionAttributeAdmission(t *testing.T) {
|
|||
if err := json.Unmarshal(raw, &doc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if doc.PolicyVersion != "v10" {
|
||||
if doc.PolicyVersion != "v11" {
|
||||
t.Fatalf("fixture policy_version = %s", doc.PolicyVersion)
|
||||
}
|
||||
exactKeys := map[string]bool{"memo_version": true, "approval_id": true, "approval_binding_digest": true}
|
||||
|
|
|
|||
130
internal/policy/informed_decision_t03_act_test.go
Normal file
130
internal/policy/informed_decision_t03_act_test.go
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
package policy_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/netkingdom/flex-auth/internal/policy"
|
||||
"github.com/netkingdom/flex-auth/pkg/api"
|
||||
)
|
||||
|
||||
// v11 allows review acts on the three list-only T03 records at memo version 3.
|
||||
var t03ActRecords = map[string][2]string{
|
||||
"memo:SECRETS-WP-0010-T03-apply": {"b5fcbfcc-ad56-456f-bc36-c823052e9917", "sha256:03cc5b37437f14e86b686ce4054f976556334eff3fa260b03e8014ed3d9217e5"},
|
||||
"memo:SECRETS-WP-0010-T03-verify": {"4e9ff881-d59f-4143-9155-929afbe8dd43", "sha256:72d9267d038c17107c880ffc9009793ce9c70defbddfe2219628854b811a04b2"},
|
||||
"memo:SECRETS-WP-0010-T03-exec": {"a24e0898-b3c5-4e50-85a8-18a2c2aa229e", "sha256:f2cf0fb53b740900756ccde5587c3578fcff44beef2f1edab17b9a198a4033d8"},
|
||||
}
|
||||
|
||||
func TestT03ReviewActs(t *testing.T) {
|
||||
pkg, err := policy.LoadAndValidateFile(context.Background(), sittingPolicyPath(t))
|
||||
if err != nil || !pkg.Valid {
|
||||
t.Fatalf("load: %v %+v", err, pkg)
|
||||
}
|
||||
if pkg.Metadata.Version != "v11" {
|
||||
t.Fatalf("version = %s", pkg.Metadata.Version)
|
||||
}
|
||||
|
||||
var doc struct {
|
||||
Cases []struct {
|
||||
ID string `json:"id"`
|
||||
Assurance string `json:"assurance"`
|
||||
Request api.CheckRequest `json:"request"`
|
||||
} `json:"cases"`
|
||||
}
|
||||
raw, err := os.ReadFile(filepath.Join(sittingDir(t), "attribute_admission_v8.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(raw, &doc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var exact api.CheckRequest
|
||||
found := false
|
||||
for _, c := range doc.Cases {
|
||||
if c.ID == "exact-record-allow" {
|
||||
exact = c.Request
|
||||
stampAssurance(t, &exact, c.Assurance)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("exact-record-allow template missing")
|
||||
}
|
||||
|
||||
var shipped map[string]struct {
|
||||
ApprovalID string `json:"approval_id"`
|
||||
BindingDigest string `json:"binding_digest"`
|
||||
MemoVersion int `json:"memo_version"`
|
||||
}
|
||||
if err := json.Unmarshal(mustRead(t, filepath.Join(sittingDir(t), "list_only_records.json")), &shipped); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
eval := func(name string, req api.CheckRequest, effect, reason string) {
|
||||
t.Helper()
|
||||
got, err := pkg.Evaluate(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", name, err)
|
||||
}
|
||||
if string(got.Effect) != effect || got.Reason != reason {
|
||||
t.Fatalf("%s: got %s %s; want %s %s", name, got.Effect, got.Reason, effect, reason)
|
||||
}
|
||||
}
|
||||
|
||||
for memo, pin := range t03ActRecords {
|
||||
row := shipped[memo]
|
||||
if row.ApprovalID != pin[0] || row.BindingDigest != pin[1] || row.MemoVersion != 3 {
|
||||
t.Fatalf("list_only pin for %s = %+v", memo, row)
|
||||
}
|
||||
for _, action := range []string{"read", "acknowledge", "accept", "return", "discuss", "decline"} {
|
||||
req := exact
|
||||
req.Action = action
|
||||
req.Resource.ID = memo
|
||||
req.Context = copyContext(exact.Context)
|
||||
req.Context["memo_version"] = float64(3)
|
||||
req.Context["approval_id"] = pin[0]
|
||||
req.Context["approval_binding_digest"] = pin[1]
|
||||
eval(memo+" "+action, req, "allow", "operator_admitted_t03_review_act")
|
||||
}
|
||||
|
||||
listed := exact
|
||||
listed.Action = "list"
|
||||
listed.Resource.ID = memo
|
||||
listed.Context = copyContext(exact.Context)
|
||||
listed.Context["memo_version"] = float64(3)
|
||||
listed.Context["approval_id"] = pin[0]
|
||||
listed.Context["approval_binding_digest"] = pin[1]
|
||||
eval(memo+" list", listed, "allow", "operator_admitted_overview_list")
|
||||
|
||||
old := exact
|
||||
old.Action = "read"
|
||||
old.Resource.ID = memo
|
||||
old.Context = copyContext(exact.Context)
|
||||
old.Context["memo_version"] = float64(2)
|
||||
old.Context["approval_id"] = pin[0]
|
||||
old.Context["approval_binding_digest"] = pin[1]
|
||||
eval(memo+" version 2", old, "deny", "compact_sitting_scope_or_identity_refused")
|
||||
|
||||
wrong := exact
|
||||
wrong.Action = "accept"
|
||||
wrong.Resource.ID = memo
|
||||
wrong.Context = copyContext(exact.Context)
|
||||
wrong.Context["memo_version"] = float64(3)
|
||||
wrong.Context["approval_id"] = pin[0]
|
||||
wrong.Context["approval_binding_digest"] = "sha256:0000000000000000000000000000000000000000000000000000000000000000"
|
||||
eval(memo+" wrong digest", wrong, "deny", "compact_sitting_scope_or_identity_refused")
|
||||
}
|
||||
|
||||
// A version-1 sitting record still uses the original act rule.
|
||||
kept := exact
|
||||
kept.Action = "read"
|
||||
kept.Resource.ID = "memo:emergent-profile-adoption-0-2-6"
|
||||
kept.Context = copyContext(exact.Context)
|
||||
kept.Context["memo_version"] = float64(1)
|
||||
kept.Context["approval_id"] = "05751e09-3a5b-4a41-a4e8-b79e96de6484"
|
||||
kept.Context["approval_binding_digest"] = "sha256:7843e660694dcd7c806dc02ee0cca05dd3a96488f614b1946291496259a02001"
|
||||
eval("v9 record", kept, "allow", "operator_admitted_compact_sitting")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue