什么是Secrets

应用程序通常会通过使用专用的存储来存储敏感信息,如连接字符串、密钥等。

通常这需要建立一个密钥存储,如Azure Key Vault、Hashicorp等,并在那里存储应用程序级别的密钥。 要访问这些密钥存储,应用程序需要导入密钥存储SDK,并使用它访问这些密钥。 这可能需要相当数量的模板代码,这些代码与应用的实际业务领域无关,因此在多云场景中,可能会使用不同厂商特定的密钥存储,这就成为一个更大的挑战。

让开发人员在任何地方更容易访问应用程序密钥, Dapr 提供一个专用的密钥构建块 ,允许开发人员从一个存储获得密钥。

使用 Dapr 的密钥存储构建块通常涉及以下内容:

  1. 设置一个特定的密钥存储解决方案的组件。
  2. 在应用程序代码中使用 Dapr Secrets API 获取密钥。
  3. 在Dapr的Component文件中引用密钥

工作原理

  1. 服务A调用 Dapr Secrets API,提供要检索的Serects的名称和要查询的项名字。
  2. Dapr sidecar 从Secrets存储中检索指定的机密。
  3. 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:123456@192.168.43.101: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

Dapr + .NET Core实战(七)Secrets的更多相关文章

  1. Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul

    前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...

  2. Dapr + .NET Core实战(九)本地调试

    前几节开发Dapr应用程序时,我们使用 dapr cli 来启动dapr服务,就像这样: dapr run --dapr-http-port 3501 --app-port 5001 --app-id ...

  3. Dapr + .NET Core实战(十一)单机Dapr集群

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  4. Dapr + .NET Core实战(十一)单机Dapr集群负载均衡

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  5. Dapr + .NET Core实战(十二)服务调用之GRPC

    什么是GRPC gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的 ...

  6. Dapr + .NET Core实战(十三)跨语言开发

    因为基于Dapr的服务架构是不限语言的,我们来看看Dapr的跨语言开发.我们使用golang,python,.NET来实现跨语言的服务调用,拓扑如下 我们继续使用.NET 5的fontend和back ...

  7. Dapr + .NET Core实战(四)发布和订阅

    什么是发布-订阅 发布订阅是一种众所周知并被广泛使用的消息传送模式,常用在微服务架构的服务间通信,高并发削峰等情况.但是不同的消息中间件之间存在细微的差异,项目使用不同的产品需要实现不同的实现类,虽然 ...

  8. Dapr + .NET Core实战(五)Actor

    什么是Actor模式 Actors 为最低级别的"计算单元" 以上解释来自官方文档,看起来"晦涩难懂".大白话就是说Actors模式是一段需要单线程执行的代码块 ...

  9. Dapr + .NET Core实战(六)绑定

    什么是绑定 处理外部事件或调用外部接口的功能就是绑定,绑定可以提供以下好处: 避免连接到消息系统 ( 如队列和消息总线 ) 并进行轮询的复杂性 聚焦于业务逻辑,而不是如何与系统交互 使代码不受 SDK ...

随机推荐

  1. C++ 中的信号的处理

    C++ 信号处理 信号是由操作系统传给进程的中断,会提早终止一个程序.在 UNIX.LINUX.Mac OS X 或 Windows 系统上,可以通过按 Ctrl+C 产生中断. 有些信号不能被程序捕 ...

  2. 深入浅出Mybatis系列(五)---配置详解之settings设置

    settings 中的设置是非常关键的,它们会改变 MyBatis 的运行时行为.下表描述了设置中各项的意图.默认值等. 设置参数 描述 有效值 默认值 cacheEnabled 该配置影响的所有映射 ...

  3. Linux下的Shell工作原理

    Linux下的Shell工作原理 Linux系统提供给用户的最重要的系统程序是Shell命令语言解释程序.它不属于内核部分,而是在核心之外,以用户态方式运行.其基本功能是解释并执行用户打入的各种命令, ...

  4. MySql 改变table的列名以及列的类型

    1 ALTER TABLE table_name CHANGE COLUMN old_col_name new_col_name datatype; #改变table的列名以及列的类型

  5. Oracle数据库 —— DDL

    时间:2016-10-5 14:55 逆风的方向更适合飞翔我不怕千万人阻挡只怕自己投降 --------------------------------------- 一.表的创建与管理1.表的基本操 ...

  6. 用vue实现扫描二维码跳转页面功能

    怎么能用vue实现扫描二维码跳转页面功能 1. 安装依赖 npm install vue-qr --save 2. <template>   <div>     <div ...

  7. 「萌新指南」SOA vs. 微服务:What’s the Difference?

    实话实说,在我还没有实习之前,我是连 SOA 是啥都不知道的,只听说过微服务,毕竟微服务实在太火了,想不知道都难,我觉得实习的时候肯定也是微服务,进组之后发现是 SOA 架构,当时都懵了,看了很多文档 ...

  8. MySQL alter table时执行innobackupex全备再看Seconds_Behind_Master

    1.场景描述 早上7:25 接到Report中心同学告警,昨天业务报表数据没有完整跑出来,缺少500位业务员的数据,并且很快定位到,缺少的是huabei_order库上的数据.Report中心的数据是 ...

  9. Kickstart部署多系统

    原文转自:https://www.cnblogs.com/itzgr/p/10029587.html作者:木二 目录 一 准备 1.1 完整架构:Kickstart+DHCP+HTTP+TFTP+PX ...

  10. MySQL高可用主从复制简介

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 简介 1.1 概述 二 技术原理 2.1 支持的复制类型 2.2 技术特点 2 ...