クラウドリソースへの到達性の分析
公開につながる条件と、経路が成立していない理由を具体的な設定値で説明します。
説明
CSPMはクラウドの資源設定を取得して公開や誤設定を評価します。公開IPがあるだけ、広い許可規則があるだけでは、通信が届く条件をすべて説明できません。
固定の資源台帳で、公開IP、経路、許可規則、待受ポートを一つずつ照合します。4条件に限定した到達性モデルであり、実通信の成功は別の観測で確認します。
公開につながる条件と、経路が成立していない理由を具体的な設定値で説明します。
1資源と許可規則を開く
routeは公開側への経路、listenは待受ポートの資料です。
from sp16 import *
from sp02 import show資源と許可規則を開く
db=connect()
show(db,"SELECT * FROM resource ORDER BY id")
show(db,"SELECT * FROM rule ORDER BY sg")web7とweb8は同じsg7ですが、web8には経路がありません。db7は公開IPを持ちません。
2公開Webへの条件を個別に評価する
外部アドレス198.51.100.10から443番へ向かう場合です。
print(explain公開Webへの条件を個別に評価する(db,'web7','198.51.100.10',443))
print(reachable(db,'web7','198.51.100.10',443))4条件ともTrueで到達候補になります。OS側の規則、ネットワークACL、アプリ認証などはこのモデルに含まれていません。
3同じ許可規則でも経路が違う資源を確認する
web8へ同じ要求条件を適用します。
print(explain同じ許可規則でも経路が違う資源を確認する(db,'web8','198.51.100.10',443))routeだけFalseです。許可規則だけで全資源を公開扱いすると、経路の違いを落としてしまいます。
4非公開資源のアドレス条件を確認する
db7には許可範囲内の送信元を指定します。
print(explain非公開資源のアドレス条件を確認する(db,'db7','192.0.2.10',5432))public_ipがFalseです。内部経路の到達性は別に評価できますが、今回の公開側モデルでは条件を満たしません。
5許可範囲を管理ネットワークへ絞る
sg7を192.0.2.0/24へ変更します。
db.execute("UPDATE rule SET cidr='192.0.2.0/24' WHERE sg='sg7'")
print(explain許可範囲を管理ネットワークへ絞る(db,'web7','198.51.100.10',443))
print(explain(db,'web7','192.0.2.20',443))外部例はruleがFalse、管理側例はTrueです。範囲を狭めると、必要な業務通信も外れる可能性があります。
6CIDRの境界を数値で確認する
192.0.2.0/24の内外を比較します。
net=ipaddress.ip_networkCIDRの境界を数値で確認する('192.0.2.0/24')
print(net.network_address,net.broadcast_address,net.num_addresses)
print(ipaddress.ip_address('192.0.3.0') in net)範囲は192.0.2.0から192.0.2.255、256個です。192.0.3.0は含まれません。
7別ポートへの許可を推測しない
同じ管理側送信元でも22番では条件が変わります。
print(explain別ポートへの許可を推測しない(db,'web7','192.0.2.20',22))ruleとlistenerがFalseです。443番の許可から管理用22番の到達性は導けません。
まとめ
複数の条件を組み合わせて到達候補を求めます。
公開側と内部側の経路を分けます。
送信元範囲とポートを具体値で確認します。
操作履歴と解説を振り返れます。
Python 3.15 / 固定のクラウド構成と限定した評価モデル
from sp16 import *
from sp02 import show
db=connect()
show(db,"SELECT * FROM resource ORDER BY id")
show(db,"SELECT * FROM rule ORDER BY sg")id | public_ip | route | listen | sg db7 | NULL | 1 | 5432 | sg8 web7 | 203.0.113.7 | 1 | 443 | sg7 web8 | 203.0.113.8 | 0 | 443 | sg7 sg | cidr | port sg7 | 0.0.0.0/0 | 443 sg8 | 192.0.2.0/24 | 5432
print(explain(db,'web7','198.51.100.10',443))
print(reachable(db,'web7','198.51.100.10',443)){'public_ip': True, 'route': True, 'rule': True, 'listener': True}
Trueprint(explain(db,'web8','198.51.100.10',443)){'public_ip': True, 'route': False, 'rule': True, 'listener': True}print(explain(db,'db7','192.0.2.10',5432)){'public_ip': False, 'route': True, 'rule': True, 'listener': True}db.execute("UPDATE rule SET cidr='192.0.2.0/24' WHERE sg='sg7'")
print(explain(db,'web7','198.51.100.10',443))
print(explain(db,'web7','192.0.2.20',443)){'public_ip': True, 'route': True, 'rule': False, 'listener': True}
{'public_ip': True, 'route': True, 'rule': True, 'listener': True}net=ipaddress.ip_network('192.0.2.0/24')
print(net.network_address,net.broadcast_address,net.num_addresses)
print(ipaddress.ip_address('192.0.3.0') in net)192.0.2.0 192.0.2.255 256 False
print(explain(db,'web7','192.0.2.20',22)){'public_ip': True, 'route': True, 'rule': False, 'listener': False}演習完了