Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulnerability Scanning Implementation for container images #1489

Merged

Conversation

karanibm6
Copy link
Contributor

@karanibm6 karanibm6 commented Feb 7, 2024

Changes

Implementation of this SHIP : https://github.com/shipwright-io/community/blob/main/ships/0033-build-output-vulnerability-scanning.md#build-output-vulnerability-scanning

  • Add vulnerability scanning options in build and buildrun types in v1alpha1 and v1beta1
  • Add vulnerable image for unit testing of vulnerability scanning feature
  • Implement vulnerability scanning for container images using trivy and lists vulnerabilities in buildrun output
  • Add e2e tests to verify options for vulnerability scanning

Fixes #1394

Submitter Checklist

  • Includes tests if functionality changed/was added
  • Includes docs if changes are user-facing
  • Set a kind label on this PR
  • Release notes block has been filled in, or marked NONE

See the contributor guide
for details on coding conventions, github and prow interactions, and the code review process.

Release Notes

Vulnerability Scanning Implementation

@openshift-ci openshift-ci bot added the do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. label Feb 7, 2024
@pull-request-size pull-request-size bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Feb 7, 2024
@karanibm6
Copy link
Contributor Author

/kind feature

@openshift-ci openshift-ci bot added the kind/feature Categorizes issue or PR as related to a new feature. label Feb 7, 2024
@karanibm6 karanibm6 force-pushed the add-vulnerability-scanning branch 8 times, most recently from c5ea814 to a8fd62f Compare February 7, 2024 20:18
@qu1queee qu1queee requested review from qu1queee and removed request for otaviof February 8, 2024 08:29
cmd/image-processing/main_test.go Outdated Show resolved Hide resolved
hack/install-trivy.sh Outdated Show resolved Hide resolved
pkg/apis/build/v1alpha1/build_types.go Outdated Show resolved Hide resolved
pkg/apis/build/v1alpha1/build_types.go Outdated Show resolved Hide resolved
pkg/apis/build/v1alpha1/build_types.go Outdated Show resolved Hide resolved
cmd/image-processing/main.go Outdated Show resolved Hide resolved
cmd/image-processing/main.go Outdated Show resolved Hide resolved
cmd/image-processing/main_test.go Outdated Show resolved Hide resolved
)

const (
VulnerabilityCountLimit = 50 // Number of vulnerabilities to be added to buildrun output.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Would be nice to have it configurable for downstream projects to adapt to their needs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HeavyWombat Shall I add it as another field for vulnerabilityScanOptions ? or Can I set it as an environment variable in some config or in the image-processing container ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My initial feeling would be an environment variable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be in config.go which reads from environment variables.

pkg/image/vulnerability_scan.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan_test.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan_test.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan_test.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan_test.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan_test.go Outdated Show resolved Hide resolved
@karanibm6 karanibm6 force-pushed the add-vulnerability-scanning branch 3 times, most recently from eaddddc to 476489d Compare February 17, 2024 12:28
@openshift-ci openshift-ci bot added release-note Label for when a PR has specified a release note and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Feb 17, 2024
@HeavyWombat HeavyWombat self-requested a review February 20, 2024 09:30
Copy link
Contributor

@HeavyWombat HeavyWombat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, thanks for the PR. I am generally speaking fine with it, but have a couple of detail questions.

pkg/apis/build/v1alpha1/build_types.go Outdated Show resolved Hide resolved
)

const (
VulnerabilityCountLimit = 50 // Number of vulnerabilities to be added to buildrun output.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My initial feeling would be an environment variable.

pkg/image/vulnerability_scan.go Outdated Show resolved Hide resolved
pkg/image/vulnerability_scan.go Outdated Show resolved Hide resolved
test/data/images/vuln-single-image/vuln-image.tar Outdated Show resolved Hide resolved
test/e2e/v1alpha1/e2e_vulnerability_scanning_test.go Outdated Show resolved Hide resolved
cmd/image-processing/main.go Outdated Show resolved Hide resolved
Copy link
Member

@SaschaSchwarze0 SaschaSchwarze0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work.

)

const (
VulnerabilityCountLimit = 50 // Number of vulnerabilities to be added to buildrun output.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be in config.go which reads from environment variables.

pkg/image/vulnerability_scan.go Outdated Show resolved Hide resolved
Comment on lines 472 to 475
return reconcile.Result{}, resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, fmt.Sprintf("Vulnerabilities have been found in the output image. For detailed information, see kubectl --namespace %s logs %s --container step-image-processing",
buildRun.Namespace,
lastTaskRun.Status.PodName,
), "VulnerabilitiesFound")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the message, should we say "check the BuildRun status, or see kubectl ..." ?

Can we put VulnerabilitiesFound into a constant ? Would be nearby here:

BuildRunStatePodEvicted = "PodEvicted"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -145,6 +145,12 @@ type GitSourceResult struct {
BranchName string `json:"branchName,omitempty"`
}

// Vulnerability defines a vulnerability by its ID and severity
type Vulnerability struct {
VulnerabilityID string `json:"vulnerabilityID,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section is called vulnerabilities, then no nead to call it vulnerabilityID insight of it.

Suggested change
VulnerabilityID string `json:"vulnerabilityID,omitempty"`
ID string `json:"id,omitempty"`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that because it was easy to map it with the result from Trivy scan. I will create a different struct for trivy result.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

test/data/images/vuln-single-image/vuln-image.tar Outdated Show resolved Hide resolved
test/e2e/v1alpha1/e2e_vulnerability_scanning_test.go Outdated Show resolved Hide resolved

// Ensure the BuildRun has been created
err := testBuild.CreateBR(testBuildRun)
Expect(err).ToNot(HaveOccurred(), "Failed to create BuildRun")
if _, err := testBuild.GetBR(testBuildRun.Name); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand that check. Why do we need to check if the BuildRun exists ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because in my tests, I have already created the buildrun, otherwise I had to create a new function for running buildruns.
This condition is also present in validateBuildRunToSucceed function.

cmd/image-processing/main.go Outdated Show resolved Hide resolved
Comment on lines 186 to 214
if img != nil {
entries, err := os.ReadDir(flagValues.push)
if err != nil {
return err
}
imagePath = filepath.Join(imagePath, entries[0].Name())
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment, took me while to understand that img != nil is the condition for a single image in a tar file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what u mean with a single image tar, how we can get N tars? lacking of context on the topic

@karanibm6 karanibm6 force-pushed the add-vulnerability-scanning branch from 6ddd690 to 313ea2d Compare May 5, 2024 15:19
"--vuln-count-limit", "10",
)).ToNot(HaveOccurred())
output := filecontent(filename)
Expect(strings.Contains(output, "CVE-2019-8457")).To(BeTrue())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will produce a better output in case substring is not found:

Suggested change
Expect(strings.Contains(output, "CVE-2019-8457")).To(BeTrue())
Expect(output).To(ContainSubstring("CVE-2019-8457"))

"--vuln-settings", vulnSettings.String(),
"--result-file-image-vulnerabilities", filename,
)).ToNot(HaveOccurred())
Expect(strings.Contains(filecontent(filename), "CVE-2019-8457")).To(BeTrue())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Expect(strings.Contains(filecontent(filename), "CVE-2019-8457")).To(BeTrue())
output := filecontent(filename)
Expect(output).To(ContainSubstring("CVE-2019-8457"))

"--vuln-settings", vulnSettings.String(),
"--result-file-image-vulnerabilities", filename,
)).To(HaveOccurred())
Expect(strings.Contains(filecontent(filename), "CVE-2019-8457")).To(BeTrue())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Expect(strings.Contains(filecontent(filename), "CVE-2019-8457")).To(BeTrue())
output := filecontent(filename)
Expect(output).To(ContainSubstring("CVE-2019-8457"))

})
})

It("should run vulnerability scanning on a image if it is already pushed by the strategy", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It("should run vulnerability scanning on a image if it is already pushed by the strategy", func() {
It("should run vulnerability scanning on an image that is already pushed by the strategy", func() {

"--vuln-settings", vulnSettings.String(),
"--result-file-image-vulnerabilities", filename,
)).ToNot(HaveOccurred())
Expect(strings.Contains(filecontent(filename), "CVE-2019-12900")).To(BeTrue())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Expect(strings.Contains(filecontent(filename), "CVE-2019-12900")).To(BeTrue())
output := filecontent(filename)
Expect(output).To(ContainSubstring("CVE-2019-12900"))

@@ -103,6 +106,7 @@ type Config struct {
Controllers Controllers
KubeAPIOptions KubeAPIOptions
GitRewriteRule bool
VulnerabilityCountLimit string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a number. The error returned by SetConfigFromEnv will cause the controller to panic and that's the desired behavior for invalid values.

cmd := exec.CommandContext(ctx, "trivy", trivyArgs...)

// Print the command to be executed
log.Println(cmd.String())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would print the password, correct? If so, is a no-go.


if failedContainer.Name == "step-image-processing" && exitCode == 22 {
reason = buildv1beta1.BuildRunStateVulnerabilitiesFound
message = fmt.Sprintf("Vulnerabilities have been found in the image which can be seen in the buildrun status. For detailed information,see kubectl --namespace %s logs %s --container=%s",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be reasonable output in the container logs?

Copy link
Contributor Author

@karanibm6 karanibm6 May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, just the vulnerabilities list. In case trivy command fails, it will print an error, but in that case exit code won't be 22.

Comment on lines 232 to 233
// Generate a pod with the status to be evicted
failedTaskRunEvictedPod := corev1.Pod{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls adjust

severityStr := *b.Build.Spec.Output.VulnerabilityScan.Ignore.Severity
if !isValidSeverity(severityStr) {
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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message is not correct.

- Add vulnerability scanning options in build and buildrun types in v1alpha1 and v1beta1
- Changes for conversion to v1beta1
@SaschaSchwarze0
Copy link
Member

Looks mostly good @karanibm6. I put a few small changes in karanibm6#37. Please check.

Copy link
Member

@SaschaSchwarze0 SaschaSchwarze0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/approve

Copy link
Contributor

openshift-ci bot commented Jun 10, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: SaschaSchwarze0

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 10, 2024
Copy link
Contributor

@HeavyWombat HeavyWombat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jun 10, 2024
@openshift-merge-bot openshift-merge-bot bot merged commit 977a065 into shipwright-io:main Jun 10, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. release-note Label for when a PR has specified a release note size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[FEATURE] Implement Build Output Vulnerability Scanning
6 participants