Allow all authenticated users to push/pull (not just human+user role)
The previous default policy required both AccountTypes=["human"] and Roles=["user"], but MCIAS validate responses don't reliably include these fields. For a private registry, any successfully authenticated caller should have content access. Admin-only operations (policy management) still require the admin role. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,12 +23,10 @@ func DefaultRules() []Rule {
|
|||||||
Actions: allActions,
|
Actions: allActions,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: -2,
|
ID: -2,
|
||||||
Priority: 0,
|
Priority: 0,
|
||||||
Description: "human users have full content access",
|
Description: "authenticated users have full content access",
|
||||||
Effect: Allow,
|
Effect: Allow,
|
||||||
Roles: []string{"user"},
|
|
||||||
AccountTypes: []string{"human"},
|
|
||||||
Actions: []Action{
|
Actions: []Action{
|
||||||
ActionPull,
|
ActionPull,
|
||||||
ActionPush,
|
ActionPush,
|
||||||
|
|||||||
@@ -27,15 +27,15 @@ func TestEngineDefaultsOnly(t *testing.T) {
|
|||||||
t.Fatalf("admin push with defaults: got %s, want allow", effect)
|
t.Fatalf("admin push with defaults: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// System account should be denied.
|
// System account should be allowed (rule -2: authenticated users).
|
||||||
effect, _ = e.Evaluate(PolicyInput{
|
effect, _ = e.Evaluate(PolicyInput{
|
||||||
Subject: "system-uuid",
|
Subject: "system-uuid",
|
||||||
AccountType: "system",
|
AccountType: "system",
|
||||||
Action: ActionPull,
|
Action: ActionPull,
|
||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
})
|
})
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("system pull with defaults: got %s, want deny", effect)
|
t.Fatalf("system pull with defaults: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,15 +62,15 @@ func TestEngineWithCustomRules(t *testing.T) {
|
|||||||
t.Fatalf("ci pull with custom rule: got %s, want allow", effect)
|
t.Fatalf("ci pull with custom rule: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Different subject should still be denied.
|
// Different subject is still allowed via default rule -2 (authenticated users).
|
||||||
effect, _ = e.Evaluate(PolicyInput{
|
effect, _ = e.Evaluate(PolicyInput{
|
||||||
Subject: "other-uuid",
|
Subject: "other-uuid",
|
||||||
AccountType: "system",
|
AccountType: "system",
|
||||||
Action: ActionPull,
|
Action: ActionPull,
|
||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
})
|
})
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("other pull: got %s, want deny", effect)
|
t.Fatalf("other pull: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,15 +117,15 @@ func TestEngineReload(t *testing.T) {
|
|||||||
t.Fatalf("Reload (second): %v", err)
|
t.Fatalf("Reload (second): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ci-uuid should now be denied (old rule gone).
|
// ci-uuid custom rule is gone, but still allowed via default rule -2.
|
||||||
effect, _ = e.Evaluate(PolicyInput{
|
effect, _ = e.Evaluate(PolicyInput{
|
||||||
Subject: "ci-uuid",
|
Subject: "ci-uuid",
|
||||||
AccountType: "system",
|
AccountType: "system",
|
||||||
Action: ActionPull,
|
Action: ActionPull,
|
||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
})
|
})
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("ci pull after second reload: got %s, want deny", effect)
|
t.Fatalf("ci pull after second reload: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deploy-uuid should now be allowed.
|
// deploy-uuid should now be allowed.
|
||||||
@@ -149,14 +149,14 @@ func TestEngineReloadDisabledExcluded(t *testing.T) {
|
|||||||
t.Fatalf("Reload: %v", err)
|
t.Fatalf("Reload: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No custom rules, so system account should be denied.
|
// No custom rules, but system account is allowed via default rule -2.
|
||||||
effect, _ := e.Evaluate(PolicyInput{
|
effect, _ := e.Evaluate(PolicyInput{
|
||||||
Subject: "ci-uuid",
|
Subject: "ci-uuid",
|
||||||
AccountType: "system",
|
AccountType: "system",
|
||||||
Action: ActionPull,
|
Action: ActionPull,
|
||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
})
|
})
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("system pull with no custom rules: got %s, want deny", effect)
|
t.Fatalf("system pull with no custom rules: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func TestEvaluateUserAllow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEvaluateSystemAccountDeny(t *testing.T) {
|
func TestEvaluateSystemAccountAllow(t *testing.T) {
|
||||||
rules := DefaultRules()
|
rules := DefaultRules()
|
||||||
input := PolicyInput{
|
input := PolicyInput{
|
||||||
Subject: "system-uuid",
|
Subject: "system-uuid",
|
||||||
@@ -47,11 +47,11 @@ func TestEvaluateSystemAccountDeny(t *testing.T) {
|
|||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
}
|
}
|
||||||
effect, rule := Evaluate(input, rules)
|
effect, rule := Evaluate(input, rules)
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("system pull: got %s, want deny", effect)
|
t.Fatalf("system pull: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
if rule != nil {
|
if rule == nil || rule.ID != -2 {
|
||||||
t.Fatalf("system pull: expected default deny (nil rule), got %+v", rule)
|
t.Fatalf("system pull: expected authenticated content rule (ID -2), got %+v", rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +75,11 @@ func TestEvaluateExactRepoMatch(t *testing.T) {
|
|||||||
t.Fatalf("exact repo match: got %s, want allow", effect)
|
t.Fatalf("exact repo match: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Different repo should deny.
|
// Different repo still allowed via default rule -2 (authenticated users).
|
||||||
input.Repository = "other"
|
input.Repository = "other"
|
||||||
effect, _ = Evaluate(input, rules)
|
effect, _ = Evaluate(input, rules)
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("different repo: got %s, want deny", effect)
|
t.Fatalf("different repo: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,11 +103,12 @@ func TestEvaluateGlobMatch(t *testing.T) {
|
|||||||
t.Fatalf("glob match production/myapp: got %s, want allow", effect)
|
t.Fatalf("glob match production/myapp: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nested repo should not match (path.Match: * doesn't cross /).
|
// Nested repo does not match the glob rule, but default rule -2
|
||||||
|
// (authenticated users) allows it.
|
||||||
input.Repository = "production/team/myapp"
|
input.Repository = "production/team/myapp"
|
||||||
effect, _ = Evaluate(input, rules)
|
effect, _ = Evaluate(input, rules)
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("glob no-match production/team/myapp: got %s, want deny", effect)
|
t.Fatalf("glob no-match production/team/myapp: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,8 +186,9 @@ func TestEvaluateEmptyRepoGlobalOperation(t *testing.T) {
|
|||||||
t.Fatalf("admin catalog: got %s, want allow", effect)
|
t.Fatalf("admin catalog: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// System account with a repo-scoped rule should be denied for catalog
|
// System account catalog: default rule -2 (authenticated users)
|
||||||
// (global op doesn't match repo-scoped rules).
|
// allows catalog with no repo restriction, so this is allowed even
|
||||||
|
// though the custom repo-scoped rule would not match.
|
||||||
rules = append(rules, Rule{
|
rules = append(rules, Rule{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Priority: 50,
|
Priority: 50,
|
||||||
@@ -201,8 +203,8 @@ func TestEvaluateEmptyRepoGlobalOperation(t *testing.T) {
|
|||||||
Action: ActionCatalog,
|
Action: ActionCatalog,
|
||||||
}
|
}
|
||||||
effect, _ = Evaluate(input, rules)
|
effect, _ = Evaluate(input, rules)
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Fatalf("system catalog with repo-scoped rule: got %s, want deny", effect)
|
t.Fatalf("system catalog: got %s, want allow", effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,10 +291,12 @@ func TestDefaultRulesUserContentAccess(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultRulesSystemAccountDeny(t *testing.T) {
|
func TestDefaultRulesSystemAccountAccess(t *testing.T) {
|
||||||
rules := DefaultRules()
|
rules := DefaultRules()
|
||||||
actions := []Action{ActionPull, ActionPush, ActionDelete, ActionCatalog, ActionPolicyManage}
|
|
||||||
for _, a := range actions {
|
// System accounts are now allowed for content actions via rule -2.
|
||||||
|
allowed := []Action{ActionPull, ActionPush, ActionDelete, ActionCatalog}
|
||||||
|
for _, a := range allowed {
|
||||||
input := PolicyInput{
|
input := PolicyInput{
|
||||||
Subject: "system-uuid",
|
Subject: "system-uuid",
|
||||||
AccountType: "system",
|
AccountType: "system",
|
||||||
@@ -300,10 +304,21 @@ func TestDefaultRulesSystemAccountDeny(t *testing.T) {
|
|||||||
Repository: "myapp",
|
Repository: "myapp",
|
||||||
}
|
}
|
||||||
effect, _ := Evaluate(input, rules)
|
effect, _ := Evaluate(input, rules)
|
||||||
if effect != Deny {
|
if effect != Allow {
|
||||||
t.Errorf("system %s: got %s, want deny", a, effect)
|
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) {
|
func TestDefaultRulesVersionCheckAlwaysAllowed(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user