Config文法チェックツールとしてのBatfish

# はじめに
[Advent Calender 5日目](https://qiita.com/tech_kitara/items/be71005ad7b5091d25a4)でご紹介した通り、ネットワーク解析ツールであるBatfishには、現在42種類のQuestion機能があります。
本記事では、その中でも個人的にお気に入りの`parseWarning`についてご紹介したいと思います。

# parseWarningでできること
ずばり「Configの文法チェック」です。Batfishは様々な解析を行うために、各ベンダー機器固有の文法を理解し、Configのパース(構文解析)を行います。parseWarningは、定義された文法ルールから外れているコマンド、行番号、コメントを出力してくれます。
実はこれ、公式チュートリアル「Getting started with Batfish」の一番始めに出てくるんですが、あまりにさらっと書きすぎててほぼ素通りしていました。おそらく、解析の前段階として使われるものであり、メイン機能ではないからだと思います。ただ、実際にわざと間違えたConfigを読み込ませると、実機を使っていないとは思えないほど高い精度で誤りを認識してくれます。
新規構築時など、Configを事前投入できる場合は必要ないかもしれませんが、セグメントやACLの追加作業等で、機器在庫や時間的な理由で流し込み確認までできない時は、レビューの補助ツールとして重宝すると思います。
次の項目以降で、具体例を交えて見ていきたいと思います。

# 使用したConfigファイル
2種類のCisco IOS(Cisco1812J)のConfigファイルを用意しました。左側(brborder2.log)は、実機から取得したRunning Config。右側(brborder-error.log)は、以下のような誤りを含めたConfigになります。

- 文字の不足、余剰
- 単語の不足、余剰
- 半角スペースの不足
- 全角文字 (分かりにくいですが6行目の右端です)
- IPアドレスのレンジ(0～255)からの逸脱 (111行目)
- ネットワークアドレスとサブネットマスクの不一致 (119行目)
![compare_result.jpg](https://qiita-image-store.s3.amazonaws.com/0/310082/52003bf0-9cde-2c34-efa7-19abd24a727e.jpeg)

# Pythonコード
上記2つのConfigファイルを、`networks/branch/configs`ディレクトリ配下に格納し、以下のコードを実行します。

```python:parse_warning.py
# Pybatfishをインポート
from pybatfish.client.commands import *
from pybatfish.question.question import load_questions, list_questions
from pybatfish.question import bfq
import pprint

# questionテンプレートをBatfishサービスからPybatfishへロード
load_questions()

# config等のスナップショットを保管したパスを指定し、読み込みを実施
SNAPSHOT_PATH = "networks/branch"
bf_init_snapshot(SNAPSHOT_PATH)

# parseWarning Questionを実行
parse_warning = bfq.parseWarning().answer().frame()
parse_warning
```
ご参考までに、文法を理解するためのソースコードらしきものを発見したので、URLを記載しておきます。
https://github.com/batfish/batfish/tree/master/projects/batfish/src/main/antlr4/org/batfish/grammar

# 実行結果
実行結果は以下の通りです。brborder2も`no inservice`というコマンドのみパースできず、"This syntax is unrecognized(この構文は認識されない)"というコメントが出力されています。brborder2-errorは、ほぼほぼ誤り検知できていますが、以下は検知できませんでした。

#### 誤り検知できなかったコマンド

| コマンド       |       行番号 |    備考    |
|:-----------------|:------------------:|:------------------|
|version 12.4　←全角文字| 6|もともと入っているコマンドなので、入らなくてもOK|
|service timestamps deug datetime localtime| 7||
|service tmestamps log datetime localtime| 8||
|service password-ecryption| 9||
|clock timezone JST|  23||
|username test privilege 19 password 7 051F031C35| 35||
|interface Tunnel| 61||
|interface Loopback01| 70|これは文法的にはOK。Loopback1と同義|
|ip route 1.1.1.1255.255.255.255 10.1.1.5| 118||
|ip route 2.2.2.2 255.255.255.0 10.1.1.5|	119||
|no http server| 122||
|line console 0| 144|文法的にOK。Batfishさん疑ってゴメンナサイ。。|
|login loca| 147|このパターンもコマンドは問題なく入るのでOK|

#### 誤り検知できたコマンド
![6-1.png](https://qiita-image-store.s3.amazonaws.com/0/310082/3f31158a-0729-c1cb-eff6-b9b3694e0ac5.png)

**補足：** 設定無効化するための"no ～"コマンドなど、本来Configには表示されないものは、誤りと認識されました。

まとめると、今回のCisco IOS機器で誤り検知できたのは以下パターンでした。

- 文字の不足、余剰　⇒**一部〇**
- 単語の不足、余剰　⇒**一部〇**
- 半角スペースの不足　⇒**一部〇**
- 全角文字 (分かりにくいですが6行目の右端です)　⇒**一部〇(文中の全角スペースを誤り検知してくれるケースあり)**
- IPアドレスのレンジ(0～255)からの逸脱 (111行目)　⇒**少なくともIPアドレスの場合は〇**
- ネットワークアドレスとサブネットマスクの不一致 (119行目)　⇒**少なくともStaticルートの場合は×**

# 最後に
さすがに実機と比べると精度は劣りますが、OSSで無償で入手でき、かつボタン一つで瞬時にチェックできるのは大変魅力的だと思います。
Batfishは現在盛んに開発、ブラッシュアップが行われており、今回検知できなかったパターンも、プルリクエストを出せば反映してくれるかもしれません。今後のさらなる発展に期待です:thumbsup: