From 86af5ca9d8b062b3aa818bd0aadffaec98347a9b Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Tue, 5 Jul 2022 17:29:15 +0100 Subject: [PATCH] distro: oscap customization validation Add basic validation to ensure that the oscap customizations are valid and required fields have been provided. The validation also ensures that the manifest generation errors out if oscap customization has been enabled for older or unsupported distros. --- internal/distro/fedora/distro.go | 23 +++++++++++++++ internal/distro/rhel7/distro.go | 4 +++ internal/distro/rhel8/distro.go | 49 ++++++++++++++++++++++++++++++-- internal/distro/rhel90/distro.go | 49 ++++++++++++++++++++++++++++++-- 4 files changed, 119 insertions(+), 6 deletions(-) diff --git a/internal/distro/fedora/distro.go b/internal/distro/fedora/distro.go index 3d739b6e6..56affff1d 100644 --- a/internal/distro/fedora/distro.go +++ b/internal/distro/fedora/distro.go @@ -14,6 +14,7 @@ import ( "github.com/osbuild/osbuild-composer/internal/environment" "github.com/osbuild/osbuild-composer/internal/image" "github.com/osbuild/osbuild-composer/internal/manifest" + "github.com/osbuild/osbuild-composer/internal/oscap" "github.com/osbuild/osbuild-composer/internal/platform" "github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/runner" @@ -49,6 +50,12 @@ var ( "/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home", "/tmp", } + oscapProfileAllowList = []oscap.Profile{ + oscap.Ospp, + oscap.PciDss, + oscap.Standard, + } + // Services iotServices = []string{ "NetworkManager.service", @@ -704,6 +711,22 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio return fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints) } + if osc := customizations.GetOpenSCAP(); osc != nil { + supported := oscap.IsProfileAllowed(osc.ProfileID, oscapProfileAllowList) + if !supported { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported profile: %s", osc.ProfileID)) + } + if t.rpmOstree { + return fmt.Errorf("OpenSCAP customizations are not supported for ostree types") + } + if osc.DataStream == "" { + return fmt.Errorf("OpenSCAP datastream cannot be empty") + } + if osc.ProfileID == "" { + return fmt.Errorf("OpenSCAP profile cannot be empty") + } + } + return nil } diff --git a/internal/distro/rhel7/distro.go b/internal/distro/rhel7/distro.go index 17ded1f02..00726e639 100644 --- a/internal/distro/rhel7/distro.go +++ b/internal/distro/rhel7/distro.go @@ -448,6 +448,10 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio return fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints) } + if osc := customizations.GetOpenSCAP(); osc != nil { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported os version: %s", t.arch.distro.osVersion)) + } + return nil } diff --git a/internal/distro/rhel8/distro.go b/internal/distro/rhel8/distro.go index 39971dd4d..a21e0838c 100644 --- a/internal/distro/rhel8/distro.go +++ b/internal/distro/rhel8/distro.go @@ -14,6 +14,7 @@ import ( "github.com/osbuild/osbuild-composer/internal/disk" "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/osbuild" + "github.com/osbuild/osbuild-composer/internal/oscap" "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/rpmmd" ) @@ -67,9 +68,31 @@ const ( blueprintPkgsKey = "blueprint" ) -var mountpointAllowList = []string{ - "/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home", "/tmp", -} +var ( + mountpointAllowList = []string{ + "/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home", "/tmp", + } + + // rhel8 allow all + oscapProfileAllowList = []oscap.Profile{ + oscap.AnssiBp28Enhanced, + oscap.AnssiBp28High, + oscap.AnssiBp28Intermediary, + oscap.AnssiBp28Minimal, + oscap.Cis, + oscap.CisServerL1, + oscap.CisWorkstationL1, + oscap.CisWorkstationL2, + oscap.Cui, + oscap.E8, + oscap.Hippa, + oscap.IsmO, + oscap.Ospp, + oscap.PciDss, + oscap.Stig, + oscap.StigGui, + } +) type distribution struct { name string @@ -646,6 +669,26 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio return fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints) } + if osc := customizations.GetOpenSCAP(); osc != nil { + // only add support for RHEL 8.7 and above. centos not supported. + if !t.arch.distro.isRHEL() || versionLessThan(t.arch.distro.osVersion, "8.7") { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported os version: %s", t.arch.distro.osVersion)) + } + supported := oscap.IsProfileAllowed(osc.ProfileID, oscapProfileAllowList) + if !supported { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported profile: %s", osc.ProfileID)) + } + if t.rpmOstree { + return fmt.Errorf("OpenSCAP customizations are not supported for ostree types") + } + if osc.DataStream == "" { + return fmt.Errorf("OpenSCAP datastream cannot be empty") + } + if osc.ProfileID == "" { + return fmt.Errorf("OpenSCAP profile cannot be empty") + } + } + return nil } diff --git a/internal/distro/rhel90/distro.go b/internal/distro/rhel90/distro.go index f4c60efb3..9784523c8 100644 --- a/internal/distro/rhel90/distro.go +++ b/internal/distro/rhel90/distro.go @@ -14,6 +14,7 @@ import ( "github.com/osbuild/osbuild-composer/internal/disk" "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/osbuild" + "github.com/osbuild/osbuild-composer/internal/oscap" "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/rpmmd" ) @@ -37,9 +38,33 @@ const ( blueprintPkgsKey = "blueprint" ) -var mountpointAllowList = []string{ - "/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home", "/tmp", -} +var ( + mountpointAllowList = []string{ + "/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home", "/tmp", + } + + // rhel9 & cs9 share the same list + // of allowed profiles so a single + // allow list can be used + oscapProfileAllowList = []oscap.Profile{ + oscap.AnssiBp28Enhanced, + oscap.AnssiBp28High, + oscap.AnssiBp28Intermediary, + oscap.AnssiBp28Minimal, + oscap.Cis, + oscap.CisServerL1, + oscap.CisWorkstationL1, + oscap.CisWorkstationL2, + oscap.Cui, + oscap.E8, + oscap.Hippa, + oscap.IsmO, + oscap.Ospp, + oscap.PciDss, + oscap.Stig, + oscap.StigGui, + } +) type distribution struct { name string @@ -580,6 +605,24 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio return fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints) } + if osc := customizations.GetOpenSCAP(); osc != nil { + if t.arch.distro.osVersion == "9.0" { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported os version: %s", t.arch.distro.osVersion)) + } + if !oscap.IsProfileAllowed(osc.ProfileID, oscapProfileAllowList) { + return fmt.Errorf(fmt.Sprintf("OpenSCAP unsupported profile: %s", osc.ProfileID)) + } + if t.rpmOstree { + return fmt.Errorf("OpenSCAP customizations are not supported for ostree types") + } + if osc.DataStream == "" { + return fmt.Errorf("OpenSCAP datastream cannot be empty") + } + if osc.ProfileID == "" { + return fmt.Errorf("OpenSCAP profile cannot be empty") + } + } + return nil }