From 6b9593be6fc322ed5751ac8b1458382cf48d6beb Mon Sep 17 00:00:00 2001 From: Vincent Shen Date: Wed, 14 Aug 2024 15:56:00 -0700 Subject: [PATCH] Have optional result server Adding a Disabled filed in ScanSetting.Spec.RawResultStorage.Disabled, defaulting to false, if setting to true we will not create result server to store arf report. --- ...mpliance.openshift.io_compliancescans.yaml | 6 ++ ...pliance.openshift.io_compliancesuites.yaml | 6 ++ .../compliance.openshift.io_scansettings.yaml | 5 ++ cmd/manager/common.go | 5 +- cmd/manager/resultcollector.go | 67 ++++++++++--------- ...mpliance.openshift.io_compliancescans.yaml | 6 ++ ...pliance.openshift.io_compliancesuites.yaml | 6 ++ .../compliance.openshift.io_scansettings.yaml | 5 ++ .../v1alpha1/compliancescan_types.go | 5 ++ .../compliancescan_controller.go | 46 +++++++------ pkg/controller/compliancescan/resultserver.go | 8 +++ pkg/controller/compliancescan/scan.go | 2 + tests/e2e/parallel/main_test.go | 60 +++++++++++++++++ 13 files changed, 174 insertions(+), 53 deletions(-) diff --git a/bundle/manifests/compliance.openshift.io_compliancescans.yaml b/bundle/manifests/compliance.openshift.io_compliancescans.yaml index d512ae913..e19777afa 100644 --- a/bundle/manifests/compliance.openshift.io_compliancescans.yaml +++ b/bundle/manifests/compliance.openshift.io_compliancescans.yaml @@ -95,6 +95,12 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. + This is useful in case the raw results are not needed. Defaults + to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/bundle/manifests/compliance.openshift.io_compliancesuites.yaml b/bundle/manifests/compliance.openshift.io_compliancesuites.yaml index bd2eaaec3..ab989eab4 100644 --- a/bundle/manifests/compliance.openshift.io_compliancesuites.yaml +++ b/bundle/manifests/compliance.openshift.io_compliancesuites.yaml @@ -116,6 +116,12 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. + This is useful in case the raw results are not needed. + Defaults to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/bundle/manifests/compliance.openshift.io_scansettings.yaml b/bundle/manifests/compliance.openshift.io_scansettings.yaml index 1855401c2..fe01aac51 100644 --- a/bundle/manifests/compliance.openshift.io_scansettings.yaml +++ b/bundle/manifests/compliance.openshift.io_scansettings.yaml @@ -69,6 +69,11 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. This + is useful in case the raw results are not needed. Defaults to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/cmd/manager/common.go b/cmd/manager/common.go index 206745f0c..88ec0da6e 100644 --- a/cmd/manager/common.go +++ b/cmd/manager/common.go @@ -2,11 +2,12 @@ package manager import ( "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/discovery" "os" "path/filepath" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery" + ocpcfgv1 "github.com/openshift/api/config/v1" mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" "github.com/spf13/cobra" diff --git a/cmd/manager/resultcollector.go b/cmd/manager/resultcollector.go index 54b69b081..794a38d05 100644 --- a/cmd/manager/resultcollector.go +++ b/cmd/manager/resultcollector.go @@ -64,20 +64,21 @@ func init() { } type scapresultsConfig struct { - ArfFile string - XccdfFile string - ExitCodeFile string - CmdOutputFile string - WarningsOutputFile string - ScanName string - ConfigMapName string - NodeName string - Namespace string - ResultServerURI string - Timeout int64 - Cert string - Key string - CA string + ArfFile string + XccdfFile string + ExitCodeFile string + CmdOutputFile string + WarningsOutputFile string + ScanName string + ConfigMapName string + NodeName string + Namespace string + ResultServerURI string + Timeout int64 + Cert string + Key string + CA string + DisableRawResultUpload bool } func defineResultcollectorFlags(cmd *cobra.Command) { @@ -117,6 +118,7 @@ func parseConfig(cmd *cobra.Command) *scapresultsConfig { conf.CA = getValidStringArg(cmd, "tls-ca") conf.Timeout, _ = cmd.Flags().GetInt64("timeout") conf.ResultServerURI, _ = cmd.Flags().GetString("resultserveruri") + conf.DisableRawResultUpload, _ = cmd.Flags().GetBool("disable-raw-upload") // Set default if needed if conf.ResultServerURI == "" { conf.ResultServerURI = "http://" + conf.ScanName + "-rs:8080/" @@ -370,31 +372,36 @@ func uploadErrorConfigMap(errorMsg *resultFileContents, exitcode string, } func handleCompleteSCAPResults(exitcode string, scapresultsconf *scapresultsConfig, client *complianceCrClient) { - arfContents, err := readResultsFile(scapresultsconf.ArfFile, scapresultsconf.Timeout) - if err != nil { - cmdLog.Error(err, "Failed to read ARF file") - os.Exit(1) - } - defer arfContents.close() - xccdfContents, err := readResultsFile(scapresultsconf.XccdfFile, scapresultsconf.Timeout) if err != nil { cmdLog.Error(err, "Failed to read XCCDF file") os.Exit(1) } defer xccdfContents.close() - var wg sync.WaitGroup - wg.Add(2) - go func() { - serverUploadErr := uploadToResultServer(arfContents, scapresultsconf) - if serverUploadErr != nil { - cmdLog.Error(serverUploadErr, "Failed to upload results to server") + numWG := 1 + if !scapresultsconf.DisableRawResultUpload { + numWG++ + } + wg.Add(numWG) + + if !scapresultsconf.DisableRawResultUpload { + arfContents, err := readResultsFile(scapresultsconf.ArfFile, scapresultsconf.Timeout) + if err != nil { + cmdLog.Error(err, "Failed to read ARF file") os.Exit(1) } - cmdLog.Info("Uploaded to resultserver") - wg.Done() - }() + defer arfContents.close() + go func() { + serverUploadErr := uploadToResultServer(arfContents, scapresultsconf) + if serverUploadErr != nil { + cmdLog.Error(serverUploadErr, "Failed to upload results to server") + os.Exit(1) + } + cmdLog.Info("Uploaded to resultserver") + wg.Done() + }() + } go func() { cmUploadErr := uploadResultConfigMap(xccdfContents, exitcode, scapresultsconf, client) diff --git a/config/crd/bases/compliance.openshift.io_compliancescans.yaml b/config/crd/bases/compliance.openshift.io_compliancescans.yaml index 58dd9ca32..6df39db8e 100644 --- a/config/crd/bases/compliance.openshift.io_compliancescans.yaml +++ b/config/crd/bases/compliance.openshift.io_compliancescans.yaml @@ -95,6 +95,12 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. + This is useful in case the raw results are not needed. Defaults + to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/config/crd/bases/compliance.openshift.io_compliancesuites.yaml b/config/crd/bases/compliance.openshift.io_compliancesuites.yaml index aa8f09567..859650ae1 100644 --- a/config/crd/bases/compliance.openshift.io_compliancesuites.yaml +++ b/config/crd/bases/compliance.openshift.io_compliancesuites.yaml @@ -116,6 +116,12 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. + This is useful in case the raw results are not needed. + Defaults to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/config/crd/bases/compliance.openshift.io_scansettings.yaml b/config/crd/bases/compliance.openshift.io_scansettings.yaml index b997c7a67..ab0ec771e 100644 --- a/config/crd/bases/compliance.openshift.io_scansettings.yaml +++ b/config/crd/bases/compliance.openshift.io_scansettings.yaml @@ -69,6 +69,11 @@ spec: rawResultStorage: description: Specifies settings that pertain to raw result storage. properties: + disabled: + default: false + description: Specifies if the raw result storage is disabled. This + is useful in case the raw results are not needed. Defaults to false. + type: boolean nodeSelector: additionalProperties: type: string diff --git a/pkg/apis/compliance/v1alpha1/compliancescan_types.go b/pkg/apis/compliance/v1alpha1/compliancescan_types.go index 219345372..1ca7c4e54 100644 --- a/pkg/apis/compliance/v1alpha1/compliancescan_types.go +++ b/pkg/apis/compliance/v1alpha1/compliancescan_types.go @@ -132,6 +132,11 @@ type ComplianceScanType string // When changing the defaults, remember to change also the DefaultRawStorageSize and // DefaultStorageRotation constants type RawResultStorageSettings struct { + // Specifies if the raw result storage is disabled. This is useful in case + // the raw results are not needed. Defaults to false. + // +kubebuilder:validation:Default=false + // +kubebuilder:default=false + Disabled bool `json:"disabled,omitempty"` // Specifies the amount of storage to ask for storing the raw results. Note that // if re-scans happen, the new results will also need to be stored. Defaults to 1Gi. // +kubebuilder:validation:Default=1Gi diff --git a/pkg/controller/compliancescan/compliancescan_controller.go b/pkg/controller/compliancescan/compliancescan_controller.go index 4195fd41b..7627eca22 100644 --- a/pkg/controller/compliancescan/compliancescan_controller.go +++ b/pkg/controller/compliancescan/compliancescan_controller.go @@ -335,26 +335,29 @@ func (r *ReconcileComplianceScan) phaseLaunchingHandler(h scanTypeHandler, logge return reconcile.Result{}, err } - if err = r.handleResultServerSecret(scan, logger); err != nil { - logger.Error(err, "Cannot create result server cert secret") - return reconcile.Result{}, err - } + if !scan.Spec.RawResultStorage.Disabled { + if err = r.handleResultServerSecret(scan, logger); err != nil { + logger.Error(err, "Cannot create result server cert secret") + return reconcile.Result{}, err + } - if err = r.handleResultClientSecret(scan, logger); err != nil { - logger.Error(err, "Cannot create result Client cert secret") - return reconcile.Result{}, err - } + if err = r.handleResultClientSecret(scan, logger); err != nil { + logger.Error(err, "Cannot create result Client cert secret") + return reconcile.Result{}, err + } - if resume, err := r.handleRawResultsForScan(scan, logger); err != nil || !resume { - if err != nil { - logger.Error(err, "Cannot create the PersistentVolumeClaims") + if resume, err := r.handleRawResultsForScan(scan, logger); err != nil || !resume { + if err != nil { + logger.Error(err, "Cannot create the PersistentVolumeClaims") + } + return reconcile.Result{}, err + } + + if err = r.createResultServer(scan, logger); err != nil { + logger.Error(err, "Cannot create result server") + return reconcile.Result{}, err } - return reconcile.Result{}, err - } - if err = r.createResultServer(scan, logger); err != nil { - logger.Error(err, "Cannot create result server") - return reconcile.Result{}, err } if err = r.handleRuntimeKubeletConfig(scan, logger); err != nil { @@ -745,11 +748,12 @@ func (r *ReconcileComplianceScan) phaseDoneHandler(h scanTypeHandler, instance * } } else { // If we're done with the scan but we're not cleaning up just yet. - - // scale down resultserver so it's not still listening for requests. - if err := r.scaleDownResultServer(instance, logger); err != nil { - logger.Error(err, "Cannot scale down result server") - return reconcile.Result{}, err + if !instance.Spec.RawResultStorage.Disabled { + // scale down resultserver so it's not still listening for requests. + if err := r.scaleDownResultServer(instance, logger); err != nil { + logger.Error(err, "Cannot scale down result server") + return reconcile.Result{}, err + } } } diff --git a/pkg/controller/compliancescan/resultserver.go b/pkg/controller/compliancescan/resultserver.go index e7b18aa1d..3e5510dd5 100644 --- a/pkg/controller/compliancescan/resultserver.go +++ b/pkg/controller/compliancescan/resultserver.go @@ -282,3 +282,11 @@ func getResultServerName(instance *compv1alpha1.ComplianceScan) string { func getResultServerURI(instance *compv1alpha1.ComplianceScan) string { return "https://" + getResultServerName(instance) + fmt.Sprintf(":%d/", ResultServerPort) } + +func getDisableRawResultUploadValue(instance *compv1alpha1.ComplianceScan) string { + if instance.Spec.RawResultStorage.Disabled { + return "true" + } else { + return "false" + } +} diff --git a/pkg/controller/compliancescan/scan.go b/pkg/controller/compliancescan/scan.go index 3b703eb45..60fbb9c3e 100644 --- a/pkg/controller/compliancescan/scan.go +++ b/pkg/controller/compliancescan/scan.go @@ -182,6 +182,7 @@ func newScanPodForNode(scanInstance *compv1alpha1.ComplianceScan, node *corev1.N "--tls-client-cert=/etc/pki/tls/tls.crt", "--tls-client-key=/etc/pki/tls/tls.key", "--tls-ca=/etc/pki/tls/ca.crt", + "--disable-raw-upload=" + getDisableRawResultUploadValue(scanInstance), }, ImagePullPolicy: corev1.PullAlways, SecurityContext: &corev1.SecurityContext{ @@ -508,6 +509,7 @@ func (r *ReconcileComplianceScan) newPlatformScanPod(scanInstance *compv1alpha1. "--tls-client-cert=/etc/pki/tls/tls.crt", "--tls-client-key=/etc/pki/tls/tls.key", "--tls-ca=/etc/pki/tls/ca.crt", + "--disable-raw-upload=" + getDisableRawResultUploadValue(scanInstance), }, ImagePullPolicy: corev1.PullAlways, SecurityContext: &corev1.SecurityContext{ diff --git a/tests/e2e/parallel/main_test.go b/tests/e2e/parallel/main_test.go index 8707611f5..f770ce1fd 100644 --- a/tests/e2e/parallel/main_test.go +++ b/tests/e2e/parallel/main_test.go @@ -1833,6 +1833,66 @@ func TestScheduledSuitePriorityClass(t *testing.T) { } } +func TestScheduledSuiteNoStorage(t *testing.T) { + t.Parallel() + f := framework.Global + suiteName := "test-scheduled-suite-no-storage" + workerScanName := fmt.Sprintf("%s-workers-scan", suiteName) + selectWorkers := map[string]string{ + "node-role.kubernetes.io/worker": "", + } + + testSuite := &compv1alpha1.ComplianceSuite{ + ObjectMeta: metav1.ObjectMeta{ + Name: suiteName, + Namespace: f.OperatorNamespace, + }, + Spec: compv1alpha1.ComplianceSuiteSpec{ + ComplianceSuiteSettings: compv1alpha1.ComplianceSuiteSettings{ + AutoApplyRemediations: false, + }, + Scans: []compv1alpha1.ComplianceScanSpecWrapper{ + { + Name: workerScanName, + ComplianceScanSpec: compv1alpha1.ComplianceScanSpec{ + ContentImage: contentImagePath, + Profile: "xccdf_org.ssgproject.content_profile_moderate", + Content: framework.RhcosContentFile, + Rule: "xccdf_org.ssgproject.content_rule_no_netrc_files", + NodeSelector: selectWorkers, + ComplianceScanSettings: compv1alpha1.ComplianceScanSettings{ + RawResultStorage: compv1alpha1.RawResultStorageSettings{ + Disabled: true, + }, + Debug: true, + }, + }, + }, + }, + }, + } + + err := f.Client.Create(context.TODO(), testSuite, nil) + if err != nil { + t.Fatal(err) + } + defer f.Client.Delete(context.TODO(), testSuite) + + pvcList := &corev1.PersistentVolumeClaimList{} + err = f.Client.List(context.TODO(), pvcList, client.InNamespace(f.OperatorNamespace), client.MatchingLabels(map[string]string{ + compv1alpha1.ComplianceScanLabel: workerScanName, + })) + if err != nil { + t.Fatal(err) + } + + // Ensure that all the scans in the suite have finished and are marked as Done + err = f.WaitForSuiteScansStatus(f.OperatorNamespace, suiteName, compv1alpha1.PhaseDone, compv1alpha1.ResultCompliant) + if err != nil { + t.Fatal(err) + } +} + func TestScheduledSuiteInvalidPriorityClass(t *testing.T) { t.Parallel() f := framework.Global