github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/k8sclient/cani.go (about) 1 package k8sclient 2 3 import ( 4 "context" 5 "fmt" 6 7 v1 "k8s.io/api/authorization/v1" 8 meta "k8s.io/apimachinery/pkg/apis/meta/v1" 9 10 "github.com/datawire/dlib/dlog" 11 "github.com/datawire/k8sapi/pkg/k8sapi" 12 ) 13 14 func CanI(ctx context.Context, ra *v1.ResourceAttributes) (bool, error) { 15 authHandler := k8sapi.GetK8sInterface(ctx).AuthorizationV1().SelfSubjectAccessReviews() 16 review := v1.SelfSubjectAccessReview{Spec: v1.SelfSubjectAccessReviewSpec{ResourceAttributes: ra}} 17 ar, err := authHandler.Create(ctx, &review, meta.CreateOptions{}) 18 if err == nil && ar.Status.Allowed { 19 return true, nil 20 } 21 where := "" 22 if ra.Namespace != "" { 23 where = " in namespace " + ra.Namespace 24 } 25 if err != nil { 26 err = fmt.Errorf(`unable to do "can-i %s %s%s": %v`, ra.Verb, ra.Resource, where, err) 27 if ctx.Err() == nil { 28 dlog.Error(ctx, err) 29 } 30 } else { 31 dlog.Infof(ctx, `"can-i %s %s%s" is not allowed`, ra.Verb, ra.Resource, where) 32 } 33 return false, err 34 } 35 36 // CanWatchNamespaces answers the question if this client has the RBAC permissions necessary 37 // to watch namespaces. The answer is likely false when using a namespaces scoped installation. 38 func CanWatchNamespaces(ctx context.Context) bool { 39 ok, err := CanI(ctx, &v1.ResourceAttributes{ 40 Verb: "watch", 41 Resource: "namespaces", 42 }) 43 return err == nil && ok 44 } 45 46 // CanPortForward answers the question if this client has the RBAC permissions necessary 47 // to perform a port-forward to the connected namespace. 48 func CanPortForward(ctx context.Context, namespace string) bool { 49 ok, err := CanI(ctx, &v1.ResourceAttributes{ 50 Verb: "create", 51 Resource: "pods", 52 Subresource: "portforward", 53 Namespace: namespace, 54 }) 55 return err == nil && ok 56 }