什么是Secrets
應用程式通常會通過使用專用的存盤來存盤敏感資訊,如連接字串、密鑰等,
通常這需要建立一個密鑰存盤,如Azure Key Vault、Hashicorp等,并在那里存盤應用程式級別的密鑰, 要訪問這些密鑰存盤,應用程式需要匯入密鑰存盤SDK,并使用它訪問這些密鑰, 這可能需要相當數量的模板代碼,這些代碼與應用的實際業務領域無關,因此在多云場景中,可能會使用不同廠商特定的密鑰存盤,這就成為一個更大的挑戰,
讓開發人員在任何地方更容易訪問應用程式密鑰, Dapr 提供一個專用的密鑰構建塊 ,允許開發人員從一個存盤獲得密鑰,
使用 Dapr 的密鑰存盤構建塊通常涉及以下內容:
- 設定一個特定的密鑰存盤解決方案的組件,
- 在應用程式代碼中使用 Dapr Secrets API 獲取密鑰,
- 在Dapr的Component檔案中參考密鑰
作業原理

- 服務A呼叫 Dapr Secrets API,提供要檢索的Serects的名稱和要查詢的項名字,
- Dapr sidecar 從Secrets存盤中檢索指定的機密,
- Dapr sidecar 將Secrets資訊回傳給服務,
Dapr目前支持的Secrets存盤請見存盤
使用Secrets時,應用程式與 Dapr sidecar 互動, sidecar 公開Secrets API, 可以使用 HTTP 或 gRPC 呼叫 API, 使用以下 URL 呼叫 HTTP API:
http://localhost:<dapr-port>/v1.0/secrets/<store-name>/<name>?<metadata>
URL 包含以下欄位:
<dapr-port>指定 Dapr sidecar 偵聽的埠號,<store-name>指定 Dapr Secrets存盤的名稱,<name>指定要檢索的密鑰的名稱,<metadata>提供Secrets的其他資訊, 此段是可選的,每個Secrets存盤的元資料屬性不同, 有關元資料屬性詳細資訊
專案實戰
通過Dapr SDK獲取secrets
仍然使用FrontEnd專案,并使用本地檔案存盤Secrets,首先在默認component目錄C:\Users\<username>\.dapr\components中新建檔案secrets01.json,宣告密鑰內容
{ "RabbitMQConnectStr": "amqp://admin:[email protected]:5672" }
在此目錄新建secrets01.yaml定義store
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: secrets01 spec: type: secretstores.local.file version: v1 metadata: - name: secretsFile value: C:\Users\username\.dapr\components\secrets01.json - name: nestedSeparator value: ":"
定義介面獲取Secrets01的內容,新建SecretsController
using Dapr.Client; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Threading.Tasks; namespace FrontEnd.Controllers { [Route("[controller]")] [ApiController] public class SecretsController : ControllerBase { private readonly ILogger<SecretsController> _logger; private readonly DaprClient _daprClient; public SecretsController(ILogger<SecretsController> logger, DaprClient daprClient) { _logger = logger; _daprClient = daprClient; } [HttpGet] public async Task<ActionResult> GetAsync() { Dictionary<string, string> secrets = await _daprClient.GetSecretAsync("secrets01", "RabbitMQConnectStr"); return Ok(secrets); } } }
運行Frontend
dapr run --dapr-http-port 3501 --app-port 5001 --app-id frontend dotnet .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll
驗證此api,獲取成功

通過IConfiguration訪問Secrets
Dapr還提供了從IConfiguration中訪問Secrets的方法,首先引入nuget包Dapr.Extensions.Config

在Program.cs中修改注冊
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration(config => { var daprClient = new DaprClientBuilder().Build(); var secretDescriptors = new List<DaprSecretDescriptor> { new DaprSecretDescriptor("RabbitMQConnectStr") }; config.AddDaprSecretStore("secrets01", secretDescriptors, daprClient); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>().UseUrls("http://*:5001"); });
在SecretsController注入IConfiguration
private readonly ILogger<SecretsController> _logger; private readonly DaprClient _daprClient; private readonly IConfiguration _configuration; public SecretsController(ILogger<SecretsController> logger, DaprClient daprClient, IConfiguration configuration) { _logger = logger; _daprClient = daprClient; _configuration = configuration; }
在SecretsController中新增介面
[HttpGet("get01")] public async Task<ActionResult> Get01Async() { return Ok(_configuration["RabbitMQConnectStr"]); }
呼叫介面,獲取資料成功

其他組件參考Secrets
Dapr的其他組件,同樣可以參考Secrets,我們以上節RabbitMQBinding為例,修改rabbitbinding.yaml
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: RabbitBinding spec: type: bindings.rabbitmq version: v1 metadata: - name: queueName value: queue1 - name: host secretKeyRef: name: RabbitMQConnectStr key: RabbitMQConnectStr - name: durable value: true - name: deleteWhenUnused value: false - name: ttlInSeconds value: 60 - name: prefetchCount value: 0 - name: exclusive value: false - name: maxPriority value: 5 auth: secretStore: secrets01
secretKeyRef元素參考指定的密鑰, 它將替換以前的 明文 值, 在 auth 中找到對應的secretStore,
現在運行Frontend
dapr run --dapr-http-port 3501 --app-port 5001 --app-id frontend dotnet .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll
在RabbitMQ Management中發送訊息,消費成功
== APP == info: FrontEnd.Controllers.RabbitBindingController[0] == APP == .............binding.............11122444
限制Secrets訪問權限
我們可以在Dapr的默認組態檔C:\Users\username\.dapr\config.yaml中設定Secrets的訪問權限,現在我們嘗試禁止secrets01的權限
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: daprConfig spec: tracing: samplingRate: "1" zipkin: endpointAddress: http://localhost:9411/api/v2/spans secrets: scopes: - storeName: secrets01 defaultAccess: deny
設定之后,Frontend會啟動失敗,因為我們在Program.cs中設定了讀取secrets01,
== APP == Unhandled exception. Dapr.DaprException: Secret operation failed: the Dapr endpoint indicated a failure. See InnerException for details. == APP == ---> Grpc.Core.RpcException: Status(StatusCode="PermissionDenied", Detail="access denied by policy to get "RabbitMQConnectStr" from "secrets01"") == APP == at Dapr.Client.DaprClientGrpc.GetSecretAsync(String storeName, String key, IReadOnlyDictionary`2 metadata, CancellationToken cancellationToken) == APP == --- End of inner exception stack trace --- == APP == at Dapr.Client.DaprClientGrpc.GetSecretAsync(String storeName, String key, IReadOnlyDictionary`2 metadata, CancellationToken cancellationToken) == APP == at Dapr.Extensions.Configuration.DaprSecretStore.DaprSecretStoreConfigurationProvider.LoadAsync() == APP == at Dapr.Extensions.Configuration.DaprSecretStore.DaprSecretStoreConfigurationProvider.Load() == APP == at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers) == APP == at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build() == APP == at Microsoft.Extensions.Hosting.HostBuilder.BuildAppConfiguration() == APP == at Microsoft.Extensions.Hosting.HostBuilder.Build() == APP == at FrontEnd.Program.Main(String[] args) in C:\demo\test\DaprBackEnd\FrontEnd\Program.cs:line 20
我們可以修改配置讓其允許
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: daprConfig spec: tracing: samplingRate: "1" zipkin: endpointAddress: http://localhost:9411/api/v2/spans secrets: scopes: - storeName: secrets01 defaultAccess: deny allowedSecrets: ["RabbitMQConnectStr"]
重啟Frontend成功
以下表格列出了所有可能的訪問權限配置
| Scenarios | defaultAccess | allowedSecrets | deniedSecrets | permission |
|---|---|---|---|---|
| 1 - Only default access | deny/allow | empty | empty | deny/allow |
| 2 - Default deny with allowed list | deny | [“s1”] | empty | only “s1” can be accessed |
| 3 - Default allow with deneied list | allow | empty | [“s1”] | only “s1” cannot be accessed |
| 4 - Default allow with allowed list | allow | [“s1”] | empty | only “s1” can be accessed |
| 5 - Default deny with denied list | deny | empty | [“s1”] | deny |
| 6 - Default deny/allow with both lists | deny/allow | [“s1”] | [“s2”] | only “s1” can be accessed |
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/308045.html
標籤:.NET Core
