WebApp如何安全的存放機密資訊

WebApp如何安全的存放機密資訊

每一個重要的應用程式裡面都有機密資訊,從資料庫的連線字串,到後台admin的帳號密碼,這些大大小小的機密資訊,常常被開發人員存放在source code的某處…咦? 等等…

對,你應該有所警覺,這些資訊怎麼能存放在程式碼裡呢? 這顯然不夠安全啊。但…直到上周,我在上課的時候,還有學員依舊把連線字串和帳密寫死在程式碼中😮。

那你說,好吧,不寫在程式碼『裡面』,那我獨立寫在一個檔案裡面好了,在 .net 的世界裡,這就是 web.config或是 appsettings.json,但…這樣就安全了嗎?

只能說,『相對』安全了點,但還是不夠安全。

關鍵在於,誰能(或誰該)經手這些機密資訊? 早期的概念是把開發和維運團隊切開,讓開發人員無法得知最終的帳密,讓維運的人無法得知程式碼的內容,這樣,除非這兩個人同時被綁架(或彼此串通),不然企業的機密資訊還是可以得到保障。有點像是出納和會計不能是同一個人的道理。

這種保護是,不讓『某一個人』知道所有的資訊。只能說相對安全,並非絕對安全,因為經手機密資訊的人還是太多了。安全的定義是,不該知道的人,就不要知道。

因此,更好的方式是,讓機密資訊只有單一一個安全存放點,且由單一的某一個人寫入。並且,在取用的過程中維持『不落地』。所謂的不落地,就是不儲存在任何地方。簡單的說,就是需要使用時(例如建立資料庫連線),從安全的存放點取出(帳密),然後就保存在記憶體中,永遠不寫入任何的檔案、資料庫、硬碟…等儲存體。

真能夠實現這件事情嗎? 可以的。

微軟在Azure雲端上,有一個專門提供存放機密資料的儲存庫,稱為Key Vault(金鑰儲存庫),管理人員可以把機密資訊(例如admin的帳號密碼、資料庫的連線帳密…etc.),存放在這個Key Vault中,然後在WebApp的原始程式碼(檔案)中,就不要再存放這些資訊了。當WebApp需要使用的時候,直接問Key Vault拿就可以了:
enter image description here
這樣還有一個莫大的好處,管理人員可以隨時rotate(滾動轉換)帳密資訊,無須開發或維運人員經手。

由於Key Vault是被重重大鎖給保障的(採用高安全性的加密機制),因此可以說是固若金湯,安全無庸置疑…等…等等,不對啊,那我們的WebApp在存取KeyVault的時候,不是也會有帳密或連線字串嗎? 那這連線字串要放哪? 另一個KeyValut嗎??? 😛

如果存取KeyValue的帳密或連線字串,還是放在web.config或是AppSettings.json裡面,那這一切豈不都是白搭?

萬一 web.config 或 AppSettings.json被竊取,機密資訊不是被駭客整碗捧去? 原本只是損失個db連線字串,現在是損失整個KeyVault,豈不更慘?

所以關鍵來了,如果有一個方法,可以不用帳密就能讓WebApp『安全的』存取KeyValue,那不就解決了所有問題? 能嗎? 可以的。

由於WebApp和KeyValue都是Azure管理的,因此,我們可以設定KeyValue『信任』該WebApp,讓該WebApp存取KeyVault中的特定機密資料。只要設定完成,未來WebApp內的程式碼,跟KeyVaule拿資料的時候,就無需帳密驗證(其實不是沒有驗證,而是由Azure自行做驗證),開發人員不需要把KeyVault的存取連線字串或權限放置在WebApp的appsetting.json或任何地方,如此一來,機密資料的存取流程就安全無懈可擊了。

如何讓WebApp被KeyVault信任?
首先,請在Azure上建立該WebApp的身分識別:
enter image description here
這個動作會讓該WebApp在AAD上被註冊,你會得到一個物件識別碼,請取得該物件識別碼,然後到KeyVault的存取原則設定:enter image description here

請新增存取原則,出現底下畫面後,設定服務主體為剛才紀錄的WebApp 服務主體物件識別碼,並提供它具有存取該 secret (帳密)的權限:
enter image description here

完成後,你會發現神奇的事情發生了,該WebApp存取KeyVault中的該機密資訊時,是不需要連線字串或帳密的(類似底下這樣):
enter image description here

而WebApp取得機密資訊後,只要沒有儲存在任何儲存體上,就沒有外洩的可能(應該說外洩可能極低,除非記憶體被動態竊取)。如此一來,從KeyVault取得的機密資訊的流程不僅安全,也不須將機密存放在KeyVault以外的任何地方,達成機密資訊『不落地』的效果,這才是真正的高安全性應用程式開發。😎

留言

aeifkz寫道…
請教一下你所提到的 Azure 的物件識別碼不需要寫在 WebAPP 嗎?? 如果有寫的話那我拿到識別碼是不是就能到 Azure 拿到密碼之類的?
謝謝。
isDavid寫道…
aeifkz,
不需要,是從Azure Portal直接設定兩者之間的信任關係。code裡面不須寫任何東西。

這個網誌中的熱門文章

原來使用 .net 寫個 MCP Server 如此簡單

使用LM Studio輕鬆在本地端以API呼叫大語言模型(LLM)

開啟 teams 中的『會議轉錄(謄寫)』與Copilot會議記錄、摘要功能

在VS Code當中使用 Azure DevOps MCP Server

原來使用 .net 寫個 MCP Client 也如此簡單