クラウドの権限と委譲の分析
直接の実効権限と、別の主体へ移ることで得られる権限を分けて評価します。
説明
CIEMはクラウド主体の権限や利用状況を調べます。付与された許可だけでなく、上限となる境界、明示的拒否、別ロールへ委譲する経路も確認する必要があります。
許可集合と境界集合を使う限定モデルで実効操作を求めます。使用記録と比較した後、別ロールへの委譲をたどります。AWS IAM全条件の評価器ではありません。
直接の実効権限と、別の主体へ移ることで得られる権限を分けて評価します。
1三つの条件を表示する
read・write・delete・assumeという教材用の操作名です。
from sp16 import *
from sp02 import show
db=connect()
print('allow',sorted三つの条件を表示する(ALLOW))
print('boundary',sorted(BOUNDARY))
print('deny',sorted(DENY))境界は上限であり、それだけで新しい操作を許可する集合ではありません。
2許可と境界の共通部分を求める
両方にある操作だけを残します。
print(sorted(ALLOW & BOUNDARY許可と境界の共通部分を求める))deleteが外れます。許可文にdeleteがあっても、今回の境界では使えません。
3明示的拒否を適用する
共通部分からdenyを引きます。
active=effective明示的拒否を適用する(ALLOW,BOUNDARY,DENY)
print(sorted(active))readとassumeだけです。writeは許可と境界に含まれていても明示的拒否で外れます。
4境界だけにある操作が付与されないことを確認する
許可をreadだけにした場合です。
print(sorted(effective境界だけにある操作が付与されないことを確認する({'read'},BOUNDARY,DENY)))readだけです。境界にassumeが含まれるだけではassumeを実行できません。
5観測期間に使われなかった実効権限を探す
使用記録の範囲は10秒と20秒の固定2行です。
used={r[0] for r in db.execute("SELECT DISTINCT action FROM usage")}
print('used',sorted(used))
print('not_seen',sorted(active-used観測期間に使われなかった実効権限を探す))assumeは未観測です。未使用と判断するには、記録の期間・サービス・アカウント範囲を確認します。
6委譲による別主体への経路を読む
builderからdeploy-roleへ移る関係がある資料です。
show委譲による別主体への経路を読む(db,"SELECT * FROM delegation ORDER BY src")deploy-roleにはrelease-secretのreadがあります。元の主体の直接権限だけでは、この先の到達範囲を表せません。
7委譲を経由する対象を抽出する
assumeの先のread対象を結びます。
show(db,"SELECT a.src,a.dst AS role,b.dst AS target FROM delegation a JOIN委譲を経由する対象を抽出する delegation b ON a.dst=b.src WHERE a.action='assume' AND b.action='read'")builder→deploy-role→release-secretという経路です。実際には信頼ポリシー、セッション条件、対象資源側の規則も照合します。
まとめ
許可、境界、拒否の役割を分けます。
使用記録の範囲を添えて未観測権限を評価します。
委譲先の権限もたどります。
操作履歴と解説を振り返れます。
Python 3.15 / 固定のクラウド構成と限定した評価モデル
from sp16 import *
from sp02 import show
db=connect()
print('allow',sorted(ALLOW))
print('boundary',sorted(BOUNDARY))
print('deny',sorted(DENY))allow ['assume', 'delete', 'read', 'write'] boundary ['assume', 'read', 'write'] deny ['write']
print(sorted(ALLOW & BOUNDARY))['assume', 'read', 'write']
active=effective(ALLOW,BOUNDARY,DENY)
print(sorted(active))['assume', 'read']
print(sorted(effective({'read'},BOUNDARY,DENY)))['read']
used={r[0] for r in db.execute("SELECT DISTINCT action FROM usage")}
print('used',sorted(used))
print('not_seen',sorted(active-used))used ['read'] not_seen ['assume']
show(db,"SELECT * FROM delegation ORDER BY src")src | dst | action builder | deploy-role | assume deploy-role | release-secret | read
show(db,"SELECT a.src,a.dst AS role,b.dst AS target FROM delegation a JOIN delegation b ON a.dst=b.src WHERE a.action='assume' AND b.action='read'")src | role | target builder | deploy-role | release-secret
演習完了