From 05c88a5e6b5bf9baf22fde4f032e4254b3ef3eea Mon Sep 17 00:00:00 2001 From: Karan Kumar Date: Thu, 14 Mar 2024 14:15:32 +0530 Subject: [PATCH] add validation for vulnerability scan options --- pkg/apis/build/v1beta1/build_types.go | 2 ++ pkg/validate/output.go | 33 +++++++++++++++++ pkg/validate/output_test.go | 51 +++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/pkg/apis/build/v1beta1/build_types.go b/pkg/apis/build/v1beta1/build_types.go index 36c3fb0bb5..e491571487 100644 --- a/pkg/apis/build/v1beta1/build_types.go +++ b/pkg/apis/build/v1beta1/build_types.go @@ -76,6 +76,8 @@ const ( OutputTimestampNotSupported BuildReason = "OutputTimestampNotSupported" // OutputTimestampNotValid indicates that the output timestamp value is not valid OutputTimestampNotValid BuildReason = "OutputTimestampNotValid" + // VulnerabilityScanSeverityNotValid indicates that the output vulnerability scan severity is not valid + VulnerabilityScanSeverityNotValid BuildReason = "VulnerabilityScanSeverityNotValid" // AllValidationsSucceeded indicates a Build was successfully validated AllValidationsSucceeded = "all validations succeeded" diff --git a/pkg/validate/output.go b/pkg/validate/output.go index fd5ea0eb58..9bfdbfcea7 100644 --- a/pkg/validate/output.go +++ b/pkg/validate/output.go @@ -7,6 +7,7 @@ package validate import ( "context" "strconv" + "strings" build "github.com/shipwright-io/build/pkg/apis/build/v1beta1" "k8s.io/utils/pointer" @@ -47,6 +48,19 @@ func (b *BuildSpecOutputValidator) ValidatePath(_ context.Context) error { } } + if b.Build.Spec.Output.VulnerabilityScan != nil { + if b.Build.Spec.Output.VulnerabilityScan.Ignore != nil { + if b.Build.Spec.Output.VulnerabilityScan.Ignore.Severity != nil { + severitiesStr := *b.Build.Spec.Output.VulnerabilityScan.Ignore.Severity + severities := strings.Split(severitiesStr, ",") + if !areValidSeverities(severities) { + b.Build.Status.Reason = build.BuildReasonPtr(build.VulnerabilityScanSeverityNotValid) + b.Build.Status.Message = pointer.String("output vulnerability scan severity is invalid, must be a comma separated combination of these values: Low, Medium, High, Critical, Unknown") + } + } + } + } + return nil } @@ -54,3 +68,22 @@ func (b *BuildSpecOutputValidator) isEmptySource() bool { return b.Build.Spec.Source == nil || b.Build.Spec.Source.Git == nil && b.Build.Spec.Source.OCIArtifact == nil && b.Build.Spec.Source.Local == nil } + +func areValidSeverities(severities []string) bool { + for _, severity := range severities { + if !isValidSeverity(strings.ToUpper(severity)) { + return false + } + } + return true +} + +func isValidSeverity(severity string) bool { + switch severity { + case "LOW", "MEDIUM", "HIGH", "CRITICAL", "UNKNOWN": + return true + default: + return false + } + +} diff --git a/pkg/validate/output_test.go b/pkg/validate/output_test.go index 2cc8d27ab8..f60710dfd5 100644 --- a/pkg/validate/output_test.go +++ b/pkg/validate/output_test.go @@ -99,4 +99,55 @@ var _ = Describe("BuildSpecOutputValidator", func() { Expect(*build.Status.Message).To(ContainSubstring("output timestamp value is invalid")) }) }) + + Context("output vulnerabilityScan is specified", func() { + var sampleBuild = func(vulnerabilitySettings VulnerabilityScanOptions) *Build { + return &Build{ + ObjectMeta: corev1.ObjectMeta{ + Namespace: "foo", + Name: "bar", + }, + Spec: BuildSpec{ + Source: &Source{ + Type: GitType, + Git: &Git{ + URL: "https://github.com/shipwright-io/sample-go", + }, + }, + Strategy: Strategy{ + Name: "magic", + }, + Output: Image{ + VulnerabilityScan: &vulnerabilitySettings, + }, + }, + } + } + + It("should pass for valid severities", func() { + severities := "Low,HIGH,Medium" + vulnerabilitySettings := VulnerabilityScanOptions{ + Ignore: &VulnerabilityIgnoreOptions{ + Severity: &severities, + }, + } + build := sampleBuild(vulnerabilitySettings) + validate(build) + Expect(build.Status.Reason).To(BeNil()) + Expect(build.Status.Message).To(BeNil()) + }) + + It("should fail for invvalid severities", func() { + severities := "LOWE" + vulnerabilitySettings := VulnerabilityScanOptions{ + Ignore: &VulnerabilityIgnoreOptions{ + Severity: &severities, + }, + } + build := sampleBuild(vulnerabilitySettings) + validate(build) + Expect(*build.Status.Reason).To(Equal(VulnerabilityScanSeverityNotValid)) + Expect(*build.Status.Message).To(ContainSubstring("vulnerability scan severity is invalid")) + }) + }) })