【Ansible】FortiGateへのIPアドレス許可設定を自動化する


これまで手動で行っていた、FortiGateへのIPアドレス許可設定を自動化したいと思いました。
そこでAnsibleを使った設定方法を試してみたので、その手順をまとめます。


# 目次
* [1. はじめに](#1-はじめに)
* [2. インベントリを作成する](#2-インベントリを作成する)
* [3. プレイブックを作成する](#3-プレイブックを作成する)
    - [3-1. ipアドレスを設定する](#3-1-ipアドレスを設定する)
    - [3-2. ipアドレスグループを設定する](#3-2-ipアドレスグループを設定する)
    - [3-3. ポリシーを設定する](#3-3-ポリシーを設定する)
* [4. プレイブックを実行する](#4-プレイブックを実行する)
* [5. 実行結果を確認する](#5-実行結果を確認する)
* [補足. 2台の機器に実行してみた](#補足-2台の機器に実行してみた)


# 1. はじめに
今回は以下の3つのタスクをAnsibleによって実行します。

>①接続を許可したいIPアドレスを作成する
②作成したIPアドレスをIPアドレスグループに追加する
③ポリシーを作成してIPアドレスグループを有効化する
  
ディレクトリ構成は以下のようにしました。

>root/
　├ home/
　　　├ user/
　　　　　├ forigate/
　　　　　　　　├ ansible/
　　　　　　　　　　　├ inventory/
　　　　　　　　　　　│　　　└ hosts.yml
　　　　　　　　　　　├ playbook/
　　　　　　　　　　　　　　　└ config.yml

もしFortiOSのモジュールがインストールされていない場合は、以下のインストールコマンドを実行してください。

```bash:bash
ansible-galaxy collection install fortinet.fortios:任意のバージョン
```

>最新バージョンは [公式ドキュメント](https://ansible-galaxy-fortios-docs.readthedocs.io/en/latest/version.html) を参照してください。


# 2. インベントリを作成する
まず、`inventory/hosts.yml` の中にFortiGateの接続情報を記述します。
ホスト名は自由です。FortiGateの情報は環境に合わせて設定してください。

```yml:hosts.yml
---
all:
  hosts:
    ホスト名:
      ansible_host: FortiGateのIPアドレス
      ansible_user: FortiGateのログインユーザ
      ansible_password: FortiGateのログインパスワード
      ansible_network_os: fortinet.fortios.fortios
```


# 3. プレイブックを作成する
次に、`playbook/config.yml` の中にAnsibleの接続情報を記述します。
先頭の `hosts:` には hosts.yml で記述したホスト名を設定してください。

```yml:config.yml
---
- hosts: ホスト名
  connection: httpapi
  gather_facts: no
  vars:
   vdom: "root"
   ansible_httpapi_use_ssl: yes
   ansible_httpapi_validate_certs: no
   ansible_httpapi_port: 443
```


# 3-1. ipアドレスを設定する
ここからAnsibleに実行させるタスクを記述していきます。
[3. ](#3-プレイブックを作成する) の設定内容に続いて、`config.yml` の中に許可したい「IPアドレスの情報」を記述します。

今回設定する項目は、FortiGateのWebページにある「アドレス作成」画面の項目と合わせています。
念のため既存の設定を確認しながら記述してください。以降のタスクに関しても同様にお願いします。

```yml:config.yml
tasks:
- name: Configure_IPv4_address.
  fortios_firewall_address:
    vdom: "root"
    state: "present"
    firewall_address:
        name: "作成するIPアドレスの名前"
        type: "ipmask"
        associated_interface: "設定するインターフェース"
        subnet: "作成するIPアドレス/サブネットマスク"
        visibility: "enable"
        allow_routing: "disable"
        comment: "任意で設定（Allow IPv4 address など）"
```

>※詳細は [公式ドキュメント](https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_firewall_address_module.html) を参照してください。


# 3-2. ipアドレスグループを設定する
[3-1.](#3-1-ipアドレスを設定する) で作成したIPアドレスを「IPアドレスグループ」に追加します。
`member:` の中に追加するIPアドレスを記述していきます。
`name:` で設定したIPアドレスグループが存在しない場合には、新しく作成されます。

```yml:config.yml
- name: Configure_IPv4_address_group.
  fortios_firewall_addrgrp:
    vdom: "root"
    state: "present"
    firewall_addrgrp:
        name: "設定するIPアドレスグループの名前"
        exclude: "disable"
        visibility: "enable"
        allow_routing: "disable"
        comment: "任意で設定（Allow IPv4 address group など）"
        member:
            - name: "3-1.で作成したIPアドレスの名前"
            - name: "3-1.で作成したIPアドレスの名前"
            - name: "3-1.で作成したIPアドレスの名前"
```

>※詳細は [公式ドキュメント](https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_firewall_addrgrp_module.html) を参照してください。


# 3-3. ポリシーを設定する
[3-2.](#3-2-ipアドレスグループを設定する) で作成したIPアドレスグループを「ポリシー」に追加します。
`policyid:` に **"既存のID"** を設定するとそのポリシーが変更になり、**"存在しないID"** を設定するとポリシーが新しく作成されます。
`action:` に **"accept"** を設定すると、割り当てたIPアドレスグループが接続許可されます。
`status:` に **"enable"** を設定すると、ポリシーが有効化されます。

```yml:config.yml
- name: Configure_IPv4_policy.
  fortios_firewall_policy:
      vdom:  "root"
      state: "present"
      firewall_policy:
        policyid: ""
        name: "設定するポリシーの名前"
        srcintf:
            - name: "着信インターフェース"
        dstintf:
            - name: "発信インターフェース"
        srcaddr:
            - name: "送信元のIPアドレスグループの名前"
        dstaddr:
            - name: "宛先のIPアドレスグループの名前"
        schedule: "設定するスケジュール"
        service:
            - name: "設定するサービスの名前 または サービスグループの名前"
        action: "accept"
        inspection_mode: "flow"
        nat: "disable"
        profile_protocol_options: "設定するプロトコルオプションの名前"
        av_profile: "設定するアンチウイルスの名前"
        webfilter_profile: "設定するWebフィルタの名前"
        dnsfilter_profile: "設定するDNSフィルタの名前"
        waf_profile: "設定するアプリケーションコントロールの名前"
        ips_voip_filter: "設定するIPSの名前"
        ssl_ssh_profile: "設定するSSLインスペクションの名前"
        logtraffic: "all"
        comments: "任意で設定（Allow IPv4 policy など）"
        status: "enable"
```

>※詳細は [公式ドキュメント](https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_firewall_policy_module.html) を参照してください。
※オプションの設定項目の記述は任意です。（profile系など）


# 4. プレイブックを実行する
`config.yml` の作成が完了したら、Ansible を実行します。

実行するコマンドは以下になります。


```bash:bash
# 「/ansible」ディレクトリに移動する 
1. cd /home/user/fortigate/ansible

# 実行するファイルの構文をチェックする
2. ansible-playbook -i inventory/hosts.yml playbook/config.yml --syntax-check

# 実行するタスクの内容を表示する
3. ansible-playbook -i inventory/hosts.yml playbook/config.yml --list-tasks

# ホストに対して設定を検証反映させてみて、現在実行可能な状態かをチェックする
4. ansible-playbook -i inventory/hosts.yml playbook/config.yml --check

# ホストに対して設定を実行する
5. ansible-playbook -i inventory/hosts.yml playbook/config.yml
```


# 5. 実行結果を確認する
FortiGateのWebページにアクセスして、画面のサイドメニューから `「ポリシー&オブジェクト > IPv4ポリシー」` を選択してください。
一覧の中に作成したポリシーが存在していれば、無事に成功となります。


# 補足. 2台の機器に実行してみた
検証では以下の2台に対して実行しました。
OSのバージョンはそれぞれ Ansible が推奨している 6.0.0以上 になっています。

|     機種名    |            OS         | 通常時CPU |  実行時CPU  |
|      :-:      |           :-:         |    :-:    |    :-:     |
| FortiGate-60D | v6.0.12 build0419     |     0%    |  80%~100%  |
| FortiGate-60F | v6.2.5 build1142 (GA) |     0%    |  40%~70%   |

結果として、それぞれ設定の自動化は行えたのですが、設定実行時のCPU率に差異がありました。
これは 60Fの機種が「CPU：4コア」だったのに対して、60Dの機種が「CPU：1コア」だったことが原因のようでした。
今後 Ansible に設定を任せる際には、対象機種のCPU数についても注意する必要がありそうです。