Ansible(ansible/ansible)是 GitHub 上累積 71,020 顆星標的開源 IT 自動化平台,於 2026 年 10 月 13 日發布 ansible-core 2.22.0rc1。這個版本的新聞價值不在於新增模組數量,而在於它改寫了十餘年來的秘密處理邏輯:過去靠字串樣式猜測哪裡藏著密碼,現在改為由執行環境主動登記每一個已知的秘密值,再於輸出階段統一替換為 $REDACTED$。對每天以 playbook 管理數百台主機的維運團隊而言,這是一次影響深遠的語意變更。

Ansible 是什麼?
Ansible 是以 SSH 傳輸、無需代理程式的開源 IT 自動化平台,以 YAML 撰寫 playbook 管理組態、部署與雲端資源。
專案由 Michael DeHaan 於 2012 年 3 月建立,原始碼以 Python 撰寫,採 GPL-3.0 授權,目前由 Red Hat 主導的社群維護。其設計原則寫在 README 的第一段:安裝流程極簡、平行管理大量機器、不引入自訂代理程式與額外開放埠口、以機器與人類都能閱讀的語言描述基礎設施。這套「無代理」取向讓它在需要管理既有伺服器、網路設備與 Windows 主機的環境中快速普及。
截至 2026 年 10 月中旬,儲存庫累積 24,375 次複製、373 位具名貢獻者與 55,583 次提交,維護 57 個分支與 753 個標籤。核心程式碼約 980 萬行 Python、85 萬行 PowerShell,另有 Shell、C# 與 Jinja 模板。這種多語言結構反映它的實際使用場景:控制端以 Python 執行,受管端則需同時支援 Unix shell 與 Windows 的 WinRM 通道。
ansible-core 2.22 帶來了哪些重大變更?
四大變更:秘密值改登記制遮罩並新增 secrets API、控制端改要求 Python 3.13、修補 CVE-2026-89091、設定驗證改驗全部區段。
版本節奏延續一貫的預發布流程:2.22.0b1 於 9 月 18 日發布,b2 於 9 月 29 日,rc1 於 10 月 13 日。b1 帶入絕大多數新功能,b2 修正 callback 外掛收到未遮罩結果的問題,rc1 則收斂了 b1 引入的秘密長度上下限限制,改為任意長度的秘密都能登記與替換。
rc1 的變更清單相對精簡,卻包含一項安全修補與數項行為修正。其中 ansible-galaxy collection install 的 FILES.json 路徑驗證問題被編號為 CVE-2026-89091,屬於封裝完整性層面的缺陷;另有 argspec 驗證在 no_log 選項帶有非字串預設值時的崩潰、錯誤鏈中 show_content=False 未被完整套用導致原始碼行外洩,以及 sudo-rs 在非英語語系下的相容性修正。
Secret masking 為何被視為這次最關鍵的改動?
因為它把靠樣式猜測換成主動登記:已知秘密在輸出前替換為 $REDACTED$,涵蓋錯誤訊息、模組日誌與 callback 結果,且不破壞實際值。
舊機制的問題在於它是一組啟發式規則。heuristic_log_sanitize() 會嘗試從字串中辨識 user:password@host 這類形態並改寫,但規則必然有例外,只要格式稍有變化、密碼出現在意料之外的位置,或模組自行拼接輸出,就可能整段原文外洩。2.22 改為登記制之後,判斷依據不再是「看起來像不像密碼」,而是「這個值有沒有被登記為秘密」。
登記的來源相當廣泛:由提示、檔案或腳本提供的 vault 密碼,vault 加密值的解密明文與加密變數檔中的所有字串與數值,--ask-pass 與 --ask-become-pass 的輸入,no_log 模組選項值,sudo、su、runas 的 become_pass,ssh 連線外掛的 password、private_key 與 private_key_passphrase,winrm 與 psrp 的密碼與憑證金鑰密碼,url lookup 的密碼,以及 password 與 unvault lookup 的回傳值與 vault、unvault 篩選器收到的秘密。
遮罩本身是非破壞性的。真實值仍然可供任務、條件判斷與已註冊變數使用,只有被渲染出來的輸出入內容會被替換。這一點對實務相當關鍵:過去某些團隊為了避免日誌外洩而刻意不使用 no_log,因為一旦標記就無法在後續任務中取用該值;新機制解除了這個兩難。專案同時新增 ansible.module_utils.secrets 公開 API,提供 register_secret、register_secrets 與 mask_secrets 三個函式,讓自訂模組能主動登記非 no_log 路徑傳入的秘密,PowerShell 模組則對應 Ansible.Secrets 的 RegisterSecret() 與 MaskString()。
為什麼 no_log 的行為改變會影響現有 playbook?
因為結果中的佔位字串改為 $REDACTED$ 並保留實際值,凡以舊字串做比對的測試與 CI 斷言都會失效,需改寫判斷條件。
這是 2.22 最具體的回歸風險。過去標記 no_log: true 的模組選項,在模組結果與 invocation.module_args 中會被字面替換為 "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",因此不少測試腳本與 CI 檢查會以該字串是否存在來斷言「敏感資料已被遮蔽」。新版本改為在結果中保留真實值、只在輸出階段遮罩,這些斷言將全部落空。
同一項變更也波及 AnsibleModule 的日誌行為。log() 與自動的 invocation 記錄不再套用啟發式清理,no_log 與類密碼選項改記為 $REDACTED$,而非舊有的 NOT_LOGGING_PARAMETER 或 NOT_LOGGING_PASSWORD。run_command() 亦不再把失敗結果中的 --password=*** 改寫為星號,uri 模組不再針對 no_log 值重寫回傳鍵名。專案在變更說明中給出明確指引:若模組透過命令列傳遞非 no_log 的秘密,應主動以 register_secret() 登記。
被標記為棄用的三個函式同樣需要留意:heuristic_log_sanitize()、remove_values() 與 sanitize_keys() 將於 ansible-core 2.25 移除。run_cmd 的 live 參數亦因繞過遮罩機制而進入棄用名單。對自行維護 collection 的團隊而言,這是一次必須排入時程的技術債清理。
Python 版本要求有什麼變化?
控制端最低版本由 Python 3.12 升至 3.13,同時新增 3.15 支援;2.22 分支已標示 requires-python 為 3.13 以上。
版本要求的推移在近幾個分支相當規律:2.19 要求 Python 3.11,2.20 與 2.21 停在 3.12,2.22 一舉跳至 3.13。專案在 b1 的變更說明中同時記載「終止控制端 Python 3.12 支援」與「新增 Python 3.15 支援」,代表這次是上下界同時移動,而非單純提高下限。
受影響最直接的是仍以 Python 3.12 執行控制端的環境,包括部分長期支援發行版的預設直譯器、以容器映像固定版本的 CI 流程,以及仍在使用舊虛擬環境的維運工作站。由於 Ansible 控制端只需在一台機器或一個容器內升級,實際遷移成本通常低於受管端;但若 CI 映像與本機環境版本不一致,容易出現「本機可跑、Pipeline 失敗」的分歧。
值得注意的是 ansible-test 的測試容器同步更新至 Python 3.15.0,並把 Ubuntu 22.04、Fedora 43、RHEL 10.1 等測試目標推進到較新版本。對 collection 維護者而言,這意味著 sanity 測試的基準線跟著上移,宣告支援的版本矩陣需要重新核對。
CVE-2026-89091 修復了什麼問題?
修復 ansible-galaxy collection install 未驗證 FILES.json 條目是否位於 collection 目錄內的問題,屬路徑逃逸缺陷。
問題出在安裝流程的驗證順序。ansible-galaxy collection install 會讀取 collection 內的 FILES.json 決定要建立哪些檔案,舊版在建立之前沒有確認每個條目都落在 collection 目錄之內,於是帶有 ../ 的條目可以指向目錄外。rc1 的修補把驗證提前到建立檔案之前,屬於結構性修正而非事後過濾。
這類缺陷的實際風險取決於安裝來源。若 collection 來自 Galaxy 官方倉庫,風險受上游審核機制約束;若來自私有倉庫、內部 Artifact 或直接以 git 位址安裝,防線就只剩客戶端本身。這也解釋為何此項被列為 security fix 而非一般 bugfix:它影響的是「安裝第三方內容」這個幾乎所有團隊都會執行的動作。
同版另有多項與權限相關的收斂。ansible-connection 確保持久連線目錄具備私有權限,涵蓋上層目錄不存在或權限過寬的邊界情況;user 模組在寫入 SSH 金鑰前會先解除指向他處的符號連結,避免覆寫來源檔案;tempfile 則拒絕含有路徑成分的前後綴,以防路徑穿越。
-vvv 除錯輸出為什麼被移除?
因為模組原始輸出可能含未登記的 no_log 值,在結果解析前印出等於繞過遮罩;需要時改以 ANSIBLE_DEBUG=1 取得原文。
這項改動對習慣以高詳細度輸出的使用者而言最直接。過去 ssh 在 -vvv、winrm 與 psrp 在 -vvvvv 會顯示遠端命令的原始標準輸出與錯誤輸出,這些內容在模組結果被解析之前就已經印出,而秘密值要等到解析完成才會完成登記。換言之,詳細度越高,外洩窗口越大。
新版本因此取消這些層級的原始輸出,只保留回傳碼。若確實需要原文,可設定 ANSIBLE_DEBUG=1,但專案的已知問題段落同時註明:在此模式下,模組結果中的秘密可能以明文顯示,因為它們尚未完成登記。這是刻意保留的取捨,除錯能力與預設安全性之間並未假裝可以兩全。
同族的另一項調整是 invocation 欄位。Python 與 PowerShell 模組預設不再於任務結果中附帶 invocation,需要時可透過 INJECT_INVOCATION 設定開啟。由於多數 callback 在顯示任務結果時會遮罩該欄位,這項預設關閉同時降低了輸出體積與外洩面。
ansible-config 的預設行為如何改變?
所有動作預設改為 -t all,插件專屬區段不再被判為未知區段且鍵值會實際驗證;需保留舊行為可指定 -t base。
這是一項容易被忽略卻會改變驗證結果的調整。舊版 ansible-config 預設只驗證基礎設定,當設定檔出現由外掛擁有的區段時,會被視為未知區段而略過,區段內的鍵值也從未被檢查。改為 -t all 之後,這些區段會被納入驗證範圍,拼錯的鍵名將直接報錯。
對已累積多年設定檔的環境而言,這意味著升級後首次執行 ansible-config validate 可能出現過去從未見過的錯誤。這些錯誤多半是真實存在的設定問題,但在升級窗口內被發現,仍可能被誤判為版本缺陷。專案保留 -t base 作為回退手段,讓團隊可以分階段清理。
專案數據呈現怎樣的維護規模?
儲存庫累積 71,020 星標、24,375 次複製、373 位貢獻者與 55,583 次提交,採 GPL-3.0 授權,主要語言為 Python。

從提交節奏觀察,儲存庫在 10 月中旬仍維持每日多次提交的活躍度,最近一次推送落在 10 月 16 日。753 個標籤對應十四年的版本演進,而 57 個分支中包含多條仍在維護的穩定分支,這正是 2.19 至 2.22 對 Python 版本要求各自不同的原因:舊分支維持原有下限,新分支才提高門檻。
複製數與星標數的比例約為三分之一,對基礎設施類專案屬於正常水位,因為多數使用者會直接以 pip install ansible-core 安裝,而非複製儲存庫。真正反映採用的指標是發行版打包情況與雲端供應商的整合深度,這兩者在專案的公開資料中並未直接呈現。

升級到 2.22 前應該注意什麼?
先確認控制端已達 Python 3.13、排查以舊佔位字串作斷言的測試、預期設定驗證出現新錯誤,並檢視自訂模組是否依賴已棄用函式。
實務上可從三條線並行。第一條是執行環境,把控制端直譯器與 CI 映像同步升級到 3.13 以上,並確認容器基底映像已提供對應版本。第二條是測試與監控,搜尋程式碼中對舊佔位字串的依賴,改以「是否出現 $REDACTED$」或直接比對結構化欄位的方式斷言。第三條是自訂程式碼,檢查 collection 與模組是否呼叫 heuristic_log_sanitize()、remove_values()、sanitize_keys(),並改以 ansible.module_utils.secrets 的 API 取代。
由於 2.22 目前處於 rc1 階段,正式版尚未發布,生產環境可先在測試分支驗證。專案同時提醒,ANSIBLE_DEBUG=1 會讓模組結果中的秘密以明文顯示,除錯完成後應確認該變數未殘留在 CI 或容器環境中。
出處連結有哪些?
主要出處為 GitHub 儲存庫 ansible/ansible,含 v2.22.0rc1 發布說明、CHANGELOG-v2.22 與變更片段目錄,另可對照官方移植指南。
本文數據取自專案公開資料,包括儲存庫統計、v2.22.0rc1 發布說明、changelogs/CHANGELOG-v2.22.rst、changelogs/fragments 目錄下的變更片段,以及 pyproject.toml 的版本要求宣告。讀者如需核對個別技術細節,可依下列連結前往原始來源。
- 儲存庫:https://github.com/ansible/ansible
- v2.22.0rc1 發布說明:https://github.com/ansible/ansible/releases/tag/v2.22.0rc1
- 2.22 變更日誌:https://github.com/ansible/ansible/blob/stable-2.22/changelogs/CHANGELOG-v2.22.rst
- 2.22 移植指南:https://docs.ansible.com/ansible-core/2.22/porting_guides/porting_guide_core_2.22.html
- 專案文件:https://docs.ansible.com/
總結:哪些團隊應該優先升級到 Ansible 2.22?
輸出入會流經共用日誌、CI 或第三方平台的團隊最應優先評估;僅在隔離環境執行且大量依賴舊清理函式者可先觀望再排程。
2.22 的定位並非功能擴張,而是把長年累積的秘密處理債一次結清。從啟發式比對走向登記制,意味著安全邊界由「猜得準不準」轉為「有沒有漏登記」,責任部分轉移到模組作者身上,但也換來可預期的行為與更小的外洩面。搭配 ansible.module_utils.secrets 的公開 API,自訂模組終於有一個正式管道處理非 no_log 路徑的秘密。
代價同樣清楚。舊佔位字串消失、ansible-config 驗證變嚴、-vvv 原始輸出取消、控制端 Python 下限提高到 3.13,四項都可能在升級當日造成中斷。這些變更並非難以處理,但都需要事前搜尋與測試,而非在發布後才發現。對於把 Ansible 當成核心維運工具、且 playbook 與日誌會流經多個系統的團隊,提早完成這輪清理的效益,遠高於多等一個版本。