一覧SP-16-1 · CSPM・CIEM:クラウド構成と権限

クラウドリソースへの到達性の分析

公開につながる条件と、経路が成立していない理由を具体的な設定値で説明します。

説明

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 / 固定のクラウド構成と限定した評価モデル

1
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
2
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}
True
3
print(explain(db,'web8','198.51.100.10',443))
{'public_ip': True, 'route': False, 'rule': True, 'listener': True}
4
print(explain(db,'db7','192.0.2.10',5432))
{'public_ip': False, 'route': True, 'rule': True, 'listener': True}
5
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}
6
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
7
print(explain(db,'web7','192.0.2.20',22))
{'public_ip': True, 'route': True, 'rule': False, 'listener': False}

演習完了