From 0ce511de45fa380105418c94078c757e41040abf Mon Sep 17 00:00:00 2001 From: Jeremie Lagarde Date: Thu, 9 Jun 2022 18:06:59 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Ignore=20groups=20not=20served?= =?UTF-8?q?=20=20by=20the=20cluster=20(#440)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/k8sinternal/client.go | 19 ++++++++++++++----- internal/k8sinternal/client_test.go | 22 +++++++++++++--------- kubeaudit.go | 10 ++++++++-- util.go | 10 +++++++--- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/internal/k8sinternal/client.go b/internal/k8sinternal/client.go index 1ea9f0fa..1123fbf0 100644 --- a/internal/k8sinternal/client.go +++ b/internal/k8sinternal/client.go @@ -106,7 +106,7 @@ type ClientOptions struct { type KubeClient interface { // GetAllResources gets all supported resources from the cluster - GetAllResources(options ClientOptions) []k8s.Resource + GetAllResources(options ClientOptions) ([]k8s.Resource, error) // GetKubernetesVersion returns the kubernetes client version GetKubernetesVersion() (*version.Info, error) // ServerPreferredResources returns the supported resources with the version preferred by the server. @@ -123,11 +123,14 @@ func NewKubeClient(dynamic dynamic.Interface, discovery discovery.DiscoveryInter } // GetAllResources gets all supported resources from the cluster -func (kc kubeClient) GetAllResources(options ClientOptions) []k8s.Resource { +func (kc kubeClient) GetAllResources(options ClientOptions) ([]k8s.Resource, error) { var resources []k8s.Resource lists, err := kc.ServerPreferredResources() - if err == nil { + if err != nil { + return nil, err + } + if lists != nil { for _, list := range lists { if len(list.APIResources) == 0 { continue @@ -169,7 +172,7 @@ func (kc kubeClient) GetAllResources(options ClientOptions) []k8s.Resource { if !options.IncludeGenerated { resources = excludeGenerated(resources) } - return resources + return resources, nil } // unstructuredToObject unstructured to Go typed object conversions @@ -207,5 +210,11 @@ func (kc kubeClient) GetKubernetesVersion() (*version.Info, error) { // ServerPreferredResources returns the supported resources with the version preferred by the server. func (kc kubeClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return discovery.ServerPreferredResources(kc.discoveryClient) + list, err := discovery.ServerPreferredResources(kc.discoveryClient) + // If a group is not served by the cluster the resources of this group will not be audited. + var e *discovery.ErrGroupDiscoveryFailed + if errors.As(err, &e) { + return list, nil + } + return list, err } diff --git a/internal/k8sinternal/client_test.go b/internal/k8sinternal/client_test.go index 6ba377ad..2f333219 100644 --- a/internal/k8sinternal/client_test.go +++ b/internal/k8sinternal/client_test.go @@ -102,12 +102,13 @@ func TestGetAllResources(t *testing.T) { } client := newFakeKubeClient(resources...) - assert.Len(t, client.GetAllResources(k8sinternal.ClientOptions{}), len(resourceTemplates)*len(namespaces)) - assert.Len( - t, - client.GetAllResources(k8sinternal.ClientOptions{Namespace: namespaces[0]}), - len(resourceTemplates), - ) + k8sresources, err := client.GetAllResources(k8sinternal.ClientOptions{}) + require.NoError(t, err) + assert.Len(t, k8sresources, len(resourceTemplates)*len(namespaces)) + + k8sresources, err = client.GetAllResources(k8sinternal.ClientOptions{Namespace: namespaces[0]}) + require.NoError(t, err) + assert.Len(t, k8sresources, len(resourceTemplates)) } func setNamespace(resource k8s.Resource, namespace string) { @@ -147,21 +148,24 @@ func TestIncludeGenerated(t *testing.T) { require.NoError(t, err) // Test IncludeGenerated = false - resources := client.GetAllResources( + resources, err := client.GetAllResources( k8sinternal.ClientOptions{Namespace: namespace, IncludeGenerated: false}, ) + require.NoError(t, err) assert.False(t, hasPod(resources), "Expected no pods for IncludeGenerated=false") // Test IncludeGenerated unspecified defaults to false - resources = client.GetAllResources( + resources, err = client.GetAllResources( k8sinternal.ClientOptions{Namespace: namespace}, ) + require.NoError(t, err) assert.False(t, hasPod(resources), "Expected no pods if IncludeGenerated is unspecified (ie. default to false)") // Test IncludeGenerated = true - resources = client.GetAllResources( + resources, err = client.GetAllResources( k8sinternal.ClientOptions{Namespace: namespace, IncludeGenerated: true}, ) + require.NoError(t, err) assert.True(t, hasPod(resources), "Expected pods for IncludeGenerated=true") } diff --git a/kubeaudit.go b/kubeaudit.go index 6c450231..d1e7e175 100644 --- a/kubeaudit.go +++ b/kubeaudit.go @@ -170,7 +170,10 @@ func (a *Kubeaudit) AuditCluster(options AuditOptions) (*Report, error) { return nil, err } - resources := getResourcesFromClient(client, options) + resources, err := getResourcesFromClient(client, options) + if err != nil { + return nil, err + } results, err := auditResources(resources, a.auditors) if err != nil { return nil, err @@ -190,7 +193,10 @@ func (a *Kubeaudit) AuditLocal(configpath string, options AuditOptions) (*Report return nil, err } - resources := getResourcesFromClient(client, options) + resources, err := getResourcesFromClient(client, options) + if err != nil { + return nil, err + } results, err := auditResources(resources, a.auditors) if err != nil { return nil, err diff --git a/util.go b/util.go index c620241a..27391988 100644 --- a/util.go +++ b/util.go @@ -9,14 +9,18 @@ import ( "gopkg.in/yaml.v3" ) -func getResourcesFromClient(client k8sinternal.KubeClient, options k8sinternal.ClientOptions) []KubeResource { +func getResourcesFromClient(client k8sinternal.KubeClient, options k8sinternal.ClientOptions) ([]KubeResource, error) { var resources []KubeResource - for _, resource := range client.GetAllResources(options) { + k8sresources, err := client.GetAllResources(options) + if err != nil { + return nil, err + } + for _, resource := range k8sresources { resources = append(resources, &kubeResource{object: resource}) } - return resources + return resources, nil } func getResourcesFromManifest(data []byte) ([]KubeResource, error) {