Files
troubleshoot/pkg/supportbundle/rbac.go
Diamon Wiggins 06506ed95d Fix remote host collection RBAC checks (#1672)
* fix remote host collection rbac checks

* move saveNodeList into collectRemoteHost function

* fix resource attribute list and retrieve namespace from kubeconfig

* revert change to set a default namespace from kubeconfig

* remove duplicate code
2024-11-07 10:07:27 -05:00

114 lines
2.5 KiB
Go

package supportbundle
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/pkg/collect"
authorizationv1 "k8s.io/api/authorization/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
// Custom error type for RBAC permission errors
type RBACPermissionError struct {
Forbidden []error
}
func (e *RBACPermissionError) Error() string {
return fmt.Sprintf("insufficient permissions: %v", e.Forbidden)
}
func (e *RBACPermissionError) HasErrors() bool {
return len(e.Forbidden) > 0
}
// checkRBAC checks if the current user has the necessary permissions to run the collectors
func checkRemoteCollectorRBAC(ctx context.Context, clientConfig *rest.Config, title string, namespace string) error {
client, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return errors.Wrap(err, "failed to create client from config")
}
var forbidden []error
resourceAttributesList := []authorizationv1.ResourceAttributes{
{
Namespace: namespace,
Verb: "get",
Resource: "pods",
},
{
Namespace: namespace,
Verb: "create",
Resource: "pods",
},
{
Namespace: namespace,
Verb: "delete",
Resource: "pods",
},
{
Namespace: namespace,
Verb: "get",
Resource: "pods/log",
},
{
Verb: "list",
Resource: "nodes",
},
{
Namespace: namespace,
Verb: "get",
Resource: "configmaps",
},
{
Namespace: namespace,
Verb: "create",
Resource: "configmaps",
},
{
Namespace: namespace,
Verb: "delete",
Resource: "configmaps",
},
{
Namespace: namespace,
Verb: "get",
Resource: "serviceaccounts",
},
}
for _, resourceAttributes := range resourceAttributesList {
spec := authorizationv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &resourceAttributes,
}
sar := &authorizationv1.SelfSubjectAccessReview{
Spec: spec,
}
resp, err := client.AuthorizationV1().SelfSubjectAccessReviews().Create(ctx, sar, metav1.CreateOptions{})
if err != nil {
return errors.Wrap(err, "failed to run subject review")
}
if !resp.Status.Allowed {
forbidden = append(forbidden, collect.RBACError{
DisplayName: title,
Namespace: spec.ResourceAttributes.Namespace,
Resource: spec.ResourceAttributes.Resource,
Verb: spec.ResourceAttributes.Verb,
})
}
}
if len(forbidden) > 0 {
return &RBACPermissionError{Forbidden: forbidden}
}
return nil
}