kubestronautへの道 ~CKS編 その16 killer coda「Image Vulnerability Scanning Trivy」~

tech article

今日覚えて帰ること

Trivy

  • コンテナイメージの脆弱性診断ツール
  • trivy image <image name> でイメージスキャンを実行する
  • 動作中のコンテナの脆弱性は診断できない

Image Vulnerability Scanning Trivy

Use trivy to scan images for known vulnerabilities

Using trivy :

Scan images in Namespaces applications and infra for the vulnerabilities CVE-2021-28831 and CVE-2016-9841 .

Scale those Deployments containing any of these down to 0 .

trivyを使ってイメージスキャンし、脆弱性がある場合は deployment のレプリカ数を0にせよ、と言っています。

trivy も例のごとく CKS を攻略するのに必須のツールかと思われます。
そして例のごとく何なのかよくわからないので調査します。

Trivy〜コンテナイメージの脆弱性診断ツール〜 | OSSのデージーネット
Trivyとは、コンテナイメージの脆弱性を診断するツールです。対応OSのパッケージ情報などから脆弱性を検出し、診断結果を出力することができます。CIなどでも簡単に組み込んで使えるようにシンプルに作られています。

Trivyとは、コンテナイメージの脆弱性診断ツールです。

端的に説明されています。

こまごまとした説明としては、元はOSSだったものをAqua Security社が買収して今の形になっているみたいです。
kube-benchもこの会社だった気がします。

特徴としては、シンプルなCLIでイメージスキャンができるため、操作に特段困ることがない点が挙げられていました。
また、イメージスキャンに特化しており、動作中のコンテナの脆弱性を検査することが出来ないみたいです。

似たようなツールの Vuls を使えば動作中のコンテナの脆弱性を診断することができるみたいです。

また、Trivy も Vuls もコンテナへの侵入検知や改竄検知を行うことはできません。
コンテナへの侵入検知や改竄検知がしたい場合は Falco を使いましょう。

Trivy の概要が分かったところで、実際に解いていきましょう。

まずは deployment を確認します。

controlplane $ k get deployments.apps  -n applications 
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   2/2     2            2           40m
web2   1/1     1            1           40

次に、deployment で使用されているイメージを確認します。

controlplane $ k get po -n applications -o yaml | grep image
    - image: nginx:1.19.1-alpine-perl
      imagePullPolicy: IfNotPresent
      image: docker.io/library/nginx:1.19.1-alpine-perl
      imageID: docker.io/library/nginx@sha256:6c659b6aa4df6074de4579902e052eb4cf7062f826328588f91681a81229ebc0
    - image: nginx:1.19.1-alpine-perl
      imagePullPolicy: IfNotPresent
      image: docker.io/library/nginx:1.19.1-alpine-perl
      imageID: docker.io/library/nginx@sha256:6c659b6aa4df6074de4579902e052eb4cf7062f826328588f91681a81229ebc0
    - image: nginx:1.20.2-alpine
      imagePullPolicy: IfNotPresent
      image: docker.io/library/nginx:1.20.2-alpine
      imageID: docker.io/library/nginx@sha256:016789c9a2d021b2dcb5e1c724c75ab0a57cc4e8cd7aab7bb28e69fec7c8c4fc

出力されている数から、web1 で使用されているイメージはnginx:1.19.1-alpine-perl、web2 で使用されているイメージはnginx:1.20.2-alpine ということがわかります。

次に、trivy を使ってイメージスキャンをしていきます。
困ったらときは -h で使い方を確認しましょう。

controlplane $ trivy -h
NAME:
   trivy - A simple and comprehensive vulnerability scanner for containers

USAGE:
   trivy [global options] command [command options] target

VERSION:
   0.22.0

COMMANDS:
   image, i          scan an image
   filesystem, fs    scan local filesystem for language-specific dependencies and config files
   rootfs            scan rootfs
   repository, repo  scan remote repository
   client, c         client mode
   server, s         server mode
   config, conf      scan config files
   plugin, p         manage plugins
   help, h           Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --quiet, -q        suppress progress bar and log output (default: false) [$TRIVY_QUIET]
   --debug, -d        debug mode (default: false) [$TRIVY_DEBUG]
   --cache-dir value  cache directory (default: "/root/.cache/trivy") [$TRIVY_CACHE_DIR]
   --help, -h         show help (default: false)
   --version, -v      print the version (default: false)

コンテナイメージもいろいろスキャンできそうです。
イメージをスキャンする場合は trivy image <image name> とすればよさそうです。

実際にスキャンします。
そのままスキャンするとすべての CVE に対するスキャン結果が出力されてしまうので、grep で対象の値だけ出力します。

controlplane $ trivy image  nginx:1.19.1-alpine-perl | grep CVE-2021-28831
| busybox      | CVE-2021-28831   |          | 1.31.1-r9         | 1.31.1-r10    | busybox: invalid free or segmentation |
| ssl_client   | CVE-2021-28831   | HIGH     | 1.31.1-r9         | 1.31.1-r10    | busybox: invalid free or segmentation |
controlplane $ trivy image  nginx:1.19.1-alpine-perl | grep CVE-2016-9841 

controlplane $ trivy image nginx:1.20.2-alpine | grep CVE-2021-28831
controlplane $ trivy image nginx:1.20.2-alpine | grep CVE-2016-9841 

nginx:1.19.1-alpine-perl の方だけ脆弱性が見つかりました。

ということで、web1 のほうのレプリカ数を0にします。
k edit でdeployment のマニフェストファイルを編集してもよいですが、今回は k scale コマンドを使用します。

controlplane $ k scale deployment -n applications web1 --replicas=0
deployment.apps/web1 scaled

あとは infra という namespace でも同じ作業を繰り返せばOKです。
詳細は省略します。手順のみ載せておきます。

controlplane $ k get deployments.apps  -n infra
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
inf-hjk   3/3     3            3           40m

controlplane $ k get po -n infra -o yaml | grep image
    - image: httpd:2.4.39-alpine
      imagePullPolicy: IfNotPresent
      image: docker.io/library/httpd:2.4.39-alpine
      imageID: docker.io/library/httpd@sha256:addd70e4ee83f3bc9a4c1c7c41e37927ba47faf639312fc936df3afad7926f5a
    - image: httpd:2.4.39-alpine
      imagePullPolicy: IfNotPresent
      image: docker.io/library/httpd:2.4.39-alpine
      imageID: docker.io/library/httpd@sha256:addd70e4ee83f3bc9a4c1c7c41e37927ba47faf639312fc936df3afad7926f5a
    - image: httpd:2.4.39-alpine
      imagePullPolicy: IfNotPresent
      image: docker.io/library/httpd:2.4.39-alpine
      imageID: docker.io/library/httpd@sha256:addd70e4ee83f3bc9a4c1c7c41e37927ba47faf639312fc936df3afad7926f5a


controlplane $ trivy image httpd:2.4.39-alpine | grep CVE-2021-28831
| busybox                 | CVE-2021-28831   |          | 1.30.1-r2         | 1.30.1-r5     | busybox: invalid free or segmentation |
| ssl_client              | CVE-2021-28831   | HIGH     | 1.30.1-r2         | 1.30.1-r5     | busybox: invalid free or segmentation |
controlplane $ trivy image httpd:2.4.39-alpine | grep CVE-2016-9841 

controlplane $ k scale deployment -n infra inf-hjk --replicas=0
deployment.apps/inf-hjk scaled
controlplane $ 

参考

いつも参照している対策記事です。
とても助かっています。

【対策メモ】Certified Kubernetes Security Specialist (CKS)試験 - Qiita
はじめに本記事は、Certified Kubernetes Security Specialist (CKS)試験の対策をしている上で覚えておくべきだと感じたことをメモとして残しておくものです。…
【 更新者も必見 】 CKS 攻略ガイド ( 2023 年 6 月版 )

ちなみに、対策記事によると trivy の公式サイトは試験中に参照できないらしいです。
-h で確認できるので特に問題はなさそうです。

また、HIGH や CRITICAL だけを出力できるようになっておくといいらしいです。
コマンドはこちら。

trivy image --severity HIGH,CRITICAL nginx:1.19.1-alpine-perl 

このように –severity コマンドを使えばOKです。
オプションではなく出力をパイプして grep という方法では求めている出力が得られないので注意が必要です。

タイトルとURLをコピーしました