一覧SP-14-2 · SSPM:SaaS設定の継続評価

SaaSの共有リンクとアプリへの同意

是正した対象と残った経路を、変更後の保存状態で説明します。

説明

SaaSの公開範囲には共有リンク、利用者への直接権限、アプリへの同意など複数の経路があります。一つの経路を削除しても、ほかの経路が残る場合があります。

固定の共有権限台帳で対象リンクだけを削除し、残る権限を読み直します。アプリ同意と発行済みトークンも別の表として確認します。

是正した対象と残った経路を、変更後の保存状態で説明します。

1文書ごとの権限を読む

linkはリンク経由、directは主体へ直接付与した権限です。

from sp14 import * from sp02 import show文書ごとの権限を読む db=connect() show(db,"SELECT * FROM permission ORDER BY id")

doc7には匿名リンクとbobの直接権限、doc8には別の匿名リンクがあります。

2修正対象を文書IDと権限IDで固定する

p1だけを対象にします。

show修正対象を文書IDと権限IDで固定する(db,"SELECT id,object,principal,version FROM permission WHERE id='p1' AND object='doc7'")

versionは1です。取得から更新までに変更された場合を検出するため、世代も条件へ含めます。

3古い世代での削除を試す

期待世代を0にした削除です。

cur=db.execute("DELETE FROM permission WHERE id='p1' AND object='doc7' AND version=0") print(cur.rowcount古い世代での削除を試す)

0行です。対象が消えていない状態を成功として報告しません。実APIでも条件付き更新の結果を確認します。

4一致する世代で削除して読み直す

世代1を指定し、doc7に残る権限を取得します。

print(db.execute("DELETE FROM permission WHERE id='p1' AND object='doc7' AND version=1").rowcount) show一致する世代で削除して読み直す(db,"SELECT id,kind,principal FROM permission WHERE object='doc7'")

1行削除され、bobの直接権限は残ります。匿名リンクの削除と、すべての利用者からのアクセス取消しは別です。

5別文書の権限を保持したことを確認する

doc8のp3を読み直します。

show別文書の権限を保持したことを確認する(db,"SELECT id,object,principal FROM permission WHERE object='doc8'")

p3は残っています。目的がdoc7だけの是正なら、同じ種類のリンクを全件削除しないよう対象を絞ります。

6アプリの同意種別と範囲を読む

applicationとdelegatedを分けて表示します。

showアプリの同意種別と範囲を読む(db,"SELECT * FROM consent ORDER BY id")

g1は利用者なしで使うapplication権限、g2は利用者に代わるdelegated権限の資料です。実効権限の判断には両者で異なる条件があります。

7同意取消しと既存トークンを別に確認する

g1を無効にした後、期限内のトークンを検索します。

db.execute("UPDATE consent SET active=0 WHERE id='g1'") show同意取消しと既存トークンを別に確認する(db,"SELECT c.id,c.active,t.id AS token,t.expires FROM consent c LEFT JOIN token t ON t.grant_id=c.id ORDER BY c.id")

g1は無効でもt1が残ります。既存トークンをいつ拒否するかはサービスの検証・失効方式を確認し、同意取消しだけで即時終了したと推測しません。

まとめ

共有の各経路を個別に棚卸しします。

対象と世代を条件にして変更し、読み直します。

同意取消しと発行済みトークンの扱いを確認します。

操作履歴と解説を振り返れます。

Python 3.15 / SQLite / 固定の主体・権限・操作記録

1
from sp14 import * from sp02 import show db=connect() show(db,"SELECT * FROM permission ORDER BY id")
id | object | kind | principal | role | version
p1 | doc7 | link | anyone | read | 1
p2 | doc7 | direct | bob | read | 1
p3 | doc8 | link | anyone | read | 1
2
show(db,"SELECT id,object,principal,version FROM permission WHERE id='p1' AND object='doc7'")
id | object | principal | version
p1 | doc7 | anyone | 1
3
cur=db.execute("DELETE FROM permission WHERE id='p1' AND object='doc7' AND version=0") print(cur.rowcount)
0
4
print(db.execute("DELETE FROM permission WHERE id='p1' AND object='doc7' AND version=1").rowcount) show(db,"SELECT id,kind,principal FROM permission WHERE object='doc7'")
1
id | kind | principal
p2 | direct | bob
5
show(db,"SELECT id,object,principal FROM permission WHERE object='doc8'")
id | object | principal
p3 | doc8 | anyone
6
show(db,"SELECT * FROM consent ORDER BY id")
id | app | scope | kind | active
g1 | app7 | Files.Read.All | application | 1
g2 | app7 | User.Read | delegated | 1
7
db.execute("UPDATE consent SET active=0 WHERE id='g1'") show(db,"SELECT c.id,c.active,t.id AS token,t.expires FROM consent c LEFT JOIN token t ON t.grant_id=c.id ORDER BY c.id")
id | active | token | expires
g1 | 0 | t1 | 200
g2 | 1 | NULL | NULL

演習完了