Skip to content
This repository was archived by the owner on Nov 14, 2024. It is now read-only.

Commit 575b134

Browse files
committed
chore: internal/rbac: address comment from #11
1 parent e4a32e0 commit 575b134

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

internal/checks/kube/rbac.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,29 @@ import (
2222
"k8s.io/kubectl/pkg/util/slice"
2323
)
2424

25+
var errSelfSubjectRulesReviewNotSupported = xerrors.New("cluster does not support SelfSubjectRulesReview")
26+
2527
// CheckRBAC checks the cluster for the RBAC permissions required by Coder.
2628
// It will attempt to first use a SelfSubjectRulesReview to determine the capabilities
2729
// of the user. If this fails (notably on GKE), fall back to using SelfSubjectAccessRequests
2830
// which is slower but is more likely to work.
2931
func (k *KubernetesChecker) CheckRBAC(ctx context.Context) []*api.CheckResult {
30-
if ssrrResults := k.checkRBACDefault(ctx); ssrrResults != nil {
32+
ssrrResults, err := k.checkRBACDefault(ctx)
33+
if err == nil {
3134
return ssrrResults
3235
}
3336

34-
k.log.Warn(ctx, "SelfSubjectRulesReview response incomplete, falling back to SelfSubjectAccessRequests (slow)")
35-
return k.checkRBACFallback(ctx)
37+
if xerrors.Is(err, errSelfSubjectRulesReviewNotSupported) {
38+
// In this case, we should fall back to using SelfSubjectAccessRequests.
39+
k.log.Warn(ctx, "unable to check via SelfSubjectRulesReview, falling back to SelfSubjectAccessRequests (slow)")
40+
return k.checkRBACFallback(ctx)
41+
}
42+
43+
// something else went wrong
44+
return []*api.CheckResult{api.ErrorResult("kubernetes-rbac", "unable to check rbac", err)}
3645
}
3746

38-
func (k *KubernetesChecker) checkRBACDefault(ctx context.Context) []*api.CheckResult {
47+
func (k *KubernetesChecker) checkRBACDefault(ctx context.Context) ([]*api.CheckResult, error) {
3948
const checkName = "kubernetes-rbac-ssrr"
4049
authClient := k.client.AuthorizationV1()
4150
results := make([]*api.CheckResult, 0)
@@ -48,11 +57,11 @@ func (k *KubernetesChecker) checkRBACDefault(ctx context.Context) []*api.CheckRe
4857

4958
response, err := authClient.SelfSubjectRulesReviews().Create(ctx, sar, metav1.CreateOptions{})
5059
if err != nil {
51-
return []*api.CheckResult{api.SkippedResult(checkName, "unable to create SelfSubjectRulesReview request ", err)}
60+
return nil, xerrors.Errorf("create SelfSubjectRulesReview: %w", err)
5261
}
5362

5463
if response.Status.Incomplete {
55-
return nil // In this case, we should fall back to using SelfSubjectAccessRequests.
64+
return nil, errSelfSubjectRulesReviewNotSupported
5665
}
5766

5867
// convert the list of rules from the server to PolicyRules and dedupe/compact
@@ -97,7 +106,7 @@ func (k *KubernetesChecker) checkRBACDefault(ctx context.Context) []*api.CheckRe
97106
results = append(results, api.PassResult(checkName, summary))
98107
}
99108

100-
return results
109+
return results, nil
101110
}
102111

103112
func satisfies(req *ResourceRequirement, verbs ResourceVerbs, rules []rbacv1.PolicyRule) error {

internal/checks/kube/rbac_test.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ import (
1515
"github.com/cdr/coder-doctor/internal/api"
1616
)
1717

18+
func Test_CheckRBAC_Error(t *testing.T) {
19+
t.Parallel()
20+
21+
srv := newTestHTTPServer(t, 500, nil)
22+
defer srv.Close()
23+
client, err := kubernetes.NewForConfig(&rest.Config{Host: srv.URL})
24+
assert.Success(t, "failed to create client", err)
25+
26+
checker := NewKubernetesChecker(client)
27+
results := checker.CheckRBAC(context.Background())
28+
assert.True(t, "should contain one result", len(results) == 1)
29+
assert.True(t, "result should be failed", results[0].State == api.StateFailed)
30+
}
1831
func Test_CheckRBACFallback(t *testing.T) {
1932
t.Parallel()
2033

@@ -99,15 +112,16 @@ func Test_CheckRBACDefault(t *testing.T) {
99112
tests := []struct {
100113
Name string
101114
Response *authorizationv1.SelfSubjectRulesReview
102-
F func(*testing.T, []*api.CheckResult)
115+
TestFunc func(*testing.T, []*api.CheckResult, error)
103116
}{
104117
{
105118
Name: "nothing allowed",
106119
Response: &selfSubjectRulesReviewEmpty,
107-
F: func(t *testing.T, results []*api.CheckResult) {
120+
TestFunc: func(t *testing.T, results []*api.CheckResult, err error) {
108121
assert.False(t, "results should not be empty", len(results) == 0)
109122
for _, result := range results {
110-
assert.True(t, result.Name+" should have an error", result.Details["error"] != nil)
123+
assert.True(t, result.Name+" should not return an error", err == nil)
124+
assert.True(t, result.Name+" should contain an error in details", result.Details["error"] != nil)
111125
assert.True(t, result.Name+" should fail", result.State == api.StateFailed)
112126
}
113127
},
@@ -126,16 +140,16 @@ func Test_CheckRBACDefault(t *testing.T) {
126140
assert.Success(t, "failed to create client", err)
127141

128142
checker := NewKubernetesChecker(client)
129-
results := checker.checkRBACDefault(context.Background())
130-
test.F(t, results)
143+
results, err := checker.checkRBACDefault(context.Background())
144+
test.TestFunc(t, results, err)
131145
})
132146
}
133147
}
134148

135149
func Test_Satisfies(t *testing.T) {
136150
t.Parallel()
137151

138-
testCases := []struct {
152+
tests := []struct {
139153
Name string
140154
Requirement *ResourceRequirement
141155
Verbs ResourceVerbs
@@ -209,14 +223,14 @@ func Test_Satisfies(t *testing.T) {
209223
// TODO(cian): add many, many, more.
210224
}
211225

212-
for _, testCase := range testCases {
213-
testCase := testCase
214-
t.Run(testCase.Name, func(t *testing.T) {
215-
actual := satisfies(testCase.Requirement, testCase.Verbs, testCase.Rules)
216-
if testCase.Expected == nil {
217-
assert.Success(t, testCase.Name+"- should not error", actual)
226+
for _, test := range tests {
227+
test := test
228+
t.Run(test.Name, func(t *testing.T) {
229+
actual := satisfies(test.Requirement, test.Verbs, test.Rules)
230+
if test.Expected == nil {
231+
assert.Success(t, test.Name+"- should not error", actual)
218232
} else {
219-
assert.ErrorContains(t, testCase.Name+" - expected error contains", actual, *testCase.Expected)
233+
assert.ErrorContains(t, test.Name+" - expected error contains", actual, *test.Expected)
220234
}
221235
})
222236
}

0 commit comments

Comments
 (0)