脆弱性情報の収集→slack通知→backlog登録を自動化してみた

## 前提
実行環境： CentOS6.X, ruby, slack-incoming-webhooks, backlog_kit
アラート通知先： slack
チケット登録先： backlog

今回はnginxの脆弱性情報をサンプルに取得してみます。

(参考)Vulsなんていうすばらしいツールがあるのをあとから知りました・・・
http://qiita.com/sadayuki-matsuno/items/0bb8bb1689425bb9a21c

## 脆弱性情報をどこから収集するか
IPAが提供している「MyJVN API」を利用します。LACさんが脆弱性情報を提供していると、どこかで聞いたような気がするので、提供される情報は信じていいとおもいます。
http://jvndb.jvn.jp/apis/

API経由で脆弱性情報を取得するには製品ID(productId)が必要になりますので、事前に調べておきましょう。以下のページのキーワードに「nginx」と入れて検索すると、レスポンスXMLが返ってきます。

http://jvndb.jvn.jp/apis/getProductList.html

```response.xml
<?xml version="1.0" encoding="UTF-8" ?>   
<Result 
version="3.2" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://jvndb.jvn.jp/myjvn/Results" 
xmlns:mjres="http://jvndb.jvn.jp/myjvn/Results" 
xmlns:status="http://jvndb.jvn.jp/myjvn/Status" 
xsi:schemaLocation="http://jvndb.jvn.jp/myjvn/Results http://jvndb.jvn.jp/schema/results_3.2.xsd">
    <VendorInfo xml:lang="ja">
      <Vendor vname="Igor Sysoev" cpe="cpe:/:igor_sysoev" vid="551">
        <Product pname="nginx" cpe="cpe:/a:nginx:nginx" pid="2221"/>
        <Product pname="nginx" cpe="cpe:/a:igor_sysoev:nginx" pid="2221"/>
      </Vendor>
    </VendorInfo>
    <status:Status version="3.2" method="getProductList" lang="ja" retCd="0" retMax="10000" errCd="" errMsg="" totalRes="2" totalResRet="2" firstRes="1" keyword="nginx" xsl="0" startItem="1"/>
  </Result>
```

Productのpid=productIdとなりますので控えておきます。今回は2221です。

## 脆弱性情報をいつ収集するか
最新の情報が漏れなければいいとおもうので、毎日午前3時に前日に発表された脆弱性を収集することにします。

## slack通知の準備

![スクリーンショット 2017-03-22 15.20.28.png](https://qiita-image-store.s3.amazonaws.com/0/32289/3e6d359b-acf2-fc00-66fc-048cb153aeb9.png)
「Team Settings」を開き「Configure Apps」を選択します。

![スクリーンショット 2017-03-22 15.20.58.png](https://qiita-image-store.s3.amazonaws.com/0/32289/6eaae392-9101-e3fa-5617-a963fd60be67.png)
「Custom Integrations」から「Incoming WebHooks」を選択します。

![スクリーンショット 2017-03-22 15.21.24.png](https://qiita-image-store.s3.amazonaws.com/0/32289/5d1af9b5-8347-0669-a7fe-77db25dfc97c.png)
「Add Configuration」を選択します。

![スクリーンショット 2017-03-22 15.22.55.png](https://qiita-image-store.s3.amazonaws.com/0/32289/5a61a972-afe2-22d5-2ce4-10a5b88b489b.png)
「create a new channel」を選択

![スクリーンショット 2017-03-22 15.23.30.png](https://qiita-image-store.s3.amazonaws.com/0/32289/db0b5517-baa4-2f91-e8fe-4f7fb53d0218.png)
Nameに任意のチャネル名を入れて、「Create Channel」を選択

![スクリーンショット 2017-03-22 15.24.39.png](https://qiita-image-store.s3.amazonaws.com/0/32289/4d53effb-2590-9018-d57f-372a7457bfcd.png)
「WebHook URL」をメモしておきます。

## backlog登録の準備

![スクリーンショット 2017-03-22 16.31.14.png](https://qiita-image-store.s3.amazonaws.com/0/32289/3c3a1fbb-43ce-7b6b-961e-1f33e68be4c4.png)
個人設定の「API」を選択

![スクリーンショット 2017-03-22 16.31.29.png](https://qiita-image-store.s3.amazonaws.com/0/32289/b32c837f-1246-a666-2fab-1527da88583f.png)
メモを記入して「登録」選択
APIキーが発行されますのでメモしておきます。

![スクリーンショット 2017-03-22 16.34.47.png](https://qiita-image-store.s3.amazonaws.com/0/32289/2b9a1dd5-d61b-89c9-05cd-a83d731b1dd8.png)
次に、「課題」から、「高度な検索」を選択します。
種別「バグ」を選択した状態でURLをコピーしてください。

```url
https://hoge.backlog.jp/find/SECURITY_CHECK?condition.projectId=XXXXXX&condition.issueTypeId=YYYYYY&condition.componentId=&condition.versionId=&condition.fixedVersionId=&condition.statusId=1&・・・
```
このようなURLが取得できますので、hoge(space_id)とprojectId=XXXXXXとissueTypeId=YYYYYYをメモしておきます。

## rubyの環境を準備する

```command
# バージョン確認
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

# インストール
$ gem install slack-incoming-webhooks
$ gem install backlog_kit
$ gem install nokogiri
```

## チェックスクリプト作成

``` securityCheck.rb
# -*- coding: utf-8 -*-
require 'rubygems'
require 'kconv'
require 'nokogiri'
require 'open-uri'
require 'mysql2'
require 'mechanize'
require "date"
require 'slack/incoming/webhooks'
require 'backlog_kit'

# 脆弱性を取得する日(昨日)
checkdate=Date.today - 1

#slack webhook
slack = Slack::Incoming::Webhooks.new "https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXXXXXXXXXXXXXX"

#backlog api
projectid  = XXXXXX
issueypeid = YYYYYY
priorutyid = 1
client = BacklogKit::Client.new(
  space_id: 'hoge',
  api_key: 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'
)

#MyJVNのXMLを解析するためのクローラー
agent = Mechanize.new
agent.user_agent_alias = 'Mac Safari'

# Nginxの脆弱性を取得するためのURL
# productId=2221でnginxを指定
url="http://jvndb.jvn.jp/myjvn?rangeDateFirstPublished=n&dateFirstPublishedStartM=#{checkdate.mon}&dateFirstPublishedEndM=#{checkdate.mon}&productId=2221&dateFirstPublishedStartY=#{checkdate.year}&dateFirstPublishedEndY=#{checkdate.year}&dateFirstPublishedStartD=#{checkdate.day}&dateFirstPublishedEndD=#{checkdate.day}&rangeDatePublic=n&method=getVulnOverviewList&rangeDatePublished=n&lang=ja"

page = agent.get(url)
baseHTML = Nokogiri::HTML(page.body)
baseHTML.css("item").each do |item|
  title=item.css("title").text
  link=item.attr('rdf:about')
  opend_at=item.css("issued").text.gsub("+09:00","").gsub("T"," ")

  #slackにアラート通知
  attachments = [{
    title: "#{title}",
    title_link: "#{link}",
    text: "公開日時：#{opend_at}",
    color: "#7CD197"
  }]
  slack.post "nginx脆弱性情報", attachments: attachments

  #backlogチケット登録
  params = {
    "projectId" => projectid,
    "issueTypeId" => issueypeid,
    "priorityId" => priorutyid,
    "summary"=> "#{title}",
    "description"=> "#{link}\n公開日時：#{opend_at}"
  }
  client.create_issue("security issue", params)
end
```

## 実行してみる

```command
$ ruby securityCheck.rb
```

うまく動いたら、cronに登録して自動化