てくなべ (tekunabe)

ansible / network / automation

[Batfish/Ansible] Batfish と Ansible によるネットワークコンフィグ事前検証のウェビナーのまとめ



これは Batfish Advent Calendar 2018 の1日目の記事です。



先日、Ansible と Batfish を使ったネットワークコンフィグの事前検証についてのウェビナーがあり、Ansible 公式サイトに動画も公開されました。 この記事では、動画の内容のまとめと補足をしたいと思います。

なお、Batfish とは、ネットワークコンフィグの検証ツールです。概要については以下の記事を参照してください。

[Batfish] ネットワーク機器のコンフィグを読み込んでルーティングなどの様々な検証ができるツール「Batfish」の紹介 - てくなべ (tekunabe)


ソース

動画の内容の詳細については以下のソースを参照してください。

動画

www.ansible.com

スライド (PDF)

https://www.ansible.com/hubfs/2018_Content/Ansible-Intentionet-Webinar-Slides.pdf

デモ Playbook 一式

https://github.com/batfish/ansible-demo



以下、内容

■ Part I Network validation today

(P6) Batfish とは

  • 包括的なネットワーク検証ソリューション
  • Apache 2.0 License の OSS

(P7) なぜこのようなツールが必要か?

  • 自動化がスケールラビリティやスピードが得られる
  • しかし、ちょっとしたミスでも影響が大きい
  • そのため、ワークフローには自動化された効果的な変更の検証が重要

(P8) 効果的な変更の検証とは?

  • プロアクティブ
    • 事前、自動的な検証
  • 包括的
    • 商用環境スケール、すべての障害時経路の検証

(P9-) こんにちの検証方法の比較

テキスト解析

  • コンフィグのテキストをチェックする
  • 確認できる例
    • NTPサーバー、DNSサーバーなどが設定さているか
  • 事前検証可能か: ○
  • 包括的か: ×
    • ネットワークの振る舞いを検証できない

エミュレーション

  • VM などによるネットワーク環境のシミュレーション環境を準備して行うチェック
  • 確認できる例
    • BGPセッションが確率されているか、
    • テストクライアントが DNS サーバーに到達できるか
    • リンク障害時にどうなるか
  • 事前検証可能か: ○
  • 包括的か: ×
    • 商用環境スケールにならない、すべての障害経路はテストできない

Operational State Analysis

  • 実環境での確認
  • 確認できる例
    • BGPセッションが確率されているか
    • テストクライアントが DNS サーバーに到達できるか
    • traceroute は想定通りか
  • 事前検証可能か: ×
  • 包括的か: ×
    • すべての障害経路はテストできない

事前検証可能、かつ包括的な検証方法がなかっため、新しいアプローチが必要。

モデルベース検証

  • Batfish で可能なタイプの検証アプローチ
  • 確認できる例
    • サブネットAからBへのフローはあるか
    • すべてのクライアントが DNS サーバーに到達できるか
    • 特定のサービスを中断させるリンク障害はあるか
  • 事前検証可能か: ○
  • 包括的か: ○



■ Part II Comprehensive pre-commit validation with Batfish

(P16) Batfish とは?

内部処理

  • Cisco、Juniper、Arista、PaloAlto などの機器のコンフィグを読み込み
  • ベンダーニュートラルなコンフィグモデルを生成
  • ルーティングモデルを生成
  • ネットワークの振る舞いのモデルを生成

なにをテストできるか

    • すべての機器がパスワードで保護されていること
    • 通信不可能な箇所
    • 可用性を低下させる機器障害

(P18) Batfish Network Policies

Security

  • 通信できてはいけないトラフィックがないこと
  • 暗号化されていること

Reliability

  • 単一リンク障害で停止しないこと

Compliance

  • 機器へのアクセスが安全な通信のみに制限されていること
  • 未定義の設定がないこと

(P20) Batfish の活用方法

  • ネットワーク CI/CD パイプラインへの組み込み
  • シナリオテスト



■ Part III Demo of Ansible + Batfish

(P22-) デモシナリオ

  • シナリオ1
    • DC ファブリックに新たなリーフスイッチを追加する
  • シナリオ2

(P23) シナリオ1: リーフスイッチの追加

AS番号 65003 を利用するリーフスイッチ leaf-03 を追加する。

流れ

  1. ユーザーからの入力
    • リーフスイッチの名前
    • POD ID
    • BGP AS番号
  2. Jinja2 テンプレートによるコンフィグ生成
  3. git コミット
  4. Batfish による検証
    • NTPサーバーの設定、未定義の参照がないか、BGP設定が正しいかなど
  5. 検証結果を S3 に記録
  6. Slack へ通知

デモ

(詳細は動画の 20:35 頃からご覧ください)

最初の実行

意図的に、すでに利用されている AS番号(65002)を新しいリーフスイッチで利用しようとしたため、Badfish が FAIL という結果を返す。

実行コマンド
ansible-playbook -i playbooks/inventory playbooks/master.yml --tags "create, git, s3, slack"
実行する Playbook (playbooks/master.yml)

https://github.com/batfish/ansible-demo/blob/master/playbooks/master.yml

2回目の実行

AS 番号を修正(65003)して OK に。

シナリオ1 のまとめ

入力された AS 番号の間違いを Batfish で検出できた。

(P27) シナリオ2: サービスの有効化

シナリオ1 で追加したリーフスイッチ leaf-03 配下のホスト向けに、TCP/80 を許可するポリシーを追加する。 Provably safe ACL and firewall rule changes と同様の 検証。

流れ

  1. ユーザーからの入力 (シナリオ1と異なり、入力パラメータはコンフィグ生成ではなく、検証目的で利用される)
    • 対象の FW はどこか
    • 検証したいポリシー(送信元IP、宛先IP、宛先ポート)
  2. Jinja2 テンプレートによるコンフィグ生成
  3. git コミット
  4. Batfish による検証
    • シナリオ1と同様の検証に加えて、今回の変更固有の検証
      • すでに設定済みのポリシーでないこと
      • 仕様が満たされること
      • 既存のフローに意図しない影響がないこと
  5. 検証結果を S3 に記録
  6. Slack へ通知

デモ

(詳細は動画の 24:40 頃からご覧ください)

最初の実行

permit tcp any 10.1.5.0 0.0.0.63 eq 80 を追加した candidate config に対して、意図通りのポリシーになるかチェックするために以下のパラメーターを入力(最初の実行と同じ)

  • 送信元アドレス: 0.0.0.0/0
  • 宛先アドレス: 10.1.5.0/27
  • 宛先ポート: TCP/80
検証1: すでに設定済みのポリシーでないこと (OK)

f:id:akira6592:20181114155652p:plain

検証2: 要件が満たされること (OK)

f:id:akira6592:20181114155710p:plain

検証3: 既存のフローに意図しない影響がないこと (NG)

f:id:akira6592:20181114155736p:plain

入力した 10.1.5.0/27 に対して、candidate config の 10.1.5.0 0.0.0.63 (/26) の範囲が広すぎるため、エラーとなる。 例として、10.1.5.32 TCP/8010.1.5.0/27 の範囲外) へのフローが、意図せず 許可されることが示される。

検出の仕組み

ポイントは playbooks/validate_acl_change.yml の question3に対応するタスク

- name: "Checking: {{ question3 }}"
  batfish_searchfilters:
    name: "{{ bf_base_snapshot }}"
    reference_snapshot: "{{ bf_candidate_snapshot }}"
    network: "{{ bf_network }}"
    filters: "{{ filters }}"
    nodes: "{{ nodes }}"
    source_ips: "{{ source_ips }}"
    destination_ips: "{{ destination_ips }}"
    ip_protocols: "{{ ip_protocols }}"
    destination_ports: "{{ destination_ports }}"
    invert_search: yes
  register: answer3
  tags:
    - always

ACLエントリ追加前のコンフィグのスナップショットと、追加後の candidate config の違いを抽出しています。 抽出する条件は、ユーザーによって入力されたポリシー(送信元IP、宛先IPなど)の範囲外(invert_search: yes)です。 これにより、意図しないポリシー(今回の場合、広すぎるプレフィックスによる許可)検出できることになります。

なお、 batfish_searchfilters モジュールと、内部で呼び出されている [pybatfish](https://github.com/batfish/pybatfish) の主なパラメータの対応は以下の通りです。

項目 batfish_searchfilters pybatfish
検証スナップショット名 name pybatfish.client.commands.bf_get_answersnapshot
比較対象スナップショット名 reference_snapshot pybatfish.client.commands.bf_get_answerreference_snapshot
入力ポリシーの範囲外を検証するかどうか invert_search pybatfish.question.bfq.searchfiltersinvertSearch
宛先IPアドレス destination_ips pybatfish.datamodel.flow.HeaderConstraintsdstIps
実行コマンド
ansible-playbook -i playbooks/inventory playbooks/maste_acl.yml --tags "create, git, s3, slack"
実行する Playbook (playbooks/master_acl.yml)

https://github.com/batfish/ansible-demo/blob/master/playbooks/master_acl.yml

2回目の実行

ワイルドカードマスクを修正した condidate config permit tcp any 10.1.5.0 0.0.0.31 eq 80 に対して、意図通りのポリシーになるかチェックするために以下のパラメーターを入力(最初の実行と同じ)

  • 送信元アドレス: 0.0.0.0/0
  • 宛先アドレス: 10.1.5.0/27
  • 宛先ポート: TCP/80
(再)検証2: 仕様が満たされること (OK)

f:id:akira6592:20181114155710p:plain

(再)検証3 :既存のフローに意図しない影響がないこと (OK)

f:id:akira6592:20181114155813p:plain

正しくワイルドカードマスクに修正され、要件を満たし、意図しない影響もないため OK になった。

シナリオ2 のまとめ

部分的に正しいかったような、とても見つけにくいエラーを Batfish で検出できた。



■ (P30) まとめ

  • 自動化は効果的な検証なしではリスキー
  • Batfish は、包括的な事前検証が可能