From 44d3613c1f950837c6b112ddde0dc3e90f73dc1b Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 25 Aug 2023 17:37:53 +0100 Subject: [PATCH] feat: configauditreport (#609) * feat: adding config audit report Signed-off-by: Alex Jones * feat: adding config audit report Signed-off-by: Alex Jones * feat: adding config audit report analyzer mechnics Signed-off-by: Alex Jones Signed-off-by: Alex Jones * feat: adding config audit report analyzer mechnics Signed-off-by: Alex Jones Signed-off-by: Alex Jones * chore: updated naming Signed-off-by: Alex Jones * chore: updated naming Signed-off-by: Alex Jones * chore: updated var names Signed-off-by: Alex Jones --------- Signed-off-by: Alex Jones Signed-off-by: Alex Jones Co-authored-by: Alex Jones --- pkg/analyzer/analyzer.go | 7 ++- pkg/common/types.go | 1 + pkg/integration/integration.go | 20 ++++--- pkg/integration/trivy/analyzer.go | 86 ++++++++++++++++++++++++++++++- pkg/integration/trivy/trivy.go | 15 ++++-- 5 files changed, 116 insertions(+), 13 deletions(-) diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index cd67d929e0..09a0e82078 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -61,7 +61,7 @@ func ListFilters() ([]string, []string, []string) { for k := range additionalAnalyzerMap { additionalKeys = append(additionalKeys, k) } - + // Current analyzer integrationProvider := integration.NewIntegration() var integrationAnalyzers []string @@ -73,7 +73,10 @@ func ListFilters() ([]string, []string, []string) { fmt.Println(color.RedString(err.Error())) os.Exit(1) } - integrationAnalyzers = append(integrationAnalyzers, in.GetAnalyzerName()) + for _, analyzers := range in.GetAnalyzerName() { + + integrationAnalyzers = append(integrationAnalyzers, analyzers) + } } } diff --git a/pkg/common/types.go b/pkg/common/types.go index 1ec0e04f03..6d781ceb56 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -59,6 +59,7 @@ type PreAnalysis struct { MutatingWebhook regv1.MutatingWebhookConfiguration // Integrations TrivyVulnerabilityReport trivy.VulnerabilityReport + TrivyConfigAuditReport trivy.ConfigAuditReport } type Result struct { diff --git a/pkg/integration/integration.go b/pkg/integration/integration.go index e89e434c00..d5c7268b7d 100644 --- a/pkg/integration/integration.go +++ b/pkg/integration/integration.go @@ -35,7 +35,7 @@ type IIntegration interface { // RemoveAnalyzer removes an analyzer from the cluster RemoveAnalyzer() error - GetAnalyzerName() string + GetAnalyzerName() []string IsActivate() bool } @@ -71,7 +71,11 @@ func (*Integration) Activate(name string, namespace string, activeFilters []stri return errors.New("integration not found") } - mergedFilters := append(activeFilters, integrations[name].GetAnalyzerName()) + mergedFilters := activeFilters + + for _, integrationAnalyzer := range integrations[name].GetAnalyzerName() { + mergedFilters = append(mergedFilters, integrationAnalyzer) + } uniqueFilters, dupplicatedFilters := util.RemoveDuplicates(mergedFilters) @@ -108,11 +112,15 @@ func (*Integration) Deactivate(name string, namespace string) error { // This might be a bad idea, but we cannot reference analyzer here foundFilter := false for i, v := range activeFilters { - if v == integrations[name].GetAnalyzerName() { - foundFilter = true - activeFilters = append(activeFilters[:i], activeFilters[i+1:]...) - break + + for _, intanal := range integrations[name].GetAnalyzerName() { + if v == intanal { + foundFilter = true + activeFilters = append(activeFilters[:i], activeFilters[i+1:]...) + break + } } + } if !foundFilter { color.Red("Ingregation %s does not exist in configuration file. Please use k8sgpt integration add.", name) diff --git a/pkg/integration/trivy/analyzer.go b/pkg/integration/trivy/analyzer.go index 486a280205..1341493034 100644 --- a/pkg/integration/trivy/analyzer.go +++ b/pkg/integration/trivy/analyzer.go @@ -23,10 +23,11 @@ import ( ) type TrivyAnalyzer struct { + vulernabilityReportAnalysis bool + configAuditReportAnalysis bool } -func (TrivyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { - +func (TrivyAnalyzer) analyzeVulnerabilityReports(a common.Analyzer) ([]common.Result, error) { // Get all trivy VulnerabilityReports result := &v1alpha1.VulnerabilityReportList{} @@ -84,4 +85,85 @@ func (TrivyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { } return a.Results, nil + +} + +func (t TrivyAnalyzer) analyzeConfigAuditReports(a common.Analyzer) ([]common.Result, error) { + // Get all trivy VulnerabilityReports + result := &v1alpha1.ConfigAuditReportList{} + + config := a.Client.GetConfig() + // Add group version to sceheme + config.ContentConfig.GroupVersion = &v1alpha1.SchemeGroupVersion + config.UserAgent = rest.DefaultKubernetesUserAgent() + config.APIPath = "/apis" + + restClient, err := rest.UnversionedRESTClientFor(config) + if err != nil { + return nil, err + } + err = restClient.Get().Resource("configauditreports").Do(a.Context).Into(result) + if err != nil { + return nil, err + } + + // Find criticals and get CVE + var preAnalysis = map[string]common.PreAnalysis{} + + for _, report := range result.Items { + + var failures []common.Failure + if report.Report.Summary.HighCount > 0 { + + failures = append(failures, common.Failure{ + Text: fmt.Sprintf("Config audit report %s detected at least one high issue", report.Name), + Sensitive: []common.Sensitive{}, + }) + + } + if len(failures) > 0 { + preAnalysis[fmt.Sprintf("%s/%s", report.Labels["trivy-operator.resource.namespace"], + report.Labels["trivy-operator.resource.name"])] = common.PreAnalysis{ + TrivyConfigAuditReport: report, + FailureDetails: failures, + } + } + } + + for key, value := range preAnalysis { + var currentAnalysis = common.Result{ + Kind: "ConfigAuditReport", + Name: key, + Error: value.FailureDetails, + } + + parent, _ := util.GetParent(a.Client, value.TrivyConfigAuditReport.ObjectMeta) + currentAnalysis.ParentObject = parent + a.Results = append(a.Results, currentAnalysis) + } + + return a.Results, nil +} + +func (t TrivyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { + + if t.vulernabilityReportAnalysis { + common := make([]common.Result, 0) + vresult, err := t.analyzeVulnerabilityReports(a) + if err != nil { + return nil, err + } + common = append(common, vresult...) + return common, nil + } + if t.configAuditReportAnalysis { + common := make([]common.Result, 0) + cresult, err := t.analyzeConfigAuditReports(a) + if err != nil { + return nil, err + } + common = append(common, cresult...) + return common, nil + } + return make([]common.Result, 0), nil } diff --git a/pkg/integration/trivy/trivy.go b/pkg/integration/trivy/trivy.go index e36f0e1b00..c3d78fb6b6 100644 --- a/pkg/integration/trivy/trivy.go +++ b/pkg/integration/trivy/trivy.go @@ -44,8 +44,11 @@ func NewTrivy() *Trivy { } } -func (t *Trivy) GetAnalyzerName() string { - return "VulnerabilityReport" +func (t *Trivy) GetAnalyzerName() []string { + return []string{ + "VulnerabilityReport", + "ConfigAuditReport", + } } func (t *Trivy) Deploy(namespace string) error { @@ -107,10 +110,16 @@ func (t *Trivy) IsActivate() bool { func (t *Trivy) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) { - (*mergedMap)["VulnerabilityReport"] = &TrivyAnalyzer{} + (*mergedMap)["VulnerabilityReport"] = &TrivyAnalyzer{ + vulernabilityReportAnalysis: true, + } + (*mergedMap)["ConfigAuditReport"] = &TrivyAnalyzer{ + configAuditReportAnalysis: true, + } } func (t *Trivy) RemoveAnalyzer() error { + return nil }