FortigateのRestAPIを使ってコンフィグを取得するpythonスクリプトを作成してみた

# 概要
FortigateのRestAPIを使ってコンフィグを取得するpythonプログラムを作成しました。
APIを使い始めてから自動化がかなり捗るようになりましたので、ぜひ試してみてください。

# 環境
- FortiGate: FortigateVM, ファームウェア 5.6.11以上
- Python：3.10.7

# コード
まず全体のコードは以下に示し、順次説明を加えていきます。
注意点としてAPIの説明の為に最小限にしてます。
実際に動かす際はloggingやエラー処理なども必要になってくるでしょう。

```python:get_config.py
# requestsライブラリのインポート、証明書エラーの非表示化
import requests
requests.packages.urllib3.disable_warnings()

# デバイス情報の設定
device = {
    'ip': '192.168.1.1',
    'port': '443',
    'username': 'admin',
    'password': 'password',
}

# sessionの作成
session = requests.session()

# ログイン用のURL
url_login = f"https://{device['ip']}:{device['port']}/logincheck"

# ログイン用のpayload
payload_login = f"username={device['username']}&secretkey={device['password']}"

# 対象のデバイスへログイン。cookieなどのセッションの情報はsessionへ保存される。
session.post(url_login, data=payload_login, verify=False)

# コンフィグ取得用のURL
url_get_config = f"https://{device['ip']}:{device['port']}/api/v2/monitor/system/config/backup?destination=file&scope=global"

# 対象のデバイスのコンフィグを取得。
response_get_config = session.get(url_get_config, verify=False)

# 取得したコンフィグを保存する。
with open('config.txt', 'wb') as f:
  f.write(response_get_config.content)

# ログアウト用のURL
url_logout = f"https://{device['ip']}:{device['port']}/logout"

# 対象のデバイスからログアウト。セッション情報が削除される。
session.post(url_logout, verify=False)
```

# コードの説明
それでは簡単ですがコードの内容を説明していきます。
```python
# requestsライブラリのインポート、証明書エラーの非表示化
import requests
requests.packages.urllib3.disable_warnings()
```
RESTAPIを扱うためのライブラリをインポートします。
URLがIPにしてある場合エラーメッセージが出てくるため、非表示にしておきます。

```python
# デバイス情報の設定
device = {
    'ip': '192.168.1.1',
    'port': '443'
    'username': 'admin',
    'password': 'password',
}
```

デバイスの情報（IPアドレス、ポート、ユーザーID、パスワード）を辞書形式で設定します。
当然ながら本来コードにログイン情報を記載するのはよろしくありませんので、
OSの環境変数から読み取らせるなどの処置が必要です。
複数のデバイスに登録する場合は外部ファイルやDBからデバイス情報を読み取るように修正するとよいでしょう。

```python
# sessionの作成
session = requests.session()
```
requests.session()でセッションオブジェクトを作成します。
Fortigateにログインするとセッション維持のために渡されれるcookieを保持しておくためです。

```python
# ログイン用のURL
url_login = f"https://{device['ip']}:{device['port']}/logincheck"
```
ログインするためのURLを設定します。

```python
# ログイン用のpayload
payload_login = f"username={device['username']}&secretkey={device['password']}"
```
ログインリクエストに必要なpayloadを作成します。
必要なパラメーターはユーザー名とパスワードです。

```python
# 対象のデバイスへログイン。cookieなどのセッションの情報はsessionへ保存される。
session.post(url_login, data=payload_login, verify=False)
```
作成したURLとpayloadを指定してログインリクエストを出し、成功すればセッション情報が保存されます。
URLがIPアドレスの場合、証明書エラーになりますので verify=Falseオプションで指定します。

```python
# コンフィグ取得用のURL
url_get_config = f"https://{device['ip']}:{device['port']}/api/v2/monitor/system/config/backup?destination=file&scope=global"
```
コンフィグ取得用のURLを設定します。
scope=VDOM名とすればVDOMスコープでコンフィグを取得することが可能です。

```python
# 対象のデバイスのコンフィグを取得。
response_get_config = session.get(url_get_config, verify=False)
```
GETリクエストで、コンフィグ取得を行います。

```python
# 取得したコンフィグを保存する。
with open('config.txt', 'wb') as f:
  f.write(response_get_config.content)
```
with openでコンフィグ情報をテキストファイルに保存します。
ちなみにresponse_get_config.contentではなくresponse_get_config.textで保存する方が一般的かもしれません。
その場合はopenのオプションを'w'としてください。
ただ.contentの方がバイナリとして扱っているため速いです。

```python
# ログアウト用のURL
url_logout = f"https://{device['ip']}:{device['port']}/logout"
```
ログアウトするためのURLを設定します。

```python
# 対象のデバイスからログアウト。セッション情報が削除される。
session.post(url_logout, verify=False)
```
忘れがちですがログアウトはきちんとやりましょう。
ログアウトしないと残セッションが蓄積していき、429エラーを引き起こす可能性があります。

スクリプトが正常に実行されればカレントディレクトリにconfig.txtという名前のコンフィグファイルが作成されるはずです。

スクリプト自体は説明用に必要最小限の構成になっていますので、こちらをベースに他の操作も試して頂ければと思います。


# 参考サイト
[1] Fortigate API の解説動画。英語だけどおススメ！
[Fortigate API Automation Using Python: API Token based and session-based authentication Postman](https://www.youtube.com/watch?v=Avw2-0wVDlI&list=PLOocymQm7YWYNiPD7d2gMz_dO9p6DtE94)

[2] cURLを使ったAPI利用方法
[FortiGateのREST APIを利用してみた](https://qiita.com/kkmiura/items/80d8f8d1f3db0d07ec32)