Skip to content

Commit

Permalink
Add uncompressed layers support using either mounts or overlayfs (#1201)
Browse files Browse the repository at this point in the history
* Add features.sbom.containerImage.uncompressedLayersSupport using either mounts or overlayfs direct scan

* Fix after rebase on main

* Change overlayfs to overlayFS

* Add test for overlayfs direct scan

---------

Co-authored-by: levan-m <[email protected]>
  • Loading branch information
lebauce and levan-m authored Jul 12, 2024
1 parent c72fc48 commit 76d9786
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 20 deletions.
7 changes: 7 additions & 0 deletions apis/datadoghq/common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ const (
const (
SystemProbeAppArmorAnnotationKey = "container.apparmor.security.beta.kubernetes.io/system-probe"
SystemProbeAppArmorAnnotationValue = "unconfined"

AgentAppArmorAnnotationKey = "container.apparmor.security.beta.kubernetes.io/agent"
AgentAppArmorAnnotationValue = "unconfined"
)

// Datadog volume names and mount paths
Expand Down Expand Up @@ -172,6 +175,10 @@ const (
SystemProbeOSReleaseDirVolumePath = "/etc/os-release"
SystemProbeOSReleaseDirMountPath = "/host/etc/os-release"

ContainerdDirVolumeName = "host-containerd-dir"
ContainerdDirVolumePath = "/var/lib/containerd"
ContainerdDirMountPath = "/host/var/lib/containerd"

ApkDirVolumeName = "host-apk-dir"
ApkDirVolumePath = "/var/lib/apk"
ApkDirMountPath = "/host/var/lib/apk"
Expand Down
2 changes: 2 additions & 0 deletions apis/datadoghq/common/envvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ const (
DDSBOMEnabled = "DD_SBOM_ENABLED"
DDSBOMContainerImageEnabled = "DD_SBOM_CONTAINER_IMAGE_ENABLED"
DDSBOMContainerImageAnalyzers = "DD_SBOM_CONTAINER_IMAGE_ANALYZERS"
DDSBOMContainerUseMount = "DD_SBOM_CONTAINER_IMAGE_USE_MOUNT"
DDSBOMContainerOverlayFSDirectScan = "DD_SBOM_CONTAINER_IMAGE_OVERLAYFS_DIRECT_SCAN"
DDSBOMHostEnabled = "DD_SBOM_HOST_ENABLED"
DDSBOMHostAnalyzers = "DD_SBOM_HOST_ANALYZERS"
DDSecretBackendCommand = "DD_SECRET_BACKEND_COMMAND"
Expand Down
29 changes: 26 additions & 3 deletions apis/datadoghq/v2alpha1/datadogagent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,12 @@ type SBOMFeatureConfig struct {
// +optional
Enabled *bool `json:"enabled,omitempty"`

ContainerImage *SBOMTypeConfig `json:"containerImage,omitempty"`
Host *SBOMTypeConfig `json:"host,omitempty"`
ContainerImage *SBOMContainerImageConfig `json:"containerImage,omitempty"`
Host *SBOMHostConfig `json:"host,omitempty"`
}

// SBOMTypeConfig contains configuration for a SBOM collection type.
type SBOMTypeConfig struct {
type SBOMHostConfig struct {
// Enable this option to activate SBOM collection.
// Default: false
// +optional
Expand All @@ -433,6 +433,29 @@ type SBOMTypeConfig struct {
Analyzers []string `json:"analyzers,omitempty"`
}

// SBOMTypeConfig contains configuration for a SBOM collection type.
type SBOMContainerImageConfig 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"`

// Enable this option to enable support for uncompressed layers.
// Default: false
// +optional
UncompressedLayersSupport bool `json:"uncompressedLayersSupport,omitempty"`

// Enable this option to enable experimental overlayFS direct scan.
// Default: false
// +optional
OverlayFSDirectScan bool `json:"overlayFSDirectScan,omitempty"`
}

// NPMFeatureConfig contains NPM (Network Performance Monitoring) feature configuration.
// Network Performance Monitoring runs in the System Probe and Process Agent.
type NPMFeatureConfig struct {
Expand Down
37 changes: 31 additions & 6 deletions apis/datadoghq/v2alpha1/zz_generated.deepcopy.go

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

20 changes: 20 additions & 0 deletions config/crd/bases/v1/datadoghq.com_datadogagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,16 @@ spec:
Enable this option to activate SBOM collection.
Default: false
type: boolean
overlayFSDirectScan:
description: |-
Enable this option to enable experimental overlayFS direct scan.
Default: false
type: boolean
uncompressedLayersSupport:
description: |-
Enable this option to enable support for uncompressed layers.
Default: false
type: boolean
type: object
enabled:
description: |-
Expand Down Expand Up @@ -7105,6 +7115,16 @@ spec:
Enable this option to activate SBOM collection.
Default: false
type: boolean
overlayFSDirectScan:
description: |-
Enable this option to enable experimental overlayFS direct scan.
Default: false
type: boolean
uncompressedLayersSupport:
description: |-
Enable this option to enable support for uncompressed layers.
Default: false
type: boolean
type: object
enabled:
description: |-
Expand Down
6 changes: 6 additions & 0 deletions config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4820,6 +4820,12 @@ spec:
enabled:
description: 'Enable this option to activate SBOM collection. Default: false'
type: boolean
overlayFSDirectScan:
description: 'Enable this option to enable experimental overlayFS direct scan. Default: false'
type: boolean
uncompressedLayersSupport:
description: 'Enable this option to enable support for uncompressed layers. Default: false'
type: boolean
type: object
enabled:
description: 'Enable this option to activate SBOM collection. Default: false'
Expand Down
45 changes: 38 additions & 7 deletions controllers/datadogagent/feature/sbom/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ type sbomFeature struct {
owner metav1.Object
logger logr.Logger

enabled bool
containerImageEnabled bool
containerImageAnalyzers []string
hostEnabled bool
hostAnalyzers []string
enabled bool
containerImageEnabled bool
containerImageAnalyzers []string
containerImageUncompressedLayersSupport bool
containerImageOverlayFSDirectScan bool
hostEnabled bool
hostAnalyzers []string
}

// ID returns the ID of the Feature
Expand All @@ -70,6 +72,8 @@ func (f *sbomFeature) Configure(dda *v2alpha1.DatadogAgent) (reqComp feature.Req
if sbomConfig.ContainerImage != nil && apiutils.BoolValue(sbomConfig.ContainerImage.Enabled) {
f.containerImageEnabled = true
f.containerImageAnalyzers = sbomConfig.ContainerImage.Analyzers
f.containerImageUncompressedLayersSupport = sbomConfig.ContainerImage.UncompressedLayersSupport
f.containerImageOverlayFSDirectScan = sbomConfig.ContainerImage.OverlayFSDirectScan
}
if sbomConfig.Host != nil && apiutils.BoolValue(sbomConfig.Host.Enabled) {
f.hostEnabled = true
Expand Down Expand Up @@ -112,14 +116,14 @@ func mergeConfigs(ddaSpec *v2alpha1.DatadogAgentSpec, ddaStatus *v2alpha1.Datado

if ddaStatus.RemoteConfigConfiguration.Features.SBOM.Host != nil && ddaStatus.RemoteConfigConfiguration.Features.SBOM.Host.Enabled != nil {
if ddaSpec.Features.SBOM.Host == nil {
ddaSpec.Features.SBOM.Host = &v2alpha1.SBOMTypeConfig{}
ddaSpec.Features.SBOM.Host = &v2alpha1.SBOMHostConfig{}
}
ddaSpec.Features.SBOM.Host.Enabled = ddaStatus.RemoteConfigConfiguration.Features.SBOM.Host.Enabled
}

if ddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage != nil && ddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage.Enabled != nil {
if ddaSpec.Features.SBOM.ContainerImage == nil {
ddaSpec.Features.SBOM.ContainerImage = &v2alpha1.SBOMTypeConfig{}
ddaSpec.Features.SBOM.ContainerImage = &v2alpha1.SBOMContainerImageConfig{}
}
ddaSpec.Features.SBOM.ContainerImage.Enabled = ddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage.Enabled
}
Expand Down Expand Up @@ -161,6 +165,33 @@ func (f *sbomFeature) ManageNodeAgent(managers feature.PodTemplateManagers, prov
Value: strings.Join(f.containerImageAnalyzers, " "),
})
}
if f.containerImageUncompressedLayersSupport {
if f.containerImageOverlayFSDirectScan {
managers.EnvVar().AddEnvVarToContainer(apicommonv1.CoreAgentContainerName, &corev1.EnvVar{
Name: apicommon.DDSBOMContainerOverlayFSDirectScan,
Value: "true",
})
} else {
managers.EnvVar().AddEnvVarToContainer(apicommonv1.CoreAgentContainerName, &corev1.EnvVar{
Name: apicommon.DDSBOMContainerUseMount,
Value: "true",
})

managers.SecurityContext().AddCapabilitiesToContainer(
[]corev1.Capability{"SYS_ADMIN"},
apicommonv1.CoreAgentContainerName,
)

managers.Annotation().AddAnnotation(apicommon.AgentAppArmorAnnotationKey, apicommon.AgentAppArmorAnnotationValue)
}

volMgr := managers.Volume()
volMountMgr := managers.VolumeMount()

containerdLibVol, containerdLibVolMount := volume.GetVolumes(apicommon.ContainerdDirVolumeName, apicommon.ContainerdDirVolumePath, apicommon.ContainerdDirMountPath, true)
volMountMgr.AddVolumeMountToContainer(&containerdLibVolMount, apicommonv1.CoreAgentContainerName)
volMgr.AddVolume(&containerdLibVol)
}

managers.EnvVar().AddEnvVar(&corev1.EnvVar{
Name: apicommon.DDSBOMHostEnabled,
Expand Down
44 changes: 42 additions & 2 deletions controllers/datadogagent/feature/sbom/feature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ func Test_sbomFeature_Configure(t *testing.T) {

sbomEnabledContainerImageEnabled := sbomEnabled.DeepCopy()
{
sbomEnabledContainerImageEnabled.Spec.Features.SBOM.ContainerImage = &v2alpha1.SBOMTypeConfig{Enabled: apiutils.NewBoolPointer(true)}
sbomEnabledContainerImageEnabled.Spec.Features.SBOM.ContainerImage = &v2alpha1.SBOMContainerImageConfig{Enabled: apiutils.NewBoolPointer(true)}
}

sbomEnabledContainerImageOverlayFSEnabled := sbomEnabled.DeepCopy()
{
sbomEnabledContainerImageOverlayFSEnabled.Spec.Features.SBOM.ContainerImage = &v2alpha1.SBOMContainerImageConfig{Enabled: apiutils.NewBoolPointer(true), UncompressedLayersSupport: true, OverlayFSDirectScan: true}
}

sbomEnabledHostEnabled := sbomEnabled.DeepCopy()
{
sbomEnabledHostEnabled.Spec.Features.SBOM.Host = &v2alpha1.SBOMTypeConfig{Enabled: apiutils.NewBoolPointer(true)}
sbomEnabledHostEnabled.Spec.Features.SBOM.Host = &v2alpha1.SBOMHostConfig{Enabled: apiutils.NewBoolPointer(true)}
}

sbomNodeAgentWantFunc := func(t testing.TB, mgrInterface feature.PodTemplateManagers) {
Expand Down Expand Up @@ -90,6 +95,35 @@ func Test_sbomFeature_Configure(t *testing.T) {
assert.True(t, apiutils.IsEqualStruct(nodeAgentEnvVars, wantEnvVars), "Node agent envvars \ndiff = %s", cmp.Diff(nodeAgentEnvVars, wantEnvVars))
}

sbomWithContainerImageOverlayFSWantFunc := 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]
nodeCoreAgentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommonv1.CoreAgentContainerName]
assert.True(t, apiutils.IsEqualStruct(nodeAgentEnvVars, wantEnvVars), "Node agent envvars \ndiff = %s", cmp.Diff(nodeAgentEnvVars, wantEnvVars))

wantEnvVars = []*corev1.EnvVar{{
Name: apicommon.DDSBOMContainerOverlayFSDirectScan,
Value: "true",
}}
assert.True(t, apiutils.IsEqualStruct(nodeCoreAgentEnvVars, wantEnvVars), "Core agent envvars \ndiff = %s", cmp.Diff(nodeCoreAgentEnvVars, wantEnvVars))
}

sbomWithHostWantFunc := func(t testing.TB, mgrInterface feature.PodTemplateManagers) {
mgr := mgrInterface.(*fake.PodTemplateManagers)

Expand Down Expand Up @@ -255,6 +289,12 @@ func Test_sbomFeature_Configure(t *testing.T) {
WantConfigure: true,
Agent: test.NewDefaultComponentTest().WithWantFunc(sbomWithContainerImageWantFunc),
},
{
Name: "SBOM enabled, ContainerImage enabled, overlayFS direct scan",
DDAv2: sbomEnabledContainerImageOverlayFSEnabled,
WantConfigure: true,
Agent: test.NewDefaultComponentTest().WithWantFunc(sbomWithContainerImageOverlayFSWantFunc),
},
{
Name: "SBOM enabled, Host enabled",
DDAv2: sbomEnabledHostEnabled,
Expand Down
2 changes: 2 additions & 0 deletions docs/configuration.v2alpha1.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ spec:
| 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.containerImage.overlayFSDirectScan | Enable this option to enable experimental overlayFS direct scan. Default: false |
| features.sbom.containerImage.uncompressedLayersSupport | Enable this option to enable support for uncompressed layers. 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 |
Expand Down
4 changes: 2 additions & 2 deletions pkg/remoteconfig/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func (r *RemoteConfigUpdater) updateInstanceStatus(dda v2alpha1.DatadogAgent, cf
// SBOM HOST
if cfg.CoreAgent.SBOM.Host != nil {
if newddaStatus.RemoteConfigConfiguration.Features.SBOM.Host == nil {
newddaStatus.RemoteConfigConfiguration.Features.SBOM.Host = &v2alpha1.SBOMTypeConfig{}
newddaStatus.RemoteConfigConfiguration.Features.SBOM.Host = &v2alpha1.SBOMHostConfig{}
}
if newddaStatus.RemoteConfigConfiguration.Features.SBOM.Host.Enabled == nil {
newddaStatus.RemoteConfigConfiguration.Features.SBOM.Host.Enabled = new(bool)
Expand All @@ -457,7 +457,7 @@ func (r *RemoteConfigUpdater) updateInstanceStatus(dda v2alpha1.DatadogAgent, cf
// SBOM CONTAINER IMAGE
if cfg.CoreAgent.SBOM.ContainerImage != nil {
if newddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage == nil {
newddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage = &v2alpha1.SBOMTypeConfig{}
newddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage = &v2alpha1.SBOMContainerImageConfig{}
}
if newddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage.Enabled == nil {
newddaStatus.RemoteConfigConfiguration.Features.SBOM.ContainerImage.Enabled = new(bool)
Expand Down

0 comments on commit 76d9786

Please sign in to comment.