この記事は エーピーコミュニケーションズ Advent Calendar 2022 の1日目の記事です。
はじめに
Cloudflare Zero Trust が 50ユーザーまで無料というプランがあるとのことで、試すにちょうどいいと思って少し触っていました。
触ってまもなく、API あるかな?どんな感じかな?と気になったので試してみました。
API を試す対象は Gateway のポリシー操作
試す機能の対象は、Gateway にしました。
SWG (Secure Web Gateway)に分類されるものでしょうか。UTM やコンテンツフィルター的なものをクラウド上のサービスとして利用できるもの、と捉えています。
(ゼロトラスト自身に詳しくないので間違っていたらすみません)
Cloudflare Zero Trust のサービスの概要や設定手順は、公式以外では以下の記事を参考にさせていただきました。ありがとうございます。
- 「Cloudflare Zero Trust」 で組織のゼロトラストネットワークを構成する
- Cloudflare Zero Trust の基本的なセットアップ手順
- Cloudflare Zero Trust クライアント側のセットアップ手順
- Cloudflare Zero Trustを導入してみた - POC環境構築編 - メモのページ - チラシの裏メモ 3枚目
Gateway の機能のうち、HTTP によるポリシーをAPIで操作してみます。
なお、今回の環境では TLS decryption
は有効化してあります。
下調べ・準備
API を叩くぞというときに、認証はどうやるのか、権限はどうなってるのかなどの基本的なお作法を知るのは避けて通れないですよね。個人的にはこのフェーズがなかなか苦手です・・・。なので少し細かく書き残しておきます。
API ドキュメント
Cloudflare の API 系ドキュメントは以下のページが見つかりました。こちらに各エンドポイントの説明やお作法などが掲載されていました。ドキュメントがしっかりしているのは助かりますね。
内容 | URL |
---|---|
お作法 | https://developers.cloudflare.com/fundamentals/api/ |
リファレンス | https://developers.cloudflare.com/api |
Cloudflare Zero Trust のドキュメントの API and Terraform |
https://developers.cloudflare.com/cloudflare-one/api-terraform/ |
Cloudflare Zero Trust 自体のドキュメント | https://developers.cloudflare.com/cloudflare-one/ |
なお、リファレンは最初 https://api.cloudflare.com/ の方にたどり着きましたが、https://api.cloudflare.com/ は古くて、2023 年のはじめに非推奨になるようです。なので、特に理由がなければ 新しい https://developers.cloudflare.com/api を参照するのが良さそうです。ただ、古い方にはその操作がどのプランでできるか明記がありますが、新しい方には見当たりませんでした。
現在は version 4.0.0 というバージョンで、エンドポイントの Base URL は https://api.cloudflare.com/client/v4
とのことです。
トークンの作成
Create an API token
を参考にしながら、API リクエストに必要なトークンを作成します。
https://dash.cloudflare.com/
にログインし、右上のアイコンをクリックして表示されたメニューのMy Profile
をクリックします- 左メニューから
API Tokens
をクリックします Create Token
をクリックしますCustom token
セクションのCreate Custom Token
欄のGet started
をクリックします(Zero Trust の操作に該当するちょうどいいテンプレートがないため)Permissions
でAccount
、Zero Trust
、Edit
をそれぞれ選択し、ページ下部のContinue to summary
をクリックしますAPI token permissions
には、Zero Trust
が見当たりませんが、おそらくこの設定で、GET も POST もいけるだろうという目論見です- あとで気が付きましたが、こちらにロールとパーミッションについてのまとめが書かれていました
- 他にも、アカウントや IP アドレス制限、TTLを制限できるようですが、とりあえずデフォルトのままで試します
- 確認画面が表示されるので
Create Token
をクリックします - トークンが表示されるので、後で使うために何かに控えておきます
ここまでで、トークンが作成できました。トークン作成画面の最後で、curl によるトークンの正常性確認コマンドが例示されていました。
(Base URL)/user/tokens/verify
というエンドポイントを利用するようです。
例示されている他コマンドに少しだけ手を加えて実行してみます。
ここではトークンを dummy_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
とします。
curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \ -H "Authorization: Bearer dummy_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type:application/json" | jq .
実行結果(正常)は以下のとおりです。ステータスコードは 200
でした。
{ "result": { "id": "6d9448f698dd3873fc3b603e3b0e0507", "status": "active" }, "success": true, "errors": [], "messages": [ { "code": 10000, "message": "This API Token is valid and active", "type": null } ]
なお、意図的に誤ったトークンを指定すると以下のようなエラーになりました。ステータスコードは 400
でした。
{ "success": false, "errors": [ { "code": 6003, "message": "Invalid request headers", "error_chain": [ { "code": 6111, "message": "Invalid format for Authorization header" } ] } ], "messages": [], "result": null }
ここまでで、API を利用するための最低限の準備が無事にできたようです。
おためし
Gateway のポリシーを API で参照、設定する操作をためします。
GET: ポリシーの一覧表示
Gateway のポリシーを参照する方法を API ドキュメントで調べるべく、Policy
/ Policies
という言葉を探しましたが、当初は分かりませんでした。やりたいことは Zero Trust Gateway Rules
という括りにありました。
Gateway のポリシーの一覧表示のメソッドとエンドポイントは以下のとおりです。
GET https://api.cloudflare.com/client/v4/accounts/{identifier}/gateway/rules
ドキュメントはこちら。 Cloudflare API Documentation
ちょっと準備に逆戻り
エンドポイントのうち、{identifier}
の部分は何を指定するのか分かりませんでした。accounts/
のあとの {identifier}
なのでアカウントの識別子的なものを指定するのだと思いました。そうえいば、Create an API token
のページの前提条件として find your zone and account IDs
とあって、そのリンク先に Find zone and account IDs
というページがあります。ドメインを選択とありますが、私の Cloudflare のサービス利用状況的にはドメインはないため、この方法では探せませんでした。
いろいろ試した結果、https://dash.cloudflare.com/
にログインしたあとにリダイレクトされる URL のうち、https://dash.cloudflare.com/
のあとの 32文字の英数字(少なくとも私の場合は)が アカウントID のようでした。本記事の説明上は dummy_account_id_xxxxxxxxxxxxxxx
とします。
ただ、確認方法はサービスの利用状況によって異なるかもしれませんので、正確なことは公式ドキュメントを参照していただければと思います。
事前に GUI でポリシーを入力(後で確認する用)
何か設定が入ってる状態で一覧を表示したいので、事前に GUI でポリシーを入力することにしました。
こんな感じで、1つのポリシーが1つあるだけです。Shopping & Auctions
カテゴリ(と配下のいくつかのサブカテゴリ)をブロックするポリシーです。
ポリシー一覧表示の実行
準備ができたところで、いよいよ実際にポリシーの一覧表示を試します。
リクエストは以下のとおりです。
curl -X GET "https://api.cloudflare.com/client/v4/accounts/dummy_account_id_xxxxxxxxxxxxxxx/gateway/rules" \ -H "Authorization: Bearer dummy_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json"
実行結果は以下のとおりです。
{ "result": [ { "id": "116dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "name": "block_shopping", "description": "", "precedence": 11000, "enabled": true, "action": "block", "filters": [ "http" ], "created_at": "2022-11-23T13:07:12Z", "updated_at": "2022-11-27T07:49:03Z", "deleted_at": null, "traffic": "any(http.request.uri.content_category[*] in {22 73 82 88 148})", "identity": "", "device_posture": "", "version": 1, "rule_settings": { "block_page_enabled": false, "block_reason": "gomen nasai", "override_ips": null, "override_host": "", "l4override": null, "biso_admin_controls": { "dp": false, "dcp": false, "dd": false, "du": false, "dk": false }, "add_headers": {}, "ip_categories": false, "check_session": null, "insecure_disable_dnssec_validation": false } } ], "success": true, "errors": [], "messages": [] }
大体は雰囲気でわかりますが、特徴的なのは以下の traffic
の箇所です。
"traffic": "any(http.request.uri.content_category[*] in {22 73 82 88 148})",
このあたりの書式は Cloudflare Zero Trust のポリシーのフィルタリングの説明ページにありました。
カテゴリの ID と名前の関連を調べる(ドキュメント・API)
レスポンスに含まれる traffic
のルールでは、カテゴリが 22
のように ID で表記されています。ドキュメントの Category and subcategory IDs
に対応表がまとまっています。これを見ると ID がどの名前かが分かります。ID 22
が Shopping & Auctions
というカテゴリで、他の ID はこのカテゴリに含まれるサブカテゴリのようです。
せっかくなので、カテゴリとサブカテゴリの関係を API でも調べてみました。https://api.cloudflare.com/client/v4
/accounts/{account_id}/gateway/categories
を見れば分かるようです。カテゴリの ID 22
で絞り込むために、以下のようにリクエストしてみました。
curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/dummy_account_id_xxxxxxxxxxxxxxx/gateway/categories" \ -H "Authorization: Bearer dummy_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" | jq ".result[] | select (.id==22)"
実行結果は以下のとおりです、カテゴリID 22
と配下に含まれるサブカテゴリの ID 73
、82
、 88
、148
と名前が確認できます。
{ "name": "Shopping & Auctions", "id": 22, "description": "Sites related to ecofmmerce, coupons, shopping, auctions and marketplaces.", "class": "premium", "subcategories": [ { "name": "Auctions & Marketplaces", "id": 73, // ...(略)... }, { "name": "Coupons", "id": 82, // ...(略)... }, { "name": "Ecommerce", "id": 88, // ...(略)... }, { "name": "Shopping", "id": 148, // ...(略)... } ], "beta": false, "deprecated": false }
ここまでで、参照系の API としてポリシーの一覧表示を試せました。
POST: ポリシーの追加
続いて、設定系としてポリシーの追加を試します。要件は以下のとおりです。
- Policy name:
block_YouTube
- Action:
Block
- Expression
- Selector:
Application
- Operator:
in
- Value:
YouTube
(id644
、List Application and Application Type mappings
で調査済み)
- Selector:
- Block page customised text:
suman
- 位置: 先程 GUI で追加した HTTP のポリシーの下(低い優先度)
方式は以下の通り(参考: Create Zero Trust Gateway Rule
)。
POST https://api.cloudflare.com/client/v4/accounts/{identifier}/gateway/rules
ペイロードの組み立て
重要なのはペイロードですね。ドキュメントや、ポリシー一覧の結果などを参考におためしペイロードを組み立てます。
GUIで追加したポリシーはカテゴリーによるフィルタリングでしたが、今回追加したいのはアプリケーションによるフィルタリングです。なので、traffic
の書き方が変わるはずです。
調べたらこちらのドキュメントに例がありました。
http.request.uri.content_category[*]
ではなく、app.ids[*]
という Selector を指定するようです。今回は id 644
にマッチさせたいので "traffic": "any(app.ids[*] in {644})"
です。
precedence
は、ドキュメントによると、値が小さい方が優先度が高い(Lower values indicate higher precedence
)とのことです。設定済みルールは 11000
で、これより優先度低くする要件としたため 12000
にすることにします。(あとで試してみると precedence
未指定の場合は、既存の最大 precedence
+ 1000
になりました)
ペイロード全体としては、以下のとおりです。payload.json
というファイルとして保存しておきます。
{ "name": "block_YouTube2", "description": "new policy", "enabled": true, "action": "block", "filters": [ "http" ], "traffic": "any(app.ids[*] in {644})", "rule_settings": { "block_page_enabled": true, "block_reason": "suman" } }
なお、必須のパラメータは、API ドキュメント上に Required
と記載があります。
ポリシー追加の実行
ペイロード payload.json
が準備できたので、実際にリクエストを実行してます。
curl -X POST "https://api.cloudflare.com/client/v4/accounts/dummy_account_id_xxxxxxxxxxxxxxx/gateway/rules" \ -d @payload.json \ -H "Authorization: Bearer dummy_token_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json"
レスポンスは以下のとおりです。ステータスコードは 200
でした(予想は 201
でしたが)。
{ "result": { "id": "31f0xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "name": "block_YouTube", "description": "new policy", "precedence": 12000, "enabled": true, "action": "block", "filters": [ "http" ], "created_at": "2022-11-27T11:12:44Z", "updated_at": "2022-11-27T11:12:44Z", "deleted_at": null, "traffic": "any(app.hosts_ids[*] in {644})", "identity": "", "device_posture": "", "version": 1, "rule_settings": { "block_page_enabled": true, "block_reason": "suman", "override_ips": null, "override_host": "", "l4override": null, "biso_admin_controls": null, "add_headers": null, "ip_categories": false, "check_session": null, "insecure_disable_dnssec_validation": false } }, "success": true, "errors": [], "messages": [] }
追加後の確認
GUI でポリシー一覧を確認します。
続いて、 WARP を入れて保護下にしたクライアントのブラウザから https://www.youtube.com/
にアクセスします。
無事にブロックされました。(実際は反映まで少し時間がかかりました)
(参考)エラー集
既存のポリシーと name
が重複すると以下のエラーになりました。(ステータコード 409
)
{ "result": null, "success": false, "errors": [ { "code": 2010, "message": "A rule with this name already exists." } ], "messages": [] }
一方 precedence
が重複すると以下のエラーになりました。(ステータコード 409
)
{ "result": null, "success": false, "errors": [ { "code": 2011, "message": "A rule with this precedence already exists." } ], "messages": [] }
トークンに対する Permissions が Write
ではなく Read
だと以下のエラーになりました。(ステータコード 403
)
{ "success": false, "errors": [ { "code": 10000, "message": "Authentication error" } ] }
ここまでで、設定系の API としてポリシーの追加を試せました。
その他のポリシー操作エンドポイント
今回は試せていませんが、ポリシーを操作するエンドポイントには以下のものもあります。
- ポリシーの詳細表示
GET https://api.cloudflare.com/client/v4/accounts/{identifier}/gateway/rules/{uuid}
- ドキュメント: Zero Trust Gateway Rule Details
- ポリシーの削除
DELETE https://api.cloudflare.com/client/v4/accounts/{identifier}/gateway/rules/{uuid}
- ドキュメント: Delete Zero Trust Gateway Rule
- ポリシーの更新
PUT https://api.cloudflare.com/client/v4/accounts/{identifier}/gateway/rules/{uuid}
- ドキュメント: Update Zero Trust Gateway Rule
いずれも uuid
の部分は、ポリシーの id
の部分を指定するようです。
おわりに
Cloudflare Zero Trust の機能のうち、Gateway のポリシーの一覧表示と追加をする API を試してみました。
設定系の操作は、いずれもポリシーの一つ一つを対象にした操作であり、ポリシー一式をまとめて操作する方法はないようでした。
ドキュメントの見方はなんとなく分かってきたので、サービス側の仕様をある程度理解した上であれば使えそうな気がします。
今回ためした操作を同じことができる Ansible のモジュールはなさそうですが、ansible.builtin.uri
モジュールを利用すればおそらくできると思います。
他、全く触れていないので Zero Trust サービスの操作ができるかは分かりませんが、Cloudflare のサービスを GUI 以外で操作するには以下のような方法があるようです。
- Terraform https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs
- Python (
python-cloudflare
) - Go (
cloudflare-go
)
また気が向いたら触ってみたいと思います。