From e337f6574514cfa590cae1a36e1daf02eee57326 Mon Sep 17 00:00:00 2001 From: Lance Bragstad Date: Thu, 28 Sep 2023 16:40:06 -0500 Subject: [PATCH] CMP-2130: Implement support for profile versioning This commit adds support for an optional version attribute for Profile custom resources. This attribute is parsed out of the datastream and set on the Profile by the compliance operator. It's not intended for end users to supply their own version. --- CHANGELOG.md | 2 ++ ...iance.openshift.io_compliancecheckresults.yaml | 2 +- ...iance.openshift.io_complianceremediations.yaml | 2 +- .../compliance.openshift.io_compliancescans.yaml | 2 +- .../compliance.openshift.io_compliancesuites.yaml | 7 ++++++- .../compliance.openshift.io_profilebundles.yaml | 2 +- .../compliance.openshift.io_profiles.yaml | 14 ++++++++++++-- .../manifests/compliance.openshift.io_rules.yaml | 2 +- ...mpliance.openshift.io_scansettingbindings.yaml | 10 ++++++++-- .../compliance.openshift.io_scansettings.yaml | 7 ++++++- .../compliance.openshift.io_tailoredprofiles.yaml | 2 +- .../compliance.openshift.io_variables.yaml | 2 +- .../bases/compliance.openshift.io_profiles.yaml | 12 +++++++++++- pkg/apis/compliance/v1alpha1/profile_types.go | 4 ++++ pkg/profileparser/profileparser.go | 6 ++++++ tests/e2e/parallel/main_test.go | 15 +++++++++++++++ 16 files changed, 77 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ad64261a..36cd9230a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Versioning](https://semver.org/spec/v2.0.0.html). more ergonomic to pause scans during maintenance periods. See the [enhancement](https://github.com/ComplianceAsCode/compliance-operator/pull/375) for more details. +- Implemented support for an optional `version` attribute on `Profile` custom + resources. ### Fixes diff --git a/bundle/manifests/compliance.openshift.io_compliancecheckresults.yaml b/bundle/manifests/compliance.openshift.io_compliancecheckresults.yaml index e16fca126..dd0e28cd8 100644 --- a/bundle/manifests/compliance.openshift.io_compliancecheckresults.yaml +++ b/bundle/manifests/compliance.openshift.io_compliancecheckresults.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: compliancecheckresults.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_complianceremediations.yaml b/bundle/manifests/compliance.openshift.io_complianceremediations.yaml index c7d6628fc..f1fc2c400 100644 --- a/bundle/manifests/compliance.openshift.io_complianceremediations.yaml +++ b/bundle/manifests/compliance.openshift.io_complianceremediations.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: complianceremediations.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_compliancescans.yaml b/bundle/manifests/compliance.openshift.io_compliancescans.yaml index eefa2f456..d512ae913 100644 --- a/bundle/manifests/compliance.openshift.io_compliancescans.yaml +++ b/bundle/manifests/compliance.openshift.io_compliancescans.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: compliancescans.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_compliancesuites.yaml b/bundle/manifests/compliance.openshift.io_compliancesuites.yaml index 68d4f2b3a..bd2eaaec3 100644 --- a/bundle/manifests/compliance.openshift.io_compliancesuites.yaml +++ b/bundle/manifests/compliance.openshift.io_compliancesuites.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: compliancesuites.compliance.openshift.io spec: @@ -323,6 +323,11 @@ spec: scheduled scans will start running only after the initial results are ready. type: string + suspend: + default: false + description: Defines if a schedule should be suspended and is a boolean + value, defaulting to False. + type: boolean required: - scans type: object diff --git a/bundle/manifests/compliance.openshift.io_profilebundles.yaml b/bundle/manifests/compliance.openshift.io_profilebundles.yaml index 09c18c893..7c4892098 100644 --- a/bundle/manifests/compliance.openshift.io_profilebundles.yaml +++ b/bundle/manifests/compliance.openshift.io_profilebundles.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: profilebundles.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_profiles.yaml b/bundle/manifests/compliance.openshift.io_profiles.yaml index 4d15ee5c2..32eab46d2 100644 --- a/bundle/manifests/compliance.openshift.io_profiles.yaml +++ b/bundle/manifests/compliance.openshift.io_profiles.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: profiles.compliance.openshift.io spec: @@ -17,7 +17,14 @@ spec: singular: profile scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .version + name: Version + type: string + name: v1alpha1 schema: openAPIV3Schema: description: Profile is the Schema for the profiles API @@ -55,6 +62,8 @@ spec: nullable: true type: array x-kubernetes-list-type: atomic + version: + type: string required: - description - id @@ -62,6 +71,7 @@ spec: type: object served: true storage: true + subresources: {} status: acceptedNames: kind: "" diff --git a/bundle/manifests/compliance.openshift.io_rules.yaml b/bundle/manifests/compliance.openshift.io_rules.yaml index dc08a6320..4945d7a6b 100644 --- a/bundle/manifests/compliance.openshift.io_rules.yaml +++ b/bundle/manifests/compliance.openshift.io_rules.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: rules.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_scansettingbindings.yaml b/bundle/manifests/compliance.openshift.io_scansettingbindings.yaml index 4c322df49..b09c4b081 100644 --- a/bundle/manifests/compliance.openshift.io_scansettingbindings.yaml +++ b/bundle/manifests/compliance.openshift.io_scansettingbindings.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: scansettingbindings.compliance.openshift.io spec: @@ -16,7 +16,11 @@ spec: singular: scansettingbinding scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Status + type: string + name: v1alpha1 schema: openAPIV3Schema: description: ScanSettingBinding is the Schema for the scansettingbindings @@ -124,6 +128,8 @@ spec: - name type: object x-kubernetes-map-type: atomic + phase: + type: string type: object type: object served: true diff --git a/bundle/manifests/compliance.openshift.io_scansettings.yaml b/bundle/manifests/compliance.openshift.io_scansettings.yaml index 8e1811f52..1855401c2 100644 --- a/bundle/manifests/compliance.openshift.io_scansettings.yaml +++ b/bundle/manifests/compliance.openshift.io_scansettings.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: scansettings.compliance.openshift.io spec: @@ -247,6 +247,11 @@ spec: be strict and error out. `false` means that we don't need to be strict and we can proceed. type: boolean + suspend: + default: false + description: Defines if a schedule should be suspended and is a boolean + value, defaulting to False. + type: boolean timeout: default: 30m description: Timeout is the maximum amount of time the scan can run. If diff --git a/bundle/manifests/compliance.openshift.io_tailoredprofiles.yaml b/bundle/manifests/compliance.openshift.io_tailoredprofiles.yaml index 28b332f51..8fe66582c 100644 --- a/bundle/manifests/compliance.openshift.io_tailoredprofiles.yaml +++ b/bundle/manifests/compliance.openshift.io_tailoredprofiles.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: tailoredprofiles.compliance.openshift.io spec: diff --git a/bundle/manifests/compliance.openshift.io_variables.yaml b/bundle/manifests/compliance.openshift.io_variables.yaml index 857986fc4..b5e9e5396 100644 --- a/bundle/manifests/compliance.openshift.io_variables.yaml +++ b/bundle/manifests/compliance.openshift.io_variables.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: variables.compliance.openshift.io spec: diff --git a/config/crd/bases/compliance.openshift.io_profiles.yaml b/config/crd/bases/compliance.openshift.io_profiles.yaml index 5da9ae792..ece2062b5 100644 --- a/config/crd/bases/compliance.openshift.io_profiles.yaml +++ b/config/crd/bases/compliance.openshift.io_profiles.yaml @@ -17,7 +17,14 @@ spec: singular: profile scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .version + name: Version + type: string + name: v1alpha1 schema: openAPIV3Schema: description: Profile is the Schema for the profiles API @@ -55,6 +62,8 @@ spec: nullable: true type: array x-kubernetes-list-type: atomic + version: + type: string required: - description - id @@ -62,3 +71,4 @@ spec: type: object served: true storage: true + subresources: {} diff --git a/pkg/apis/compliance/v1alpha1/profile_types.go b/pkg/apis/compliance/v1alpha1/profile_types.go index 8686f66a8..0052c95eb 100644 --- a/pkg/apis/compliance/v1alpha1/profile_types.go +++ b/pkg/apis/compliance/v1alpha1/profile_types.go @@ -35,12 +35,16 @@ type ProfilePayload struct { // +optional // +listType=atomic Values []ProfileValue `json:"values,omitempty"` + // +optional + Version string `json:"version"` } // +kubebuilder:object:root=true // Profile is the Schema for the profiles API // +kubebuilder:resource:path=profiles,scope=Namespaced,shortName=profs;prof +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=`.version` type Profile struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/pkg/profileparser/profileparser.go b/pkg/profileparser/profileparser.go index 756ce662b..a56a9ddd9 100644 --- a/pkg/profileparser/profileparser.go +++ b/pkg/profileparser/profileparser.go @@ -311,6 +311,11 @@ func parseProfileFromNode(profileRoot *xmlquery.Node, pb *cmpv1alpha1.ProfileBun if description == nil { return LogAndReturnError("no description in profile") } + v := profileObj.SelectElement("xccdf-1.2:version") + var version string + if v != nil { + version = v.InnerText() + } log.Info("Found profile", "id", id) // In case the profile sets its own CPE string @@ -362,6 +367,7 @@ func parseProfileFromNode(profileRoot *xmlquery.Node, pb *cmpv1alpha1.ProfileBun Description: utils.XmlNodeAsMarkdown(description), Rules: selectedrules, Values: selectedvalues, + Version: version, }, } diff --git a/tests/e2e/parallel/main_test.go b/tests/e2e/parallel/main_test.go index b85b1d05a..76639e326 100644 --- a/tests/e2e/parallel/main_test.go +++ b/tests/e2e/parallel/main_test.go @@ -55,6 +55,21 @@ func TestMain(m *testing.M) { os.Exit(exitCode) } +func TestProfileVersion(t *testing.T) { + t.Parallel() + f := framework.Global + + profile := &compv1alpha1.Profile{} + // We know this profile has a version and it's set in the ComplianceAsCode/content + profileName := "ocp4-cis" + if err := f.Client.Get(context.TODO(), types.NamespacedName{Namespace: f.OperatorNamespace, Name: profileName}, profile); err != nil { + t.Fatalf("failed to get profile %s: %s", profileName, err) + } + if profile.Version == "" { + t.Fatalf("expected profile %s to have version set", profileName) + } +} + func TestProfileModification(t *testing.T) { t.Parallel() f := framework.Global