2020年12月11日 星期五

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以外的任何地方,達成機密資訊『不落地』的效果,這才是真正的高安全性應用程式開發。😎

2 則留言:

aeifkz 提到...

請教一下你所提到的 Azure 的物件識別碼不需要寫在 WebAPP 嗎?? 如果有寫的話那我拿到識別碼是不是就能到 Azure 拿到密碼之類的?
謝謝。

isDavid 提到...

aeifkz,
不需要,是從Azure Portal直接設定兩者之間的信任關係。code裡面不須寫任何東西。

熱門文章