Skip to content

Commit

Permalink
tim resset extended action (#37)
Browse files Browse the repository at this point in the history
* resset: allow custom Action types in ResourceSet

---------

Co-authored-by: btoews <[email protected]>
  • Loading branch information
timflyio and btoews authored Sep 11, 2024
1 parent 6e96925 commit f04e4cb
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 96 deletions.
2 changes: 1 addition & 1 deletion flyio/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (a *Access) GetPermittedRoles() []Role {
return []Role{RoleMember}
}

if memberAllowed, ok := MemberFeatures[*a.Feature]; ok && a.Action.IsSubsetOf(memberAllowed) {
if memberAllowed, ok := MemberFeatures[*a.Feature]; ok && resset.IsSubsetOf(a.Action, memberAllowed) {
return []Role{RoleMember}
}

Expand Down
64 changes: 32 additions & 32 deletions flyio/caveat_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func TestScopeOrganizationID(t *testing.T) {
// error if not org constrained
_, err := OrganizationScope(macaroon.NewCaveatSet(
&Apps{resset.ResourceSet[uint64]{123: resset.ActionAll}},
&Apps{resset.ResourceSet[uint64, resset.Action]{123: resset.ActionAll}},
))

assert.True(t, errors.Is(err, macaroon.ErrUnauthorized))
Expand Down Expand Up @@ -52,15 +52,15 @@ func TestScopeOrganizationID(t *testing.T) {
// ok - no permission allowed by IfPresent
_, err = OrganizationScope(macaroon.NewCaveatSet(
&Organization{ID: 123, Mask: resset.ActionAll},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64]{123: resset.ActionAll}})},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64, resset.Action]{123: resset.ActionAll}})},
))

assert.NoError(t, err)

// ok - some child resource is required
id, err = OrganizationScope(macaroon.NewCaveatSet(
&Organization{ID: 123, Mask: resset.ActionAll},
&Apps{resset.ResourceSet[uint64]{234: resset.ActionAll}},
&Apps{resset.ResourceSet[uint64, resset.Action]{234: resset.ActionAll}},
))

assert.NoError(t, err)
Expand All @@ -77,8 +77,8 @@ func TestAppIDs(t *testing.T) {
// try each case with a id=* caveat, which should be a noop for scoping.
bases := [][]macaroon.Caveat{
{},
{&Apps{resset.ResourceSet[uint64]{0: resset.ActionAll}}},
{&Apps{resset.ResourceSet[uint64]{0: resset.ActionNone}}},
{&Apps{resset.ResourceSet[uint64, resset.Action]{0: resset.ActionAll}}},
{&Apps{resset.ResourceSet[uint64, resset.Action]{0: resset.ActionNone}}},
}

for _, base := range bases {
Expand All @@ -98,24 +98,24 @@ func TestAppIDs(t *testing.T) {

// {} for disjoint Apps
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64]{2: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64, resset.Action]{2: resset.ActionRead}},
)...))

assert.Equal(t, empty, ids)

// {} for disjoint Apps/IfPresent
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64]{2: resset.ActionRead}})},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64, resset.Action]{2: resset.ActionRead}})},
)...))

assert.Equal(t, empty, ids)

// {} for disjoint IfPresents
ids = AppScope(macaroon.NewCaveatSet(append(base,
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64]{2: resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64, resset.Action]{2: resset.ActionRead}})},
)...))

assert.Equal(t, empty, ids)
Expand All @@ -127,44 +127,44 @@ func TestAppIDs(t *testing.T) {

// nil if app unconstrained and has unrelated caveats
ids = AppScope(macaroon.NewCaveatSet(append(base,
&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string]{"wg": resset.ActionAll}})},
&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string, resset.Action]{"wg": resset.ActionAll}})},
)...))

assert.Equal(t, unconstrained, ids)

// {123} if app constrained
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}},
)...))

assert.Equal(t, constrained, ids)

// {123} if no permissions allowed on app
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionNone}},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionNone}},
)...))

assert.Equal(t, constrained, ids)

// {123} if disjoint permissions allowed on app
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64]{1: resset.ActionWrite}},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionWrite}},
)...))

assert.Equal(t, constrained, ids)

// {123} if app constrained by IfPresent
ids = AppScope(macaroon.NewCaveatSet(append(base,
&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64]{1: resset.ActionRead}})},
&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionRead}})},
)...))

assert.Equal(t, constrained, ids)

// {123} if app constrained and other IfPresent
ids = AppScope(macaroon.NewCaveatSet(append(base,
&Apps{resset.ResourceSet[uint64]{1: resset.ActionAll}},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string]{"wg": resset.ActionAll}})},
&Apps{resset.ResourceSet[uint64, resset.Action]{1: resset.ActionAll}},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string, resset.Action]{"wg": resset.ActionAll}})},
)...))

assert.Equal(t, constrained, ids)
Expand All @@ -186,48 +186,48 @@ func TestClusters(t *testing.T) {
assert.Equal(t, empty, ids)

// {} for disjoint Clusters
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}}, &Clusters{resset.ResourceSet[string]{"2": resset.ActionRead}}))
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}}, &Clusters{resset.ResourceSet[string, resset.Action]{"2": resset.ActionRead}}))
assert.Equal(t, empty, ids)

// {} for disjoint Clusters/IfPresent
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}}, &resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"2": resset.ActionRead}})}))
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}}, &resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"2": resset.ActionRead}})}))
assert.Equal(t, empty, ids)

// {} for disjoint IfPresents
ids = ClusterScope(macaroon.NewCaveatSet(
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"2": resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}})},
&resset.IfPresent{Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"2": resset.ActionRead}})},
))
assert.Equal(t, empty, ids)

// {123} if cluster constrained
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}}))
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}}))
assert.Equal(t, constrained, ids)

// {123} if no permissions allowed on cluster
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionNone}}))
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionNone}}))
assert.Equal(t, constrained, ids)

// {123} if disjoint permissions allowed on cluster
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}}, &Clusters{resset.ResourceSet[string]{"1": resset.ActionWrite}}))
ids = ClusterScope(macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}}, &Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionWrite}}))
assert.Equal(t, constrained, ids)

// {123} if cluster constrained by IfPresent
ids = ClusterScope(macaroon.NewCaveatSet(&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string]{"1": resset.ActionRead}})}))
ids = ClusterScope(macaroon.NewCaveatSet(&resset.IfPresent{Else: resset.ActionRead, Ifs: macaroon.NewCaveatSet(&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionRead}})}))
assert.Equal(t, constrained, ids)

// {123} if cluster constrained and other IfPresent
ids = ClusterScope(macaroon.NewCaveatSet(
&Clusters{resset.ResourceSet[string]{"1": resset.ActionAll}},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string]{"wg": resset.ActionAll}})},
&Clusters{resset.ResourceSet[string, resset.Action]{"1": resset.ActionAll}},
&resset.IfPresent{Else: resset.ActionNone, Ifs: macaroon.NewCaveatSet(&FeatureSet{resset.ResourceSet[string, resset.Action]{"wg": resset.ActionAll}})},
))
assert.Equal(t, constrained, ids)
}

func TestAppsAllowing(t *testing.T) {
// OrganizationScope error
_, _, err := AppsAllowing(macaroon.NewCaveatSet(
&Apps{resset.ResourceSet[uint64]{123: resset.ActionAll}},
&Apps{resset.ResourceSet[uint64, resset.Action]{123: resset.ActionAll}},
), resset.ActionNone)

assert.True(t, errors.Is(err, macaroon.ErrUnauthorized))
Expand All @@ -250,7 +250,7 @@ func TestAppsAllowing(t *testing.T) {
// action prohibited on all apps
_, _, err = AppsAllowing(macaroon.NewCaveatSet(
&Organization{ID: 987, Mask: resset.ActionAll},
&Apps{resset.ResourceSet[uint64]{123: resset.ActionRead}},
&Apps{resset.ResourceSet[uint64, resset.Action]{123: resset.ActionRead}},
), resset.ActionWrite)

assert.True(t, errors.Is(err, resset.ErrUnauthorizedForAction))
Expand All @@ -267,7 +267,7 @@ func TestAppsAllowing(t *testing.T) {
// action allowed on some apps
orgID, appIDs, err = AppsAllowing(macaroon.NewCaveatSet(
&Organization{ID: 987, Mask: resset.ActionAll},
&Apps{Apps: resset.ResourceSet[uint64]{123: resset.ActionAll, 234: resset.ActionWrite, 345: resset.ActionRead}},
&Apps{Apps: resset.ResourceSet[uint64, resset.Action]{123: resset.ActionAll, 234: resset.ActionWrite, 345: resset.ActionRead}},
), resset.ActionWrite)

assert.NoError(t, err)
Expand Down
20 changes: 10 additions & 10 deletions flyio/caveats.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ func (c *Organization) Prohibits(a macaroon.Access) error {
return fmt.Errorf("%w org", resset.ErrResourceUnspecified)
case c.ID != resset.ZeroID[uint64]() && c.ID != *f.GetOrgID():
return fmt.Errorf("%w org %d, only %d", resset.ErrUnauthorizedForResource, *f.GetOrgID(), c.ID)
case !f.GetAction().IsSubsetOf(c.Mask):
return fmt.Errorf("%w access %s (%s not allowed)", resset.ErrUnauthorizedForAction, f.GetAction(), f.GetAction().Remove(c.Mask))
case !resset.IsSubsetOf(f.GetAction(), c.Mask):
return fmt.Errorf("%w access %s (%s not allowed)", resset.ErrUnauthorizedForAction, f.GetAction(), resset.Remove(f.GetAction(), c.Mask))
default:
return nil
}
Expand All @@ -86,7 +86,7 @@ func (c *Organization) Prohibits(a macaroon.Access) error {
// only with the listed apps, regardless of what the token says. Additional Apps can be added,
// but they can only narrow, not expand, which apps (or access levels) can be reached from the token.
type Apps struct {
Apps resset.ResourceSet[uint64] `json:"apps"`
Apps resset.ResourceSet[uint64, resset.Action] `json:"apps"`
}

func init() {
Expand All @@ -106,7 +106,7 @@ func (c *Apps) Prohibits(a macaroon.Access) error {
}

type Volumes struct {
Volumes resset.ResourceSet[string] `json:"volumes"`
Volumes resset.ResourceSet[string, resset.Action] `json:"volumes"`
}

func init() { macaroon.RegisterCaveatType(&Volumes{}) }
Expand All @@ -122,7 +122,7 @@ func (c *Volumes) Prohibits(a macaroon.Access) error {
}

type Machines struct {
Machines resset.ResourceSet[string] `json:"machines"`
Machines resset.ResourceSet[string, resset.Action] `json:"machines"`
}

func init() { macaroon.RegisterCaveatType(&Machines{}) }
Expand All @@ -138,7 +138,7 @@ func (c *Machines) Prohibits(a macaroon.Access) error {
}

type MachineFeatureSet struct {
Features resset.ResourceSet[string] `json:"features"`
Features resset.ResourceSet[string, resset.Action] `json:"features"`
}

func init() { macaroon.RegisterCaveatType(&MachineFeatureSet{}) }
Expand All @@ -159,7 +159,7 @@ func (c *MachineFeatureSet) Prohibits(a macaroon.Access) error {
// individually with a Networks caveat. The feature name is free-form and more
// should be addded as it makes sense.
type FeatureSet struct {
Features resset.ResourceSet[string] `json:"features"`
Features resset.ResourceSet[string, resset.Action] `json:"features"`
}

func init() { macaroon.RegisterCaveatType(&FeatureSet{}) }
Expand Down Expand Up @@ -225,7 +225,7 @@ func (c *IsUser) Prohibits(a macaroon.Access) error {
// Clusters is a set of Cluster caveats, with their RWX access levels. Clusters
// belong to the "litefs-cloud" org-feature.
type Clusters struct {
Clusters resset.ResourceSet[string] `json:"clusters"`
Clusters resset.ResourceSet[string, resset.Action] `json:"clusters"`
}

func init() { macaroon.RegisterCaveatType(&Clusters{}) }
Expand Down Expand Up @@ -389,7 +389,7 @@ func (c *Commands) Prohibits(a macaroon.Access) error {
}

type AppFeatureSet struct {
Features resset.ResourceSet[string] `json:"features"`
Features resset.ResourceSet[string, resset.Action] `json:"features"`
}

func init() { macaroon.RegisterCaveatType(&AppFeatureSet{}) }
Expand All @@ -410,7 +410,7 @@ func (c *AppFeatureSet) Prohibits(a macaroon.Access) error {
// provider (e.g. `https://storage.fly/my_bucket`), or a object within a bucket
// (e.g. `https://storage.fly/my_bucket/my_file`).
type StorageObjects struct {
Prefixes resset.ResourceSet[resset.Prefix] `json:"storage_objects"`
Prefixes resset.ResourceSet[resset.Prefix, resset.Action] `json:"storage_objects"`
}

func init() {
Expand Down
2 changes: 1 addition & 1 deletion flyio/caveats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
func TestCaveatSerialization(t *testing.T) {
cs := macaroon.NewCaveatSet(
&Organization{ID: 123, Mask: resset.ActionRead},
&Apps{Apps: resset.ResourceSet[uint64]{123: resset.ActionRead}},
&Apps{Apps: resset.ResourceSet[uint64, resset.Action]{123: resset.ActionRead}},
&FeatureSet{Features: resset.New(resset.ActionRead, "123")},
&Volumes{Volumes: resset.New(resset.ActionRead, "123")},
&Machines{Machines: resset.New(resset.ActionRead, "123")},
Expand Down
24 changes: 12 additions & 12 deletions internal/test-vectors/test_vectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,18 @@ var caveats = macaroon.NewCaveatSet(
ptr(uint64Caveat(123)),
&sliceCaveat{1, 2, 3},
&mapCaveat{"c": "c", "a": "a", "b": "b"},
&intResourceSetCaveat{Body: resset.ResourceSet[uint64]{3: resset.ActionAll, 1: resset.ActionAll, 2: resset.ActionAll}},
&stringResourceSetCaveat{Body: resset.ResourceSet[string]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll}},
&prefixResourceSetCaveat{Body: resset.ResourceSet[resset.Prefix]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll}},
&intResourceSetCaveat{Body: resset.ResourceSet[uint64, resset.Action]{3: resset.ActionAll, 1: resset.ActionAll, 2: resset.ActionAll}},
&stringResourceSetCaveat{Body: resset.ResourceSet[string, resset.Action]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll}},
&prefixResourceSetCaveat{Body: resset.ResourceSet[resset.Prefix, resset.Action]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll}},
&structCaveat{
StringField: "foo",
IntField: -123,
UintField: 123,
SliceField: []byte{1, 2, 3},
MapField: map[string]string{"c": "c", "a": "a", "b": "b"},
IntResourceSetField: resset.ResourceSet[uint64]{3: resset.ActionAll, 1: resset.ActionAll, 2: resset.ActionAll},
StringResourceSetField: resset.ResourceSet[string]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll},
PrefixResourceSetField: resset.ResourceSet[resset.Prefix]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll},
IntResourceSetField: resset.ResourceSet[uint64, resset.Action]{3: resset.ActionAll, 1: resset.ActionAll, 2: resset.ActionAll},
StringResourceSetField: resset.ResourceSet[string, resset.Action]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll},
PrefixResourceSetField: resset.ResourceSet[resset.Prefix, resset.Action]{"c": resset.ActionAll, "a": resset.ActionAll, "b": resset.ActionAll},
},
auth.RequireUser(123),
auth.RequireOrganization(123),
Expand Down Expand Up @@ -205,7 +205,7 @@ func (c mapCaveat) EncodeMsgpack(enc *msgpack.Encoder) error {
}

type intResourceSetCaveat struct {
Body resset.ResourceSet[uint64]
Body resset.ResourceSet[uint64, resset.Action]
}

func init() { macaroon.RegisterCaveatType(new(intResourceSetCaveat)) }
Expand All @@ -214,7 +214,7 @@ func (c *intResourceSetCaveat) Name() string { return "IntR
func (c *intResourceSetCaveat) Prohibits(f macaroon.Access) error { return nil }

type stringResourceSetCaveat struct {
Body resset.ResourceSet[string]
Body resset.ResourceSet[string, resset.Action]
}

func init() { macaroon.RegisterCaveatType(new(stringResourceSetCaveat)) }
Expand All @@ -223,7 +223,7 @@ func (c *stringResourceSetCaveat) Name() string { return "S
func (c *stringResourceSetCaveat) Prohibits(f macaroon.Access) error { return nil }

type prefixResourceSetCaveat struct {
Body resset.ResourceSet[resset.Prefix]
Body resset.ResourceSet[resset.Prefix, resset.Action]
}

func init() { macaroon.RegisterCaveatType(new(prefixResourceSetCaveat)) }
Expand All @@ -237,9 +237,9 @@ type structCaveat struct {
UintField uint64
SliceField []byte
MapField map[string]string
IntResourceSetField resset.ResourceSet[uint64]
StringResourceSetField resset.ResourceSet[string]
PrefixResourceSetField resset.ResourceSet[resset.Prefix]
IntResourceSetField resset.ResourceSet[uint64, resset.Action]
StringResourceSetField resset.ResourceSet[string, resset.Action]
PrefixResourceSetField resset.ResourceSet[resset.Prefix, resset.Action]
}

func init() { macaroon.RegisterCaveatType(new(structCaveat)) }
Expand Down
14 changes: 2 additions & 12 deletions resset/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ import (
// implementations.
type Action uint16

// IsSubsetOf returns wether all bits in p are set in other.
func (a Action) IsSubsetOf(other Action) bool {
return a&other == a
}

// Remove returns the bits in p but not other
func (a Action) Remove(other Action) Action {
return (a & other) ^ a
}

const (
// ActionRead indicates reading attributes of the specified objects.
ActionRead Action = 1 << iota
Expand Down Expand Up @@ -131,8 +121,8 @@ func (c *Action) Prohibits(a macaroon.Access) error {
switch {
case !ok:
return macaroon.ErrInvalidAccess
case !rsa.GetAction().IsSubsetOf(*c):
return fmt.Errorf("%w access %s (%s not allowed)", ErrUnauthorizedForAction, rsa.GetAction(), rsa.GetAction().Remove(*c))
case !IsSubsetOf(rsa.GetAction(), *c):
return fmt.Errorf("%w access %s (%s not allowed)", ErrUnauthorizedForAction, rsa.GetAction(), Remove(rsa.GetAction(), *c))
default:
return nil
}
Expand Down
Loading

0 comments on commit f04e4cb

Please sign in to comment.