一時資格情報とAPI操作の追跡
CloudTrailの主要項目を抽出した固定表で、ポリシー変更とオブジェクト読取りを検索します。キー識別子は秘密鍵ではありません。操作の主体、成功・失敗、管理イベントとデータイベントの違いを確認します。
説明
クラウドのAPI記録には、長期の利用者名ではなく引き受けたロールのセッションが現れる場合があります。アカウント、アクセスキー識別子、セッションの期間を照合して、どの資格情報で操作されたか調べます。
CloudTrailの主要項目を抽出した固定表で、ポリシー変更とオブジェクト読取りを検索します。キー識別子は秘密鍵ではありません。操作の主体、成功・失敗、管理イベントとデータイベントの違いを確認します。
1API操作を一覧する
errorがNULLの行とAccessDeniedの行を分けて読みます。
from oplab import *
db=connect(6)
show(db, 'SELECTAPI操作を一覧する * FROM api ORDER BY t')同じGetObjectでも成功と拒否があります。イベント名だけでデータ取得に成功したと数えないようにします。
2ロールのセッションを確認する
source_identityは、この試料で引受け時に付与された元の主体です。常に記録される項目とは限りません。
show(db, 'SELECTロールのセッションを確認する * FROM sessions ORDER BY id')二つのアカウントに同名のReportRoleがあります。ロール名だけでは主体を特定できません。
3アカウントとキーと時間を結合する
同名ロールの混同を避ける条件で対応させます。
show(db, 'SELECTアカウントとキーと時間を結合する a.id,s.id,s.source_identity,a.event,a.error FROM api a JOIN sessions s ON a.account=s.account AND a.key_id=s.key_id AND a.t>=s.start AND a.t<s.end ORDER BY a.t')e1、e2、e4はalice由来、e3はbob由来のセッションです。元の主体が記録されても、実際に操作した人の本人性は別の検討事項です。
4管理操作とデータ利用を分ける
categoryはAPIの記録区分です。収集設定も区分ごとに確認します。
show(db, 'SELECT管理操作とデータ利用を分ける category,event,COUNT(*) AS records FROM api GROUP BY category,event ORDER BY category')PutBucketPolicyは管理操作、GetObjectはデータ利用です。管理イベントがあることから全てのデータ操作も収集済みとは言えません。
5成功した読取りだけを抽出する
結果コードを条件に含めます。
show(db, 'SELECT成功した読取りだけを抽出する id,account,resource FROM api WHERE event="GetObject" AND error IS NULL')成功記録はreports/a.csvのe2です。b.csvや別アカウントの拒否を成功件数へ含めてはいけません。
6同じセッションの変更と利用を並べる
キーを起点に調査対象を広げ、操作の順序を確認します。
show(db, 'SELECT同じセッションの変更と利用を並べる id,t,event,resource,error FROM api WHERE key_id="ASIAEXAMPLE7" ORDER BY t')ポリシー変更後にa.csvの読取りが成功し、b.csvは拒否されています。この順序は関連の手掛かりであり、ポリシーの具体的な差分も追加確認します。
まとめ
ポリシー変更後にa.csvの読取りが成功し、b.csvは拒否されています。この順序は関連の手掛かりであり、ポリシーの具体的な差分も追加確認します。
表示された証拠IDと検索条件を残すと、調査結果を元の記録までたどれます。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite・固定の調査記録
from oplab import *
db=connect(6)
show(db, 'SELECT * FROM api ORDER BY t')id | t | account | key_id | event | category | error | resource e1 | 12 | 111111111111 | ASIAEXAMPLE7 | PutBucketPolicy | Management | NULL | reports e2 | 14 | 111111111111 | ASIAEXAMPLE7 | GetObject | Data | NULL | reports/a.csv e3 | 16 | 222222222222 | ASIAEXAMPLE8 | GetObject | Data | AccessDenied | reports/a.csv e4 | 18 | 111111111111 | ASIAEXAMPLE7 | GetObject | Data | AccessDenied | reports/b.csv
show(db, 'SELECT * FROM sessions ORDER BY id')id | account | key_id | role | source_identity | start | end s1 | 111111111111 | ASIAEXAMPLE7 | ReportRole | alice | 10 | 50 s2 | 222222222222 | ASIAEXAMPLE8 | ReportRole | bob | 10 | 50
show(db, 'SELECT a.id,s.id,s.source_identity,a.event,a.error FROM api a JOIN sessions s ON a.account=s.account AND a.key_id=s.key_id AND a.t>=s.start AND a.t<s.end ORDER BY a.t')id | id | source_identity | event | error e1 | s1 | alice | PutBucketPolicy | NULL e2 | s1 | alice | GetObject | NULL e3 | s2 | bob | GetObject | AccessDenied e4 | s1 | alice | GetObject | AccessDenied
show(db, 'SELECT category,event,COUNT(*) AS records FROM api GROUP BY category,event ORDER BY category')category | event | records Data | GetObject | 3 Management | PutBucketPolicy | 1
show(db, 'SELECT id,account,resource FROM api WHERE event="GetObject" AND error IS NULL')id | account | resource e2 | 111111111111 | reports/a.csv
show(db, 'SELECT id,t,event,resource,error FROM api WHERE key_id="ASIAEXAMPLE7" ORDER BY t')id | t | event | resource | error e1 | 12 | PutBucketPolicy | reports | NULL e2 | 14 | GetObject | reports/a.csv | NULL e4 | 18 | GetObject | reports/b.csv | AccessDenied
演習完了