Skip to content

Commit c4ee590

Browse files
committed
test: Unit test permission string
- Add some docs
1 parent def010f commit c4ee590

File tree

9 files changed

+89
-7
lines changed

9 files changed

+89
-7
lines changed

coderd/authz/authz_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package authz_test
22

33
import (
4-
"github.com/coder/coder/coderd/authz"
5-
"github.com/coder/coder/coderd/authz/authztest"
64
"math/bits"
75
"strings"
86
"testing"
7+
8+
"github.com/coder/coder/coderd/authz"
9+
"github.com/coder/coder/coderd/authz/authztest"
910
)
1011

1112
var nilSet = authztest.Set{nil}

coderd/authz/authztest/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Authztest
2+
3+
An authz permission is a combination of `level`, `resource_type`, `resource_id`, and action`. For testing purposes, we can assume only 1 action and resource exists. This package can generate all possible permissions from this.
4+
5+
A `Set` is a slice of permissions. The search space of all possible sets is too large, so instead this package allows generating more meaningful sets for testing. This is equivalent to pruning in AI problems: a technique to reduce the size of the search space by removing parts that do not have significance.
6+
7+
This is the final pruned search space used in authz. Each set is represented by a ✅, ❌, or ⛶. The leftmost set in a row that is not '⛶' is the impactful set. The impactful set determines the access result. All other sets are non-impactful, and should include the `<nil>` permission. The resulting search space for a row is the cross product between all sets in said row.
8+
9+
| Row | * | Site | Org | Org:mem | User | Access |
10+
|-----|------|------|------|---------|------|--------|
11+
| W+ | ✅⛶ | ✅❌⛶ | ✅❌⛶ | ✅❌⛶ | ✅❌⛶ ||
12+
| W- | ❌+✅⛶ | ✅❌⛶ | ✅❌⛶ | ✅❌⛶ | ✅❌⛶ ||
13+
| S+ || ✅⛶ | ✅❌⛶ | ❌✅⛶ | ❌✅⛶ ||
14+
| S- || ❌+✅⛶ | ✅❌⛶ | ❌✅⛶ | ❌✅⛶ ||
15+
| O+ ||| ✅⛶ | ❌✅⛶ | ❌✅⛶ ||
16+
| O- ||| ❌+✅⛶ | ❌✅⛶ | ❌✅⛶ ||
17+
| M+ |||| ✅⛶ | ❌✅⛶ ||
18+
| M- |||| ❌+✅⛶ | ❌✅⛶ ||
19+
| U+ ||||| ✅⛶ ||
20+
| U- ||||| ❌+✅⛶ ||
21+
| A+ ||||| ✅+⛶ ||
22+
| A- |||||||
23+

coderd/authz/authztest/doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package authztest is a helper package for generating permissions to test the authz library.
2+
package authztest

coderd/authz/authztest/iterator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Iterator interface {
1818
Size() int
1919
}
2020

21-
// unionIterator is very primitive, just used to hold a place in a set.
21+
// unionIterator is used to merge sets, or a union in set theory.
2222
type unionIterator struct {
2323
// setIdx determines which set the offset is for
2424
setIdx int

coderd/authz/authztest/role.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import (
44
"github.com/coder/coder/coderd/authz"
55
)
66

7-
// Role can print all possible permutations of the given iterators.
7+
// Role can print all possible permutations of the given iterators. It represents
8+
// the cross product between all sets given.
89
type Role struct {
910
// returnSize is how many permissions are the returned set for the role
1011
returnSize int
1112
// N is the total number of permutations of sets this role will produce.
1213
N int
1314
PermissionSets []Iterator
14-
// This is kinda werird, but the first scan should not move anything.
15+
// This is kinda weird, but the first scan should not move anything.
1516
first bool
1617

1718
buffer []*authz.Permission

coderd/authz/authztest/set_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package authztest_test
22

33
import (
4-
"github.com/coder/coder/coderd/authz"
5-
"github.com/coder/coder/coderd/authz/authztest"
64
"testing"
75

6+
"github.com/coder/coder/coderd/authz"
7+
"github.com/coder/coder/coderd/authz/authztest"
88
crand "github.com/coder/coder/cryptorand"
99
"github.com/stretchr/testify/require"
1010
)

coderd/authz/object.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var _ OrgResource = (*zObject)(nil)
2323
// hand to run the check on.
2424
// An example is if you want to list all workspaces, you can create a zObject
2525
// that represents the set of workspaces you are trying to get access too.
26+
// Do not export this type, as it can be created from a resource type constant.
2627
type zObject struct {
2728
ObjectID string `json:"object_id"`
2829
OwnedBy string `json:"owner_id"`

coderd/authz/permission_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,65 @@
11
package authz_test
22

33
import (
4+
"github.com/stretchr/testify/require"
45
"testing"
56

67
"github.com/coder/coder/coderd/authz"
78
crand "github.com/coder/coder/cryptorand"
89
)
910

11+
func Test_PermissionString(t *testing.T) {
12+
testCases := []struct {
13+
Name string
14+
Permission authz.Permission
15+
Expected string
16+
}{
17+
{
18+
Name: "BasicPositive",
19+
Permission: authz.Permission{
20+
Sign: true,
21+
Level: authz.LevelSite,
22+
LevelID: "",
23+
ResourceType: authz.ResourceWorkspace,
24+
ResourceID: "*",
25+
Action: authz.ActionRead,
26+
},
27+
Expected: "+site.workspace.*.read",
28+
},
29+
{
30+
Name: "BasicNegative",
31+
Permission: authz.Permission{
32+
Sign: false,
33+
Level: authz.LevelUser,
34+
LevelID: "",
35+
ResourceType: authz.ResourceDevURL,
36+
ResourceID: "1234",
37+
Action: authz.ActionWrite,
38+
},
39+
Expected: "-user.devurl.1234.write",
40+
},
41+
{
42+
Name: "OrgID",
43+
Permission: authz.Permission{
44+
Sign: false,
45+
Level: authz.LevelOrg,
46+
LevelID: "default",
47+
ResourceType: authz.ResourceProject,
48+
ResourceID: "456",
49+
Action: authz.ActionModify,
50+
},
51+
Expected: "-org:default.project.456.modify",
52+
},
53+
}
54+
55+
for _, c := range testCases {
56+
t.Run(c.Name, func(t *testing.T) {
57+
require.Equal(t, c.Expected, c.Permission.String())
58+
})
59+
}
60+
61+
}
62+
1063
func BenchmarkPermissionString(b *testing.B) {
1164
total := 10000
1265
if b.N < total {

coderd/authz/subject.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type Subject interface {
2222

2323
// SubjectTODO is a placeholder until we get an actual actor struct in place.
2424
// This will come with the Authn epic.
25+
// TODO: @emyrk delete this data structure when authn exists
2526
type SubjectTODO struct {
2627
UserID string `json:"user_id"`
2728

0 commit comments

Comments
 (0)