ANDREW/
選單觀點
中文EN
← 回到文章庫

TECHNOLOGY / ACCESS / REVOCATION

權限撤銷了,哪些事情真的停了?

Andrew Yuan · 技術實驗

撤權之後,還在會議室的人怎麼辦?

想像公司停用了帳號、註銷門禁卡,系統顯示 Access Revoked。主管很滿意,直到有人問:「那他現在在哪裡?」「會議室。」「怎麼還在?」「他是在撤權之前進去的。」

公司禁止他再次進入,卻還沒處理已經進去的人。連線也有類似問題:拒絕下一次登入,不會自動中止已經建立的 Session。

我做的 Grantweft,是為固定 TCP Service 提供臨時存取的小型 Gateway。它使用個別 mTLS 憑證辨識身分,將提出申請與核准分開,並在授權過期或撤銷時中止既有連線。這是一個有明確容量與部署範圍的單節點 MVP。

Grantweft 概念插圖:關閉的黃銅小門、門禁讀卡器,以及門後已有文件的托盤;關閉連線不等於撤回已發生的操作。
概念插圖:門關上後,已送達的文件仍在另一側;並非產品管理介面。

這次最想釐清的,是三個容易被合併成一句「權限撤銷了」的問題:能否建立新連線?既有連線是否停止?先前送到後端的操作,是否還在執行?三者需要不同的機制,也需要不同的完成證據。

核准有紀錄,不代表現在仍有權傳資料

Grantweft 將個別用戶端憑證對應到固定身分與 requester/approver 角色。申請者不能核准自己的申請;可存取的也是事先指定的服務識別與數字位址,不是讓使用者自由指定任意目的地。mTLS 在這裡證明連線身分,實際存取仍需要有效核准。

這裡撤銷的是指定的存取授權(Grant),不是停用整個使用者帳號或吊銷 mTLS 憑證。撤銷一份 Grant,也不會順帶撤銷同一身分的其他 Grant;憑證與身分的生命週期需要另外管理。

核准、操作去重與稽核紀錄保存在 SQLite。歷史核准是「曾經同意」的紀錄;允許現在這條連線傳輸資料,還要通過目前的期限、狀態與執行世代等檢查。期限在核准提交之前固定,延遲完成的儲存作業也不能因此把失效權限重新帶回來。

這個區分也影響失敗處理。持久化錯誤會讓服務進入 DEGRADED,停止資料傳輸與新的授權工作;修復目錄權限本身,不會自動恢復舊授權。若待處理核准與撤權發生版本衝突,目前會保守地停用整個服務,需要操作人員處理。這是有可用性代價的限制,不是已完成透明競態復原。

撤銷既有 Session,仍然不是撤回操作

受測的每條 TLS Tunnel 對應一條後端 TCP Session。授權過期或撤銷時,Gateway 會中止傳輸連線;測試除了確認舊 Grant 不能建立新存取,也要實際看到保留中的 Tunnel 結束,並確認閒置時沒有剩餘 Session。

但關閉 Socket 不能收回已交給核心緩衝區的位元組,也不能保證後端已接受的工作隨即取消。即使應用程式已執行完操作、尚未送回結果,斷線也不能證明那次操作沒有發生。

就像主管撤銷付款核准時,款項已經匯出。把核准欄位改成 Revoked,可以記錄現在的決定;銀行裡的錢,不會因此自己回來。授權狀態與外部效果,需要分開確認。

窄螢幕可左右滑動表格,查看完整內容。

三種承諾,三種不同的證據
要承諾什麼需要確認什麼不能順便推論什麼
撤權後拒絕新存取用原身分與舊 Grant 嘗試,確實被拒絕。既有 Session 也已結束。
停止經 Gateway 的既有連線保留中的 Tunnel 出現 EOF/reset,Session 歸零。已送達後端的操作被取消。
取消或處理已接受的工作後端提供取消、交易或補償流程,並驗證結果。單靠關閉連線就已完成;這不是 Grantweft 已驗證的能力。

上述控制還有一個必要前提:使用者不能另有直達 Backend 的路徑。若能繞過 Gateway,這裡的撤權就管不到那條連線。後端隔離與網路配置因此是部署責任的一部分,不能只驗 Gateway 內的狀態。

重新啟動:保留歷史,重新取得授權

Gateway 啟動時,會先使所有先前 PENDING/ACTIVE Grant 失效,再開啟 Listener。舊 Session 與舊 Grant 都不跨程序或 VM 重啟延續;需要重新提出申請並取得核准。保留歷史,與延續當前授權,是兩個決定。

這是這個 MVP 的保守選擇,也有實際成本:重啟會中斷存取,值班人員與核准者必須有重新申請的安排。它不是所有存取系統都應採用的唯一答案。若服務需要授權跨重啟延續,就要另外設計期限、撤權與復原規則。

正式套件附有 systemd Service,Gateway 使用獨立非 root 帳號、沒有 capabilities,並限制可寫狀態目錄。READY 表示日誌復原與 Listener 初始化完成;仍需用身分驗證狀態查詢與新核准的應用請求確認可用。主機的網路與儲存啟動順序,不能由一個 READY 訊號代替。

保留證據:51 項檢查與十分鐘觀察

本文引用既有 grantweft-closeout-review-v8 紀錄,沒有重跑產品 VM 或硬體。macOS 與已安裝套件的 Linux 各通過相同的 51 項檢查:38 項正式實作/CLI/就緒檢查,加上 13 項觀察器與清理控制;無失敗、錯誤或跳過。它們不能全部改稱 51 項產品功能測試。

保留紀錄另包含七組儲存/容量/延遲提交案例與真正安裝的 systemd 生命週期,包括 SIGKILL 後接手、停止與重啟額度。兩個自動啟動的正常 VM 重開機情境,分別檢查正常復原與唯讀儲存失敗後的人工修復。服務啟動之前,唯讀見證先核對舊 ACTIVE/PENDING 日誌未變,避免把關機時的清理誤當開機復原。

在 40 次、600.001 秒的固定觀察中,20 次明確撤權與 20 次自然過期交替執行,Gateway 程序、執行世代與重啟次數維持不變。每輪都有新申請、核准、20 次有序 8-KiB 往返,接著確認 Tunnel 結束、舊 Grant 被拒絕及閒置 Session 歸零。

閒置 FD 樣本維持 10。五輪暖機後,主程序閒置 RSS 取樣為 26,412–28,188 KiB,約 25.8–27.5 MiB;觀察期間呈上升趨勢。這不是峰值、整台 VM 或用戶端/後端的記憶體成本,也沒有證明沒有洩漏,或記憶體使用已長期趨於平穩。

十分鐘觀察有它的價值,但不能當十個月保證。就像新同事第一天準時上班,主管就宣布:「長期出勤穩定性,驗證完成。」證據是真的,承諾卻走到了證據前面。

133 個損壞報告控制會被驗收器拒絕,這些是對證據檢查器的挑戰,不是 133 次產品故障。兩次失敗試驗也保留:一次是測試用 loop 裝置意外唯讀,另一次是前情境遺留的新核准影響後續初始狀態。修正測試配置後重做,不會讓原先失敗變成成功。

有限歷史,也需要明確的維運決定

這次觀察的 Grant 歷史由 14 增至 54,設定容量為 96;操作與稽核資料各由 28 增至 128,容量各為 512。終止紀錄仍占容量,目前沒有自動 GC 或 Rollover。十分鐘工作量刻意在有限額度內,不能證明可無限持續運作;部署前要安排容量監測與維護,不能靠刪除日誌繞過權屬檢查。

正常 VM 重開機不等於突然斷電;開機零空窗、真實 suspend、實體儲存故障、長期運轉與任意正式網路配置,仍未完成驗證。惡意 root/同 UID 程序與完整憑證生命週期,也不在這次驗證結論內。

專案原始碼與文件現採 MIT。授權採用只改套件 metadata 與 notices,原先 VM 數據仍保留原來源指紋。這次文章核對了保留報告與 metadata-only 對照,確認執行模組、服務單元與驗證工具未變;這不是一輪新的 MIT 套件 VM 測試。

部署前,先說清楚「停止」的範圍

我會和服務負責人先約定:撤權要停止新連線、既有連線,還是已被後端接受的工作?誰維護身分與核准角色?重新啟動或容量耗盡時,誰能恢復可用存取?若後端結果不明,誰負責查詢、取消或補償?

Grantweft 可以讓這些界線更具體,但不能替每個後端決定復原語意。Access Revoked 證明授權狀態改變;連線是否停止、外部效果是否需要處理,仍要有各自的證據與接手人。

來源與保留證據

分享這篇