Skip to content

Commit b6c3305

Browse files
authored
Detect cycles in check functions (#57)
* Add cycle detection to check/check_relation/check_permission * Use protobuf helpers from go-directory/pkg/pb
1 parent 0f76237 commit b6c3305

File tree

14 files changed

+47
-104
lines changed

14 files changed

+47
-104
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/Masterminds/semver v1.5.0
1010
github.com/aserto-dev/azm v0.0.15
1111
github.com/aserto-dev/errors v0.0.6
12-
github.com/aserto-dev/go-directory v0.30.3
12+
github.com/aserto-dev/go-directory v0.30.4
1313
github.com/bufbuild/protovalidate-go v0.4.0
1414
github.com/gonvenience/ytbx v1.4.4
1515
github.com/google/uuid v1.4.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ github.com/aserto-dev/azm v0.0.15 h1:GO222vhAfcEeJJBTuWJBHNm1lIMA6qxkFjiVHN5pPeo
1212
github.com/aserto-dev/azm v0.0.15/go.mod h1:oNNvPYysttO/otHryQDm6u71jAt/Qhs9izhrde7HlD0=
1313
github.com/aserto-dev/errors v0.0.6 h1:iH5fkJwBGFPbcdS4B8mwvNdwODlhDEXXPduZtjLh6vo=
1414
github.com/aserto-dev/errors v0.0.6/go.mod h1:kenI1gamsemaR2wS+M2un0kXIJ9exTrmeRT/fCFwlWc=
15-
github.com/aserto-dev/go-directory v0.30.3 h1:agzqBvC1biaJUBzkJYCqUiKnmNXRQ67JVlxlLFsxu2c=
16-
github.com/aserto-dev/go-directory v0.30.3/go.mod h1:jHn6ckERuci6nWz9vCzAbYoF2UnbOwEzl++sA1L3nyc=
15+
github.com/aserto-dev/go-directory v0.30.4 h1:MifQgaA2ino54mWcmJAbJZSmUPNqat0V/u60EpFd9Vs=
16+
github.com/aserto-dev/go-directory v0.30.4/go.mod h1:jHn6ckERuci6nWz9vCzAbYoF2UnbOwEzl++sA1L3nyc=
1717
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
1818
github.com/bufbuild/protovalidate-go v0.4.0 h1:ModSkCLEW07fiyGtdtMXKY+Gz3oPFKSfiaSCgL+FtpU=
1919
github.com/bufbuild/protovalidate-go v0.4.0/go.mod h1:QqeUPLVYEKQc+/rkoUXFqXW03zPBfrEfIbX+zmA0VxA=

pkg/bdb/generic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"context"
66
"encoding/json"
77

8-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
8+
"github.com/aserto-dev/go-directory/pkg/pb"
99
bolt "go.etcd.io/bbolt"
1010
"google.golang.org/protobuf/proto"
1111
)

pkg/bdb/migrate/mig001/migrate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"time"
66

77
"github.com/Masterminds/semver"
8+
"github.com/aserto-dev/go-directory/pkg/pb"
89
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
910
"github.com/aserto-dev/go-edge-ds/pkg/bdb/metadata"
1011
"github.com/aserto-dev/go-edge-ds/pkg/bdb/migrate/mig"
11-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1212
"github.com/rs/zerolog"
1313
bolt "go.etcd.io/bbolt"
1414
"google.golang.org/protobuf/types/known/timestamppb"

pkg/bdb/migrate/mig002/migrate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import (
66
"os"
77

88
dsc2 "github.com/aserto-dev/go-directory/aserto/directory/common/v2"
9+
"github.com/aserto-dev/go-directory/pkg/pb"
910
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
1011
"github.com/aserto-dev/go-edge-ds/pkg/bdb/migrate/mig"
1112
"github.com/aserto-dev/go-edge-ds/pkg/ds"
12-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1313
"github.com/rs/zerolog"
1414

1515
"github.com/Masterminds/semver"

pkg/directory/v3/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import (
1212
dsm3 "github.com/aserto-dev/go-directory/aserto/directory/model/v3"
1313
"github.com/aserto-dev/go-directory/pkg/derr"
1414
"github.com/aserto-dev/go-directory/pkg/gateway/model/v3"
15+
"github.com/aserto-dev/go-directory/pkg/pb"
1516
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
1617
"github.com/aserto-dev/go-edge-ds/pkg/ds"
17-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1818

1919
"github.com/bufbuild/protovalidate-go"
2020
"github.com/pkg/errors"

pkg/directory/v3/reader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (s *Reader) CheckPermission(ctx context.Context, req *dsr3.CheckPermissionR
303303
return resp, err
304304
}
305305

306-
// CheckRelation, check if subject is permitted to access resource (object).
306+
// CheckRelation, check if subject has the specified relation to a resource (object).
307307
func (s *Reader) CheckRelation(ctx context.Context, req *dsr3.CheckRelationRequest) (*dsr3.CheckRelationResponse, error) {
308308
resp := &dsr3.CheckRelationResponse{}
309309

pkg/ds/check.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55

66
"github.com/aserto-dev/azm/cache"
77
"github.com/aserto-dev/azm/model"
8+
"github.com/aserto-dev/go-directory/pkg/pb"
89
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
9-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1010

1111
dsc3 "github.com/aserto-dev/go-directory/aserto/directory/common/v3"
1212
dsr3 "github.com/aserto-dev/go-directory/aserto/directory/reader/v3"
@@ -99,11 +99,18 @@ func (i *check) newChecker(ctx context.Context, tx *bolt.Tx, path []string, mc *
9999
filter: relations,
100100
trace: [][]*dsc3.Relation{},
101101
mc: mc,
102+
visited: map[ot]bool{},
102103
}
103104

104105
return checker, nil
105106
}
106107

108+
// value type to be used as a key in a map.
109+
type ot struct {
110+
ObjectType string
111+
ObjectID string
112+
}
113+
107114
type checker struct {
108115
ctx context.Context
109116
tx *bolt.Tx
@@ -113,6 +120,7 @@ type checker struct {
113120
filter []model.RelationName
114121
trace [][]*dsc3.Relation
115122
mc *cache.Cache
123+
visited map[ot]bool
116124
}
117125

118126
func (c *checker) check(root *dsc3.ObjectIdentifier) (bool, error) {
@@ -123,14 +131,16 @@ func (c *checker) check(root *dsc3.ObjectIdentifier) (bool, error) {
123131
return false, err
124132
}
125133

134+
c.visited[ot{ObjectType: root.ObjectType, ObjectID: root.ObjectId}] = true
135+
126136
for _, r := range relations {
127137
if c.isMatch(r) {
128138
return true, nil
129139
}
130140
}
131141

132142
for _, r := range relations {
133-
if lo.Contains(c.filter, model.RelationName(r.Relation)) {
143+
if c.isCandidate(r) {
134144
match, err := c.check(Relation(r).Subject())
135145
if err != nil {
136146
return false, err
@@ -146,8 +156,11 @@ func (c *checker) check(root *dsc3.ObjectIdentifier) (bool, error) {
146156
}
147157

148158
func (c *checker) isMatch(relation *dsc3.Relation) bool {
149-
if lo.Contains(c.filter, model.RelationName(relation.Relation)) && pb.Contains[*dsc3.ObjectIdentifier](c.userSet, Relation(relation).Subject()) {
150-
return true
151-
}
152-
return false
159+
return lo.Contains(c.filter, model.RelationName(relation.Relation)) &&
160+
pb.Contains(c.userSet, Relation(relation).Subject())
161+
}
162+
163+
func (c *checker) isCandidate(r *dsc3.Relation) bool {
164+
return lo.Contains(c.filter, model.RelationName(r.Relation)) &&
165+
!c.visited[ot{ObjectType: r.SubjectType, ObjectID: r.SubjectId}]
153166
}

pkg/ds/check_permission.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"github.com/aserto-dev/azm/model"
88
dsc3 "github.com/aserto-dev/go-directory/aserto/directory/common/v3"
99
dsr3 "github.com/aserto-dev/go-directory/aserto/directory/reader/v3"
10+
"github.com/aserto-dev/go-directory/pkg/pb"
1011
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
11-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1212

1313
"github.com/samber/lo"
1414
bolt "go.etcd.io/bbolt"
@@ -87,6 +87,7 @@ func (i *checkPermission) newChecker(ctx context.Context, tx *bolt.Tx, path []st
8787
userSet: userSet,
8888
filter: relations,
8989
trace: [][]*dsc3.Relation{},
90+
visited: map[ot]bool{},
9091
}, nil
9192
}
9293

@@ -98,6 +99,7 @@ type permissionChecker struct {
9899
userSet []*dsc3.ObjectIdentifier
99100
filter []model.RelationName
100101
trace [][]*dsc3.Relation
102+
visited map[ot]bool
101103
}
102104

103105
func (c *permissionChecker) check(root *dsc3.ObjectIdentifier) (bool, error) {
@@ -108,14 +110,16 @@ func (c *permissionChecker) check(root *dsc3.ObjectIdentifier) (bool, error) {
108110
return false, err
109111
}
110112

113+
c.visited[ot{root.ObjectType, root.ObjectId}] = true
114+
111115
for _, r := range relations {
112116
if c.isMatch(r) {
113117
return true, nil
114118
}
115119
}
116120

117121
for _, r := range relations {
118-
if lo.Contains(c.filter, model.RelationName(r.Relation)) || r.Relation == "parent" {
122+
if c.isCandidate(r) {
119123
match, err := c.check(Relation(r).Subject())
120124
if err != nil {
121125
return false, err
@@ -136,3 +140,8 @@ func (c *permissionChecker) isMatch(relation *dsc3.Relation) bool {
136140
}
137141
return false
138142
}
143+
144+
func (c *permissionChecker) isCandidate(r *dsc3.Relation) bool {
145+
return (lo.Contains(c.filter, model.RelationName(r.Relation)) || r.Relation == "parent") &&
146+
!c.visited[ot{r.SubjectType, r.SubjectId}]
147+
}

pkg/ds/check_relation.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"github.com/aserto-dev/azm/model"
88
dsc3 "github.com/aserto-dev/go-directory/aserto/directory/common/v3"
99
dsr3 "github.com/aserto-dev/go-directory/aserto/directory/reader/v3"
10+
"github.com/aserto-dev/go-directory/pkg/pb"
1011
"github.com/aserto-dev/go-edge-ds/pkg/bdb"
11-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
1212

1313
"github.com/samber/lo"
1414
bolt "go.etcd.io/bbolt"
@@ -87,6 +87,7 @@ func (i *checkRelation) newChecker(ctx context.Context, tx *bolt.Tx, path []stri
8787
userSet: userSet,
8888
filter: relations,
8989
trace: [][]*dsc3.Relation{},
90+
visited: map[ot]bool{},
9091
}, nil
9192
}
9293

@@ -98,6 +99,7 @@ type relationChecker struct {
9899
userSet []*dsc3.ObjectIdentifier
99100
filter []model.RelationName
100101
trace [][]*dsc3.Relation
102+
visited map[ot]bool
101103
}
102104

103105
func (c *relationChecker) check(root *dsc3.ObjectIdentifier) (bool, error) {
@@ -115,7 +117,7 @@ func (c *relationChecker) check(root *dsc3.ObjectIdentifier) (bool, error) {
115117
}
116118

117119
for _, r := range relations {
118-
if lo.Contains(c.filter, model.RelationName(r.Relation)) {
120+
if c.isCandidate(r) {
119121
match, err := c.check(Relation(r).Subject())
120122
if err != nil {
121123
return false, err
@@ -136,3 +138,7 @@ func (c *relationChecker) isMatch(relation *dsc3.Relation) bool {
136138
}
137139
return false
138140
}
141+
142+
func (c *relationChecker) isCandidate(r *dsc3.Relation) bool {
143+
return lo.Contains(c.filter, model.RelationName(r.Relation)) && !c.visited[ot{r.SubjectType, r.SubjectId}]
144+
}

pkg/ds/object.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/aserto-dev/azm/model"
1010
dsc3 "github.com/aserto-dev/go-directory/aserto/directory/common/v3"
1111
"github.com/aserto-dev/go-directory/pkg/derr"
12-
"github.com/aserto-dev/go-edge-ds/pkg/pb"
12+
"github.com/aserto-dev/go-directory/pkg/pb"
1313

1414
"github.com/mitchellh/hashstructure/v2"
1515
)

pkg/pb/generic.go

Lines changed: 0 additions & 12 deletions
This file was deleted.

pkg/pb/pb.go

Lines changed: 0 additions & 65 deletions
This file was deleted.

pkg/pb/struct.go

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)