IDとグループの権限分析
表示名ではなく出所付きのIDで主体を特定し、権限が届く経路を示します。
説明
ITDRでは認証や権限変更の記録を結び、アイデンティティを使った行動を調べます。同じ表示名でも別の組織やテナントの主体である場合があります。
固定の主体台帳を正規化し、グループやロールを経由する権限のつながりをSQLで検索します。サービスIDも含め、直接付与だけでは見えない関係を調べます。
表示名ではなく出所付きのIDで主体を特定し、権限が届く経路を示します。
1出所を含めて主体を列挙する
realmはIDの発行元を表す教材用の区分です。
from sp13 import *
from sp02 import show出所を含めて主体を列挙する
db=connect()
show(db,"SELECT realm,id,name,kind FROM identity ORDER BY realm,id")corpとlabのu7は、IDと名前が同じでも別主体です。svc7は人のアカウントではなくサービスIDです。
2同名の主体を検索する
aliceという表示名だけで検索します。
show同名の主体を検索する(db,"SELECT realm,id FROM identity WHERE name='alice'")2件残ります。表示名は調査の入口には使えますが、一つの主体を確定するキーには不足しています。
3直接の関係を開く
srcからdstへ、member・grant・readという関係があります。
show直接の関係を開く(db,"SELECT * FROM edge ORDER BY src,dst")corp:u7はgroup:opsへ所属し、グループはrole:readerを付与されています。サービスIDには別の経路があります。
4グループ経由の到達先を求める
再帰CTEで次の関係を繰り返したどります。
query="WITH RECURSIVEグループ経由の到達先を求める reach(node) AS (VALUES(?) UNION SELECT e.dst FROM edge e JOIN reach r ON e.src=r.node) SELECT node FROM reach ORDER BY node"
show(db,query,('corp:u7',))group:opsとrole:readerに到達します。この関係表は権限経路の資料で、denyや期限などの条件は別に照合します。
5サービスIDの経路を比較する
同じ検索をsvc7から始めます。
showサービスIDの経路を比較する(db,query,('corp:svc7',))role:deploy経由でsecret:releaseへ到達します。利用者だけの棚卸しではサービスIDの経路を見落とします。
6新しい付与による到達範囲の変化を確認する
opsグループにdeployロールへの関係を追加します。
db.execute("INSERT INTO edge VALUES ('group:ops','role:deploy','grant')")
show新しい付与による到達範囲の変化を確認する(db,query,('corp:u7',))u7からもsecret:releaseへの経路ができました。変更した1行だけでなく、継承先を含めて影響を確認します。
7別の発行元の同名主体へ波及しないことを確認する
lab:u7からの到達先を検索します。
show別の発行元の同名主体へ波及しないことを確認する(db,query,('lab:u7',))出発点だけです。表示名で関係を結んでいたら、本来関係のない主体へ権限を誤って対応付けるところでした。
まとめ
発行元とIDを組にして主体を特定します。
グループやロールを経由する関係もたどります。
権限変更の影響は継承先まで確認します。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite / 固定の主体・権限・操作記録
from sp13 import *
from sp02 import show
db=connect()
show(db,"SELECT realm,id,name,kind FROM identity ORDER BY realm,id")realm | id | name | kind corp | svc7 | builder | service corp | u7 | alice | human lab | u7 | alice | human
show(db,"SELECT realm,id FROM identity WHERE name='alice'")realm | id corp | u7 lab | u7
show(db,"SELECT * FROM edge ORDER BY src,dst")src | dst | kind corp:svc7 | role:deploy | grant corp:u7 | group:ops | member group:ops | role:reader | grant role:deploy | secret:release | read
query="WITH RECURSIVE reach(node) AS (VALUES(?) UNION SELECT e.dst FROM edge e JOIN reach r ON e.src=r.node) SELECT node FROM reach ORDER BY node"
show(db,query,('corp:u7',))node corp:u7 group:ops role:reader
show(db,query,('corp:svc7',))node corp:svc7 role:deploy secret:release
db.execute("INSERT INTO edge VALUES ('group:ops','role:deploy','grant')")
show(db,query,('corp:u7',))node corp:u7 group:ops role:deploy role:reader secret:release
show(db,query,('lab:u7',))node lab:u7
演習完了