diff --git a/cluster/iam/adapter/policy.go b/cluster/iam/adapter/policy.go index 4e78db7c..2fb46d40 100644 --- a/cluster/iam/adapter/policy.go +++ b/cluster/iam/adapter/policy.go @@ -1,7 +1,6 @@ package adapter import ( - "strings" "sync" "github.com/datarhei/core/v16/cluster/store" @@ -36,11 +35,15 @@ func (a *policyAdapter) LoadPolicy(model model.Model) error { p.Domain = "$none" } + if len(p.Types) == 0 { + p.Types = []string{"$none"} + } + rule := []string{ p.Name, p.Domain, - p.Resource, - strings.Join(p.Actions, "|"), + iamaccess.EncodeResource(p.Types, p.Resource), + iamaccess.EncodeActions(p.Actions), } domains[p.Domain] = struct{}{} diff --git a/cluster/store/policy.go b/cluster/store/policy.go index c809c1c0..b3d5fe29 100644 --- a/cluster/store/policy.go +++ b/cluster/store/policy.go @@ -3,6 +3,8 @@ package store import ( "fmt" "time" + + "github.com/datarhei/core/v16/iam/access" ) func (s *store) setPolicies(cmd CommandSetPolicies) error { @@ -27,11 +29,12 @@ func (s *store) setPolicies(cmd CommandSetPolicies) error { } for i, p := range cmd.Policies { - if len(p.Domain) != 0 { - continue + p = s.updatePolicy(p) + + if len(p.Domain) == 0 { + p.Domain = "$none" } - p.Domain = "$none" cmd.Policies[i] = p } @@ -75,3 +78,12 @@ func (s *store) ListUserPolicies(name string) Policies { return p } + +// updatePolicy updates a policy such that the resource type is split off the resource +func (s *store) updatePolicy(p access.Policy) access.Policy { + if len(p.Types) == 0 { + p.Types, p.Resource = access.DecodeResource(p.Resource) + } + + return p +} diff --git a/cluster/store/store.go b/cluster/store/store.go index 58db3bb2..3ee7e12a 100644 --- a/cluster/store/store.go +++ b/cluster/store/store.go @@ -473,6 +473,14 @@ func (s *store) Restore(snapshot io.ReadCloser) error { data.Users.Users[name] = u } + for name, policies := range data.Policies.Policies { + for i, p := range policies { + policies[i] = s.updatePolicy(p) + } + + data.Policies.Policies[name] = policies + } + if data.Version == 0 { data.Version = 1 } diff --git a/http/handler/api/cluster_iam.go b/http/handler/api/cluster_iam.go index 95271281..fa9a71b4 100644 --- a/http/handler/api/cluster_iam.go +++ b/http/handler/api/cluster_iam.go @@ -206,6 +206,7 @@ func (h *ClusterHandler) UpdateIdentityPolicies(c echo.Context) error { accessPolicies = append(accessPolicies, access.Policy{ Name: name, Domain: p.Domain, + Types: p.Types, Resource: p.Resource, Actions: p.Actions, }) @@ -359,6 +360,7 @@ func (h *ClusterHandler) ListPolicies(c echo.Context) error { policies = append(policies, api.IAMPolicy{ Name: pol.Name, Domain: pol.Domain, + Types: pol.Types, Resource: pol.Resource, Actions: pol.Actions, }) diff --git a/iam/access/access.go b/iam/access/access.go index 4be22631..3bbcf2fd 100644 --- a/iam/access/access.go +++ b/iam/access/access.go @@ -80,13 +80,13 @@ func New(config Config) (Manager, error) { } func (am *access) HasPolicy(name, domain string, types []string, resource string, actions []string) bool { - policy := []string{name, domain, encodeResource(types, resource), encodeActions(actions)} + policy := []string{name, domain, EncodeResource(types, resource), EncodeActions(actions)} return am.enforcer.HasPolicy(policy) } func (am *access) AddPolicy(name, domain string, types []string, resource string, actions []string) error { - policy := []string{name, domain, encodeResource(types, resource), encodeActions(actions)} + policy := []string{name, domain, EncodeResource(types, resource), EncodeActions(actions)} if am.enforcer.HasPolicy(policy) { return nil @@ -98,7 +98,7 @@ func (am *access) AddPolicy(name, domain string, types []string, resource string } func (am *access) RemovePolicy(name, domain string, types []string, resource string, actions []string) error { - policies := am.enforcer.GetFilteredPolicy(0, name, domain, encodeResource(types, resource), encodeActions(actions)) + policies := am.enforcer.GetFilteredPolicy(0, name, domain, EncodeResource(types, resource), EncodeActions(actions)) _, err := am.enforcer.RemovePolicies(policies) return err @@ -107,16 +107,16 @@ func (am *access) RemovePolicy(name, domain string, types []string, resource str func (am *access) ListPolicies(name, domain string, types []string, resource string, actions []string) []Policy { policies := []Policy{} - ps := am.enforcer.GetFilteredPolicy(0, name, domain, encodeResource(types, resource), encodeActions(actions)) + ps := am.enforcer.GetFilteredPolicy(0, name, domain, EncodeResource(types, resource), EncodeActions(actions)) for _, p := range ps { - types, resource := decodeResource(p[2]) + types, resource := DecodeResource(p[2]) policies = append(policies, Policy{ Name: p[0], Domain: p[1], Types: types, Resource: resource, - Actions: decodeActions(p[3]), + Actions: DecodeActions(p[3]), }) } @@ -145,15 +145,15 @@ func (am *access) Enforce(name, domain, rtype, resource, action string) (bool, s return ok, strings.Join(rule, ", ") } -func encodeActions(actions []string) string { +func EncodeActions(actions []string) string { return strings.Join(actions, "|") } -func decodeActions(actions string) []string { +func DecodeActions(actions string) []string { return strings.Split(actions, "|") } -func encodeResource(types []string, resource string) string { +func EncodeResource(types []string, resource string) string { if len(types) == 0 { return resource } @@ -163,10 +163,10 @@ func encodeResource(types []string, resource string) string { return strings.Join(types, "|") + ":" + resource } -func decodeResource(resource string) ([]string, string) { +func DecodeResource(resource string) ([]string, string) { before, after, found := strings.Cut(resource, ":") if !found { - return []string{}, resource + return []string{"$none"}, resource } return strings.Split(before, "|"), after diff --git a/iam/access/access_test.go b/iam/access/access_test.go index cf2c9dd2..220cfa26 100644 --- a/iam/access/access_test.go +++ b/iam/access/access_test.go @@ -44,7 +44,7 @@ func TestAccessManager(t *testing.T) { }, }, policies) - am.AddPolicy("foobar", "group", []string{"bla"}, "/", []string{"write"}) + am.AddPolicy("foobar", "group", []string{"bla", "blubb"}, "/", []string{"write"}) policies = am.ListPolicies("", "", nil, "", nil) require.ElementsMatch(t, []Policy{ @@ -65,7 +65,7 @@ func TestAccessManager(t *testing.T) { { Name: "foobar", Domain: "group", - Types: []string{"bla"}, + Types: []string{"bla", "blubb"}, Resource: "/", Actions: []string{"write"}, }, @@ -82,7 +82,7 @@ func TestAccessManager(t *testing.T) { { Name: "foobar", Domain: "group", - Types: []string{"bla"}, + Types: []string{"bla", "blubb"}, Resource: "/", Actions: []string{"write"}, }, @@ -97,4 +97,7 @@ func TestAccessManager(t *testing.T) { ok, _ = am.Enforce("foobar", "group", "bla", "/", "write") require.True(t, ok) + + ok, _ = am.Enforce("foobar", "group", "blubb", "/", "write") + require.True(t, ok) }