package policy import "testing" func TestEvaluateAdminWildcard(t *testing.T) { rules := DefaultRules() input := PolicyInput{ Subject: "admin-uuid", AccountType: "human", Roles: []string{"admin"}, Action: ActionPush, Repository: "myapp", } effect, rule := Evaluate(input, rules) if effect != Allow { t.Fatalf("admin push: got %s, want allow", effect) } if rule == nil || rule.ID != -1 { t.Fatalf("admin push: expected admin wildcard rule (ID -1), got %+v", rule) } } func TestEvaluateUserAllow(t *testing.T) { rules := DefaultRules() input := PolicyInput{ Subject: "user-uuid", AccountType: "human", Roles: []string{"user"}, Action: ActionPull, Repository: "myapp", } effect, rule := Evaluate(input, rules) if effect != Allow { t.Fatalf("user pull: got %s, want allow", effect) } if rule == nil || rule.ID != -2 { t.Fatalf("user pull: expected user content rule (ID -2), got %+v", rule) } } func TestEvaluateSystemAccountAllow(t *testing.T) { rules := DefaultRules() input := PolicyInput{ Subject: "system-uuid", AccountType: "system", Action: ActionPull, Repository: "myapp", } effect, rule := Evaluate(input, rules) if effect != Allow { t.Fatalf("system pull: got %s, want allow", effect) } if rule == nil || rule.ID != -2 { t.Fatalf("system pull: expected authenticated content rule (ID -2), got %+v", rule) } } func TestEvaluateExactRepoMatch(t *testing.T) { rules := append(DefaultRules(), Rule{ ID: 1, Priority: 50, Effect: Allow, SubjectUUID: "ci-uuid", Actions: []Action{ActionPull}, Repositories: []string{"myapp"}, }) input := PolicyInput{ Subject: "ci-uuid", AccountType: "system", Action: ActionPull, Repository: "myapp", } effect, _ := Evaluate(input, rules) if effect != Allow { t.Fatalf("exact repo match: got %s, want allow", effect) } // Different repo still allowed via default rule -2 (authenticated users). input.Repository = "other" effect, _ = Evaluate(input, rules) if effect != Allow { t.Fatalf("different repo: got %s, want allow", effect) } } func TestEvaluateGlobMatch(t *testing.T) { rules := append(DefaultRules(), Rule{ ID: 1, Priority: 50, Effect: Allow, SubjectUUID: "ci-uuid", Actions: []Action{ActionPush, ActionPull}, Repositories: []string{"production/*"}, }) input := PolicyInput{ Subject: "ci-uuid", AccountType: "system", Action: ActionPush, Repository: "production/myapp", } effect, _ := Evaluate(input, rules) if effect != Allow { t.Fatalf("glob match production/myapp: got %s, want allow", effect) } // Nested repo does not match the glob rule, but default rule -2 // (authenticated users) allows it. input.Repository = "production/team/myapp" effect, _ = Evaluate(input, rules) if effect != Allow { t.Fatalf("glob no-match production/team/myapp: got %s, want allow", effect) } } func TestEvaluateDenyWins(t *testing.T) { rules := []Rule{ { ID: 1, Priority: 50, Effect: Allow, SubjectUUID: "agent-uuid", Actions: []Action{ActionPull}, }, { ID: 2, Priority: 10, Effect: Deny, SubjectUUID: "agent-uuid", Actions: []Action{ActionPull}, }, } input := PolicyInput{ Subject: "agent-uuid", AccountType: "system", Action: ActionPull, Repository: "myapp", } effect, rule := Evaluate(input, rules) if effect != Deny { t.Fatalf("deny-wins: got %s, want deny", effect) } if rule == nil || rule.ID != 2 { t.Fatalf("deny-wins: expected deny rule (ID 2), got %+v", rule) } } func TestEvaluatePriorityOrdering(t *testing.T) { rules := []Rule{ { ID: 1, Priority: 100, Effect: Allow, Actions: []Action{ActionPull}, }, { ID: 2, Priority: 10, Effect: Deny, Actions: []Action{ActionPull}, }, } input := PolicyInput{ Subject: "any", AccountType: "system", Action: ActionPull, Repository: "myapp", } effect, _ := Evaluate(input, rules) if effect != Deny { t.Fatalf("priority: got %s, want deny", effect) } } func TestEvaluateEmptyRepoGlobalOperation(t *testing.T) { rules := DefaultRules() // Admin should be allowed for catalog (admin wildcard, empty Repositories = wildcard). input := PolicyInput{ Subject: "admin-uuid", AccountType: "human", Roles: []string{"admin"}, Action: ActionCatalog, } effect, _ := Evaluate(input, rules) if effect != Allow { t.Fatalf("admin catalog: got %s, want allow", effect) } // System account catalog: default rule -2 (authenticated users) // allows catalog with no repo restriction, so this is allowed even // though the custom repo-scoped rule would not match. rules = append(rules, Rule{ ID: 1, Priority: 50, Effect: Allow, SubjectUUID: "ci-uuid", Actions: []Action{ActionCatalog}, Repositories: []string{"myapp"}, }) input = PolicyInput{ Subject: "ci-uuid", AccountType: "system", Action: ActionCatalog, } effect, _ = Evaluate(input, rules) if effect != Allow { t.Fatalf("system catalog: got %s, want allow", effect) } } func TestEvaluateMultipleMatchingRules(t *testing.T) { rules := []Rule{ { ID: 1, Priority: 50, Effect: Allow, Actions: []Action{ActionPull}, }, { ID: 2, Priority: 100, Effect: Allow, Actions: []Action{ActionPull, ActionPush}, }, } input := PolicyInput{ Subject: "any", AccountType: "system", Action: ActionPull, Repository: "myapp", } effect, rule := Evaluate(input, rules) if effect != Allow { t.Fatalf("multiple allow: got %s, want allow", effect) } if rule == nil || rule.ID != 1 { t.Fatalf("multiple allow: expected rule ID 1 (higher priority), got %+v", rule) } } // --- Default rules tests (Step 4.2) --- func TestDefaultRulesAdminAllActions(t *testing.T) { rules := DefaultRules() actions := []Action{ ActionVersionCheck, ActionPull, ActionPush, ActionDelete, ActionCatalog, ActionPolicyManage, } for _, a := range actions { input := PolicyInput{ Subject: "admin-uuid", AccountType: "human", Roles: []string{"admin"}, Action: a, Repository: "myapp", } effect, _ := Evaluate(input, rules) if effect != Allow { t.Errorf("admin %s: got %s, want allow", a, effect) } } } func TestDefaultRulesUserContentAccess(t *testing.T) { rules := DefaultRules() allowed := []Action{ActionPull, ActionPush, ActionDelete, ActionCatalog} for _, a := range allowed { input := PolicyInput{ Subject: "user-uuid", AccountType: "human", Roles: []string{"user"}, Action: a, Repository: "myapp", } effect, _ := Evaluate(input, rules) if effect != Allow { t.Errorf("user %s: got %s, want allow", a, effect) } } // policy:manage should be denied for regular user. input := PolicyInput{ Subject: "user-uuid", AccountType: "human", Roles: []string{"user"}, Action: ActionPolicyManage, } effect, _ := Evaluate(input, rules) if effect != Deny { t.Errorf("user policy:manage: got %s, want deny", effect) } } func TestDefaultRulesSystemAccountAccess(t *testing.T) { rules := DefaultRules() // System accounts are now allowed for content actions via rule -2. allowed := []Action{ActionPull, ActionPush, ActionDelete, ActionCatalog} for _, a := range allowed { input := PolicyInput{ Subject: "system-uuid", AccountType: "system", Action: a, Repository: "myapp", } effect, _ := Evaluate(input, rules) if effect != Allow { t.Errorf("system %s: got %s, want allow", a, effect) } } // policy:manage should still be denied for system accounts. input := PolicyInput{ Subject: "system-uuid", AccountType: "system", Action: ActionPolicyManage, } effect, _ := Evaluate(input, rules) if effect != Deny { t.Errorf("system policy:manage: got %s, want deny", effect) } } func TestDefaultRulesVersionCheckAlwaysAllowed(t *testing.T) { rules := DefaultRules() for _, acctType := range []string{"human", "system"} { input := PolicyInput{ Subject: "any-uuid", AccountType: acctType, Action: ActionVersionCheck, } effect, _ := Evaluate(input, rules) if effect != Allow { t.Errorf("%s version_check: got %s, want allow", acctType, effect) } } }