摘要:簽名正確但傳輸後壞掉的典型路徑
許多團隊在 遠程 Mac 上已跑通 codesign、notarytool、stapler,問題常在之後:ZIP/同步/SFTP 預設把 .app 當普通目錄複製,嵌套 helper 失可執行位或 symlink 變實體,導致 codesign --verify --deep --strict 失敗,使用者卻看到像惡意軟體的 Gatekeeper 文案。
SHA256 與簽名圖譜要並用:《傳輸完整性》管雜湊閘門;本文強調每跳的 codesign。頻寬瓶頸先讀《大檔上傳吞吐》。
同平台 macOS→macOS 的 rsync 在旗標寫對時,常能保留 POSIX 權限與多數擴展屬性。路徑中若出現 Linux runner 或通用工件儲存,預設應在 Mac 側先打 tar.gz,讓 symlink 以歸檔成員存在。原子發佈寫入暫存前綴,通過校驗後才切換指標(見《原子發佈》);公開樹上的 --inplace 會讓使用者抓到半套目錄。工單應保存 submission id、git sha、Xcode build;支援可先當包裝迴歸處理 verify 失敗。
痛點拆解:flatten、Linux 中繼、inplace 與 staple 漂移
展平 bundle。 某些 ZIP 編碼器與同步軟體會重建目錄但不還原 macOS 專屬中繼資料;檔案總管裡看起來完整,深層 verify 卻失敗。
Linux 中繼儲存。 macOS runner 上傳目錄到 Linux job 時,symlink 常被解引用或權限位無法表達;tar 可避免「提早解引用」,直到你在 Mac 上明確解包。
對活樹 inplace rsync。 --inplace 搭配使用者可下載的路徑,會暴露傳輸中的部分目錄;應使用暫存前綴並在指標切換前完成 verify(見《原子發佈》)。
Staple 漂移。 對 DMG 完成 staple 後若再壓縮或重包,票據與最終位元組可能不一致;對外檔名與 staple 時間點應凍結在工單。
只驗源站。 節省幾分鐘只在構建機 verify,會在事故時放大成數小時;消費該構建的下一台 Mac 必須重跑嚴格驗證並保留退出碼紀錄。
決策矩陣:先選包裝,再談頻寬技巧
評審時固定欄位:構建號、簽名身分、submission id、分發格式、傳輸工具、每跳 verify、SHA256 是否綁定核准。
| 場景 | 風險假設 | 建議路徑 | 站內對照 |
|---|---|---|---|
| 遠程 Mac→另一台 Mac,低延遲 | 元資料可完整保留 | 顯式 rsync 保留權限與 xattr;禁止多工寫同一前綴 | 併發 SFTP、原子發佈 |
| 遠程 Mac→Linux→回到 Mac | symlink 與權限易遺失 | Mac 側 tar.gz 單一 blob;Linux 只搬檔;回 Mac 立刻 verify | 傳輸完整性 |
| 對外測試 DMG | 鏡像層與票據綁定 | 固定打包腳本;staple 後凍結檔名;SHA256 登記 | 完整性閘門 |
| 僅內部 CI 快取 | 可重建 | 可接受未公證中間態,但晉級發佈前須跑完整簽名鏈 | CI 憑據文 |
| 大體積 app 與窄頻寬 | 逾時與中斷 | 先 tar 成單檔再調平行上傳;搭配暫存與原子切換 | 大檔上傳吞吐 |
簽名依賴 macOS 檔案語意;跨平台須用能保留語意的歸檔,勿假設目錄複製安全。
實操步驟:從打包、上傳到每跳 verify(How-to)
教學骨架;生產環境請對齊《CI/CD 憑據》與 releases/<build_id>/ 前綴策略。
# 步驟 1:在構建 Mac 將 .app 打成 tar.gz(保留 symlink)
cd /path/to/output
COPYFILE_DISABLE=1 tar -czvf MyApp_build.tar.gz MyApp.app
# 步驟 2:構建機上再跑一次嚴格驗證
codesign --verify --deep --strict --verbose=2 MyApp.app
# 步驟 3:以 rsync/SFTP 推到遠程 Mac 暫存前綴
rsync -av MyApp_build.tar.gz [email protected]:uploads/staging/build-9001/
# 步驟 4:遠程 Mac 解包到同 build 目錄
ssh [email protected] 'cd uploads/staging/build-9001 && tar -xzvf MyApp_build.tar.gz'
# 步驟 5:到岸 verify(關鍵)
ssh [email protected] 'codesign --verify --deep --strict uploads/staging/build-9001/MyApp.app'
# 步驟 6:若含已 staple 的 DMG,再對 DMG 執行 stapler validate/spctl 評估
# 步驟 7:僅校驗通過後才允許晉級 current 或對外下載(見《原子發佈》)
# 步驟 8:將命令、退出碼、構建號寫入 CI 摘要行,與 SHA256 清單對齊
互動式 SFTP 請把「保留權限/遞迴」寫進 SOP 並附截圖,避免手滑毀內測視窗。
工單欄位、公證輪詢與磁碟餘量
建議欄位:Git SHA、Xcode/macOS 小版本、簽名身分摘要、submission id、對外檔名、staple 狀態、源站/到岸 verify 退出碼、傳輸工具版本、SHA256 核准。公證佇列繁忙時可能超過三十分鐘;磁碟長期低於約 120GB 可用易誘發 Archive/解包異常。簽名產物與素材宜分帳號;輪替簽名憑證節奏對齊 deploy key,PR 流程勿與生產簽名主機共用身分。
詞彙表、FAQ 與託管遠程 Mac
Bundle 為目錄語意而非單檔;Developer ID 搭配公證用於 Store 外分發;ticket/stapling 綁定公證證明;symlink/xattr 常在跨平台複製時遺失;atomic pointer 僅在校驗後切換。
能否只靠 SHA256 證明簽名沒問題?
不能。SHA256 只證明位元組一致;若一致仍 verify 失敗,代表你記錄的「應然位元組」本身已不含有效簽名圖。兩道檢查都要:先 verify,再登記雜湊。
Linux 上能當最終裁判嗎?
工程上不應把 Linux 當作 Apple 簽名鏈的權威;可在 Linux 搬 tarball,但嚴格驗證應在 Mac 完成。
SFTP 是否一定比 rsync 差?
不一定。無人值守場景兩者都能寫好;差在是否明確規定參數與驗證步驟。rsync 對目錄增量較強,SFTP 對簡單 put/get 較直觀。
總結:簽名與公證只解一半問題;另一半是歸檔/傳輸保留 bundle 語意,並在每一跳 verify,并联 SHA256 與原子發佈。
局限:多入口自建成本高;SFTPMAC 託管遠程 Mac 收斂構建主機、加密入口與會話策略,減少「解壓後簽名壞掉」類排障時間。
了解 SFTPMAC 方案與節點區域,統一遠程 Mac 承載簽名與分發。
