使用 Managed Identity 讓 WebApp 毋須帳密直接存取 KeyVault
你有沒有過這種經驗?把資料庫密碼寫在設定檔裡,commit 之後才驚覺「慘了!」然後開始瘋狂 Google「如何從 Git 歷史紀錄中永久刪除檔案」。
或者更糟的是,一時偷懶把 API Key 硬寫在程式碼裡,結果被同事在 Code Review 時抓包,尷尬地說「我只是暫時測試用的啦」(但其實已經在 Production 跑了三個月)。
歡迎來到~密碼管理地獄。😈
然而你可能不知道,Azure 提供了一個叫做 Managed Identity(受控識別) 的機制,可以跟本性的解決這類問題。
Managed Identity 是 Azure AD 中的一種應用身分(Service Principal),它就像是幫你的應用程式辦了一張「雲端身分證」。有了這張身分證,你的 WebApp 可以直接向 Azure 的各種服務(像是 Key Vault、Storage、Database)亮出證件說:「嘿,我是合法的!讓我進去!」同時完全不需要在程式碼裡寫任何帳號密碼。 😲
這就像是住在有門禁管理的大樓,你不需要每次都掏出鑰匙,因為管理員認識你的臉。系統會自動幫你驗證身份,既方便又安全。
為什麼這麼做會讓老闆和資安長都笑開懷?那你得先知道,究竟使用 Managed Identity 的好處有多少?
1. 零密碼外洩風險 💪
當你的程式碼裡完全沒有密碼時,就算有人偷看你的 GitHub Repository、翻遍你的設定檔、甚至把整個專案下載回去,也拿不到任何可以用來入侵的憑證。因為根本就不存在!這就像是你家的保險箱沒有鑰匙孔,只能透過虹膜辨識開啟,小偷就算把保險箱搬走也沒用。
2. 不用再煩惱密碼輪替(Rotate) 🔄
傳統做法中,如果要定期更換密碼(資安政策通常要求 90 天換一次),你常常得改設定檔檔、重新部署、還要確保所有環境都同步更新。一個不小心,Production 就掛了。但使用 Managed Identity,Azure 會在背後自動處理所有的憑證更新,就像是有個超敬業的助理幫你處理所有煩人的行政工作。
3. 精準的權限管理 🎯
透過 Azure 的 IAM(Identity and Access Management),你可以精確控制「誰」可以「對什麼資源」做「哪些操作」。想讓 WebApp 只能讀取 Key Vault 的 secrets,但不能刪除或修改?沒問題!這種細膩的權限控制,讓你可以實踐「最小權限原則」(Principle of Least Privilege),大幅降低被攻擊時的損害範圍。
4. 審計紀錄自動留存 📝
可設定審計紀錄,透過 Azure Monitor 留存,如此一來所有透過 Managed Identity 的存取行為都會被記錄在 Azure Monitor 中。誰在什麼時候存取了什麼資源?一目了然。當資安稽核來敲門時,你可以自信地拿出完整的存取日誌,而不是支支吾吾地回答「應該…沒有人亂用吧?」
5. 開發者負擔大減 🧘
開發人員不需要再煩惱「這個密碼要放哪裡」、「如何在本機和雲端使用不同的設定」、「密碼過期了怎麼辦」。程式碼變得更乾淨、更簡單、更容易維護。當你的程式碼只要 new DefaultAzureCredential()
就能搞定所有認證問題時,那種愉悅感就像是用了 GitHub Copilot 後再也不想回去傳統手動開發一樣。
進行實作
好了,理論講完了,讓我們實際動手做!接下來會帶你一步步建立一個真正能運作的範例。當你看到程式碼裡完全沒有任何密碼,但一切運作卻如絲般順滑時,你會有種「哇,真讚」的感覺。
步驟一:建立 Key Vault(金鑰保存庫)
首先,我們需要一個安全的地方來存放機敏資料。在 Azure Portal 中建立一個 Key Vault,取個好記的名字(像是 my-super-secret-vault
,雖然其實一點也不 secret,因為名稱是公開的 😄)。
這個 Key Vault 就像是你的數位保險箱,專門用來存放那些「絕對不能讓另一半知道的」…喔不對,是「絕對不能外洩的敏感資料」,比如資料庫連線字串、API 金鑰、加密用的證書等等。
步驟二:建立 Web App
接著,我們需要一個 Web App 來執行我們的範例程式。在 Azure 中建立一個 App Service,選擇適合的規格(如果只是測試,選最便宜的 F1 Free tier 就夠了,省錢是王道)。
步驟三:在 Key Vault 中建立 Secret
現在我們要在 Key Vault 裡放一個 secret(機密資料)。這裡我們示範存放一個資料庫密碼,取名為 DatabasePassword
。
重要提醒:在建立 secret 之前,記得先到 Key Vault 的 IAM(存取控制)頁面,把自己設定為 Key Vault 系統管理員(Key Vault Administrator)角色。不然你會發現你在自己建立的保險箱裡放東西都不行,這種窘境就像是買了房子卻發現自己沒鑰匙一樣尷尬。
Azure 的權限管理就是這麼嚴謹,即使你是訂閱的擁有者,也不代表你自動擁有 Key Vault 內容的存取權。這是「職責分離」(Separation of Duties)的最佳實踐,雖然一開始會讓人有點不習慣,但日後你會感謝這個設計。
確定具有Key Vault 系統管理員權限之後,你就可以建立一個 secret:
步驟四:撰寫程式碼(重頭戲來了!)
現在是最精彩的部分。看看下面這段程式碼,注意看,仔細看 — 完全沒有任何帳號密碼!
public void OnGet()
{
var keyValueName = _configuration["KeyVault:Name"];
SecretClientOptions options = new SecretClientOptions()
{
Retry =
{
Delay= TimeSpan.FromSeconds(2),
MaxDelay = TimeSpan.FromSeconds(16),
MaxRetries = 5,
Mode = RetryMode.Exponential
}
};
var client = new SecretClient(new Uri($"https://{keyValueName}.vault.azure.net/"), new DefaultAzureCredential(), options);
KeyVaultSecret secret = client.GetSecret("DatabasePassword");
//show in view
this.secretValue = secret.Value;
}
看到那行 new DefaultAzureCredential()
了嗎?這就是魔法所在!
DefaultAzureCredential
是 Azure SDK 提供的一個聰明小幫手,它會按照優先順序嘗試各種認證方式:
- 環境變數(適合在本機開發時使用)
- Managed Identity(這是我們在 Azure 上跑時會用到的)
- Visual Studio 登入的帳號(開發者最愛)
- Azure CLI 登入的帳號
- 還有其他幾種方式…
這個設計超貼心,意思是你的程式碼可以「一個版本到處跑」— 在本機開發時用你的 VS 帳號,部署到 Azure 後自動切換成 Managed Identity。完全不需要寫一堆 if (environment == "production")
這種醜陋的判斷。
不過,在安全性要求高的環境,建議明確使用ManagedIdentityCredential()
取代DefaultAzureCredential()
,以避免混淆。
另外注意到我們還設定了 retry policy(重試策略)嗎?這是個好習慣。網路世界充滿了不確定性,偶爾會有短暫的連線問題。設定 exponential backoff(指數退避)的重試機制,可以讓你的應用程式更有韌性。從 2 秒開始,逐步增加到 16 秒,最多重試 5 次。這樣即使遇到暫時性的網路抖動,程式也能優雅地處理,而不是直接掛掉。
步驟五:發佈應用程式到 Web App
程式碼寫好了,接下來就是把它推上雲端。你可以用 Visual Studio 或 Visual Studio Code 的發佈功能,或是透過 CI/CD pipeline(如果你想帥一點的話)。
步驟六:啟用 Web App 的系統指派受控識別
重點來了!到你的 Web App 設定頁面,找到「身分識別」(Identity)的選項,把「系統指派」(System assigned)的受控識別狀態切換成「開啟」。
這個動作就像是幫你的 Web App 辦了一張身分證。Azure 會自動產生一個唯一的身份識別碼,並且在背後處理所有的認證憑證管理。你會看到一個「物件 (主體) 識別碼」(Object/Principal ID),長得像這樣:
6dff2ee0-9f60-4e61-b7ab-a89374445998
把這串 ID 記下來(或是複製起來),等一下會用到。這串 ID 就是你的 Web App 在 Azure 世界裡的「身分證字號」。
步驟七:設定 Key Vault 的存取權限
最後一步!回到 Key Vault,進入 IAM(存取控制)頁面,新增一個角色指派(Role Assignment)。
你要做的事情很簡單:
- 選擇適當的角色,例如「Key Vault 祕密使用者」(Key Vault Secrets User)— 這個角色只能「讀取」secrets,不能修改或刪除,符合最小權限原則。
- 把剛才複製的「物件主體識別碼」貼上去,搜尋並選取你的 Web App。
- 儲存!
搞定!🎉
現在你的 Web App 已經獲得授權,可以讀取 Key Vault 裡的 secrets 了。而且整個過程中,程式碼裡完全不需要任何帳號密碼。你的應用程式透過 Managed Identity 亮出身分證,Key Vault 核對身分後說:「沒問題,你是合法的,進來吧!」然後就把 secret 交給你了。
試著執行 Web App,你會看到它成功地從 Key Vault 中取得了 DatabasePassword
。整個流程行雲流水,而且安全無虞。
技術背後的哲學思考
當我們把這個實作完整走過一遍後,你有沒有發現一個有趣的現象?
傳統的安全思維是「把秘密藏好」— 加密、混淆、放在 config 檔案的深處、用環境變數遮起來。但這些做法的本質都是「秘密還是在那裡」,只是藏得比較隱密而已。就像是把鑰匙藏在門墊下面,只要有心人知道這個慣例,還是能找到。
Managed Identity 則是一種思維的轉移:與其想辦法「藏好秘密」,不如徹底消滅秘密的存在。當系統本身就能認出你的身份時,你根本不需要帶鑰匙出門。
這讓我想到有句名言:「The best password is no password」(最好的密碼就是沒有密碼)。聽起來很玄,但確實是終極真理。每一個存在的密碼都是一個潛在的弱點,每一個需要儲存的 secret 都可能被偷走。那麼,如果能做到不需要密碼,為什麼還要冒這個險呢?
更深一層來說,這反映了現代雲端架構設計的核心理念:信任是由系統建立的,而不是由人類記憶的字串建立的。當你的應用程式在 Azure 上執行,Azure 本身就是最強大的身份認證來源。你不需要再另外搞一套帳密系統,而是直接利用平台提供的身份基礎設施。
這種做法不只更安全,還帶來了另一個意想不到的好處:簡化。
當你不需要管理密碼時,你的架構變簡單了、程式碼變簡單了、部署流程變簡單了、團隊協作也變簡單了。複雜性是軟體系統的頭號敵人,而 Managed Identity 透過「減法」的方式,讓整個系統變得更優雅。
所以下次當你在寫程式時,不妨問問自己:「我真的需要這個密碼嗎?」說不定,你可以找到一個更聰明的做法,一個完全不需要密碼的做法。
這或許就是雲端原生(Cloud Native)架構美麗的地方:不是把舊有的做法整套搬到雲端上,而是重新思考「在這個新世界裡,事情應該怎麼做」。
當你掌握了這種思維,寫出來的不只是更安全的程式碼,而是更有智慧的程式碼。
*現在,去把你專案裡那些設定檔裡的密碼都刪掉吧。你的未來會感謝你的。🖖
留言