Cloudflare 提供的服務協助營運 20% 的網路,但我們並非單打獨鬥。我們平台上的開發人員也會使用來自其他公司的眾多工具與服務。Cloudflare 為我們的平台提供豐富的 API,讓開發人員能夠建立自動化、CI/CD 以及整合機制,將他們基礎架構的各個部分串聯起來。本月稍早,我們宣布推出自管理 OAuth,讓客戶能更輕鬆地建立和管理自己的 OAuth 用戶端,以進行 Cloudflare API 的委派存取。
Cloudflare 其實早已支援 OAuth。如果您用過 Wrangler,或使用過來自 PlanetScale 等合作夥伴的整合功能,那您已經使用過它了。然而,到目前為止,第三方 OAuth 僅能透過少數手動加入的整合功能使用,並未廣泛提供給開發人員。這意味著自行建立整合功能的開發人員必須依賴 API 權杖,而 API 權杖不僅更難管理,也不太適用於許多委派應用程式的流程。
在過去一年中,我們陸續加入了越來越多的早期合作夥伴,同時也持續改進 Cloudflare OAuth 背後的同意、撤銷及安全模型。但隨著我們的開發人員平台成長,以及自主式工具帶動了對委派存取的需求,我們清楚意識到,向所有客戶開放 OAuth 對我們平台的成功至關重要。
有了自管理 OAuth,開發人員現在可以提供標準的 OAuth 流程,讓客戶直接授予範圍限定的存取權限,從而更輕鬆地建立 SaaS 整合、內部開發人員平台及自主式工具,同時也為使用者提供更清晰的同意機制、更簡便的撤銷方式,以及對應用程式權限的更多掌控。
雖然我們早期的 OAuth 解決方案對於數量有限、經過審慎管理的合作夥伴來說已足夠,但我們意識到,我們的權限模型、同意體驗,以及減輕潛在濫用風險的方式還不夠成熟。
今年早些時候,我們更新了同意體驗,使其更清楚地呈現是哪個應用程式正在申請存取權限,以及將獲得哪些權限。我們也在儀表板中加入了撤銷功能,讓開發人員能輕鬆控制哪些應用程式可以存取他們的資料,並提高了應用程式擁有權的透明度,以防止 OAuth 網路釣魚攻擊。
向所有客戶開放自管理 OAuth,也需要對我們底層的 OAuth 引擎進行重大升級。這個過程需要大量的規劃,以盡量減少對使用者的干擾,同時確保資料的穩定性與安全性。
數年前,我們部署了開放原始碼 OAuth 引擎 Hydra,作為 Cloudflare OAuth 的底層支援。在用量有限的時候,該部署運作良好,但隨著開發人員平台成長,智慧體工作流程變得越來越普遍,我們意識到需要一次重大升級,以解鎖新功能並提升效能。
在規劃升級時,我們決定分兩次進行較小的順序升級,而不是一次進行大型升級。首先,我們會升級到最新的 1.X 版本,評估任何行為或效能變化,然後再進行 2.X 升級。
在我們的升級規劃過程中,我們發現即便只是升級至 1.X,仍會對客戶造成影響。因為 Hydra 資料庫需要進行大規模的結構描述遷移,這些遷移會:
以會對關鍵資料表取得獨佔鎖定的方式建立索引,導致活躍使用者無法執行重要的 OAuth 操作
在關鍵資料表中新增欄位,並將其他欄位移至新資料表
此外,我們當時使用的 Hydra 版本有一個特殊問題:其 SDK 會執行 SELECT * 操作,在結構描述變更時會導致反序列化問題。
為了避免影響使用者,我們改寫了 SQL 遷移,改用 CREATE INDEX CONCURRENTLY 這類功能,並建置了一個自訂版本的 Hydra,讓它選取明確的欄位,而不是使用 SELECT *。
在規劃好最新的 1.X 升級後,我們現在需要為規模更大的 2.X 升級制定計畫。我們確定了三個潛在選項,並權衡了每個選項的優缺點。就地升級對我們來說行不通,因為主要版本升級帶來了大量的結構描述變更。我們決定採用藍綠部署策略,但這不只是單純切換到新版本這麼簡單。升級和遷移過程需要數小時,而我們需要系統在那段時間內繼續正常運作。
第一個藍綠部署方案是停用對資料庫的寫入操作,以防止任何新的授權發生。這意味著現有授權不會在遷移過程中遺失,但也意味著除非使用者已擁有有效的認證,否則將無法使用現有的 OAuth 應用程式。這也帶來了另一個大問題:如果使用者因任何原因需要撤銷對應用程式的存取權限,在升級執行期間將無法做到。
為了解決這些問題,我們想出一個方法,在切換到綠色版本時,以損失部分寫入資料為代價,讓資料庫的寫入操作保持啟用。首先要解決的是減少新權杖的寫入數量。我們採取了營運層面的措施:將權杖的有效期限延長至數小時。這樣一來,在升級前獲得新權杖的應用程式就可以繼續使用,而不需要重新整理。
在解決了減少寫入量的問題之後,我們需要一套機制,確保不會遺漏使用者在升級期間執行的任何撤銷操作。為此,我們建立了一個佇列系統(使用 Cloudflare Queues!):每當發生撤銷事件時,系統就會將包含該撤銷資訊的記錄寫入佇列。這樣一來,當資料庫切換到綠色版本後,我們就能處理佇列中的積壓任務,重新執行那些原本可能因切換而遺失的撤銷事件。這一步至關重要,必須正確執行,否則使用者已撤銷的應用程式可能會在無意間恢復其存取權限。
從營運角度來看,我們第一次升級到最後一個 1.X 版本的過程非常順利,沒有任何差錯。我們自訂的資料庫遷移執行速度比預期更快,且未對使用者造成任何影響。我們必須進行硬切換至新版本,因為舊版本無法檢查由新版本建立的權杖。
切換完成後,我們觀察到重新整理權杖錯誤的數量增加,這是之前未曾見過的狀況。最終發現,這是因為新版本採用了更嚴格的重新整理失效行為;如果重新整理權杖被重複使用,Hydra 會讓整個存取權杖和重新整理權杖鏈失效。這會對 Wrangler 和 MCP 用戶端造成問題。這兩個用戶端都有大量的請求量,只要有一個重新整理權杖被重複使用,就會導致整個工作階段失效。
為了解決這個問題,我們在負責將 OAuth 流量路由到正確目的地的 Worker 中,加入了「重新整理權杖合併行為」。這讓我們能夠在請求到達 Hydra 之前,短暫地快取重新整理權杖的請求,如此一來,如果我們偵測到重試,就可以先行中斷請求並直接回應,而不會使權杖失效。幸運的是,Hydra 的 2.X 版本具有可設定的「重新整理權杖寬限期」,允許在一定時間內重試重新整理權杖而不導致整個權杖鏈失效,從而徹底解決了這一問題。
由於長時間嚴重影響使用者體驗是不可接受的,我們制定了藍綠升級策略。乍聽之下這很簡單:在正式資料庫的副本上執行遷移,完成後連同新版 Hydra 一併切換。但在實際操作中,涉及的環節要複雜得多:
我們選擇了一個 Hydra 每秒請求量最低的時段進行升級,以盡量減少遺失的權杖寫入。除了一些逾時調整之外,我們的正式環境遷移在新資料庫上執行得很順利:在正式環境中的實際執行時間約為三小時。遷移完成後,我們謹慎地推出了新版本的 Hydra 服務,並同時更新了另外兩項系統設定,以將我們的系統切換為使用新的 SDK 版本。
在切換流量後不久,我們發現授權服務中的一項資料清理作業(依賴 Hydra 同意工作階段 API)在清除 OAuth 策略資料時過於積極。經過調查,我們發現 Hydra 的某個遷移中存在一個問題,該問題損壞了某些有效 OAuth 工作階段的狀態,導致遷移將其標記為無效。有效工作階段被損壞,導致 Hydra 和我們的授權服務之間產生不一致,表現為 403 錯誤的增加。為了解決這個問題,我們進行了資料還原,並開始著手改進 OAuth 授權行為,以消除對靜態政策資料的依賴。
除了資料清理問題外,我們還針對特定用戶端行為進行了一些小幅修復,並迅速完成了部署。
隨著 Hydra 版本升級完成,OAuth 流量保持穩定,系統效能和客戶可靠性都獲得了改善。此次升級也讓正式環境的基礎架構,與我們在預備環境中已驗證過的新版 OAuth API 保持一致,為我們在 6 月 3 日發布自管理 OAuth 鋪平了道路。
在完成如此大規模的升級後,分析相關指標的整體影響既有意義又能帶來啟發。我們在資料庫遷移期間收集了額外指標,並觀察到升級完成後效能有了顯著改善。
| 指標 |
大約數值 |
| 更新列數 |
132.5M |
| 插入列數 |
114.7M |
| 暫存位元組 |
136.97GB |
| 交易提交數 |
22.2k |
| 指標(平均值) |
之前 |
之後 |
變更 |
| API P95 |
185 毫秒 |
101 毫秒 |
-45% |
| RSS 記憶體 |
888MB |
763MB |
-14% |
| Go 堆積分配 |
449MB |
271MB |
-40% |
| Goroutines |
4015 |
3076 |
-23% |
| CPU |
1.07 核心 |
0.67 核心 |
-37% |
向所有客戶開放 OAuth,是邁向更廣泛的 Cloudflare 應用程式生態系統的重要一步。如今,任何 Cloudflare 客戶都可以建立自己的 OAuth 應用程式,並在 Cloudflare 之上建置整合功能。我我們非常高興能向所有用戶推出 Cloudflare 自管理 OAuth。
若要開始使用,請參閱我們的技術文件,或直接前往儀表板中的 OAuth 應用程式頁面,建立您的第一個 OAuth 應用程式。