diff --git a/service/internal/auth/casbin.go b/service/internal/auth/casbin.go index 51539e0f8..bacf038ba 100644 --- a/service/internal/auth/casbin.go +++ b/service/internal/auth/casbin.go @@ -215,9 +215,8 @@ func (e *Enforcer) ExtendDefaultPolicy(policies [][]string) error { policy := strings.TrimSpace(defaultPolicy) policy += "\n\n## Extended Policies" - for p := range policies { - pol := policies[p] - polCsv := strings.Join(policies[p], ", ") + for _, pol := range policies { + polCsv := strings.Join(pol, ", ") if len(pol) < defaultPolicyPartsLen { return fmt.Errorf("policy missing one of 'p, subject, resource, action, effect', pol: [%s] %w", polCsv, ErrPolicyMalformed) } diff --git a/service/internal/auth/casbin_test.go b/service/internal/auth/casbin_test.go index f7a299ad8..0dc7f5f0f 100644 --- a/service/internal/auth/casbin_test.go +++ b/service/internal/auth/casbin_test.go @@ -434,6 +434,60 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies() { s.False(allowed) } +func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MultipleExtensions() { + enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) + s.Require().NoError(err) + + // Org-admin role + err = enforcer.ExtendDefaultPolicy([][]string{ + {"p", "role:org-admin", "new.service.*", "*", "allow"}, + {"p", "role:admin", "new.hello.*", "*", "allow"}, + }) + s.Require().NoError(err) + + orgAdminTok := s.newTokWithDefaultClaim(true, false, false) + adminTok := s.newTokWithDefaultClaim(false, true, false) + standardTok := s.newTokWithDefaultClaim(false, false, true) + cases := []struct { + tok jwt.Token + expectedAllowed bool + resource string + action string + }{ + // original default policy still evaluates correctly + {orgAdminTok, true, "policy.attributes.CreateAttribute", "write"}, + // both new policies are evaluated correctly + {orgAdminTok, true, "new.service.ActionableObject", "read"}, + {orgAdminTok, true, "new.service.ActionableObject", "write"}, + {orgAdminTok, false, "new.hello.World", "read"}, + {orgAdminTok, false, "new.hello.World", "write"}, + {orgAdminTok, false, "new.hello.SomethingElse", "read"}, + {orgAdminTok, false, "new.hello.SomethingElse", "write"}, + {adminTok, false, "new.service.ActionableObject", "read"}, + {adminTok, false, "new.service.ActionableObject", "write"}, + {adminTok, true, "new.hello.World", "read"}, + {adminTok, true, "new.hello.World", "write"}, + {adminTok, true, "new.hello.SomethingElse", "read"}, + {adminTok, true, "new.hello.SomethingElse", "write"}, + {standardTok, false, "new.service.ActionableObject", "read"}, + {standardTok, false, "new.service.ActionableObject", "write"}, + {standardTok, false, "new.hello.World", "read"}, + {standardTok, false, "new.hello.World", "write"}, + {standardTok, false, "new.hello.SomethingElse", "read"}, + {standardTok, false, "new.hello.SomethingElse", "write"}, + } + + for _, c := range cases { + allowed, err := enforcer.Enforce(c.tok, c.resource, c.action) + if !c.expectedAllowed { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } + s.Equal(c.expectedAllowed, allowed) + } +} + func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MalformedErrors() { enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger()) s.Require().NoError(err)