最後更新於 2026 年 9 月 11 日;日期、subject 格式與產品範圍已對照 GitHub OIDC 參考文件、OIDC REST API 文件及 Apple 官方文件核實。
2026 年 7 月 15 日後建立的 GitHub repository,預設可能使用包含 owner ID 與 repository ID 的不可變 subject 格式;這是 GitHub 官方文件已確認的規則變化,而不是 workflow 一定改過才會出現的故障。GitHub OIDC 參考文件 已說明新舊格式與主動啟用邊界。
因此,遇到 GitHub Actions OIDC 失效,本週不要先把雲端角色改成 *,也不要回退到長期雲端密鑰。先從實際 OIDC token 讀出 iss、aud、sub、repository_id 和 owner_id,再依照收到的 subject 更新信任策略,最後驗收遠端 Mac 的雲端權限與 Apple 簽名權限是否分層。
這篇適合以下團隊:
- 管理 GitHub Actions OIDC 與雲端角色信任策略的平台工程、企業 IT 團隊。
- 維護 self-hosted runner、Xcode 建置及生產發布鏈路的研發效能負責人。
- 準備重新命名、轉移 repository,或統一企業 OIDC 模板的安全與身份治理負責人。
指標一:實際 token 的 subject 才是第一個診斷依據
GitHub Actions OIDC 為什麼會突然無法登入雲端平台? 常見原因不是程式碼突然失效,而是雲端收到的 sub 已經不再符合原有信任條件。repository 重新命名、轉移,或啟用不可變 subject,都可能讓既有角色條件失配。
你需要把「GitHub workflow 寫了什麼」和「雲端實際收到什麼」分開看。工作流程中的 repository 名稱不能取代真實 token。先在隔離的測試 job 取得 token,於本機解碼 payload,再刪除原始 token。不要把完整 JWT 寫入公開 log、artifact 或 issue。
至少核對以下欄位:
iss:確認簽發者是否仍是預期的 GitHub OIDC issuer。aud:確認 audience 是否與雲端角色或內部閘道要求一致。sub:確認完整 subject,這是多數信任策略的主要匹配欄位。repository_id:辨識 repository 本身,避免只依賴可變的名稱。owner_id:辨識組織或擁有者,核對組織層級模板是否已套用。
GitHub 也提供 OIDC REST API 參考,適合用來核對 API 能力與欄位邊界,而不是把 API 回應直接當成雲端角色的信任條件。OIDC REST API 文件 可作為測試紀錄的引用依據。
舊格式、新格式與自訂模板的對照
| 類型 | sub 的判讀方式 |
常見故障訊號 | 修復方向 |
|---|---|---|---|
| 舊格式 | 通常以組織、repository、branch 或 environment 組成 | 重新命名後原條件不再命中 | 比對實際 token,再決定保留或更新舊條件 |
| 不可變格式 | subject 會納入 owner ID、repository ID 等不可變識別資訊 | 新 repository 或主動加入後,舊的名稱條件失效 | 以新 token 的完整 sub 更新信任策略 |
| 自訂模板 | 欄位與格式取決於組織或 repository 設定 | 同一組織內不同 repository 的 token 不一致 | 先確認模板來源,再逐一驗證受影響 repository |
這張表只能協助你分類,不能代替 token。尤其在不可變格式的情況下,不要自行猜測 ID 的排列方式;實際 token 才是准入依據。
02指標二:雲端信任條件要與完整身份匹配
repository 重新命名後,OIDC 信任策略應該怎樣修改? 先保存失敗 token、當前信任策略版本和失敗時間,再以測試 repository 驗證新 sub。不要只把 workflow 中的 repository 字串改成新名稱,因為信任端可能同時匹配 branch、Environment 或 audience。
雲端或內部閘道常見的條件維度包括:
- 完整
sub,例如 repository 加上 branch 或 Environment。 - 特定 branch,例如只允許發布分支。
- 指定 Environment,並要求人工核准。
- 固定
aud,防止同一 token 被另一個服務重用。 - 可重用 workflow 的身份條件,限制呼叫來源。
修復順序應是:
第一步:保存失敗證據。
保留脫敏後的 iss、aud、sub、repository_id、owner_id,以及雲端拒絕訊息。帳號、角色 ARN、內部專案名稱和資源 ID 必須遮蔽。
第二步:建立測試信任條件。
在非生產角色上只允許測試 repository、指定 branch 和固定 audience。先確認新 subject 可以換取短期雲端 token。
第三步:比較三個版本。
把舊信任策略、實際新 token 和預計修改版本並列。若只有 sub 改變,才處理 subject;若 aud 或 issuer 也改變,必須另行檢查 workflow 和雲端設定。
第四步:逐個環境放量。
先測試分支,再測試受保護的 Environment,最後才套用到生產發布角色。不要在一次變更中同時修改所有 repository 的信任條件。
第五步:驗證拒絕路徑。
使用未授權 branch、未授權 Environment 和另一個 repository 測試。成功取得 token 不足以證明安全;未授權來源確實被拒絕,才代表條件沒有被放寬。
03提醒: 擴大
sub通配符可能讓流水線快速恢復,但也可能把同一雲端角色授予其他 repository 或 workflow。修復 OIDC 失效不應以取消 subject 條件作為代價。
指標三:組織模板與變更範圍決定爆炸半徑
GitHub 官方規則需要按 repository 狀態判讀。依任務書所核實的邊界,2026 年 7 月 15 日後建立的 repository 預設使用包含 owner ID 與 repository ID 的不可變 subject 格式;舊 repository 維持原格式,除非主動啟用。repository 重新命名或轉移,也可能切換到不可變格式。GitHub Enterprise Server 的適用範圍則不能直接套用 GitHub.com 的結論,需按官方文件另行核實。
你要先分出三種狀態:
- 新建立的 repository,自動採用新格式。
- 舊 repository 主動加入不可變 subject。
- 管理員把組織級自訂模板套用到 repository。
這三種狀態的影響範圍不同。組織級模板可能一次改變多個 workflow 的 token;repository 管理員主動啟用,則通常只影響單一 repository,但仍可能牽動多個 Environment 和雲端角色。
企業變更前的盤點清單
- 列出所有使用 OIDC 的 repository。
- 標記每個 repository 的 branch、Environment 和可重用 workflow。
- 找出每個
sub對應的雲端角色或內部服務。 - 確認組織是否存在自訂 subject 模板。
- 將生產發布角色與測試角色分開盤點。
- 為每個變更指定回退條件和負責人。
新版 OIDC subject 為什麼包含 owner ID 和 repository ID? 企業治理上,這是為了降低只依賴可變名稱的風險。名稱可以被重新命名或轉移;ID 更適合用來維持資源身份的穩定匹配。但這不代表你可以忽略 branch、Environment 或 audience,因為身份穩定不等於權限範圍自動正確。
04指標四:權限收斂要同時檢查 workflow 與雲端角色
OIDC 修復後,先看 workflow 是否只在必要的 job 授予 id-token: write。不要把這項權限放到整個 workflow 的頂層,除非每個 job 都確實需要換取 OIDC token。
建議用以下四層檢查:
- 允許主體: 只列出指定 repository、branch、Environment 或可重用 workflow。
- 拒絕主體: 明確測試 pull request、非發布分支和其他 repository 必須被拒絕。
- 令牌有效範圍: OIDC token 只用來向受支援的服務交換短期存取 token,不應轉存為長期 Secret。
- 審批證據: 生產 Environment 保留審批紀錄,並把角色策略版本與部署紀錄綁定。
GitHub 的安全文件特別提醒,自託管 Runner 可能承載敏感資料;公開 repository 的不受信任程式碼若能在持久環境執行,會增加憑證與工作區殘留風險。GitHub 自託管 Runner 安全說明 應納入企業 Runner 的准入審查。
企業案例:OIDC 修好,但發布仍不應立即放量
假設你有一條 iOS CI/CD 流水線。雲端部署 job 使用 OIDC 取得短期雲端權限;Xcode 建置 job 在 self-hosted runner 執行;最後的生產簽名 job 使用隔離的 Mac 節點。
如果你只修改雲端 sub,部署 job 可能恢復,但不代表 Mac 節點安全。你仍要確認:
- 非可信 pull request 不能路由到含簽名資料的節點。
- 建置 job 不會讀取生產 Keychain。
- 雲端角色不能直接存取 Apple 簽名私鑰。
- 任務結束後,工作區、暫存檔和衍生資料會被清理。
- Runner 重啟後仍能正確接收指定標籤的工作。
指標五:OIDC 與 Apple 簽名身份必須分層
GitHub Actions OIDC 能否替代 Apple 簽名密鑰? 不能把兩者視為同一種憑證。OIDC 是工作流程向受支援服務交換短期存取 token 的聯合身份機制;它不能推導出 Apple 接受 OIDC 取代 Apple Distribution、Developer ID 或 App Store Connect API 私鑰。
Apple App Store Connect API 使用 API key、issuer ID 和私鑰建立 API 存取身份,具體建立方式應以 Apple App Store Connect API 金鑰文件 為準。Apple 的雲端管理證書也有獨立的帳戶與證書管理規則,不能因為雲端角色已改用 OIDC,就刪除簽名流程的必要身份。Apple 雲端管理證書說明 可用來核對這個邊界。
你可以把權限拆成四層:
- 非可信程式碼層: 只允許檢查或測試,不接觸雲端生產角色與簽名 Keychain。
- 雲端部署層: 使用 OIDC 換取短期雲端 token,限制 repository、branch、Environment 和 audience。
- Xcode 建置層: 只取得必要的建置工具與測試資料,不持有生產簽名私鑰。
- 生產簽名層: 使用隔離的可信 Mac 節點,限制工作路由、登入權限、Keychain 和人工審批。
這也是遠端 Mac 的關鍵邊界。長期共享 Mac、一次性 Runner 和專用發布 Mac 的風險不同:
- 長期共享 Mac: 維護成本較低,但工作區、登入狀態和 Keychain 殘留風險較高。
- 一次性 Runner: 任務結束後可清理或重建,適合不可信建置,但需要可靠的註冊、路由和恢復流程。
- 專用發布 Mac: 隔離效果較好,適合生產簽名;代價是需要獨立節點、監控和備援安排。
如果你正在設計 團隊共享 Mac 權限管理,請先把「可以存取雲端角色」和「可以讀取 Apple 簽名身份」視為兩條不同的存取路徑。它們不應只依靠同一個 Runner label 來區分。
06指標六:審計與恢復證據決定能否重新放量
修復不能以「某次部署成功」作結。你需要建立一組可重複的生產准入指標:
- 允許的 branch 能取得短期雲端 token。
- 未授權 branch 被信任策略拒絕。
- 受保護 Environment 仍需要預期的審批。
- 可重用 workflow 只能由允許來源呼叫。
- OIDC token 沒有被保存為長期 Secret。
- Mac Runner 重啟後能重新註冊並接收正確任務。
- 簽名節點與一般建置節點的 Keychain、工作區和任務路由互不混用。
- 失敗時可以按既定條件回退,而不是臨時開放通配符。
建議保存以下證據:
- 組織模板與 repository 設定版本。
- 雲端信任策略版本及審批人。
- 脫敏後的 token claims。
- 成功與拒絕測試的 workflow log。
- Runner 路由、重啟、工作區清理和 Keychain 隔離紀錄。
- 生產放量前的回退條件。
若你的團隊準備把發布流程移到遠端 Mac,可以先閱讀 遠端 Mac 建置節點方案,再用非生產 repository 驗證路由、權限和簽名分層。不要先把正式 Apple 私鑰放上共享節點,再用事故結果反推架構是否安全。
07修復後的企業選擇:保留現有節點,還是試點專用遠端 Mac
如果現有 Mac 節點同時執行一般建置、雲端部署和生產簽名,問題不只是 OIDC。共享主機會留下工作區、Keychain、Runner 註冊和任務路由的交叉風險;自購 Mac 也需要承擔硬體折舊、閒置容量、故障更換和遠端維護。
對需要短期驗證或按專案擴展的團隊,使用 VpsMesh 的遠端 Mac 試點,可以把專用發布節點與現有建置環境分開,再逐項驗收 OIDC、Runner 重啟、工作區清理和簽名隔離。你可以先查看 VpsMesh 遠端 Mac 方案,確認租用週期與節點安排是否符合企業測試流程。
但如果你的工作負載是長期、穩定且高強度的持續建置,或必須直接接觸特定實體介面,自購 Mac 可能更適合;如果你只需要一次性測試,也不必為租用建立長期架構。租用的價值在於先用隔離節點驗證權限邊界與故障接管,而不是把所有企業身份永久搬到共享主機。
完成 OIDC 修復後,先用測試 repository 證明「允許來源能取得、未授權來源會被拒絕」,再讓生產 Mac 節點接手簽名。這樣你得到的不只是一次登入恢復,而是一套可審計、可回退、能承受 repository 變更的發布鏈路。