看程式範例學到用 .NET Secret Manager 儲存秘密設定(如 API Key)的小技巧。

參考文件:在 ASP.NET Core 的開發中安全儲存應用程式秘密

應用程式會用到的一些具機密性設定 API Key 等,存放在 appsettings.json 或自訂 JSON/XML 容易連同原始碼一起外流,並有不小心簽進版控在雲端裸奔的風險(資安人:超過18000個API 金鑰外洩! 影響多個主流網站使用之令牌),改存到環境變數是個選擇。環境變數的缺點是所有專案共用像全域變數,有被其他專案覆寫改掉的風險。.NET Core 3.0+ 推出 Secret Manager (秘密管理員)可用來儲存應用程式開發期間的敏感數據,每個專案擁有個別儲存空間(但要共用也可以)不會彼此干擾,儲存位置和方式等實作細節被 Secret Manager 隱藏 (Windows 在 %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json,Linux/macOS 在 ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json),程式端只需透過 IConfiguration 介面可比照 appsettings.json 或環境變數輕鬆讀取設定值。

使用方式很簡單,在專案目錄下執行 dotnet user-secrets init[1] 後,.NET 會隨機產生專案專屬 UserSecretsId 寫入 .csproj [2],接著便可使用 dotnet user-secrets set "設定名稱" "設定值" 進行設定 [3]:

設定後,到 AppData\Roaming 使用者私有區可找到隨機 UserSecretsId 名稱的資料夾,其中有個 secrets.json,裡面存有設定值:(注意:設定值會以明碼儲存未加密,它主要是方便本機開發測試,勿視為可信任的存放區 參考)

在 .NET 專案如要使用 Secret Manager 儲存的設定,需先參照 Microsoft.Extensions.Configuration.UserSecrets 程式庫 dotnet add package Microsoft.Extensions.Configuration.UserSecrets,之後透過 ConfigurationBuilder.AddUserSecrets<Program>() 加為來源,其餘存取概念與 appsettings.json 一致:

using Microsoft.Extensions.Configuration;

IConfiguration config = new ConfigurationBuilder()
        .AddUserSecrets<Program>().Build();
Console.WriteLine(config["OpenApiKey"]);

心得:.NET 內建支援,專案各有專屬存放區不必擔心共用環境變數被覆寫是 Secret Manager 的最大優點。但我對明碼儲存有些疑慮,仍偏向如何在 .NET 工具程式安全儲存 API Key 設定一文的概念,主張至少用 DPAPI 簡單加密也好,找時間再來研究怎麼摻在一起做瀨尿牛丸。


Comments

# by cloud

請問, 環境有分 appsettings.Development.json、appsettings.Production.json 會根據環境變數各自取得設定時, 在 user-secrets 下如何處理?

# by cloud

另一問, 在開發機使用上述 user-secrets 機制可以正確輸出 "the_api_key", 但將程式發佈至正式機就只輸出空白, 需將 secrts.json 複制一份過去才可生效, 這樣跟把 appsettings.json 發佈到正式機不就一樣了?

# by Jeffrey

to cloud, users-secrets 綁定特定使用者資料夾,主要應用場景為本機開發測試,不適合部署到正式機。可以同時 AddJsonFile() 及 .AddUserSecrets<Program>(),程式不用改,測試用 user-secrets,正式用 appsettings.json 即可。

# by cloud

感謝解惑.

# by SHIH HUNG YANG

存放在 appsettings.son 或自訂 JSON/XML,是否少了一個J?

# by Jeffrey

to SHIH HUNG YANG,是的,謝謝指正。

Post a comment