はじめに

自分の管理下にある仮想マシンの脆弱性を継続的に管理するのは義務だと思うんです。
New Relicなどの有償のサービスであればメトリクス収集でagentをサーバに仕込んでおけば、追加料金で脆弱性管理までできるみたい。

Get started with Vulnerability Management

自宅サーバにそんなお金はかけていられないので無料で脆弱性が確認できるツールを調べたものの、SBOM管理関連でも語られることの多いTrivysyft&grypeはどちらかといえばコンテナimageを対象にしているようで、仮想マシン自体のスキャンという文脈でいうと外れていそうだった。
CiscoがリードしているOpenClarityプロジェクトのvmclarityも気になったが、他の仮想マシンからの脆弱性を収集するところができるかわからなかった。(GitHubのReleaseにてvmclarity-cliが配布されているので、cliで取得した脆弱性情報を管理サーバに送信することはできるかも・・・)

そんななか、国産OSSのVulsはLinuxの脆弱性をスキャンできるようで、remote scanなどにも対応しているとのことで試してみる。
ただ、検出結果の可視化ツールであるVulsRepoは今どきじゃない見た目なのでなんとかGrafanaで可視化したいと思った。
(SaaSとしてFutureさんが商売をしているのであまり力を入れてもしょうがないところなんでしょうけど)

MITライセンスで公開されているprometheus-vuls-exporterを使ってGrafanaのダッシュボードで確認することを目標とする
Vulsのスキャン結果 → prometheus-vuls-exporter → Prometheus → Grafana

時系列データのPrometheusで脆弱性情報を管理するのもナンセンスな気もするので自己責任で。

2024/04/01 追記

その後New Relicを使い始めたため、Vulsでの脆弱性スキャンはやめてしまいました。
Trivyでも trivy rootfs にてホストOSの脆弱性スキャンができるのでそちらをおすすめします。

New Relicでメトリクスとログを収集してみた

1. Vulsのインストール

Prometheusが動いているサーバにVulsをインストール
他サーバへSSHしてスキャンするので専用のvulsユーザを作成しました
Vulsを実行するときにIPアドレスにて接続するため、自身の公開鍵をauthorized_keysに書き込んでおく

1
2
3
4
sudo adduser vuls
sudo -i -u vuls
sh-keygen -t ed25519
cat id_ed25519.pub >> authorized_keys

以下のドキュメントを参考にvulsctlをgit cloneしてvulsが動くようにする
exporterはresultのディレクトリが見れればよいため、dockerでもHostOSへのインストールでもどちらでも可

install-with-vulsctl

config.toml

1
2
3
4
5
6
7
8
9
[servers]
[servers.hostos]
host        = "<hostname>"
port        = "22"
user        = "vuls"
# if ssh config file exists in .ssh, path to ssh config file in docker
sshConfigPath   = "/root/.ssh/config"
# keypath in the Vuls docker container
keyPath     = "/root/.ssh/id_ed25519"

指定したresultフォルダに脆弱性が出力されることを確認しておく

2. cronにて定期実行する

以下のshを作成したうえでcronに登録している
とても雑なのでもっと良い書き方あると思います。
最後にchmodをしているのは別ユーザで動かしているexporterで結果を読み取るため

※注意 後述するexporter起動中に新たなresultが生成されると、exporterが正しく動かなくなる仕様?不具合がありました。こちらのスクリプトの最後にexporterを再起動させる記述があってもよいかも

1
2
3
4
5
6
7
8
#!/bin/bash

VULS_PATH="/home/vuls/vulsctl/install-host"
cd $VULS_PATH
bash ./update-all.sh
vuls scan
vuls report -ignore-unfixed
chmod +xr -R ./results

3. prometheus-vuls-exporterを設定する

以下のレポジトリのexporterを使用させていただく
iakovmarkov/prometheus-vuls-exporter

作者の方が386アーキテクチャのものしかReleaseしておらずamd64環境では動作しなかったので、Golangをインストールしてビルドするか、Dockerfileを使ってコンテナイメージを作成する

3.1 コンテナイメージを使用する場合

私がビルドしたイメージはDockerHub に公開しているのでそちらを使用してもよいです。

Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
FROM golang:1.22 AS build-stage

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . ./

RUN CGO_ENABLED=0 GOOS=linux go build  -o /prometheus-vuls-exporter

# Deploy the application binary into a lean image
FROM gcr.io/distroless/base-debian12 AS build-release-stage

WORKDIR /

COPY --from=build-stage /prometheus-vuls-exporter /prometheus-vuls-exporter

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/prometheus-vuls-exporter"]

docker-compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
prometheus-vuls-exporter:
    image: ryomaholiday/prometheus-vuls-exporter:0.1.4
    container_name: prometheus-vuls-exporter
    restart: unless-stopped
    command: ["--reports_dir", "/results"]
    expose:
      - 8080
    volumes:
      - /home/vuls/vulsctl/install-host/results:/results
    networks:
      - monitoring

3.2 ビルドしたものを使用する場合

Golangをインストールした環境にて

1
2
3
4
5
cd ./src/
go build .
cp prometheus-vuls-exporter /usr/bin/
sudo chmod 755 /usr/bin/prometheus-vuls-exporter
go run . --reports_dir "/home/vuls/vulsctl/install-host/results"

Systemd Serviceの例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Unit]
Description=prometheus vuls exporter
Documentation=https://github.com/iakovmarkov/prometheus-vuls-exporter

[Service]
Restart=always
ExecStart=/usr/bin/prometheus-vuls-exporter  --reports_dir "/home/vuls/vulsctl/install-host/results"
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

deamon-reloadしてサービスを起動する

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable prometheus-vuls-exporter
sudo systemctl start prometheus-vuls-exporter

4. Prometheusの設定

prometheus.yml

1
2
3
4
5
6
  - job_name: 'vuls'
    scrape_interval: 1m
    metrics_path: /metrics
    static_configs:
      - targets:
        - 'prometheus-vuls-exporter:8080'

5. Grafanaにて確認

作者さんのダッシュボードを元に

DataLinkにhttps://nvd.nist.gov/vuln/detail/${__data.fields.cveID}などを使用するといい感じになります。

dashboard

おわりに

今どきはコンテナビルド時のスキャンやk8s上のコンテナ脆弱性管理が流行りですよね。今回調べた中でもsnykや、trivy-operatorなどなど。
クラウドでIaaS利用するならクラウドベンダー側で用意された脆弱性管理サービスを使うので、こういうニーズは減っていくのはわかるけど・・・ちゃんとお金払えってことですよね。