From 4aa86f5876da3cc70bdde8b36c6e70c166e0e767 Mon Sep 17 00:00:00 2001 From: Sylvain Baubeau Date: Fri, 3 Nov 2023 18:55:36 +0100 Subject: [PATCH] Allow enabling SBOM collection for host and container images (#836) * Allow enabling SBOM collection for host and container images * small fixes and add test * actually add test * address comments --------- Co-authored-by: Celene --- apis/datadoghq/common/envvar.go | 5 + apis/datadoghq/v2alpha1/datadogagent_types.go | 27 ++++ .../v2alpha1/zz_generated.deepcopy.go | 60 ++++++++ .../v2alpha1/zz_generated.openapi.go | 8 +- .../bases/v1/datadoghq.com_datadogagents.yaml | 33 ++++ .../v1beta1/datadoghq.com_datadogagents.yaml | 33 ++++ controllers/datadogagent/controller.go | 1 + controllers/datadogagent/feature/ids.go | 2 + .../datadogagent/feature/sbom/feature.go | 139 +++++++++++++++++ .../datadogagent/feature/sbom/feature_test.go | 142 ++++++++++++++++++ docs/configuration.v2alpha1.md | 5 + 11 files changed, 454 insertions(+), 1 deletion(-) create mode 100644 controllers/datadogagent/feature/sbom/feature.go create mode 100644 controllers/datadogagent/feature/sbom/feature_test.go diff --git a/apis/datadoghq/common/envvar.go b/apis/datadoghq/common/envvar.go index 2c591d4cb..3b7603276 100644 --- a/apis/datadoghq/common/envvar.go +++ b/apis/datadoghq/common/envvar.go @@ -105,6 +105,11 @@ const ( DDRuntimeSecurityConfigNetworkEnabled = "DD_RUNTIME_SECURITY_CONFIG_NETWORK_ENABLED" DDRuntimeSecurityConfigActivityDumpEnabled = "DD_RUNTIME_SECURITY_CONFIG_ACTIVITY_DUMP_ENABLED" DDRuntimeSecurityConfigRemoteConfigurationEnabled = "DD_RUNTIME_SECURITY_CONFIG_REMOTE_CONFIGURATION_ENABLED" + DDSBOMEnabled = "DD_SBOM_ENABLED" + DDSBOMContainerImageEnabled = "DD_SBOM_CONTAINER_IMAGE_ENABLED" + DDSBOMContainerImageAnalyzers = "DD_SBOM_CONTAINER_IMAGE_ANALYZERS" + DDSBOMHostEnabled = "DD_SBOM_HOST_ENABLED" + DDSBOMHostAnalyzers = "DD_SBOM_HOST_ANALYZERS" DDSecretBackendCommand = "DD_SECRET_BACKEND_COMMAND" DDSite = "DD_SITE" DDSystemProbeAgentEnabled = "DD_SYSTEM_PROBE_ENABLED" diff --git a/apis/datadoghq/v2alpha1/datadogagent_types.go b/apis/datadoghq/v2alpha1/datadogagent_types.go index bbf42c155..b379159a7 100644 --- a/apis/datadoghq/v2alpha1/datadogagent_types.go +++ b/apis/datadoghq/v2alpha1/datadogagent_types.go @@ -75,6 +75,8 @@ type DatadogFeatures struct { OTLP *OTLPFeatureConfig `json:"otlp,omitempty"` // Remote Configuration configuration. RemoteConfiguration *RemoteConfigurationFeatureConfig `json:"remoteConfiguration,omitempty"` + // SBOM collection configuration. + SBOM *SBOMFeatureConfig `json:"sbom,omitempty"` // Cluster-level features @@ -317,6 +319,31 @@ type RemoteConfigurationFeatureConfig struct { Enabled *bool `json:"enabled,omitempty"` } +// SBOMFeatureConfig contains SBOM (Software Bill of Materials) collection configuration. +// SBOM runs in the Agent. +type SBOMFeatureConfig struct { + // Enable this option to activate SBOM collection. + // Default: false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + ContainerImage *SBOMTypeConfig `json:"containerImage,omitempty"` + Host *SBOMTypeConfig `json:"host,omitempty"` +} + +// SBOMTypeConfig contains configuration for a SBOM collection type. +type SBOMTypeConfig struct { + // Enable this option to activate SBOM collection. + // Default: false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Analyzers to use for SBOM collection. + // +optional + // +listType=set + Analyzers []string `json:"analyzers,omitempty"` +} + // NPMFeatureConfig contains NPM (Network Performance Monitoring) feature configuration. // Network Performance Monitoring runs in the System Probe and Process Agent. type NPMFeatureConfig struct { diff --git a/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go b/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go index 8215e0701..0052477ff 100644 --- a/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go +++ b/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go @@ -785,6 +785,11 @@ func (in *DatadogFeatures) DeepCopyInto(out *DatadogFeatures) { *out = new(RemoteConfigurationFeatureConfig) (*in).DeepCopyInto(*out) } + if in.SBOM != nil { + in, out := &in.SBOM, &out.SBOM + *out = new(SBOMFeatureConfig) + (*in).DeepCopyInto(*out) + } if in.EventCollection != nil { in, out := &in.EventCollection, &out.EventCollection *out = new(EventCollectionFeatureConfig) @@ -1606,6 +1611,61 @@ func (in *RemoteConfigurationFeatureConfig) DeepCopy() *RemoteConfigurationFeatu return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SBOMFeatureConfig) DeepCopyInto(out *SBOMFeatureConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.ContainerImage != nil { + in, out := &in.ContainerImage, &out.ContainerImage + *out = new(SBOMTypeConfig) + (*in).DeepCopyInto(*out) + } + if in.Host != nil { + in, out := &in.Host, &out.Host + *out = new(SBOMTypeConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SBOMFeatureConfig. +func (in *SBOMFeatureConfig) DeepCopy() *SBOMFeatureConfig { + if in == nil { + return nil + } + out := new(SBOMFeatureConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SBOMTypeConfig) DeepCopyInto(out *SBOMTypeConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Analyzers != nil { + in, out := &in.Analyzers, &out.Analyzers + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SBOMTypeConfig. +func (in *SBOMTypeConfig) DeepCopy() *SBOMTypeConfig { + if in == nil { + return nil + } + out := new(SBOMTypeConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SeccompConfig) DeepCopyInto(out *SeccompConfig) { *out = *in diff --git a/apis/datadoghq/v2alpha1/zz_generated.openapi.go b/apis/datadoghq/v2alpha1/zz_generated.openapi.go index c0459c3c8..6f9581363 100644 --- a/apis/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/apis/datadoghq/v2alpha1/zz_generated.openapi.go @@ -491,6 +491,12 @@ func schema__apis_datadoghq_v2alpha1_DatadogFeatures(ref common.ReferenceCallbac Ref: ref("./apis/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig"), }, }, + "sbom": { + SchemaProps: spec.SchemaProps{ + Description: "SBOM collection configuration.", + Ref: ref("./apis/datadoghq/v2alpha1.SBOMFeatureConfig"), + }, + }, "eventCollection": { SchemaProps: spec.SchemaProps{ Description: "EventCollection configuration.", @@ -537,7 +543,7 @@ func schema__apis_datadoghq_v2alpha1_DatadogFeatures(ref common.ReferenceCallbac }, }, Dependencies: []string{ - "./apis/datadoghq/v2alpha1.APMFeatureConfig", "./apis/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "./apis/datadoghq/v2alpha1.CSPMFeatureConfig", "./apis/datadoghq/v2alpha1.CWSFeatureConfig", "./apis/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "./apis/datadoghq/v2alpha1.DogstatsdFeatureConfig", "./apis/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "./apis/datadoghq/v2alpha1.EventCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "./apis/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "./apis/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.LogCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.NPMFeatureConfig", "./apis/datadoghq/v2alpha1.OOMKillFeatureConfig", "./apis/datadoghq/v2alpha1.OTLPFeatureConfig", "./apis/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "./apis/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "./apis/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "./apis/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "./apis/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "./apis/datadoghq/v2alpha1.USMFeatureConfig"}, + "./apis/datadoghq/v2alpha1.APMFeatureConfig", "./apis/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "./apis/datadoghq/v2alpha1.CSPMFeatureConfig", "./apis/datadoghq/v2alpha1.CWSFeatureConfig", "./apis/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "./apis/datadoghq/v2alpha1.DogstatsdFeatureConfig", "./apis/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "./apis/datadoghq/v2alpha1.EventCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "./apis/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "./apis/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.LogCollectionFeatureConfig", "./apis/datadoghq/v2alpha1.NPMFeatureConfig", "./apis/datadoghq/v2alpha1.OOMKillFeatureConfig", "./apis/datadoghq/v2alpha1.OTLPFeatureConfig", "./apis/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "./apis/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "./apis/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "./apis/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "./apis/datadoghq/v2alpha1.SBOMFeatureConfig", "./apis/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "./apis/datadoghq/v2alpha1.USMFeatureConfig"}, } } diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index 6d5ce32b9..bc5233324 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -8359,6 +8359,39 @@ spec: description: 'Enable this option to activate Remote Configuration. Default: true' type: boolean type: object + sbom: + description: SBOM collection configuration. + properties: + containerImage: + description: SBOMTypeConfig contains configuration for a SBOM collection type. + properties: + analyzers: + description: Analyzers to use for SBOM collection. + items: + type: string + type: array + x-kubernetes-list-type: set + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + type: object + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + host: + description: SBOMTypeConfig contains configuration for a SBOM collection type. + properties: + analyzers: + description: Analyzers to use for SBOM collection. + items: + type: string + type: array + x-kubernetes-list-type: set + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + type: object + type: object tcpQueueLength: description: TCPQueueLength configuration. properties: diff --git a/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml index 725db67e3..ac96dac55 100644 --- a/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml @@ -15909,6 +15909,39 @@ spec: description: 'Enable this option to activate Remote Configuration. Default: true' type: boolean type: object + sbom: + description: SBOM collection configuration. + properties: + containerImage: + description: SBOMTypeConfig contains configuration for a SBOM collection type. + properties: + analyzers: + description: Analyzers to use for SBOM collection. + items: + type: string + type: array + x-kubernetes-list-type: set + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + type: object + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + host: + description: SBOMTypeConfig contains configuration for a SBOM collection type. + properties: + analyzers: + description: Analyzers to use for SBOM collection. + items: + type: string + type: array + x-kubernetes-list-type: set + enabled: + description: 'Enable this option to activate SBOM collection. Default: false' + type: boolean + type: object + type: object tcpQueueLength: description: TCPQueueLength configuration. properties: diff --git a/controllers/datadogagent/controller.go b/controllers/datadogagent/controller.go index dd94474d6..0e5617dbf 100644 --- a/controllers/datadogagent/controller.go +++ b/controllers/datadogagent/controller.go @@ -55,6 +55,7 @@ import ( _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/processdiscovery" _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/prometheusscrape" _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/remoteconfig" + _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/sbom" _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/tcpqueuelength" _ "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/usm" ) diff --git a/controllers/datadogagent/feature/ids.go b/controllers/datadogagent/feature/ids.go index b6c7d3274..9faa5e8eb 100644 --- a/controllers/datadogagent/feature/ids.go +++ b/controllers/datadogagent/feature/ids.go @@ -55,6 +55,8 @@ const ( OTLPIDType = "otlp" // RemoteConfigurationIDType Remote Config feature RemoteConfigurationIDType = "remote_config" + // SBOMIDType SBOM collection feature + SBOMIDType = "sbom" // DummyIDType Dummy feature. DummyIDType = "dummy" ) diff --git a/controllers/datadogagent/feature/sbom/feature.go b/controllers/datadogagent/feature/sbom/feature.go new file mode 100644 index 000000000..f547d63ce --- /dev/null +++ b/controllers/datadogagent/feature/sbom/feature.go @@ -0,0 +1,139 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package sbom + +import ( + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/DataDog/datadog-operator/apis/datadoghq/v1alpha1" + "github.com/DataDog/datadog-operator/apis/datadoghq/v2alpha1" + apiutils "github.com/DataDog/datadog-operator/apis/utils" + "github.com/go-logr/logr" + + apicommon "github.com/DataDog/datadog-operator/apis/datadoghq/common" + apicommonv1 "github.com/DataDog/datadog-operator/apis/datadoghq/common/v1" + + "github.com/DataDog/datadog-operator/controllers/datadogagent/feature" +) + +func init() { + err := feature.Register(feature.SBOMIDType, buildSBOMFeature) + if err != nil { + panic(err) + } +} + +func buildSBOMFeature(options *feature.Options) feature.Feature { + sbomFeature := &sbomFeature{} + + if options != nil { + sbomFeature.logger = options.Logger + } + + return sbomFeature +} + +type sbomFeature struct { + owner metav1.Object + logger logr.Logger + + enabled bool + containerImageEnabled bool + containerImageAnalyzers []string + hostEnabled bool + hostAnalyzers []string +} + +// ID returns the ID of the Feature +func (f *sbomFeature) ID() feature.IDType { + return feature.SBOMIDType +} + +// Configure is used to configure the feature from a v2alpha1.DatadogAgent instance. +func (f *sbomFeature) Configure(dda *v2alpha1.DatadogAgent) (reqComp feature.RequiredComponents) { + f.owner = dda + + if dda.Spec.Features != nil && dda.Spec.Features.SBOM != nil && apiutils.BoolValue(dda.Spec.Features.SBOM.Enabled) { + f.enabled = true + if dda.Spec.Features.SBOM.ContainerImage != nil && apiutils.BoolValue(dda.Spec.Features.SBOM.ContainerImage.Enabled) { + f.containerImageEnabled = true + f.containerImageAnalyzers = dda.Spec.Features.SBOM.ContainerImage.Analyzers + } + if dda.Spec.Features.SBOM.Host != nil && apiutils.BoolValue(dda.Spec.Features.SBOM.Host.Enabled) { + f.hostEnabled = true + f.hostAnalyzers = dda.Spec.Features.SBOM.Host.Analyzers + } + reqComp = feature.RequiredComponents{ + Agent: feature.RequiredComponent{ + IsRequired: apiutils.NewBoolPointer(true), + Containers: []apicommonv1.AgentContainerName{ + apicommonv1.CoreAgentContainerName, + }, + }, + } + } + + return reqComp +} + +// ConfigureV1 use to configure the feature from a v1alpha1.DatadogAgent instance. +func (f *sbomFeature) ConfigureV1(dda *v1alpha1.DatadogAgent) (reqComp feature.RequiredComponents) { + return +} + +// ManageDependencies allows a feature to manage its dependencies. +// Feature's dependencies should be added in the store. +func (f *sbomFeature) ManageDependencies(managers feature.ResourceManagers, components feature.RequiredComponents) error { + return nil +} + +// ManageClusterAgent allows a feature to configure the ClusterAgent's corev1.PodTemplateSpec +// It should do nothing if the feature doesn't need to configure it. +func (f *sbomFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { + return nil +} + +// ManageNodeAgent allows a feature to configure the Node Agent's corev1.PodTemplateSpec +// It should do nothing if the feature doesn't need to configure it. +func (f *sbomFeature) ManageNodeAgent(managers feature.PodTemplateManagers) error { + managers.EnvVar().AddEnvVar(&corev1.EnvVar{ + Name: apicommon.DDSBOMEnabled, + Value: apiutils.BoolToString(&f.enabled), + }) + + managers.EnvVar().AddEnvVar(&corev1.EnvVar{ + Name: apicommon.DDSBOMContainerImageEnabled, + Value: apiutils.BoolToString(&f.containerImageEnabled), + }) + if len(f.containerImageAnalyzers) > 0 { + managers.EnvVar().AddEnvVar(&corev1.EnvVar{ + Name: apicommon.DDSBOMContainerImageAnalyzers, + Value: strings.Join(f.containerImageAnalyzers, " "), + }) + } + + managers.EnvVar().AddEnvVar(&corev1.EnvVar{ + Name: apicommon.DDSBOMHostEnabled, + Value: apiutils.BoolToString(&f.hostEnabled), + }) + if len(f.hostAnalyzers) > 0 { + managers.EnvVar().AddEnvVar(&corev1.EnvVar{ + Name: apicommon.DDSBOMHostAnalyzers, + Value: strings.Join(f.hostAnalyzers, " "), + }) + } + + return nil +} + +// ManageClusterChecksRunner allows a feature to configure the ClusterChecksRunner's corev1.PodTemplateSpec +// It should do nothing if the feature doesn't need to configure it. +func (f *sbomFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { + return nil +} diff --git a/controllers/datadogagent/feature/sbom/feature_test.go b/controllers/datadogagent/feature/sbom/feature_test.go new file mode 100644 index 000000000..9bfd6a5de --- /dev/null +++ b/controllers/datadogagent/feature/sbom/feature_test.go @@ -0,0 +1,142 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package sbom + +import ( + "testing" + + apicommon "github.com/DataDog/datadog-operator/apis/datadoghq/common" + apicommonv1 "github.com/DataDog/datadog-operator/apis/datadoghq/common/v1" + "github.com/DataDog/datadog-operator/apis/datadoghq/v2alpha1" + apiutils "github.com/DataDog/datadog-operator/apis/utils" + "github.com/DataDog/datadog-operator/controllers/datadogagent/feature" + "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/fake" + "github.com/DataDog/datadog-operator/controllers/datadogagent/feature/test" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" +) + +func Test_sbomFeature_Configure(t *testing.T) { + + sbomDisabled := v2alpha1.DatadogAgent{ + Spec: v2alpha1.DatadogAgentSpec{ + Features: &v2alpha1.DatadogFeatures{ + SBOM: &v2alpha1.SBOMFeatureConfig{ + Enabled: apiutils.NewBoolPointer(false), + }, + }, + }, + } + sbomEnabled := sbomDisabled.DeepCopy() + { + sbomEnabled.Spec.Features.SBOM.Enabled = apiutils.NewBoolPointer(true) + } + + sbomEnabledContainerImageEnabled := sbomEnabled.DeepCopy() + { + sbomEnabledContainerImageEnabled.Spec.Features.SBOM.ContainerImage = &v2alpha1.SBOMTypeConfig{Enabled: apiutils.NewBoolPointer(true)} + } + + sbomEnabledHostEnabled := sbomEnabled.DeepCopy() + { + sbomEnabledHostEnabled.Spec.Features.SBOM.Host = &v2alpha1.SBOMTypeConfig{Enabled: apiutils.NewBoolPointer(true)} + } + + sbomNodeAgentWantFunc := func(t testing.TB, mgrInterface feature.PodTemplateManagers) { + mgr := mgrInterface.(*fake.PodTemplateManagers) + + wantEnvVars := []*corev1.EnvVar{ + { + Name: apicommon.DDSBOMEnabled, + Value: "true", + }, + { + Name: apicommon.DDSBOMContainerImageEnabled, + Value: "false", + }, + { + Name: apicommon.DDSBOMHostEnabled, + Value: "false", + }, + } + + nodeAgentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommonv1.AllContainers] + assert.True(t, apiutils.IsEqualStruct(nodeAgentEnvVars, wantEnvVars), "Node agent envvars \ndiff = %s", cmp.Diff(nodeAgentEnvVars, wantEnvVars)) + } + + sbomWithContainerImageWantFunc := func(t testing.TB, mgrInterface feature.PodTemplateManagers) { + mgr := mgrInterface.(*fake.PodTemplateManagers) + + wantEnvVars := []*corev1.EnvVar{ + { + Name: apicommon.DDSBOMEnabled, + Value: "true", + }, + { + Name: apicommon.DDSBOMContainerImageEnabled, + Value: "true", + }, + { + Name: apicommon.DDSBOMHostEnabled, + Value: "false", + }, + } + + nodeAgentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommonv1.AllContainers] + assert.True(t, apiutils.IsEqualStruct(nodeAgentEnvVars, wantEnvVars), "Node agent envvars \ndiff = %s", cmp.Diff(nodeAgentEnvVars, wantEnvVars)) + } + + sbomWithHostWantFunc := func(t testing.TB, mgrInterface feature.PodTemplateManagers) { + mgr := mgrInterface.(*fake.PodTemplateManagers) + + wantEnvVars := []*corev1.EnvVar{ + { + Name: apicommon.DDSBOMEnabled, + Value: "true", + }, + { + Name: apicommon.DDSBOMContainerImageEnabled, + Value: "false", + }, + { + Name: apicommon.DDSBOMHostEnabled, + Value: "true", + }, + } + + nodeAgentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommonv1.AllContainers] + assert.True(t, apiutils.IsEqualStruct(nodeAgentEnvVars, wantEnvVars), "Node agent envvars \ndiff = %s", cmp.Diff(nodeAgentEnvVars, wantEnvVars)) + } + + tests := test.FeatureTestSuite{ + { + Name: "SBOM not enabled", + DDAv2: sbomDisabled.DeepCopy(), + WantConfigure: false, + }, + { + Name: "SBOM enabled", + DDAv2: sbomEnabled, + WantConfigure: true, + Agent: test.NewDefaultComponentTest().WithWantFunc(sbomNodeAgentWantFunc), + }, + { + Name: "SBOM enabled, ContainerImage enabled", + DDAv2: sbomEnabledContainerImageEnabled, + WantConfigure: true, + Agent: test.NewDefaultComponentTest().WithWantFunc(sbomWithContainerImageWantFunc), + }, + { + Name: "SBOM enabled, Host enabled", + DDAv2: sbomEnabledHostEnabled, + WantConfigure: true, + Agent: test.NewDefaultComponentTest().WithWantFunc(sbomWithHostWantFunc), + }, + } + + tests.Run(t, buildSBOMFeature) +} diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index 57117492f..c1571be67 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -122,6 +122,11 @@ spec: | features.prometheusScrape.enabled | Enable autodiscovery of pods and services exposing Prometheus metrics. Default: false | | features.prometheusScrape.version | Version specifies the version of the OpenMetrics check. Default: 2 | | features.remoteConfiguration.enabled | Enable this option to activate Remote Configuration. Default: true | +| features.sbom.containerImage.analyzers | Analyzers to use for SBOM collection. | +| features.sbom.containerImage.enabled | Enable this option to activate SBOM collection. Default: false | +| features.sbom.enabled | Enable this option to activate SBOM collection. Default: false | +| features.sbom.host.analyzers | Analyzers to use for SBOM collection. | +| features.sbom.host.enabled | Enable this option to activate SBOM collection. Default: false | | features.tcpQueueLength.enabled | Enables the TCP queue length eBPF-based check. Default: false | | features.usm.enabled | Enabled enables Universal Service Monitoring. Default: false | | global.clusterAgentToken | ClusterAgentToken is the token for communication between the NodeAgent and ClusterAgent. |