-
Notifications
You must be signed in to change notification settings - Fork 3
feature: use SelfSubjectRulesReview for RBAC, fallback to SelfSubjectAccessRequest #11
Conversation
This pull request has been linked to Clubhouse Story #15962: Checks for required cluster API resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your awesome work with this. I left some minor comments but none of them are blocking, we can merge and iterate. 👍
@@ -11,5 +11,5 @@ require ( | |||
k8s.io/apimachinery v0.19.14 | |||
k8s.io/client-go v0.19.14 | |||
k8s.io/klog/v2 v2.10.0 // indirect | |||
k8s.io/utils v0.0.0-20210305010621-2afb4311ab10 // indirect | |||
k8s.io/kubectl v0.19.14 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: tough call, seems we're either:
- doing something upstream tells us not to do (import kubectl); or
- signing on to maintain a copy of some code
Maybe this one in particular is OK and it's just stuff in k/k that we shouldn't import:
To use Kubernetes code as a library in other applications, see the list of published components. Use of the k8s.io/kubernetes module or k8s.io/kubernetes/... packages as libraries is not supported.
I'm unsure and inclined to just merge what you have 🤷♂️
|
||
test/go: | ||
@echo "--- go test" | ||
go test -parallel=$(shell nproc) ./... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: use go test -parallel ./...
I believe go test -parallel
(no options) should auto-detect available processors, per go help testflag
:
-parallel n
Allow parallel execution of test functions that call t.Parallel.
The value of this flag is the maximum number of tests to run
simultaneously; by default, it is set to the value of GOMAXPROCS.
Note that -parallel only applies within a single test binary.
The 'go test' command may run tests for different packages
in parallel as well, according to the setting of the -p flag
(see 'go help build')
in the future, we might want to consider using gotestsum as the output is nicer
|
||
response, err := authClient.SelfSubjectRulesReviews().Create(ctx, sar, metav1.CreateOptions{}) | ||
if err != nil { | ||
return []*api.CheckResult{api.SkippedResult(checkName, "unable to create SelfSubjectRulesReview request: "+err.Error())} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: consider adding the error to the Details field, since it's structured data.
the longer-term idea is that someone should be able to submit an output log (JSON dump or something) of their CheckResult logs, and we should be able to ingest those into BigQuery or something as a form of cluster telemetry, to help guide our product decisions -- parsing text out is possible but I think it's better to avoid that
breakdownRules = append(breakdownRules, rbacutil.BreakdownRule(rule)...) | ||
} | ||
|
||
compactRules, _ := rbacutil.CompactRules(breakdownRules) //nolint:errcheck - err is always nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question/suggestion: is err always guaranteed by the API contract to be nil, or is that just the current implementation? if the latter, then I think we should still check, otherwise we can have panics if they change things later
it would seem unusual to me for them to return an error that is always guaranteed to be nil, but I'm not too familiar with this API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current implementation upstream always returns nil, weirdly enough 🤷
It's probably not guaranteed though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it's not guaranteed, then IMO we should check, otherwise it's just a ticking time bomb :)
|
||
compactRules, _ := rbacutil.CompactRules(breakdownRules) //nolint:errcheck - err is always nil | ||
sort.Stable(rbacutil.SortableRuleSlice(compactRules)) | ||
for _, r := range compactRules { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: I don't know if we can check if Debug logging is enabled; if not, we could avoid the for loop/method call overhead
tests := []struct { | ||
Name string | ||
Response *authorizationv1.SelfSubjectRulesReview | ||
F func(*testing.T, []*api.CheckResult) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: just a personal preference and maybe anathema to Go's philosophy, I think it's clearer to use full names for things instead of one-letter variables, e.g. CheckFunc
or something
F: func(t *testing.T, results []*api.CheckResult) { | ||
assert.False(t, "results should not be empty", len(results) == 0) | ||
for _, result := range results { | ||
assert.True(t, result.Name+" should have an error", result.Details["error"] != nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion/nitpick: we might want to consider a helper func that does this, similar to what we do in slog
}, | ||
} | ||
|
||
func strptr(s string) *string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kubernetes has a pointer.String() util for this
@@ -116,6 +116,9 @@ func run(cmd *cobra.Command, _ []string) error { | |||
} | |||
|
|||
currentContext := rawConfig.Contexts[rawConfig.CurrentContext] | |||
if currentContext.Namespace == "" { | |||
currentContext.Namespace = "default" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess Kubernetes doesn't do this automatically, for some reason?
I don't know if we have a default namespace, if we did I'd assume it to be coder
rather than default
, so if we need a namespace we might want to consider using coder
here?
// TODO(cian): add many, many, more. | ||
} | ||
|
||
for _, testCase := range testCases { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: personally I use tests
for the array and test
for the loop var, not a strong feeling, might be nice to be consistent
default
if unspecified.make test
target because I'm lazy and don't like typing.NOTES:
a) Yes, that is a dependency on
kubectl
. I'm happy to drop it if it means just copy-pasting a couple of utility functions.b) The way we check our own requirements against the SSRR PolicyRules is probably not optimal with regards to speed, but I figure we can worry about speeding it up later.