diff --git a/acceptance/cli/cli.go b/acceptance/cli/cli.go index c9419348d..4352da09c 100644 --- a/acceptance/cli/cli.go +++ b/acceptance/cli/cli.go @@ -223,7 +223,7 @@ func setupKeys(ctx context.Context, vars map[string]string, environment []string vars[name+"_PUBLIC_KEY"] = key.Name() // Handle some variations in indentation - vars[fmt.Sprintf("__________%s_PUBLIC_KEY", name)] = snaps.Indent(publicKey, 10) + vars[fmt.Sprintf("________%s_PUBLIC_KEY", name)] = snaps.Indent(publicKey, 10) vars[name+"_PUBLIC_KEY_JSON"] = strings.ReplaceAll(publicKey, "\n", "\\n") diff --git a/cmd/validate/image.go b/cmd/validate/image.go index 2e19d99b2..8a194e7a8 100644 --- a/cmd/validate/image.go +++ b/cmd/validate/image.go @@ -301,7 +301,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { type result struct { err error component applicationsnapshot.Component - data []evaluator.Data + data map[string]evaluator.Data policyInput []byte } @@ -343,6 +343,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { } log.Debugf("Worker %d got a component %q", id, comp.ContainerImage) + out, err := validate(ctx, comp, data.spec, data.policy, evaluators, data.info) res := result{ err: err, @@ -366,8 +367,8 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { res.component.Signatures = out.Signatures res.component.Attestations = out.Attestations res.component.ContainerImage = out.ImageURL - res.data = out.Data res.component.Attestations = out.Attestations + res.data = out.Data res.policyInput = out.PolicyInput } res.component.Success = err == nil && len(res.component.Violations) == 0 @@ -400,7 +401,9 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { close(jobs) var components []applicationsnapshot.Component - var manyData [][]evaluator.Data + var manyData []evaluator.Data + // we don't want to accumulate the data from each source group for each component + sgData := make(map[string]evaluator.Data) var manyPolicyInput [][]byte var allErrors error = nil for i := 0; i < numComponents; i++ { @@ -409,12 +412,18 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { e := fmt.Errorf("error validating image %s of component %s: %w", r.component.ContainerImage, r.component.Name, r.err) allErrors = errors.Join(allErrors, e) } else { + // one copy will do. each evaluator runs for every component + if len(sgData) == 0 { + sgData = r.data + } components = append(components, r.component) - manyData = append(manyData, r.data) manyPolicyInput = append(manyPolicyInput, r.policyInput) } } close(results) + for _, val := range sgData { + manyData = append(manyData, val) + } if allErrors != nil { return allErrors } @@ -432,6 +441,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { if err != nil { return err } + p := format.NewTargetParser(applicationsnapshot.JSON, format.Options{ShowSuccesses: showSuccesses}, cmd.OutOrStdout(), utils.FS(cmd.Context())) utils.SetColorEnabled(data.noColor, data.forceColor) if err := report.WriteAll(data.output, p); err != nil { diff --git a/cmd/validate/input.go b/cmd/validate/input.go index 2259a5bd2..b4c10b82c 100644 --- a/cmd/validate/input.go +++ b/cmd/validate/input.go @@ -112,7 +112,7 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { type result struct { err error input input.Input - data []evaluator.Data + data map[string]evaluator.Data policyInput []byte } @@ -166,9 +166,11 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { close(ch) var inputs []input.Input - var manyData [][]evaluator.Data + var manyData []evaluator.Data var manyPolicyInput [][]byte var allErrors error = nil + // we don't want to accumulate the data from each source group for each component + sgData := make(map[string]evaluator.Data) for r := range ch { if r.err != nil { @@ -176,10 +178,15 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { allErrors = errors.Join(allErrors, e) } else { inputs = append(inputs, r.input) - manyData = append(manyData, r.data) + for key, val := range r.data { + sgData[key] = val + } manyPolicyInput = append(manyPolicyInput, r.policyInput) } } + for _, val := range sgData { + manyData = append(manyData, val) + } if allErrors != nil { return allErrors } diff --git a/features/__snapshots__/validate_image.snap b/features/__snapshots__/validate_image.snap index c9b458d41..62cc689ea 100755 --- a/features/__snapshots__/validate_image.snap +++ b/features/__snapshots__/validate_image.snap @@ -2383,34 +2383,34 @@ Error: success criteria not met --- [Custom rule data:${TMPDIR}/custom-rule-data.yaml - 1] -- - config: - default_sigstore_opts: - certificate_identity: "" - certificate_identity_regexp: "" - certificate_oidc_issuer: "" - certificate_oidc_issuer_regexp: "" - ignore_rekor: false - public_key: | -${__________known_PUBLIC_KEY} - rekor_url: ${REKOR} - policy: - when_ns: 1401494400000000000 - rule_data__configuration__: - custom: data1 - - config: - default_sigstore_opts: - certificate_identity: "" - certificate_identity_regexp: "" - certificate_oidc_issuer: "" - certificate_oidc_issuer_regexp: "" - ignore_rekor: false - public_key: | -${__________known_PUBLIC_KEY} - rekor_url: ${REKOR} - policy: - when_ns: 1401494400000000000 - rule_data__configuration__: - other: data2 +- config: + default_sigstore_opts: + certificate_identity: "" + certificate_identity_regexp: "" + certificate_oidc_issuer: "" + certificate_oidc_issuer_regexp: "" + ignore_rekor: false + public_key: | +${________known_PUBLIC_KEY} + rekor_url: ${REKOR} + policy: + when_ns: 1401494400000000000 + rule_data__configuration__: + custom: data1 +- config: + default_sigstore_opts: + certificate_identity: "" + certificate_identity_regexp: "" + certificate_oidc_issuer: "" + certificate_oidc_issuer_regexp: "" + ignore_rekor: false + public_key: | +${________known_PUBLIC_KEY} + rekor_url: ${REKOR} + policy: + when_ns: 1401494400000000000 + rule_data__configuration__: + other: data2 --- diff --git a/internal/image/validate.go b/internal/image/validate.go index 9240afae9..62511f2b4 100644 --- a/internal/image/validate.go +++ b/internal/image/validate.go @@ -19,6 +19,7 @@ package image import ( "context" "encoding/json" + "fmt" "runtime/trace" "sort" "time" @@ -45,7 +46,7 @@ func ValidateImage(ctx context.Context, comp app.SnapshotComponent, snap *app.Sn log.Debugf("Validating image %s", comp.ContainerImage) - out := &output.Output{ImageURL: comp.ContainerImage, Detailed: detailed, Policy: p} + out := &output.Output{ImageURL: comp.ContainerImage, Detailed: detailed, Policy: p, Data: make(map[string]evaluator.Data)} a, err := application_snapshot_image.NewApplicationSnapshotImage(ctx, comp, p, *snap) if err != nil { log.Debug("Failed to create application snapshot image!") @@ -114,7 +115,7 @@ func ValidateImage(ctx context.Context, comp app.SnapshotComponent, snap *app.Sn var allResults []evaluator.Outcome - for _, e := range evaluators { + for idx, e := range evaluators { // Todo maybe: Handle each one concurrently target := evaluator.EvaluationTarget{Inputs: []string{inputPath}} if digest, err := a.ResolveDigest(ctx); err != nil { @@ -130,7 +131,9 @@ func ValidateImage(ctx context.Context, comp app.SnapshotComponent, snap *app.Sn return nil, err } allResults = append(allResults, results...) - out.Data = append(out.Data, data) + + key := fmt.Sprintf("%d", idx) + out.Data[key] = data } out.PolicyInput = inputJSON diff --git a/internal/output/output.go b/internal/output/output.go index 6d00805e4..e1f4d1eff 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -85,7 +85,7 @@ type Output struct { Attestations []attestation.Attestation `json:"attestations,omitempty"` ImageURL string `json:"-"` Detailed bool `json:"-"` - Data []evaluator.Data `json:"-"` + Data map[string]evaluator.Data `json:"-"` Policy policy.Policy `json:"-"` PolicyInput []byte `json:"-"` }