Skip to content

Commit 9f692e2

Browse files
committed
Wire Kustomize activation through scan and CLI paths with dedupe and lint-safe scan pipeline refactors.
1 parent d349b4e commit 9f692e2

11 files changed

Lines changed: 1037 additions & 111 deletions

File tree

cmd/scanner/scan.go

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"path/filepath"
1111
"strings"
12+
"time"
1213

1314
"github.com/DataDog/datadog-iac-scanner/internal/console"
1415
"github.com/DataDog/datadog-iac-scanner/pkg/config"
@@ -74,10 +75,33 @@ var scanAction = &cli.Command{
7475
Usage: "a list of platform types to scan",
7576
Value: GetSupportedPlatforms(),
7677
},
77-
// NOTE: --x-parallelparsing flag disabled due to pre-existing race conditions
78-
// in concurrent query workers (SetupLogs shared state write, docker detector
79-
// shallow slice copy) that cause non-deterministic violation counts.
80-
// See K9VULN-13746 for the follow-up to fix and re-enable.
78+
&cli.BoolFlag{
79+
Name: "helm-include-crds",
80+
Usage: "when rendering Helm charts, include CRDs in the manifest output",
81+
Value: true,
82+
},
83+
&cli.BoolFlag{
84+
Name: "kustomize-enable-helm-inflation",
85+
Usage: "when building kustomizations, pre-render helmCharts entries with the Helm SDK",
86+
Value: true,
87+
},
88+
&cli.DurationFlag{
89+
Name: "kustomize-render-timeout",
90+
Usage: "maximum time allowed for a single kustomize build",
91+
Value: 60 * time.Second,
92+
},
93+
&cli.IntFlag{
94+
Name: "kustomize-max-fetch-mib",
95+
Usage: "soft cap for scratch data during kustomize resolve (staging, Helm prepass; best-effort)",
96+
Value: 128,
97+
},
98+
&cli.BoolFlag{
99+
Name: "kustomize-strict-loads",
100+
Usage: "use kustomize RootOnly load restrictions (safer; may reject some valid ../ references " +
101+
"like secretGenerator.envs outside the kustomization root)",
102+
Value: false,
103+
},
104+
// NOTE: --x-parallelparsing left out: parallel query workers still race → flaky counts.
81105
// &cli.BoolFlag{
82106
// Name: "x-parallelparsing",
83107
// Hidden: true,
@@ -93,6 +117,48 @@ const (
93117
dirPerms = 0755
94118
)
95119

120+
func scanParametersFromCLI(
121+
c *cli.Command,
122+
repoDir string,
123+
repoInfo *model.RepositoryCommitInfo,
124+
inputPaths []string,
125+
outputPath, payloadPath string,
126+
cfg *config.IacConfig,
127+
) *scan.Parameters {
128+
maxFetchMib := c.Int("kustomize-max-fetch-mib")
129+
if maxFetchMib <= 0 {
130+
maxFetchMib = 128
131+
}
132+
return &scan.Parameters{
133+
CloudProvider: []string{""},
134+
OutputPath: outputPath,
135+
OutputName: c.String("output-name"),
136+
PreviewLines: 3,
137+
RepoPath: repoDir,
138+
Path: inputPaths,
139+
QueriesPath: []string{"./assets/queries"},
140+
LibrariesPath: "./assets/libraries",
141+
ReportFormats: []string{"sarif"},
142+
Platform: selectPlatforms(c.StringSlice("type")),
143+
QueryExecTimeout: c.Int("timeout"),
144+
DisableSecrets: true,
145+
ScanID: "console",
146+
MaxFileSizeFlag: c.Int("max-file-size"),
147+
MaxResolverDepth: c.Int("max-resolver-depth"),
148+
ExcludePlatform: []string{""},
149+
PayloadPath: payloadPath,
150+
SCIInfo: model.SCIInfo{RepositoryDir: repoDir, RepositoryCommitInfo: *repoInfo},
151+
FlagEvaluator: getFeatureFlagEvaluator(c),
152+
Config: *cfg,
153+
DownloadQueriesFromDatadog: c.Bool("x-downloadqueriesfromdatadog"),
154+
HelmIncludeCRDs: c.Bool("helm-include-crds"),
155+
KustomizeEnableHelmInflation: c.Bool("kustomize-enable-helm-inflation"),
156+
KustomizeRenderTimeout: c.Duration("kustomize-render-timeout"),
157+
KustomizeMaxFetchBytes: int64(maxFetchMib) * 1024 * 1024,
158+
KustomizeStrictLoad: c.Bool("kustomize-strict-loads"),
159+
}
160+
}
161+
96162
func runScan(ctx context.Context, c *cli.Command) error {
97163
if c.Args().Len() > 0 {
98164
return fmt.Errorf("unexpected arguments: %v", c.Args().Slice())
@@ -141,29 +207,7 @@ func runScan(ctx context.Context, c *cli.Command) error {
141207
}
142208
cfg.OnlyPaths = onlyPaths
143209
cfg.IgnoreRules = append(c.StringSlice("exclude-queries"), cfg.IgnoreRules...)
144-
params := &scan.Parameters{
145-
CloudProvider: []string{""},
146-
OutputPath: outputPath,
147-
OutputName: c.String("output-name"),
148-
PreviewLines: 3,
149-
RepoPath: repoDir,
150-
Path: inputPaths,
151-
QueriesPath: []string{"./assets/queries"},
152-
LibrariesPath: "./assets/libraries",
153-
ReportFormats: []string{"sarif"},
154-
Platform: selectPlatforms(c.StringSlice("type")),
155-
QueryExecTimeout: c.Int("timeout"),
156-
DisableSecrets: true,
157-
ScanID: "console",
158-
MaxFileSizeFlag: c.Int("max-file-size"),
159-
MaxResolverDepth: c.Int("max-resolver-depth"),
160-
ExcludePlatform: []string{""},
161-
PayloadPath: payloadPath,
162-
SCIInfo: model.SCIInfo{RepositoryDir: repoDir, RepositoryCommitInfo: *repoInfo},
163-
FlagEvaluator: getFeatureFlagEvaluator(c),
164-
Config: *cfg,
165-
DownloadQueriesFromDatadog: c.Bool("x-downloadqueriesfromdatadog"),
166-
}
210+
params := scanParametersFromCLI(c, repoDir, repoInfo, inputPaths, outputPath, payloadPath, cfg)
167211

168212
metadata, err := console.ExecuteScan(ctx, params)
169213
if err != nil {
@@ -366,8 +410,7 @@ func selectPlatforms(platforms []string) []string {
366410

367411
func getFeatureFlagEvaluator(_ *cli.Command) featureflags.FlagEvaluator {
368412
overrides := map[string]bool{}
369-
// Parallel parsing disabled: triggers race conditions in concurrent
370-
// query workers causing non-deterministic violation counts.
413+
// Parallel parsing off until worker races are fixed (non-deterministic counts).
371414
// overrides[featureflags.IaCEnableKicsParallelFileParsing] = c.Bool("x-parallelparsing")
372415
return featureflags.NewLocalEvaluatorWithOverrides(overrides)
373416
}

pkg/analyzer/analyzer.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/DataDog/datadog-iac-scanner/pkg/engine/provider"
2020
"github.com/DataDog/datadog-iac-scanner/pkg/logger"
2121
"github.com/DataDog/datadog-iac-scanner/pkg/model"
22+
"github.com/DataDog/datadog-iac-scanner/pkg/resolver/kustomize"
2223
"github.com/DataDog/datadog-iac-scanner/pkg/utils"
2324
"github.com/pkg/errors"
2425
ignore "github.com/sabhiram/go-gitignore"
@@ -507,12 +508,26 @@ func needsOverride(check bool, returnType, key, ext string) bool {
507508
return false
508509
}
509510

511+
func (a *analyzerInfo) tryKustomizeEntry(results, unwanted chan<- string) bool {
512+
if !kustomize.IsKustomizationEntryFile(a.filePath) {
513+
return false
514+
}
515+
if a.isAvailableType(kubernetes) && checkKustomize(a.filePath) {
516+
results <- kubernetes
517+
}
518+
unwanted <- a.filePath
519+
return true
520+
}
521+
510522
// checkContent will determine the file type by content when worker was unable to
511523
// determine by ext, if no type was determined checkContent adds it to unwanted channel
512524
func (a *analyzerInfo) checkContent(ctx context.Context, results, unwanted chan<- string, locCount chan<- int, linesCount int, ext string) {
513525
contextLogger := logger.FromContext(ctx)
514526
typesFlag := a.typesFlag
515527
excludeTypesFlag := a.excludeTypesFlag
528+
if a.tryKustomizeEntry(results, unwanted) {
529+
return
530+
}
516531
// get file content
517532
content, err := os.ReadFile(a.filePath)
518533
if err != nil {
@@ -564,6 +579,9 @@ func (a *analyzerInfo) checkContent(ctx context.Context, results, unwanted chan<
564579
}
565580

566581
func checkReturnType(ctx context.Context, path, returnType, ext string, content []byte) string {
582+
if kustomize.IsKustomizationEntryFile(path) {
583+
return ""
584+
}
567585
if returnType != "" {
568586
switch returnType {
569587
case "cdkTf":
@@ -578,6 +596,9 @@ func checkReturnType(ctx context.Context, path, returnType, ext string, content
578596
if checkHelm(ctx, path) {
579597
return kubernetes
580598
}
599+
if checkKustomize(path) {
600+
return kubernetes
601+
}
581602
platform := checkYamlPlatform(ctx, content, path)
582603
if platform != "" {
583604
return platform
@@ -598,6 +619,14 @@ func checkHelm(ctx context.Context, path string) bool {
598619
return true
599620
}
600621

622+
func checkKustomize(path string) bool {
623+
dir := filepath.Dir(path)
624+
if _, ok := kustomize.Detect(dir); ok {
625+
return true
626+
}
627+
return false
628+
}
629+
601630
func checkYamlPlatform(ctx context.Context, content []byte, path string) string {
602631
// Ansible 'templates/' directories contain Jinja2 files; {{ }} syntax is invalid YAML.
603632
if isInsideAnsibleTemplatesDir(path) {

pkg/analyzer/analyzer_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,36 @@ func TestAnalyzer_Analyze(t *testing.T) {
212212
excludeGitIgnore: false,
213213
MaxFileSize: -1,
214214
},
215+
{
216+
name: "analyze_test_explicit_kustomization_file_enables_kustomize_without_raw_parse",
217+
paths: []string{
218+
filepath.FromSlash("../../test/fixtures/test_kustomize/canonical/simple/kustomization.yaml"),
219+
},
220+
wantTypes: []string{"kubernetes"},
221+
wantExclude: []string{filepath.FromSlash("../../test/fixtures/test_kustomize/canonical/simple/kustomization.yaml")},
222+
typesFromFlag: []string{""},
223+
excludeTypesFromFlag: []string{""},
224+
wantLOC: 0,
225+
wantErr: false,
226+
gitIgnoreFileName: "",
227+
excludeGitIgnore: false,
228+
MaxFileSize: -1,
229+
},
230+
{
231+
name: "analyze_test_overlay_directory_with_only_kustomization_still_enables_kubernetes",
232+
paths: []string{
233+
filepath.FromSlash("../../test/fixtures/test_kustomize/regressions/namespace_overlay/overlay"),
234+
},
235+
wantTypes: []string{"kubernetes"},
236+
wantExclude: []string{filepath.FromSlash("../../test/fixtures/test_kustomize/regressions/namespace_overlay/overlay/kustomization.yaml")},
237+
typesFromFlag: []string{""},
238+
excludeTypesFromFlag: []string{""},
239+
wantLOC: 0,
240+
wantErr: false,
241+
gitIgnoreFileName: "",
242+
excludeGitIgnore: false,
243+
MaxFileSize: -1,
244+
},
215245
{
216246
name: "analyze_test_dir_single_path_types_value",
217247
paths: []string{filepath.FromSlash("../../test/fixtures/analyzer_test")},

0 commit comments

Comments
 (0)