How to scan container images for security vulnerabilities using Trivy

How to scan container images for security vulnerabilities using Trivy

trivy-container-image-scanning

Here in this tutorial we will see how we can scan for security vulnerabilities in container images using Trivy. We will try to install the Trivy package and scan a set of container images to identify the vulnerabilities present in them. Once the scan is completed we will try to generate a report of the security vulnerabilities present in each of the container images. We are going to use Ansible playbook to configure, install and scan container images on a managed node.

Test Environment

Fedora 35 workstation

What is Trivy

Trivy is vulnerability and misconfiguration scanner for container and other artifacts. It can be used to scan for vulnerabilities in container images and scan for vulnerabilities and misconfiguration in filesystem and git repositories. It can scan OS packages, language specific packages and configuration files related to infrastructure as code.

If you are interested in watching the video. Here is the YouTube video on the same step by step procedure outlined below.

Procedure

Step1: Make sure SSH keybased authentication is enabled

Here we are going to install trivy on a Ansible managed node. In my case its a kubernetes master server on which the control plan components are running. Please follow this tutorial in case you want to setup kubernetes cluster. Otherwise you can use any managed node with docker installed and configured to use for this activity.

[admin@fedser trivy_scan]$ ssh admin@fedkubemaster
Last login: Tue Apr 19 09:04:38 2022 from 192.168.122.1

[admin@fedkubemaster ~]$ exit
logout
Connection to fedkubemaster closed.
[admin@fedser trivy_scan]$

Make sure the Ansible inventory file is updated with the managed node details as shown below.

admin@fedser trivy_scan]$ cat /etc/ansible/hosts | grep kube
[kubernetesmaster]
fedkubemaster

Step2: Create a Trivy repository file

As a first step to install trivy we need to have the RPM repository configured on the server on which we want to install trivy. Let’s create the below trivy.repo file with the following content as shown below. Please note, i am using the releases – 8 which is an RHEL8 package repository for installing on the fedora machine as there is no trivy package repository for fedora 35 server.

[admin@fedser trivy_scan]$ cat trivy.repo 
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/8/$basearch/
gpgcheck=0
enabled=1

Step3: Copy the repo file to managed node

We will be using Ansible playbook to copy the trivy repository file onto the kubernetes master node as shown below.

[admin@fedser trivy_scan]$ cat trivyscan.yml 
---
- name: Trivy install and configure
  hosts: kubernetesmaster
  become: true
  become_user: root
  tasks:
  - name: Copy the trivy repository file to managed node
    copy:
      src: /home/admin/middleware/stack/ansible/playbooks/trivy_scan/trivy.repo
      dest: /etc/yum.repos.d/trivy.repo
      owner: root
      group: root
      mode: 0755

Execute the playbook as shown below and validate if the repository has been configured on the server.

[admin@fedser trivy_scan]$ ansible-playbook trivyscan.yml -K -u admin
[admin@fedser trivy_scan]$ ssh admin@fedkubemaster
Last login: Tue Apr 19 09:14:51 2022 from 192.168.122.1
[admin@fedkubemaster ~]$ ls -ltr /etc/yum.repos.d/trivy.repo 
-rwxr-xr-x. 1 root root 137 Apr 19 09:14 /etc/yum.repos.d/trivy.repo
[admin@fedkubemaster ~]$ cat /etc/yum.repos.d/trivy.repo 
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=0
enabled=1
[admin@fedkubemaster ~]$ exit
logout
Connection to fedkubemaster closed.

Step4: Install Trivy package from repository

Let us now install the trivy package on the managed node using the below ansible playbook. Make sure your managed node system packages are updated else it will take some time to get all the packages updated using the below ansible playbook.

[admin@fedser trivy_scan]$ cat trivyscan.yml 
---
- name: Trivy install and configure
  hosts: kubernetesmaster
  become: true
  become_user: root
  tasks:
  - name: Copy the trivy repository file to managed node
    copy:
      src: /home/admin/middleware/stack/ansible/playbooks/trivy_scan/trivy.repo
      dest: /etc/yum.repos.d/trivy.repo
      owner: root
      group: root
      mode: 0755
  - name: Update packages
    dnf: 
      name=* 
      state=present
  - name: Install Trivy package
    dnf:
      name=trivy
      state=present
[admin@fedser trivy_scan]$ ansible-playbook trivyscan.yml -K -u admin
BECOME password: 

PLAY [Trivy install and configure] ***************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************
ok: [fedkubemaster]

TASK [Copy the trivy repository file to managed node] ********************************************************************************************************
ok: [fedkubemaster]

TASK [Install Trivy package] *********************************************************************************************************************************
changed: [fedkubemaster]

PLAY RECAP ***************************************************************************************************************************************************
fedkubemaster              : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Step5: Prepare the Trivy Scan script

Here is a very basic script which we will copy on the the managed node to scan the container image and store the results in html format using the html template as shown below.

[admin@fedser trivy_scan]$ cat trivyscan.sh 
#!/bin/bash

scanDate=$(date +%Y%m%d)
htmlTemplateLoc=/usr/local/share/trivy/templates/html.tpl
declare -a arr=("busybox" "nginx")

for image in "${arr[@]}"; do
trivy image --format template --template "@${htmlTemplateLoc}" ${image} > /var/tmp/result_${image}_${scanDate}.html
done

Step6: Update the ansible playbook and execute

Now here we will update our playbook to copy the script onto managed node and execute with ‘admin’ user.

[admin@fedser trivy_scan]$ cat trivyscan.yml 
---
- name: Trivy install and configure
  hosts: kubernetesmaster
  become: true
  become_user: root
  tasks:
  - name: Copy the trivy repository file to managed node
    copy:
      src: /home/admin/middleware/stack/ansible/playbooks/trivy_scan/trivy.repo
      dest: /etc/yum.repos.d/trivy.repo
      owner: root
      group: root
      mode: 0755
  - name: Update packages
    dnf: 
      name=* 
      state=present
  - name: Install Trivy package
    dnf:
      name=trivy
      state=present
  - name: Copy Trivy scan script
    copy:
      src: /home/admin/middleware/stack/ansible/playbooks/trivy_scan/trivyscan.sh
      dest: /var/tmp/trivyscan.sh
      mode: 0755
    become: true
    become: admin
  - name: Scan container images
    shell: /var/tmp/trivyscan.sh
    become: true
    become_user: admin

Let’s execute the ansible playbook and scan the image named nginx and busybox as per the script on the managed node.

[admin@fedser trivy_scan]$ ansible-playbook trivyscan.yml -K -u admin
BECOME password: 

PLAY [Trivy install and configure] ***************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************
ok: [fedkubemaster]

TASK [Copy the trivy repository file to managed node] ********************************************************************************************************
ok: [fedkubemaster]

TASK [Install Trivy package] *********************************************************************************************************************************
ok: [fedkubemaster]

TASK [Copy Trivy scan script] ********************************************************************************************************************************
changed: [fedkubemaster]

TASK [Scan container images] *********************************************************************************************************************************
changed: [fedkubemaster]

PLAY RECAP ***************************************************************************************************************************************************
fedkubemaster              : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Step6: Validate the Scan report

Now, we will transfer the results html file generated on the managed node onto our host machine and open it using the firefox browser as shown below.

[admin@fedser trivy_scan]$ scp -r admin@fedkubemaster:/var/tmp/result_* .
result_busybox_20220419.html                                                                                                100%  262     1.2MB/s   00:00    
result_nginx_20220419.html                                                                                                  100%  174KB 299.5MB/s   00:00    
[admin@fedser trivy_scan]$

Here is the sample trivy scan html report as shown below.

Hope you enjoyed reading this article. Thank you..