VulsをDockerで構築

##1. 概要
 Dockerを使ってVulsの環境を構築し、スキャン実行、Vuls Repoの表示、Slackとの連携、Cronで自動実行を試してみます。

環境は以下の通りです。

|                  |       OS  |
|:-----------------|:---------:|
|Vuls実行サーバ    |CentOS 7.3 |
|スキャン対象サーバ|CentOS 6.8 |


##2. 事前準備
Vulsのセットアップは以下の３パターンがあります（[by公式マニュアル](https://vulsdoc.github.io/ja/gettingstarted/)）。

 - Dockerコンテナ上にセットアップ
 - Chef(構成管理ツール)でセットアップ
 - 手動でセットアップ

その他、IDCFクラウド、さくらのクラウドで構築手段が用意されています。

 - [【IDCF Tech-Blog】コミュニティテンプレート Vuls の利用とTips](http://blog.idcf.jp/entry/idcf-vuls2)
 - [【さくらのクラウドニュース】脆弱性検知ツール「Vuls」のスタートアップスクリプトを公開しました](https://cloud-news.sakura.ad.jp/2017/06/27/startupscript-vuls/)
 
IDCFのテンプレートも試してみましたが、Vuls と Vuls Repo が構築済みの環境が瞬時に手に入ります！
Vuls用のユーザなども作ってあり、あとはスキャンを実行するばかり。
利用方法は、OSイメージを選択する代わりにコミュニティテンプレートを選択するだけ。簡単便利！

さて、（テンプレートではやることが無いので）
今回はDocker を使った構築を試してみたいと思います。


###2.1 Vuls実行サーバのセットアップ

####2.1.1 Vuls実行用ユーザーの追加・設定
Vuls実行用のユーザーにはSUDO権限が必要です。
まず、ユーザを追加します。

```
# useradd vuls
```

作成したユーザーに対し、SUDO可能な権限を追加します。
OSによって設定が違いますので、[公式マニュアル](https://github.com/future-architect/vuls/blob/master/README.ja.md#check-etcsudoers)の Check /etc/sudoers のサンプルを参考にしてください。

```
# visudo
vuls ALL=(ALL) NOPASSWD: \
	/usr/bin/yum --color=never repolist, \
	/usr/bin/yum --color=never --security updateinfo list updates, \
	/usr/bin/yum --color=never --security updateinfo updates
```

####2.1.2 Dockerをインストール
Dockerをインストールし、起動します。
こちらの [Dockerの日本語ドキュメント](http://docs.docker.jp/engine/installation/linux/centos.html) を参考にすると良いと思います。
####2.1.3 docker グループの作成
vulsユーザが docker を起動できるようにしておきます。

```
$ sudo usermod -aG docker vuls
```

sudo を使わずに docker が実行できることを確認します。

```
$ sudo su - vuls
$ docker run hello-world
```

以降の手順は、vulsユーザのホームで実行します。

```
$ pwd
/home/vuls
```

####2.1.4 CVEデータベースの取得
最新の脆弱性情報を取得します。時間がかかるので注意しましょう。

```
for i in `seq 2002 $(date +"%Y")`; do \
    docker run --rm -it \
    -v $PWD:/vuls \
    -v $PWD/go-cve-dictionary-log:/var/log/vuls \
    vuls/go-cve-dictionary fetchnvd -years $i; \
  done
```

スキャン結果を日本語で出力したい場合は、JVNも取得しておきます。

```
for i in `seq 1998 $(date +"%Y")`; do \
    docker run --rm -it \
    -v $PWD:/vuls \
    -v $PWD/go-cve-dictionary-log:/var/log/vuls \
    vuls/go-cve-dictionary fetchjvn -years $i; \
  done
```

###2.2 スキャン対象サーバー側のセットアップ
####2.2.1 パッケージインストール
対象のホストによってインストールが必要なパッケージがあります。
[公式マニュアル](https://github.com/future-architect/vuls/blob/master/README.ja.md#dependencies-on-target-servers) を参考に、インストールしておきます。
今回はCentOSなので、以下をインストール。

```
# yum install -y yum-plugin-changelog, yum-utils
```

####2.2.2 Vuls実行用ユーザーの追加・設定
スキャン対象サーバー側にもSSHでログインするためvulsユーザを作成して、
sudo権限を追加します。

```
# useradd vuls
# visudo
vuls ALL=(ALL) NOPASSWD: \
	/usr/bin/yum --color=never repolist, \
	/usr/bin/yum --color=never --security updateinfo list updates, \
	/usr/bin/yum --color=never --security updateinfo updateso
```

###2.3 SSHの準備
Vuls実行サーバからスキャン対象サーバへSSHで接続できるようにしておきます。

####2.3.1 【Vuls実行サーバ側】SSHキーを作成
ssh-keygenで公開鍵と秘密鍵のペアを作ります。
秘密鍵は、今回は id_rsa_vals という名前でホームディレクトリの.sshに保存します。
パスフレーズは入力せずに作成してください。

```
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cd ~/.ssh/
$ ssh-keygen -t rsa -f id_rsa_vuls
$ chmod 600 id_rsa_vuls
```

####2.3.2 【スキャン対象サーバ側】公開鍵の登録
作成した公開鍵をスキャン対象サーバ側に設置します。
2.2.2で作成したVulsユーザのホームディレクトリの.sshディレクトリ配下にauthorized_keysを置きます。

```
# su - vuls
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ mv id_rsa_vuls.pub ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
```
すでにauthorized_keysがある場合は、公開鍵を追記します。

```
# cat id_rsa_vuls.pub >> authorized_keys
```

ここまでできたら、Vuls実行サーバからスキャン対象サーバへSSHできるはずです。
2.2.2で作成した vulsユーザ でアクセスできるか、確認しておきましょう。

```
ssh -i ~/.ssh/id_rsa_vuls vuls@***.***.***.***
```

##3. スキャン
以下の作業は、vulsのホームディレクトリで行います。


###3.1 スキャン対象を設定
設定ファイルにスキャン対象のサーバーを設定します。

```
$ vi config.toml
[servers]
 
[servers.****]
host = "***.***.***.***"            # 対象サーバーのIPアドレス
port = "22"
user = "vuls"                       # 2.2.2で作成したユーザー
keyPath = "/root/.ssh/id_rsa_vuls"  # ※dockerコンテナ内でのパスである点に注意!
```

###3.2 コンフィグのテスト
設定ファイルの内容で正しく接続できるか確認します。

```
$ docker run --rm -it\
    -v ~/.ssh:/root/.ssh:ro \
    -v $PWD:/vuls \
    -v $PWD/vuls-log:/var/log/vuls \
    vuls/vuls configtest \
    -config=./config.toml
```

 -  -v オプションでホスト側のディレクトリ（ : の左）とdockerコンテナ内のディレクトリ（ : の右）をマウントしています。ホスト側のディレクトリのパスは環境によって変更してください。

###3.3 スキャン実施

```
$ docker run --rm -it \
    -v ~/.ssh:/root/.ssh:ro \
    -v $PWD:/vuls \
    -v $PWD/vuls-log:/var/log/vuls \
    -v /etc/localtime:/etc/localtime:ro \
    vuls/vuls scan \
    -config=./config.toml

One Line Summary
================
vulstest        centos6.8       31 CVEs 127 updatable packages
```

CVEに載っている脆弱性が31件、更新対象が127件 という結果が出ました。

##4. レポート出力

###4.1 CUI

```
$ docker run --rm -it \
     -v ~/.ssh:/root/.ssh:ro \
     -v $PWD:/vuls \
     -v $PWD/vuls-log:/var/log/vuls \
     -v /etc/localtime:/etc/localtime:ro \
     vuls/vuls report \
     -cvedb-path=/vuls/cve.sqlite3 \
     -format-short-text \
     -config=./config.toml -lang=ja
```

 - 日本語で出力する場合は`-lang=ja`を付けます。
 - `-format-short-text`の部分を変更すると、レポートの詳しさを変更できます。
  - format-one-line-text
  - format-short-text
  - format-full-text

###4.2 TUI(Terminal-Based User Interface)

```
$ docker run --rm -it \
    -v ~/.ssh:/root/.ssh:ro \
    -v $PWD:/vuls \
    -v $PWD/vuls-log:/var/log/vuls \
    -v /etc/localtime:/etc/localtime:ro \
    vuls/vuls tui \
    -cvedb-path=/vuls/cve.sqlite3
``` 

<img width="946" alt="vulsキャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/91757c68-2025-f278-2204-7bfe74ee5fdb.png">


###4.3 Web
Vuls Repo を実行します。

```
$ docker run -dt \
     -v $PWD:/vuls \
     -p 80:80 \
     vuls/vulsrepo
```

Webブラウザで `http://IPアドレス/vulsrepo/` にアクセスすると、結果が確認できます。

初期状態ではこんな感じに表示されました。表の項目を変更して出力形式を変えたり、棒グラフにしたりもできます。
<img width="524" alt="vuls2キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/12f0d60a-307b-186d-c6fc-05f2e1389839.png">

##5. Slackとの連携
###5.1 Slackの準備
Slack側で以下の準備をしておきます。

 - Slackのteamと投稿したいchannelを作る
 - SlackのIncoming WebHookの設定ページで投稿用URLを発行する
 - 先ほど作ったchannel名をプルダウンメニューから選択し、
Add Incoming WebHooks integration
を押す。
 - 発行されたWebhookURLを控えておく。

###5.2 Vulsの設定
 config.tomlにslackの設定を追記します。

```
[slack]
hookURL      = "https://hooks.slack.com/services/xxxxxxxx/xxxxxxxx/xxxxxxx"
channel      = "チャンネル名"
iconEmoji    = ":ghost:"
authUser     = "vuls"
notifyUsers  = ["@username"]
```

###5.3 レポート出力
`-to-slack` のオプションをつけてレポートを実行します。

```
$ docker run --rm -it \
     -v ~/.ssh:/root/.ssh:ro \
     -v $PWD:/vuls \
     -v $PWD/vuls-log:/var/log/vuls \
     -v /etc/localtime:/etc/localtime:ro \
     vuls/vuls report \
     -cvedb-path=/vuls/cve.sqlite3 \
     -format-short-text \
     -config=./config.toml \
     -lang=ja -to-slack
```

… slackに通知が来ました！
<img width="553" alt="vuls3キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/e3204ef7-28b5-d1f4-5247-3053bb3f2200.png">

##6. Cronの設定
自動実行するために、Cronに登録しておきます。
CUIから実行するときとほとんど変わりませんが、`-it`のオプションは外さないとエラーになります。

```
$ crontab -e
# 過去２年間の最新情報を取得
* 5 * * * docker run --rm -v /home/vuls:/vuls -v /home/vuls/go-cve-dictionary-log:/var/log/vuls vuls/go-cve-dictionary fetchnvd -last2y
# 最新の日本語脆弱性辞書を更新
* 6 * * * docker run --rm -v /home/vuls:/vuls -v /home/vuls/go-cve-dictionary-log:/var/log/vuls vuls/go-cve-dictionary fetchjvn -latest
# スキャン実行
* 7 * * * docker run --rm -v /home/vuls/.ssh:/root/.ssh:ro -v /home/vuls:/vuls -v /home/vuls/vuls-log:/var/log/vuls -v /etc/localtime:/etc/localtime:ro vuls/vuls scan -config=./config.toml
# レポートをSlackへ
* 8 * * * docker run --rm -v /home/vuls/.ssh:/root/.ssh:ro -v /home/vuls:/vuls -v /home/vuls/vuls-log:/var/log/vuls -v /etc/localtime:/etc/localtime:ro vuls/vuls report -cvedb-path=/vuls/cve.sqlite3 -format-one-line-text -config=./config.toml -lang=ja -to-slack
```