Vuls/Vulsrepo を cron で動かすまで

# Vuls/Vulsrepo を cron で動かすまで

* vuls report の結果を何回分残すかの設定もできます。

## 条件
  1. CentOS7
  2. ユーザー vuls （あらかじめ作っておいてください、sudo できるように）
  3. グループ vuls （あらかじめ作っておいてください）
  4. Proxy サーバーがある場合も考慮します

## TODO:

* vuls が検査対象に root でログインして検査する deep mode は書き足していない
* 動かないときの対処、ここみたらいいよとか

## ディレクトリ・ファイル構成

### vuls/vulsrepo 専用ディレクトリ

```
$ pwd
/usr/local/share/vuls
$ LANG=C tree
.
|-- config.toml            # vuls の設定ファイル
|-- cve.sqlite3            # nvd, jvn データベース
|-- cve.sqlite3-shm
|-- cve.sqlite3-wal
|-- oval.sqlite3           # oval データベース
|-- results                # vuls report -format-json
|   |-- 2017-12-17T08:01:56+09:00
|   |   `-- localhost.json
|   |-- 2017-12-18T08:01:43+09:00
|   |   `-- localhost.json
|   |-- 2017-12-19T08:01:52+09:00
|   |   `-- localhost.json
|   |-- 2017-12-20T08:01:51+09:00
|   |   `-- localhost.json
|   |-- 2017-12-21T08:01:40+09:00
|   |   `-- localhost.json
|   |-- 2017-12-22T08:02:01+09:00
|   |   `-- localhost.json
|   |-- 2017-12-23T08:01:38+09:00
|   |   `-- localhost.json
|   |-- 2017-12-24T08:01:45+09:00
|   |   `-- localhost.json
|   |-- 2017-12-25T08:01:22+09:00
|   |   `-- localhost.json
|   `-- current -> /usr/local/share/vuls/results/2017-12-25T08:01:22+09:00
|-- vuls-cron             # nvd, jvn, oval データベースアップデート vuls 実行
`-- vulsrepo-config.toml  # vulsrepo の設定ファイル
```

### 環境変数設定

```
$ pwd
/etc
$ LANG=C tree profile.d
profile.d
|-- goenv.sh              # go 用の環境変数と proxy 設定環境変数
`-- vuls.sh               # vuls 用の環境変数
```

### systemd 用 vulsrepo の自動起動
* /usr/lib/systemd/system/vulsrepo.service

### cron 設定
* /etc/crontab

### ログディレクトリ
* /var/log/vuls/

## インストール
* [vuls の github](https://github.com/future-architect/vuls/blob/master/README.ja.md#step2-install-requirements) にある正規手順を元にして少し変更します。

### Install requirements

Vulsセットアップに必要な以下のソフトウェアをインストールする。

* SQLite3
* git
* gcc
* GNU Make
* go v1.8.3（レポジトリを利用します）

```Bash
$ id
uid=33333(vuls) gid=33333(vuls) groups=33333(vuls),10(wheel)
$ sudo yum -y install sqlite git gcc make wget golang
$ sudo mkdir -p /usr/local/share/go/src
$ cd /usr/local/share/
$ sudo chown -r vuls:vuls /usr/local/share/go
```

* /etc/profile.d/goenv.sh を作成し、下記を追加する。

```Bash:/etc/profile.d/goenv.sh
$ sudo vim /etc/profile.d/goenv.sh
GOPATH=/usr/local/share/go
if [ -n "$GOPATH" ]; then
        export GOPATH
        PATH=`echo $PATH | sed -e "s|:$GOPATH/bin||"`
        PATH=$PATH:$GOPATH/bin
        export PATH
else
        unset GOPATH
fi
# proxy サーバーを設定
# 10.233.3.10:3128 は自身の　proxy サーバーに変更する
# proxy サーバーがなければ、以下は消去する
export http_proxy=http://10.233.3.10:3128
export https_proxy=http://10.233.3.10:3128
```

* カレントシェルに上記環境変数をセットする。

```
$ source /etc/profile.d/goenv.sh
```

* git の proxy 設定
 * 10.233.3.10:3128 は自身の　proxy サーバーに変更する
 * proxy がなければ設定の必要なし

```
$ git config --global http.proxy http://10.233.3.10:3128
$ git config --global https.proxy http://10.233.3.10:3128
$ cat ~/.gitconfig
[http]
        proxy = http://10.233.3.10:3128
[https]
        proxy = http://10.233.3.10:3128
[url "https://"]
        insteadOf = git://
```

### Deploy go-cve-dictionary, goval-dictionary

* [go-cve-dictionary](https://github.com/kotakanbe/go-cve-dictionary) をインストール
  * ログディレクトリ /var/log/vuls も作成

```Bash
$ sudo mkdir /var/log/vuls
$ sudo chown vuls:vuls /var/log/vuls
$ sudo chmod 700 /var/log/vuls
```

* go-cve-dictionary, goval-dictionary のインストール

```Bash
$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/go-cve-dictionary.git
$ cd go-cve-dictionary
$ make install
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/goval-dictionary.git
$ cd goval-dictionary
$ make install
```

* vuls, vulsrepo の config、NVD, JVN, OVAL データベース用の専用ディレクトリを作成します。

```Bash
$ sudo mkdir /usr/local/share/vuls
$ sudo chown vuls:vuls /usr/local/share/vuls
```

* NVD, JVN, OVAL から脆弱性データベースを構築
  * RedHat 5,6,7 について取り込みます
  * RedHat 5 については 現在 ELS で早急に上位バージョンへの乗せ換えが必要、CentOS はに至ってはサポート切れで使ってはいけない OS です（参考: [各OSのリリース日とサポート終了日を表にまとめてみた](https://qiita.com/yunano/items/4757f86f9e92bb4f503f#os%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88)）
  * RedHat 5 については vuls は正式対応ではないので、警告を与える程度に使用してください。

```Bash
$ cd /usr/local/share/vuls
$ for i in `seq 2002(date +"%Y")`; do go-cve-dictionary fetchnvd -years $i; done
-- 省略 --
$ for i in `seq 1998(date +"%Y")`; do go-cve-dictionary fetchjvn -years $i; done
-- 省略 --
$ goval-dictionary fetch-redhat 5 6 7
```
* 他の種類のOSをスキャンする場合は以下を参照し、スキャン対象用のOVALを取得する
 * [Alpine](https://github.com/kotakanbe/goval-dictionary#usage-fetch-alpine-secdb-as-oval-data-type)
 * [RedHat, CentOS](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-redhat)
 * [Debian](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-debian)
 * [Ubuntu](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-ubuntu)
 * [Oracle Linux](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-oracle)
 * [SUSE](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-suse)

### Deploy Vuls

* /etc/profile.d/vuls.sh を作成し、下記を追加する。
  * カレントディレクトリがどこであろうとも、vuls だけでオプションが渡るようにします。

```Bash:/etc/profile.d/vuls.sh
$ sudo vim /etc/profile.d/vuls.sh
function vuls() {
    case $1 in
      "scan")
        /usr/local/share/go/bin/vuls $@ --config=/usr/local/share/vuls/config.toml;;
      "configtest")
        /usr/local/share/go/bin/vuls $@ --config=/usr/local/share/vuls/config.toml;;
      "report")
        /usr/local/share/go/bin/vuls $@ --config=/usr/local/share/vuls/config.toml -cvedb-path=/usr/local/share/vuls/cve.sqlite3 -ovaldb-path=/usr/local/share/vuls/oval.sqlite3;;
      *)
        ;;
    esac
}
alias vuls=vuls
```

* カレントシェルに上記環境変数をセットする。

```Bash
$ source /etc/profile.d/vuls.sh
```

* Vuls のインストール

```Bash
$ mkdir -p $GOPATH/src/github.com/future-architect
$ cd $GOPATH/src/github.com/future-architect
$ git clone https://github.com/future-architect/vuls.git
$ cd vuls
$ make install
```

### Deploy Vulsrepo

* [Step2. Installation](https://github.com/usiusi360/vulsrepo#step2-installation) の通りに行います

```Bash
$ cd $GOPATH/src/github.com
$ git clone https://github.com/usiusi360/vulsrepo.git
$ cd $GOPATH/bin
$ ln -s $GOPATH/src/github.com/vulsrepo/server/vulsrepo-server .
```

### Config

* Vulsの設定ファイルを作成する（TOMLフォーマット）

```Bash:/usr/local/share/vuls/config.toml
$ cd /usr/local/share/vuls
$ cat config.toml
[servers]

[servers.localhost]
host = "localhost"
port = "local"
```

* config.toml の記述が正しいかどうかテストしましょう

```Bash
$ vuls configtest
```

* Vulsrepo の設定ファイルを作成する（TOMLフォーマット）

```Bash:/usr/local/share/vuls/vulsrepo-config.toml
$ cd /usr/local/share/vuls
$ cat vulsrepo-config.toml
[Server]
rootPath = "/usr/local/share/go/src/github.com/vulsrepo"
resultsPath  = "/usr/local/share/vuls/results"
serverPort  = "5111"

[Auth]
authFilePath = "/usr/local/share/vuls/.htdigest"
realm = "vulsrepo_local"
```
* そのままだと、vulsrepo がパスワード認証なしで見ることができるので basic 認証を加える
  * パスワードは vuls になります
  * ↑ vuls からの変更とオプションの意味については [DigestAuth](https://github.com/usiusi360/vulsrepo#digestauth)  を参照してください

```Bash
$ cd /usr/local/share/vuls
$ vulsrepo-server -m -c ./.htdigest
```

### Always activate vulsrepo-server (CentOS7)

* スタートアップスクリプトを投入
  * 参考: [vulsrepoをsystemd的に扱う(自動起動しよう)](https://qiita.com/hogehogehugahuga/items/f51e3e8bf2e67ee2116d)

```Bash:/usr/lib/systemd/system/vulsrepo.service
$ sudo vim /usr/lib/systemd/system/vulsrepo.service
[Unit]
Description=vulsrepo daemon
Documentation=https://github.com/usiusi360/vulsrepo

[Service]
ExecStart = /usr/local/share/go/bin/vulsrepo-server
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /usr/local/share/go/bin/vulsrepo-server
ExecStop = /bin/kill -WINCH ${MAINPID}
WorkingDirectory=/usr/local/share/vuls/
Restart = no
Type = simple
User = vuls
Group = vuls

[Install]
WantedBy = multi-user.target
```

* 自動起動にして、vulsrepo を起動します

```Bash
$ sudo chmod 644 /usr/lib/systemd/system/vulsrepo.service
$ sudo systemctl enable vulsrepo
Created symlink from /etc/systemd/system/multi-user.target.wants/vulsrepo.service to /usr/lib/systemd/system/vulsrepo.service.
$ sudo systemctl start vulsrepo
```

* 認識しているか確認

```Bash
$ systemctl list-unit-files --type=service|grep vulsrepo
vulsrepo.service                              enabled
```

* 起動しているか確認
 * vulsrepo-config.toml の serverPort で指定するポートを listen しているか
 * taep-as-svc = 5111 （/etc/services を参照）
 * **vulsrepo はそのまま Web サーバーなります**

```Bash
$ sudo lsof -i | grep taep-as-svc
vulsrepo-  7649  ansible    4u  IPv6 1520439      0t0  TCP *:taep-as-svc (LISTEN)
```

* vulsrepo-config.toml の serverPort で指定するポートが外から見えるように
  * --list-all で確認

``` Bash
$ sudo firewall-cmd --permanent --zone=public --add-port=5111/tcp
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens4 ens3
  sources:
  services: dhcpv6-client ssh
  ports: 5111/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```

* （実行の必要なし）ちなみに 5111 ポートの閉鎖は

```Bash
$ sudo firewall-cmd --permanent --zone=public --remove-port=5111/tcp
```

* Web からみてみます。 http://vulsrepoサーバーのIP:5111/
  * まだデータが入っていないので、側（ガワ）しかでません。

## Cron

* 以下処理をするスクリプトを置きます
  1. nvd, jvn, oval データベースを取り込み
  2. vuls scan
  3. vuls report で、 vulsrepo のデータを作る
  4. 過去データ消去
     * 何回分の vuls scan の結果をため込むかは BACKUPCYCLE で設定します。下記 BACKUPCYCLE=10 とすると 9 回分保存します。一日一回スキャンするとすると 9 日分です。
* RedHat 5 については 現在 ELS で早急に上位バージョンへの乗せ換えが必要、CentOS はに至ってはサポート切れで使ってはいけない OS です（参考: [各OSのリリース日とサポート終了日を表にまとめてみた](https://qiita.com/yunano/items/4757f86f9e92bb4f503f#os%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88)）
* RedHat 5 については vuls は正式対応ではないので、警告を与える程度に使用してください。

```Bash:/usr/local/share/vuls/vuls-cron
$ cd /usr/local/share/vuls
$ cat vuls-cron
#!/bin/bash
BACKUPCYCLE=10
base_dir=${0%/*}
if [ $base_dir = $0 ]; then
    base_dir="./"
fi
. /etc/profile.d/goenv.sh
. /etc/profile.d/vuls.sh
pushd $base_dir
if [ -z $http_proxy ] ; then
  go-cve-dictionary fetchnvd -years $(date +"%Y")
  go-cve-dictionary fetchjvn -years $(date +"%Y")
  goval-dictionary fetch-redhat 5 6 7
else
  go-cve-dictionary fetchnvd -http-proxy=$http_proxy -years $(date +"%Y")
  go-cve-dictionary fetchjvn -http-proxy=$http_proxy -years $(date +"%Y")
  goval-dictionary fetch-redhat -http-proxy=$http_proxy 5 6 7
fi
vuls scan >>/var/log/vuls/vuls-cron.log 2>&1
vuls report -format-json >>/var/log/vuls/vuls-cron.log 2>&1
# 古いものから順に消去
if [ -e "vulsrepo-config.toml" ]; then
  resultpath=$(grep resultsPath vulsrepo-config.toml | sed -e "s/resultsPath[\t ]*=[\t \"\']*\(.*\)[\"\']/\1/i")
  if [ -e "$resultpath" ]; then
    for dirname in `/bin/ls -d1 $resultpath/* | sed '/^$/d' | sort -r | sed -e "1,${BACKUPCYCLE}d" | sort`
    do
      /bin/rm -rfv $dirname
    done
  fi
fi
popd .
```

* vuls-cron スクリプトを実行し vuls と vulsrepo の動作確認をします

```Bash
$ cd /usr/local/share/vuls
$ chmod 775 vuls-cron
$ ./vuls-cron
```

* Web からみてみます。 http://vulsrepoサーバーのIP:5111/
  * 今度は中身もでるはずです。

* 指定時間に vuls-cron が動くようにします
  * 下記は一日一回、午前 8:00 に起動します

```Bash:/etc/crontab
$ sudo vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed
00 08 * * * vuls /usr/local/share/vuls/vuls-cron
```