Skip to content

Commit

Permalink
feat: resolve review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Soumya Ghosh Dastidar <[email protected]>
  • Loading branch information
gdsoumya committed Jul 12, 2023
1 parent e103a6a commit 05917b9
Showing 1 changed file with 43 additions and 25 deletions.
68 changes: 43 additions & 25 deletions pkg/cache/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
authType1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/pager"
Expand Down Expand Up @@ -477,10 +475,6 @@ func (c *clusterCache) startMissingWatches() error {
if err != nil {
return err
}
clientset, err := kubernetes.NewForConfig(c.config)
if err != nil {
return err
}
namespacedResources := make(map[schema.GroupKind]bool)
for i := range apis {
api := apis[i]
Expand All @@ -491,10 +485,14 @@ func (c *clusterCache) startMissingWatches() error {

err := c.processApi(client, api, func(resClient dynamic.ResourceInterface, ns string) error {
resourceVersion, err := c.loadInitialState(ctx, api, resClient, ns)
if err != nil && c.respectRBAC != RespectRbacDisabled && (k8sErrors.IsForbidden(err) || k8sErrors.IsUnauthorized(err)) {
if err != nil && c.isRestrictedResource(err) {
keep := false
if c.respectRBAC == RespectRbacStrict {
k, permErr := c.checkPermission(ctx, clientset.AuthorizationV1().SelfSubjectAccessReviews(), api)
k, permErr := c.checkPermission(ctx, client.Resource(schema.GroupVersionResource{
Group: "authorization.k8s.io",
Version: "v1",
Resource: "SelfSubjectAccessReviews",
}), api)
if permErr != nil {
return fmt.Errorf("failed to check permissions for resource %s: %w, original error=%v", api.GroupKind.String(), permErr, err.Error())
}
Expand Down Expand Up @@ -741,16 +739,26 @@ func (c *clusterCache) processApi(client dynamic.Interface, api kube.APIResource
return nil
}

// isRestrictedResource checks if the kube api call is unauthorized or forbidden
func (c *clusterCache) isRestrictedResource(err error) bool {
c.log.Info("checkingggg restrictedddd")
return c.respectRBAC != RespectRbacDisabled && (k8sErrors.IsForbidden(err) || k8sErrors.IsUnauthorized(err))
}

// checkPermission runs a self subject access review to check if the controller has permissions to list the resource
func (c *clusterCache) checkPermission(ctx context.Context, reviewInterface authType1.SelfSubjectAccessReviewInterface, api kube.APIResourceInfo) (keep bool, err error) {
sar := &authorizationv1.SelfSubjectAccessReview{
func (c *clusterCache) checkPermission(ctx context.Context, reviewInterface dynamic.ResourceInterface, api kube.APIResourceInfo) (keep bool, err error) {
c.log.Info("checkingggg permmm")
sar, err := kube.ToUnstructured(&authorizationv1.SelfSubjectAccessReview{
Spec: authorizationv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &authorizationv1.ResourceAttributes{
Namespace: "*",
Verb: "list", // uses list verb to check for permissions
Resource: api.GroupVersionResource.Resource,
},
},
})
if err != nil {
return false, err
}

switch {
Expand All @@ -760,23 +768,33 @@ func (c *clusterCache) checkPermission(ctx context.Context, reviewInterface auth
if err != nil {
return true, err
}
if resp != nil && resp.Status.Allowed {
return true, nil
if resp != nil {
allowed, ok, err := unstructured.NestedBool(resp.Object, "status", "allowed")
if err != nil || !ok {
return true, fmt.Errorf("failed to read self subject access review response, err: %v", err)
}
return allowed, nil
} else {
// unsupported, remove from watch list
return false, nil
}
// unsupported, remove from watch list
return false, nil
// if manage some namespaces and resource is namespaced
case len(c.namespaces) != 0 && api.Meta.Namespaced:
for _, ns := range c.namespaces {
sar.Spec.ResourceAttributes.Namespace = ns
if err := unstructured.SetNestedField(sar.Object, ns, "spec", "resourceAttributes", "namespace"); err != nil {
return false, err
}
resp, err := reviewInterface.Create(ctx, sar, metav1.CreateOptions{})
if err != nil {
return true, err
return false, err
}
if resp != nil && resp.Status.Allowed {
return true, nil
if resp != nil {
allowed, ok, err := unstructured.NestedBool(resp.Object, "status", "allowed")
if err != nil || !ok {
return true, fmt.Errorf("failed to read self subject access review response, err: %v", err)
}
return allowed, nil
} else {
// unsupported, remove from watch list
return false, nil
}
}
Expand Down Expand Up @@ -832,10 +850,6 @@ func (c *clusterCache) sync() error {
if err != nil {
return err
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
lock := sync.Mutex{}
err = kube.RunAllAsync(len(apis), func(i int) error {
api := apis[i]
Expand All @@ -861,10 +875,14 @@ func (c *clusterCache) sync() error {
})
})
if err != nil {
if c.respectRBAC != RespectRbacDisabled && (k8sErrors.IsForbidden(err) || k8sErrors.IsUnauthorized(err)) {
if c.isRestrictedResource(err) {
keep := false
if c.respectRBAC == RespectRbacStrict {
k, permErr := c.checkPermission(ctx, clientset.AuthorizationV1().SelfSubjectAccessReviews(), api)
k, permErr := c.checkPermission(ctx, client.Resource(schema.GroupVersionResource{
Group: "authorization.k8s.io",
Version: "v1",
Resource: "SelfSubjectAccessReviews",
}), api)
if permErr != nil {
return fmt.Errorf("failed to check permissions for resource %s: %w, original error=%v", api.GroupKind.String(), permErr, err.Error())
}
Expand Down

0 comments on commit 05917b9

Please sign in to comment.