Jenkins Pipelines
Containerization and Deployment
Vulnerability Scan using Trivy
In the previous session, we created a Docker image.
And before pushing that image to a container registry, let's do a round of vulnerability scanning using Trivy.
So what is Trivy?
Trivy is a security scanner.
Trivy has scanners that can look for security issues and targets where it can find those issues.
So it can do security analysis on a different range of targets like container images, file systems, Git repositories, Kubernetes manifest files, and others.
And it can find issues related to OS packages, software dependencies, any known vulnerabilities like CVEs, Infrastructure as Code issues, software licenses, and a few other options as well.
So it does a wide range of security analysis and it has a very comprehensive documentation available.
So I would request you to go through this documentation whenever you have any issues.
So we will be using Trivy just to scan the container image.
And at the same time, it's also going to scan the Node.js dependencies as well implicitly.
So how does this work?
Ideally speaking, you need to install this on the machine where you want to run Trivy commands, or it is also available as a Docker image as well.
You can also use the container image if required.
But we will be using the CLI.
So I've already installed this.
We'll be covering that in a minute.
And then if you want to use this, again, based on the target, you know, the commands differ.
So we want to use this for the container image.
So in the container image, the command is very simple.
You need to use Trivy image and you need to provide the Docker image or the container image which you want to run the scan for.
And it has a lot of options.
So please go through all the options when and where required.
And once it does the scanning, it also generates some reports.
And, you know, you can also get the reports in different formats like JSON, HTML, JUnit XML reports, and others.
So we'll do that as we move forward.
So now let's go ahead and create a stage for it.
So before creating a stage for it, let me show you in the CLI that I have Trivy installed.
So I'm currently using version 0.55.2.
And you can also do a simple Trivy image -h.
It's going to give you all the commands which are accessible and you can just, you know, go through that.
OK, so it is a very huge list of arguments which can be provided.
So let's add a stage.
So I want to add a stage after the Docker, you know, image build stage.
So let me quickly add it.
So I've already copied the command.
So I'll paste it and I'll try to explain it.
So let me close this.
So the name of the stage is Trivy vulnerability scanner or you can also say scanning.
And I have a single shell command where I'm running a couple of commands.
So what are these commands?
OK, so the first command is going to run Trivy image.
I'm giving the name of the image which was, you know, built or created in the previous stage.
And then I'm checking for vulnerabilities.
So it's basically going to scan for vulnerabilities.
So here I'm just going to, you know, I want this Trivy scanner to highlight only the low and medium-level severity vulnerabilities.
And if it finds any low and medium-level vulnerabilities, I want to exit using exit code 0.
It means that I don't want to raise any error if it finds any low and medium vulnerabilities.
I just want to have a log of it.
OK, so that's how you can make use of the exit code.
So if it is 0, this command, even if it finds vulnerabilities of this severity, it won't raise an error.
And then I'm using the quiet argument so that it doesn't print much on the console.
And it's going to generate the JSON report.
So I'm using format JSON and I'm outputting this, you know, using a file name.
So this is going to be Trivy image medium results.json.
Similarly, I have another command where I'm scanning the same image, but I'm scanning for high and critical level severities.
And if this command finds any high or critical level severities, I want to exit using exit code 1.
So I want to raise an error if it finds any high and critical level severities.
And similarly, I'm using quite a JSON format, you know, report.
The name of this report is Trivy image critical results.json.
So this is how I'm running a couple of commands.
It's going to scan for low, medium, high, critical severities.
If it finds low and medium, it won't raise any errors because of the exit code.
If it finds any high and critical level severity, it is going to raise an error.
So after this, it's going to generate the report in JSON format.
But if you remember in Jenkins, we can, you know, publish HTML reports and also archive JUnit reports.
So let's see if Trivy supports those formats.
So for that, you can again go back to the documentation.
So in the documentation, let me scroll down and see if I have any options.
So we have this reporting option.
And if you see the formats, it supports table, JSON, SARIF, template and GitHub.
So let's see what options we have in the template because here I don't see HTML and the JUnit thing.
So let's go to the template.
So in template, I think we can convert the JSON output to, you know, different templates.
So let's see.
Okay, let me just scroll down.
So the templates are basically available at this path.
So let me just go to this path and see what templates are available in my, you know, installation of Trivy.
So let me just go here.
Let me just search for the LS template.
So I have the HTML template.
If you see, I have around five different templates, GitLab, GitLab code quality, HTML, and JUnit templates are also available.
So since the templates are available, we'll try to convert the JSON file to this template.
So how do we do that?
So let's check the documentation.
So in the documentation, if you see there is a conversion option at the bottom.
So let's see how to convert.
So to generate multiple reports, you can generate a JSON report first and convert it to other formats with the convert subcommand.
So I think we need to just use Trivy convert.
You need to give a format and output.
And we can also use templates as well.
Okay.
So that's how you basically do the converting.
So, I mean, everything is documented in detail over here.
So I'll just copy the commands which I'll be using to convert them.
So let's go back.
So I want to convert this as a post-action.
I don't want to do this in this main body.
I want to do this after, you know, the commands are run.
So what I want to do here is, so within the same stage, I want to use a post always.
So post always can be used at a global level or even at a stage level as well.
So let me use this at this stage level.
So let me copy it.
And let me paste it.
So it's a very huge one.
So let me try to explain to you what I'm doing over here.
So this is over here.
I think I have to close this.
Okay.
So let me save this.
So here, I'm using four Trivy commands again.
So let me enter this.
So then in these four commands, if you see, I'm just converting, right?
So I'm getting a JSON, I'll be getting two JSON outputs.
One is Trivy image scanning results.json.
And the other one is the critical results.json.
So I'm converting these JSON files to HTML and XML.
So if you see, this is the HTML one and this is the XML one using the templates option.
So I'm using Trivy to convert the format template.
I'm giving the template which is available at my local machine where I've installed Trivy.
So the template is junit.tpl.
It needs the output value and it also needs the input value, which is the JSON file.
So the same thing, I'm doing it for the HTML template also.
The reason why you see four converts, because for the medium results, I'm converting them to HTML and XML, the JUnit one.
And the same thing, I'm doing it for the critical results JSON as well.
So that's the reason you see four outputs.
Okay.
So after generating the HTML and the JUnit reports, we can do another step over here.
So we just want to publish the HTML and the JUnit reports as well.
So let's do them in a single go.
So we have this over here.
So I'll again paste the content over here.
So I have, we've already done this a couple of times.
So I'm just pasting the content here.
So let me go back.
So I've just copy-pasted a couple of publish HTML commands over here.
So let me do a word wrap and explain what I've done here.
Right.
So these are the two ones which I copied.
So here I'm again using a publish HTML, which we have done earlier, where I am, you know, trying to publish the HTML of the Trivia image critical results dot HTML, which I'm generating above.
Okay.
Similarly, I'm also going to, you know, publish the Trivy image medium-hyphen results dot HTML.
And the name of the report, I'm just using Trivy image critical or medium, you know, vulnerability report.
Okay.
The rest of the things remain the same.
So it's going to pick up these files from the root directory of this workspace.
And this is similar to what we have seen in the other publish HTML commands.
So similarly, I think we can also do a quick copy-paste of the JUnit as well.
So let me quickly do that.
So we will be also, you know, archiving the XML files.
So let me quickly copy paste it here.
And I think I can copy the same critical results as well.
Okay.
So that's it.
So let me save all these things.
So we have done a lot of copy pasting here because, you know, we have done the steps multiple times earlier.
So let me quickly, you know, push these changes and I'll quickly explain what we have done once again.
So let me minimize the steps.
Okay.
So we added a new stage, Trivy vulnerability scanner, where we are scanning the image which is generated in the previous stage using a couple of Trivy image commands.
In the first command, I'm checking for low medium level vulnerabilities.
If it finds any vulnerabilities of this severity, it won't raise any error because I'm using an exit code zero.
But it's going to generate a JSON report, which will be accessible for us to review.
Similarly, in the second command, we are, you know, checking the same image for high and critical-level vulnerabilities.
If it finds them, it's going to raise an error using exit code one.
And it's also going to generate a JSON report.
And this JSON report, we are converting them to HTML and JUnit reports using the Trivy convert command and using a template which is available out of the box.
And at the end of the day, we are publishing the HTML reports and also the JUnit reports.
So that's what, you know, we have done so far.
So let's go and see if the pipeline got triggered.
Okay, the pipeline got triggered.
It is in the build Docker image stage.
And now it is running the Trivy vulnerability scanning.
So let's check them out.
So let's not wait for them.
So you won't see any output in the console because I think I'm using the quiet option, right?
So if I remove the quiet option, you might have seen a few things.
But yeah, if you see here, now the pipeline has completed and the Trivy vulnerability scanner resulted in an error.
So let's see why it resulted in an error.
Okay, so it also, you know, did the conversion.
So I think all these files should be available in our workspace.
And it is also uploaded.
So first things first.
So let's go and, you know, check the workspace.
Let's see if these files are created.
So I can go to the workspace.
And I should be able to see, you know, Trivy image reports, right?
So I think I have around six reports that have been generated.
So I can open the HTML page.
And you won't be seeing the, you know, CSS because I think I restarted Jenkins.
So when you restart Jenkins, the CSS will also be gone because it uses the Content Security Policy.
So let me quickly enable that.
But before that, let us go and see the tests.
So in tests, so now we should be seeing more tests that have failed.
So what are these?
So now this also includes the Trivy, you know, errors as well.
So you're seeing the busybox, you know, severities, which are high and medium, right?
So let me scroll down.
Does it have any critical?
So it doesn't have any critical-level vulnerabilities.
So it only has high and, you know, medium-level vulnerabilities.
Okay.
So I think I want to show you the HTML page.
So I have the Trivia medium and critical vulnerabilities.
So as you can see here, the CSS is not there, but you can still read the report.
So it only found high-level vulnerabilities.
Since they are high-level vulnerabilities, it is failing the build.
Okay.
So let me go to the medium vulnerability report.
So they are medium and, you know, low-level vulnerabilities.
But for this, it won't raise any error.
It simply, you know, generates a report.
So I guess, you know, we want to bypass this high-level vulnerabilities.
We only want to raise an error if there are any critical-level vulnerabilities.
So how do we do that?
So for doing that, I guess we can simply modify the command a bit.
So instead of, you know, checking for both high and critical level,
let's only check for critical-level vulnerabilities.
Okay.
So for doing that, so let's go back.
So here in the Trivy command, I'll just remove the hi over here and I'll be using it here.
So if there are any high-level vulnerabilities also, it's going to ignore them.
It won't raise an error.
But if it finds any critical level vulnerabilities, it is going to raise an error now.
Okay.
So let me save this.
But before I commit the changes, let me do one thing.
So I want to enable CSS.
So I'll just search for Jenkins Content Security Policy.
If you remember, we have done this earlier.
So let me do this once again.
We'll unset the header.
Let me go back to Jenkins nodes.
Let's go to the script and so on.
Add this.
Run this.
I think that should be good.
So now let me quickly commit the changes.
Commit and push.
Okay.
So it should trigger a new build.
Let me close all this.
So I'll just pause the video till it completes all the stages.
Okay.
So as we can see here, the trivia stage is also successfully completed now.
So if you see here, it won't give you any errors because for any low, medium, high,
I don't want to raise an error.
But I guess it did not find any critical level severities.
So it didn't raise an error.
So we can check this out again using the HTML reports.
So if I open the critical report, it does not have any vulnerabilities of critical level.
So you don't see anything over here.
So let me open the medium vulnerability report.
And it finds a lot of medium level, high level, low.
And I think even it should also show some high-level vulnerabilities as well.
So it also shows you where it is finding them within the Alpine image or in the Node packages as well.
So that is in the image.
And this is with respect to the Node.js packages.
Okay.
So it is running a scan on the Docker image as well as the Node.js dependencies as well.
And it gives you a lot of details like the vulnerability ID, where it was fixed,
what is the installed version currently, and some additional details using the links.
Okay.
So that's how you can do a quick round of vulnerability scanning for the Docker image and also for the Node.js packages.
And the same can also be used for a few other use cases as well,
like Kubernetes manifest files or checking the licenses or doing some benchmarking as well,
which we are not going to cover, but Privy is capable of doing those as well.
So in the next stage, we are going to publish this image to a container registry.
Thank you.
Watch Video
Watch video content