Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UD-1129: Update reconciliation of misconfigurations and vulnerabiliti… #234

Merged
merged 1 commit into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/zora/v1alpha1/clusterscan_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func (in *PluginReference) PluginKey(defaultNamespace string) types.NamespacedNa
return types.NamespacedName{Name: in.Name, Namespace: ns}
}

type PluginScanProcessedResources map[string]string

// ClusterScanStatus defines the observed state of ClusterScan
type ClusterScanStatus struct {
Status `json:",inline"`
Expand Down Expand Up @@ -104,6 +106,12 @@ type ClusterScanStatus struct {

// Total of ClusterIssues reported in the last successful scan
TotalIssues *int `json:"totalIssues,omitempty"`

// Resource versions of processed vulnerabilities
ProcessedVulnerabilities map[string]PluginScanProcessedResources `json:"processedVulnerabilities,omitempty"`

// Resource versions of processed misconfigurations
ProcessedMisconfigurations map[string]PluginScanProcessedResources `json:"processedMisconfigurations,omitempty"`
}

// GetPluginStatus returns a PluginScanStatus of a plugin
Expand Down
57 changes: 57 additions & 0 deletions api/zora/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions charts/zora/crds/zora.undistro.io_clusterscans.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,20 @@ spec:
type: object
description: Information of the last scans of plugins
type: object
processedMisconfigurations:
additionalProperties:
additionalProperties:
type: string
type: object
description: Resource versions of processed misconfigurations
type: object
processedVulnerabilities:
additionalProperties:
additionalProperties:
type: string
type: object
description: Resource versions of processed vulnerabilities
type: object
suspend:
description: Suspend field value from ClusterScan spec
type: boolean
Expand Down
14 changes: 14 additions & 0 deletions config/crd/bases/zora.undistro.io_clusterscans.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,20 @@ spec:
type: object
description: Information of the last scans of plugins
type: object
processedMisconfigurations:
additionalProperties:
additionalProperties:
type: string
type: object
description: Resource versions of processed misconfigurations
type: object
processedVulnerabilities:
additionalProperties:
additionalProperties:
type: string
type: object
description: Resource versions of processed vulnerabilities
type: object
suspend:
description: Suspend field value from ClusterScan spec
type: boolean
Expand Down
63 changes: 63 additions & 0 deletions internal/saas/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ package saas
import (
"context"
"errors"
"fmt"
"reflect"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

"github.com/undistro/zora/api/zora/v1alpha1"
)
Expand Down Expand Up @@ -107,6 +110,13 @@ func pushMisconfigs(saasClient Client, c ctrlClient.Client, ctx context.Context,
return err
}

pluginProcessedResources := getMisconfigProcessedResources(clusterScan.Status.Plugins, issueList.Items)
if reflect.DeepEqual(pluginProcessedResources, clusterScan.Status.ProcessedMisconfigurations) {
log := log.FromContext(ctx)
log.Info("Skipping misconfigurations, no changes from processed misconfigurations")
return nil
}

status := NewScanStatusWithIssues(scanList.Items, issueList.Items)
if status == nil {
return nil
Expand All @@ -120,6 +130,7 @@ func pushMisconfigs(saasClient Client, c ctrlClient.Client, ctx context.Context,
clusterScan.SetSaaSStatus(metav1.ConditionFalse, "Error", err.Error())
return err
}
clusterScan.Status.ProcessedMisconfigurations = pluginProcessedResources
clusterScan.SetSaaSStatus(metav1.ConditionTrue, "OK", "cluster scan successfully synced with SaaS")
return nil
}
Expand All @@ -142,6 +153,14 @@ func pushVulns(scl Client, cl ctrlClient.Client, ctx context.Context, cs *v1alph
if len(metaList.Items) == 0 {
return nil
}

pluginProcessedResources := getVulnerabilityProcessedResources(metaList.Items)
if reflect.DeepEqual(pluginProcessedResources, cs.Status.ProcessedVulnerabilities) {
log := log.FromContext(ctx)
log.Info("Skipping vulnerabilities, no changes from processed vulnerabilities")
return nil
}

for _, i := range metaList.Items {
vulnReport := &v1alpha1.VulnerabilityReport{}
if err := cl.Get(ctx, types.NamespacedName{Namespace: i.Namespace, Name: i.Name}, vulnReport); err != nil {
Expand All @@ -161,6 +180,7 @@ func pushVulns(scl Client, cl ctrlClient.Client, ctx context.Context, cs *v1alph
return err
}
}
cs.Status.ProcessedVulnerabilities = pluginProcessedResources
cs.SetSaaSStatus(metav1.ConditionTrue, "OK", "cluster scan successfully synced with SaaS")
return nil
}
Expand All @@ -180,3 +200,46 @@ func buildLabelSelector(clusterName string, scanIDs []string) (*ctrlClient.Match
}
return &ctrlClient.MatchingLabelsSelector{Selector: ls}, nil
}

func getMisconfigProcessedResources(pluginStatus map[string]*v1alpha1.PluginScanStatus, clusterIssues []v1alpha1.ClusterIssue) map[string]v1alpha1.PluginScanProcessedResources {
var pluginProcessedResources map[string]v1alpha1.PluginScanProcessedResources
issuePluginIncluded := false
for _, issue := range clusterIssues {
plugin := issue.Labels[v1alpha1.LabelPlugin]
if !issuePluginIncluded {
_, issuePluginIncluded = pluginStatus[plugin]
}
if pluginProcessedResources == nil {
pluginProcessedResources = map[string]v1alpha1.PluginScanProcessedResources{}
}
processedResources, ok := pluginProcessedResources[plugin]
if !ok {
processedResources = v1alpha1.PluginScanProcessedResources{}
pluginProcessedResources[plugin] = processedResources
}
processedResources[fmt.Sprintf("%s/%s", issue.Namespace, issue.Name)] = issue.ResourceVersion
}
if issuePluginIncluded {
return pluginProcessedResources
} else {
return nil
}
}

func getVulnerabilityProcessedResources(vulnerabiltiyIssues []metav1.PartialObjectMetadata) map[string]v1alpha1.PluginScanProcessedResources {
var pluginProcessedResources map[string]v1alpha1.PluginScanProcessedResources
for _, issue := range vulnerabiltiyIssues {
plugin := issue.Labels[v1alpha1.LabelPlugin]
if pluginProcessedResources == nil {
pluginProcessedResources = map[string]v1alpha1.PluginScanProcessedResources{}
}
processedResources, ok := pluginProcessedResources[plugin]
if !ok {
processedResources = v1alpha1.PluginScanProcessedResources{}
pluginProcessedResources[plugin] = processedResources
}
processedResources[fmt.Sprintf("%s/%s", issue.Namespace, issue.Name)] = issue.ResourceVersion

}
return pluginProcessedResources
}