OPNSense設定を更新したいのでAPIを利用する
OPNSenseの設定を更新しようと思うと、APIを使うのが手っ取り早い。
APIはJSONでGET/POSTができる。APIで設定を取得したり、更新したりができる。
https://docs.opnsense.org/development/api/core/firewall.html にAPIの一覧がある
APIの使い方の調べ方
APIは、管理画面で使わている。だからドキュメント以外にも管理画面のリクエストを凝視すれば、使い方がわかる。
管理画面のAPIリクエストの例
API を叩く準備:キー発行
APIを叩くには、キーを発行する。
キーは、「システム:→アクセス→ ユーザ→API 鍵→(+)ボタン」を押す。
(+)ボタンを押すと、キーがダウンロードされるので、それを変数に入れて使う。
キー発行は、ログインでもできる。ログインURLをcURLで叩いて、ワンタイムキーを取得する方法も取れる。ただパスワードをソース記載するのも面倒だしAPI鍵管理機能を使うのが楽だと思う。
API リクエスト例:ダッシュボード
管理画面のダッシュボードにある情報を取得する例
key=XXXXXXXXXXXXXXXbVt0mM8IEUv secret=XXXXXXXXXXXXXX162pKmFQ /usr/bin/curl --silent \ --basic \ --user "$key:$secret" \ --insecure \ https://192.168.1.1/api/diagnostics/activity/getActivity \ | jq .headers
JSONで受け取るので、jq と組み合わせて欲しいデータを取る。
APIリクエスト例:ファイアウォール・エイリアス
OPNSenseの目玉機能である、ファイアウォールの「エイリアス」機能にアクセスしてみる。
key=XXXXXXXXXXXXXXXbVt0mM8IEUv secret=XXXXXXXXXXXXXX162pKmFQ curl \ --basic \ --user "$key:$secret" \ --insecure \ --verbose \ https://192.168.1.1/api/firewall/alias/get \ > out.json cat out.json | jq .
エイリアスの一覧で、すべての情報を取得することができる
jq による整形
データは非常に多いので、jq でいい感じにフィルタ掛けてあげる
cat out.json | jq '.alias.aliases.alias | to_entries[] | select( .value.name | test("my-alias-name") ) '
OPNSenseのレスポンスは、無駄のないきれいなJSONになっている。綺麗すぎてjq で処理しづらいので、 to_entries[]
を使って変換する
to_entries[]
を使う
to_entries[]
を使うと、{ "uuid_a" { entry } }
を ` { key:'uuid_a', value: { entry } } に変換できる
to_entries[]
する前
{ "id_1" : { age: 100 } "id_2" : { age: 99 } }
to_entries[]
を通した後
[ { key:"id_1", value: { age:100 } , { key:"id_2", value: { age:99 } , ]
となる。
意図的に冗長なJSONに書き換えて、jqフィルタ処理が行いやすくできる。
jq 使ってJSONを整形したりフィルタする時の必須テクである。
API リクエスト POST 例:ファイアウォール・エイリアス更新
curl 'https://192.168.1.1/api/firewall/alias/setItem/1234567asdfghj' \ -H 'content-type: application/json' \ --data-raw '{"alias":{"enabled":"1",(中略)ent":""}' \ --compressed \ --insecure
POSTするデータは、管理画面のリクエストを見たほうが速い。
実際にリクエストを作成するポイント
一般的にJSONのPOSTをする場合、次のようになる。
curl http:///xxxxx \ -X POST -H 'content-type: application/json' \ --data-raw '{"alias": ...... '
json を1行にまとめる。
curl の --data-raw
に使えるように、JSONを1行にまとめる。
JSONは改行をしてこそ人間が見やすい形式になる。しかし、プログラムで扱うには、改行が邪魔である。
jq -c
で json を1行にまとめる。
cat req-data.json | jq -c .
ここまでをまとめる。
ここまで調べたことをまとめて、OPNSenseのファイアウォールのAliisを更新するAPIコールを書いてみる。
function ip_list_to_content(){ IPs=$1; IPs=$( echo $IPs | sed 's|\s|\\n|g' ) echo $IPs } function build_firewall_alias_json(){ name=$1 body=$2 description=$3 JSON=" { 'alias':{ 'enabled':'1', 'name':'${name}', 'type':'network', 'proto':'', 'updatefreq':'', 'content': '${body}', 'interface':'', 'counters':'0', 'description':'${description}', 'network_content':'' } }" echo $JSON | sed -r "s|'|\"|g" } function json_req_param(){ JSON=$1 echo $JSON | jq -c . } function post_to_opnsense(){ URL=$1 curl \ --silent \ --basic \ --user "$key:$secret" \ --insecure \ -X POST \ --data "${body}" \ -H "Content-Type: application/json" \ $URL } function get_to_opnsense(){ URL=$1 curl \ --silent \ --basic \ --user "$key:$secret" \ --insecure \ $URL } function getItem_Of_Fw_Alias(){ name=$1 filter=".alias.aliases.alias | to_entries[] | select( .value.name | test(\"${name}\") ) " URL="https://${OPNSenseAddr}/api/firewall/alias/get" get_to_opnsense $URL| jq -r "${filter}" } function get_UUID_by_name(){ name=$1 getItem_Of_Fw_Alias $name | jq -r .key } function google_smtp_ips(){ for i in $( dig txt _spf.google.com +short | \grep -Po '(?<=include:)[^\s]+' ); do dig $i +short txt | \grep -Po '(?<=ip4:)[0-9\./]+'; done | uniq | sort -n } function update_fw_alias_google_smtp(){ desc="GoogleのSMTPサーバー(spfから取得)" name="Google_SMTP" uuid=$( get_UUID_by_name $name ) ip_list=$(google_smtp_ips) content=$( ip_list_to_content "${ip_list}" ) json=$( build_firewall_alias_json $name $content $desc ) body=$( json_req_param "$json" ) URL="https://${OPNSenseAddr}/api/firewall/alias/setItem/${uuid}" ret=$(post_to_opnsense $URL $body ) echo $name echo $ret | jq . } function update_fw_alias_cloudflare_ipv4(){ desc="Cloudflare ip list" name="Cloudflare" uuid=$( get_UUID_by_name $name ) ip_list=$( curl -s https://www.cloudflare.com/ips-v4 ) content=$( ip_list_to_content "${ip_list}" ) json=$( build_firewall_alias_json $name $content $desc ) body=$( json_req_param "$json" ) URL="https://${OPNSenseAddr}/api/firewall/alias/setItem/${uuid}" ret=$(post_to_opnsense $URL $body ) echo $name echo $ret | jq . } function main(){ key=zzzzz/0mM8IEUv.... secret=.....Aj4AC3+3EC5... OPNSenseAddr=192.168.1.1 ## update_fw_alias_google_smtp; ## update_fw_alias_cloudflare_ipv4; } main;