GCPの「ファイアウォール地獄」から脱出せよ:階層型ポリシーによる統制術
「プロジェクトが100個を超えたあたりで、ファイアウォールルールの管理が破綻した」。これは私が過去に何度も耳にした、そして私自身もかつて味わった苦い経験です。
GCPの標準的なファイアウォールルールは、プロジェクト単位で管理されます。しかし、プロダクトが拡大し、マルチプロジェクト環境が当たり前になると、全プロジェクト共通で許可すべき「監視エージェントの通信」や「SSHの踏み台サーバーからのアクセス」を、すべての場所で手動設定するなんて狂気の沙汰です。
そこで登場するのが 階層型ファイアウォールポリシー(Hierarchical Firewall Policies) です。これを使いこなせば、組織レベルで「鉄の掟」を敷き、各プロジェクトの管理者に不要な権限を渡さずにガバナンスを効かせることが可能になります。
—
階層構造の魔法:評価の順序と継承のルール
GCPの階層型ファイアウォールポリシーは、組織(Organization)やフォルダ(Folder)という「親」のレベルで定義し、それを「子」のプロジェクトへ継承させる仕組みです。ここで重要なのは、「いつ、どのルールが評価されるのか」というパケットの運命です。
評価の優先順位は非常にシンプルです。
1. 階層型ファイアウォールポリシー(組織レベル → フォルダレベル)
2. VPCファイアウォールルール(プロジェクト単位)
この「階層が先、プロジェクトが後」というルールを理解していないと、「ポリシーで許可したはずなのに、プロジェクト側のルールで拒否される(あるいはその逆)」という、深夜のデバッグで最も泣きたくなる状況に陥ります。
ポリシーの評価シーケンス
パケットがインターフェースに到達した瞬間、GCPの分散ルーターは以下の順序でパケットを裁きます。
- Priority値が小さいルールが優先: 0に近い数字ほど、先に評価されます。
- 拒否(Deny)が最強: 一度
denyにマッチすれば、その時点でパケットはドロップされ、後続のルールは評価されません。 - 継承のチェーン: 組織レベルのポリシーは、自動的に配下のフォルダやプロジェクトへ適用されます。これを「上書き」することはできません。組織レベルで拒否された通信を、プロジェクトレベルで許可することは不可能です。
—
実践:gcloud CLIで階層型ポリシーを構築する
では、実際に組織レベルで「特定のIP範囲以外からのSSHを全遮断する」ポリシーを作成してみましょう。
1. ポリシーの作成
まずは、ポリシーの器を作ります。
# 組織レベルでポリシーを作成(組織IDを指定)
gcloud compute network-firewall-policies create "org-global-security-policy" \
--organization="123456789012" \
--global-firewall-policy
2. ルールの追加(SSH制限)
次に、許可されたIP(例: 10.0.0.0/8)以外からの通信を拒否するルールを、高い優先度(Priority 1000)で追加します。
gcloud compute network-firewall-policies rules create 1000 \
--action="deny" \
--direction="INGRESS" \
--global-firewall-policy \
--firewall-policy="org-global-security-policy" \
--organization="123456789012" \
--description="社内ネットワーク以外からのSSHを拒否" \
--layer4-configs="tcp:22" \
--source-ranges="0.0.0.0/0" \
--priority=1000
3. フォルダへの関連付け(アタッチ)
ここが一番重要です。作っただけではポリシーは機能しません。フォルダに対して「このポリシーを適用せよ」と明示的に関連付け(Association)を行います。
gcloud compute network-firewall-policies associations create \
--firewall-policy="org-global-security-policy" \
--folder="9876543210" \
--name="apply-to-prod-folder" \
--global-firewall-policy
—
実務でハマる「落とし穴」とデバッグ手法
階層型ポリシーを導入する際、現場でよく起きるのが「意図しない遮断」です。特に、API通信や疎通確認でパケットがどこで落ちたか分からないときは、以下の手順で切り分けます。
1. gcloud でのルール確認
今、どのルールが評価されているのかを可視化します。
# 現在適用されているポリシーの優先度順リストを表示
gcloud compute network-firewall-policies rules list \
--global-firewall-policy="org-global-security-policy"
2. VPCフローログの活用
もし通信が確立しない場合、VPC Flow Logs が最後の頼みの綱です。パケットの src_ip, dst_ip, dst_port に加え、firewall_rule_id を確認してください。ここに階層型ポリシーのルール名が出ていれば、あなたのポリシーがパケットをドロップしています。
3. Pythonで設定の整合性をチェックする(Tips)
多数のプロジェクトを管理している場合、設定漏れがないか確認するスクリプトを書いておくと安心です。
# 簡易的なポリシー適用状態のチェックイメージ
def check_firewall_status(policy_id):
# GCPのAPIを叩いて、特定のフォルダにポリシーがアタッチされているか検証
# 実際には google-cloud-compute ライブラリを使用します
print(f"Checking policy: {policy_id} ...")
# ここにロジックを実装
return "Associated"
# 運用自動化のパイプラインに組み込むことで、手動設定ミスを防ぐ
—
最後に:SREとしてのアドバイス
階層型ファイアウォールポリシーは強力ですが、「とりあえず全部拒否」をやりすぎると、後から入ったメンバーがデバッグ地獄に落ちます。
運用を開始する際は、まずは log-config を有効にして、どの通信が拒否されたのかを Cloud Logging で詳細に追えるようにしてください。セキュリティは「禁止すること」ではなく「可視化された上で制御すること」が本質です。
「守るべき場所」を階層構造で明確にし、プロジェクトレベルでは「アプリケーション固有の通信」に集中させる。この分業こそが、クラウドネイティブなインフラ管理の第一歩です。さあ、安全なクラウド環境への第一歩を踏み出しましょう。
コメント