From e2748c7b24e9b0ed002c0850f89758bbf4361d4e Mon Sep 17 00:00:00 2001 From: Marc Campbell Date: Wed, 18 Dec 2019 19:46:02 +0000 Subject: [PATCH 1/2] RBAC --- pkg/collect/cluster_resources.go | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/pkg/collect/cluster_resources.go b/pkg/collect/cluster_resources.go index dbd04681..64bd1df3 100644 --- a/pkg/collect/cluster_resources.go +++ b/pkg/collect/cluster_resources.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/replicatedhq/troubleshoot/pkg/redact" + authorizationv1 "k8s.io/api/authorization/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1beta1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,6 +33,8 @@ type ClusterResourcesOutput struct { ImagePullSecretsErrors []byte `json:"cluster-resources/image-pull-secrets-errors.json,omitempty"` Nodes []byte `json:"cluster-resources/nodes.json,omitempty"` NodesErrors []byte `json:"cluster-resources/nodes-errors.json,omitempty"` + AuthCanI map[string][]byte `json:"cluster-resources/auth-cani-list,omitempty"` + AuthCanIErrors []byte `json:"cluster-resources/auth-cani-list-errors.json,omitempty"` } func ClusterResources(ctx *Context) ([]byte, error) { @@ -131,6 +134,14 @@ func ClusterResources(ctx *Context) ([]byte, error) { return nil, err } + // auth cani + authCanI, authCanIErrors := authCanI(client, namespaceNames) + clusterResourcesOutput.AuthCanI = authCanI + clusterResourcesOutput.AuthCanIErrors, err = marshalNonNil(authCanIErrors) + if err != nil { + return nil, err + } + if ctx.Redact { clusterResourcesOutput, err = clusterResourcesOutput.Redact() if err != nil { @@ -360,6 +371,71 @@ func nodes(client *kubernetes.Clientset) ([]byte, []string) { return b, nil } +func authCanI(client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) { + // https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/auth/cani.go + + authListByNamespace := make(map[string][]byte) + errorsByNamespace := make(map[string]string) + + for _, namespace := range namespaces { + fmt.Println(namespace) + sar := &authorizationv1.SelfSubjectRulesReview{ + Spec: authorizationv1.SelfSubjectRulesReviewSpec{ + Namespace: namespace, + }, + } + response, err := client.AuthorizationV1().SelfSubjectRulesReviews().Create(sar) + if err != nil { + errorsByNamespace[namespace] = err.Error() + continue + } + + // // breakdownRules := []rbacv1.PolicyRule{} + // // for _, rule := range convertToPolicyRule(response.Status) { + // // breakdownRules = append(breakdownRules, rbacutil.BreakdownRule(rule)...) + // // } + + // // compactRules, err := rbacutil.CompactRules(breakdownRules) + // // if err != nil { + // // errorsByNamespace[namespace] = err.Error() + // // continue + // // } + + b, err := json.MarshalIndent(response.Status, "", " ") + if err != nil { + errorsByNamespace[namespace] = err.Error() + continue + } + + fmt.Printf("%s\n", b) + authListByNamespace[namespace+".json"] = b + } + + return authListByNamespace, errorsByNamespace +} + +// not exprted from: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/auth/cani.go#L339 +func convertToPolicyRule(status authorizationv1.SubjectRulesReviewStatus) []rbacv1.PolicyRule { + ret := []rbacv1.PolicyRule{} + for _, resource := range status.ResourceRules { + ret = append(ret, rbacv1.PolicyRule{ + Verbs: resource.Verbs, + APIGroups: resource.APIGroups, + Resources: resource.Resources, + ResourceNames: resource.ResourceNames, + }) + } + + for _, nonResource := range status.NonResourceRules { + ret = append(ret, rbacv1.PolicyRule{ + Verbs: nonResource.Verbs, + NonResourceURLs: nonResource.NonResourceURLs, + }) + } + + return ret +} + func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) { namespaces, err := redact.Redact(c.Namespaces) if err != nil { @@ -393,6 +469,7 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) { if err != nil { return nil, err } + return &ClusterResourcesOutput{ Namespaces: namespaces, NamespacesErrors: c.NamespacesErrors, @@ -412,5 +489,7 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) { CustomResourceDefinitionsErrors: c.CustomResourceDefinitionsErrors, ImagePullSecrets: c.ImagePullSecrets, ImagePullSecretsErrors: c.ImagePullSecretsErrors, + AuthCanI: c.AuthCanI, + AuthCanIErrors: c.AuthCanIErrors, }, nil } From f5fe4423495b1e094919ac0fcd84d5c86225d654 Mon Sep 17 00:00:00 2001 From: Marc Campbell Date: Wed, 18 Dec 2019 19:49:39 +0000 Subject: [PATCH 2/2] Printing rbac policies per namespace --- pkg/collect/cluster_resources.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/pkg/collect/cluster_resources.go b/pkg/collect/cluster_resources.go index 64bd1df3..c42816c5 100644 --- a/pkg/collect/cluster_resources.go +++ b/pkg/collect/cluster_resources.go @@ -9,6 +9,7 @@ import ( "github.com/replicatedhq/troubleshoot/pkg/redact" authorizationv1 "k8s.io/api/authorization/v1" corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apiextensionsv1beta1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -33,8 +34,10 @@ type ClusterResourcesOutput struct { ImagePullSecretsErrors []byte `json:"cluster-resources/image-pull-secrets-errors.json,omitempty"` Nodes []byte `json:"cluster-resources/nodes.json,omitempty"` NodesErrors []byte `json:"cluster-resources/nodes-errors.json,omitempty"` - AuthCanI map[string][]byte `json:"cluster-resources/auth-cani-list,omitempty"` - AuthCanIErrors []byte `json:"cluster-resources/auth-cani-list-errors.json,omitempty"` + + // TODO these should be considered for relocation to an rbac or auth package. cluster resources might not be the right place + AuthCanI map[string][]byte `json:"cluster-resources/auth-cani-list,omitempty"` + AuthCanIErrors []byte `json:"cluster-resources/auth-cani-list-errors.json,omitempty"` } func ClusterResources(ctx *Context) ([]byte, error) { @@ -378,7 +381,6 @@ func authCanI(client *kubernetes.Clientset, namespaces []string) (map[string][]b errorsByNamespace := make(map[string]string) for _, namespace := range namespaces { - fmt.Println(namespace) sar := &authorizationv1.SelfSubjectRulesReview{ Spec: authorizationv1.SelfSubjectRulesReviewSpec{ Namespace: namespace, @@ -390,24 +392,17 @@ func authCanI(client *kubernetes.Clientset, namespaces []string) (map[string][]b continue } - // // breakdownRules := []rbacv1.PolicyRule{} - // // for _, rule := range convertToPolicyRule(response.Status) { - // // breakdownRules = append(breakdownRules, rbacutil.BreakdownRule(rule)...) - // // } + rules := []rbacv1.PolicyRule{} + for _, rule := range convertToPolicyRule(response.Status) { + rules = append(rules, rule) + } - // // compactRules, err := rbacutil.CompactRules(breakdownRules) - // // if err != nil { - // // errorsByNamespace[namespace] = err.Error() - // // continue - // // } - - b, err := json.MarshalIndent(response.Status, "", " ") + b, err := json.MarshalIndent(rules, "", " ") if err != nil { errorsByNamespace[namespace] = err.Error() continue } - fmt.Printf("%s\n", b) authListByNamespace[namespace+".json"] = b }