當我準備把第一台主機加入監控時,最直覺的做法就是把帳號、密碼一起寫進 hosts.json。但游標停在密碼欄位時,我突然想到:這個檔案會被備份、可能傳給同事,也可能不小心進入版本控制。為了省下幾分鐘,卻可能讓主機密碼到處流動,這筆交換並不划算。
credentials.py 透過 keyring 使用 Windows Credential Manager。監控用的帳密和遠端操作用的帳密也分開:能讀 CPU、磁碟的人,不一定要有 RDP 或 KVM 的控制權。
這件事剛開始多了一點設定步驟,但後來很值得。設定檔可以安心備份,日誌也不會意外印出祕密;人員異動時,權限調整更清楚。
def get_password(host):
return keyring.get_password(
credential_name(host),
host.get("username", ""),
) or ""
設定檔保存連線資訊,Credential Manager 保存祕密,兩者負責不同生命週期。
這裡不應捕捉後把密碼寫進 Log;主機改名時也要考慮舊索引如何搬遷。
hosts = [{
"type": "ssh",
"host": "192.0.2.20",
"username": "monitor",
}]
save_passwords(hosts, ["example-password"])
password = get_password(hosts[0])
assert password == "example-password"
真正發布文章時,密碼只能使用明確的假資料,也不要貼出 Credential Manager 的實際畫面內容。
把密碼移到 Credential Manager 後,曾遇過主機改名便讀不到舊憑證的問題,因為憑證索引是依主機識別資料產生。修復時,我把名稱產生集中在 credential_name 與 remote_credential_name,避免各功能自行拼接不同鍵值;也替舊版遠端憑證保留相容讀取。另一個重點是例外訊息只回報認證失敗,不能把命令列或密碼內容直接寫進日誌。
今天的重點是讓祕密、一般設定與程式碼分開保存。下一篇會開始納管 Windows 機台,打通 WinRM 的首次設定與蒐集流程。