烂翻译系列之面向.NET开发人员的Dapr——机密


The Dapr secrets building block

Dapr 机密构建块

Enterprise applications require secrets. Common examples include:

  • A database connection string that contains a username and password.
  • An API key for calling an external web API.
  • A client certificate for authenticating to an external system.

企业应用程序要求保密。 常见示例包括:

  • 包含用户名和密码的数据库连接字符串。
  • 用于调用外部 web API 的 API 密钥。
  • 外部系统进行身份验证的客户端证书。

Secrets must be carefully managed so that they're never disclosed outside of the application.

必须谨慎管理机密,使其不会在应用程序外公开。

Not long ago, it was popular to store application secrets in a configuration file inside the application codebase. .NET developers will fondly recall the web.config file. While simple to implement, integrating secrets to along with code was far from secure. A common misstep was to include the file when pushing to a public GIT repository, exposing the secrets to the world.

不久前,将应用程序机密存储在应用程序代码库内的配置文件中是很常见的。 .NET 开发人员将想到 web.config 的文件。 虽然实现起来很简单,但将机密与代码集成在一起并不安全。 常见的失误是在推送到公共 GIT 存储库时包括文件,从而向世界公开机密。

A widely accepted methodology for constructing modern distributed applications is The Twelve-Factor App. It describes a set of principles and best practices. Its third factor prescribes that configuration and secrets be externalized outside of the code base.

用于构造现代分布式应用程序的一种广泛接受的方法是十二要素应用。 其中介绍了一系列原则和最佳实践。 第三个要素规定, 将配置和机密外部化在基础代码外。

To address this concern, the .NET Core platform includes a Secret Manager feature that stores sensitive data in a physical folder outside of the project tree. While secrets are outside of source control, this feature doesn't encrypt data. It's designed for development purposes only.

为了解决这一问题,.NET Core 平台包含一个 密钥管理器 功能,该功能将敏感数据存储在项目树之外的物理文件夹中。 虽然机密不受源代码管理,但此功能不会对数据进行加密。 它被设计为仅用于 开发目的 。

A more modern and secure practice is to isolate secrets in a secrets management tool like Hashicorp Vault or Azure Key Vault. These tools enable you to store secrets externally, vary credentials across environments, and reference them from application code. However, each tool has its complexities and learning curve.

更现代、安全的做法是在机密管理工具(Hashicorp Vault or Azure Key Vault)中隔离机密。 这些工具使你能够将机密存储在外部,能跨环境改变凭据,能从应用程序代码中引用它们。 然而,每个工具都有其复杂性和学习曲线。

Dapr offers a building block that simplifies managing secrets.

Dapr 提供简化密钥管理的构建块。

What it solves

解决方法

The Dapr secrets building block abstracts away the complexity of working with secrets and secret management tools.

  • It hides the underlying plumbing through a unified interface.
  • It supports various pluggable secret store components, which can vary between development and production.
  • Applications don't require direct dependencies on secret store libraries.
  • Developers don't require detailed knowledge of each secret store.

Dapr 机密构建块 消除了使用机密和机密管理工具的复杂性。

  • 它通过统一的接口隐藏基础管道。
  • 它支持各种可 插入 的机密存储组件,这些组件在开发和生产之间有所不同。
  • 应用程序无需直接依赖于密钥存储库。
  • 开发人员无需详细了解每个密钥存储。

Dapr handles all of the above concerns.

Dapr 处理上述所有问题。

Access to the secrets is secured through authentication and authorization. Only an application with sufficient rights can access secrets. Applications running in Kubernetes can also use its built-in secrets management mechanism.

通过身份验证和授权来保护对机密的访问。 只有具有足够权限的应用程序可以访问机密。 在 Kubernetes 中运行的应用程序也可以使用其内置的机密管理机制。

How it works

工作原理

Applications use the secrets building block in two ways:

  • Retrieve a secret directly from the application block.
  • Reference a secret indirectly from a Dapr component configuration.

应用程序通过两种方式使用机密构建块:

  • 直接从应用程序块检索机密。
  • 从 Dapr 组件配置中间接引用机密。

Retrieving secrets directly is covered first. Referencing a secret from a Dapr component configuration file is addressed in a later section.

首先介绍如何直接检索机密。 在后面的部分中对从 Dapr 组件配置文件引用机密进行了说明。

The application interacts with a Dapr sidecar when using the secrets building block. The sidecar exposes the secrets API. The API can be called with either HTTP or gRPC. Use the following URL to call the HTTP API:

使用机密构建块时,应用程序与 Dapr边车交互。 边车公开了机密 API。 可以通过 HTTP 或 gRPC 调用 该API。 使用以下 URL 调用 HTTP API:

http://localhost:/v1.0/secrets//?

The URL contains the following segments:

  •  specifies the port number upon which the Dapr sidecar is listening.
  •  specifies the name of the Dapr secret store.
  •  specifies the name of the secret to retrieve.
  •  provides additional information for the secret. This segment is optional and metadata properties differ per secret store. For more information on metadata properties, see the [secrets API reference](Secrets API reference | Dapr Docs).

URL 包含以下段:

  •  指定 Dapr 边车正在侦听的端口号。
  •  指定 Dapr 机密存储的名称。
  •  指定要检索的机密的名称。
  •  提供机密的附加信息。 此段是可选的,每个密钥存储的元数据属性各不相同。 有关元数据属性的详细信息,请参阅 [secrets API 参考](Secrets API reference | Dapr Docs)。

Note

The above URL represents the native Dapr API call available to any development platform that supports HTTP or gRPC. Popular platforms like .NET, Java, and Go have their own custom APIs.

备注

上述 URL 表示可用于支持 HTTP 或 gRPC 的任何开发平台的本机 Dapr API 调用。 .NET、Java 和Go等常用平台都有自己的自定义 Api。

The JSON response contains the key and value of the secret.

JSON 响应包含机密的键和值。

Figure 10-1 shows how Dapr handles a request for the secrets API:

图10-1 显示了 Dapr 如何处理secrets API请求:

Figure 10-1. Retrieving a secret with the Dapr secrets API.

图 10-1。 使用 Dapr secrets API 检索机密。

  1. The service calls the Dapr secrets API, along with the name of the secret store, and secret to retrieve.
  2. The Dapr sidecar retrieves the specified secret from the secret store.
  3. The Dapr sidecar returns the secret information back to the service.
  1. 服务使用使用机密存储的名称和要检索的机密调用 Dapr secrets API。
  2. Dapr 边车从机密存储中检索指定的机密。
  3. Dapr 边车将机密信息返回给服务。

Some secret stores support storing multiple key/value pairs in a single secret. For those scenarios, the response would contain multiple key/value pairs in a single JSON response as in the following example:

某些机密存储支持在单个机密中存储多个键/值对。 对于这些情况,响应会在单个 JSON 响应中包含多个键/值对,如以下示例中所示:

GET http://localhost:3500/v1.0/secrets/secret-store/interestRates?metadata.version_id=3
{
  "tier1-percentage": "2.5",
  "tier2-percentage": "3.8",
  "tier3-percentage": "5.1"
}

The Dapr secrets API also offers an operation to retrieve all the secrets the application has access to:

Dapr secrets API还提供了一个操作,用于检索应用程序有权访问的所有机密:

http://localhost:/v1.0/secrets//bulk

Use the Dapr .NET SDK

使用 Dapr .NET SDK

For .NET developers, the Dapr .NET SDK streamlines Dapr secret management. Consider the DaprClient.GetSecretAsync method. It enables you to retrieve a secret directly from any Dapr secret store with minimal effort. Here's an example of fetching a connection string secret for a SQL Server database:

对于 .NET 开发人员而言,Dapr .NET SDK 精简了 Dapr 机密管理。 考虑使用 DaprClient.GetSecretAsync 方法。 它使你能够以最小的努力直接从任何 Dapr 机密存储中检索机密。 下面是一个获取 SQL Server 数据库的连接字符串机密的示例:

var metadata = new Dictionary<string, string> { ["version_id"] = "3" };
Dictionary<string, string> secrets = await daprClient.GetSecretAsync("secret-store", "eshopsecrets", metadata);
string connectionString = secrets["customerdb"];

Arguments for the GetSecretAsync method include:

  • The name of the Dapr secret store component ('secret-store')
  • The secret to retrieve ('eshopsecrets')
  • Optional metadata key/value pairs ('version_id=3')

 GetSecretAsync 方法的参数包括:

  • Dapr 机密存储组件的名称( "secret store"  )
  • 要检索的机密 ( "eshopsecrets" )
  • 可选的元数据键/值对 ( "version_id = 3" )

The method responds with a dictionary object as a secret can contain multiple key/value pairs. In the example above, the secret named customerdb is referenced from the collection to return a connection string.

方法返回字典对象,因为机密可包含多个键/值对。 在上面的示例中,从集合引用名为customerdb 的机密以返回连接字符串。

The Dapr .NET SDK also features a .NET configuration provider. It loads specified secrets into the underlying .NET Core configuration API. The running application can then reference secrets from the IConfiguration dictionary that is registered in ASP.NET Core dependency injection.

Dapr .NET SDK 还提供 .NET 配置提供程序。 它将指定的机密加载到底层 .Net Core 配置 API。 然后,运行中的应用程序可以从 ASP.NET Core 依赖关系注入中注册的IConfiguration 字典中引用机密。

The secrets configuration provider is available from the Dapr.Extensions.Configuration NuGet package. The provider can be registered in the Program.cs of an ASP.NET Web API application:

Dapr.Extensions.Configu NuGet 包中提供了机密配置提供程序。 可在 ASP.NET Web API 应用程序的 Program.cs中注册提供程序 :

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(config =>
        {
            var daprClient = new DaprClientBuilder().Build();
            var secretDescriptors = new List
            {
                new DaprSecretDescriptor("eshopsecrets")
            };
            config.AddDaprSecretStore("secret-store", secretDescriptors, daprClient);
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup();
        });

The above example loads the eshopsecrets secrets collection into the .NET configuration system at startup. Registering the provider requires an instance of DaprClient to invoke the secrets API on the Dapr sidecar. The other arguments include the name of the secret store and a DaprSecretDescriptor object with the name of the secret.

上述示例在启动时将 eshopsecrets 机密集合加载到 .net 配置系统中。 注册提供程序需要 DaprClient 的实例,以在 Dapr 边车上调用secrets API 。 其他参数包括机密存储的名称,以及包含机密名称的 DaprSecretDescriptor 对象。

Once loaded, you can retrieve secrets directly from application code:

加载后,可以直接从应用程序代码中检索机密:

public void GetCustomer(IConfiguration config)
{
    var connectionString = config["eshopsecrets"]["customerdb"];
}

Secret store components

机密存储组件

The secrets building block supports several secret store components. At the time of writing, the following secret stores are available:

  • Environment Variables
  • Local file
  • Kubernetes secrets
  • AWS Secrets Manager
  • Azure Key Vault
  • GCP Secret Manager
  • HashiCorp Vault

机密构建块支持多个机密存储组件。 撰写本文时,可以使用以下机密存储:

  • 环境变量
  • 本地文件
  • Kubernetes secrets
  • AWS 机密管理器
  • Azure Key Vault
  • GCP 机密管理器
  • HashiCorp Vault

Important

The environment variables and local file components are designed for development workloads only.

重要

环境变量和本地文件组件被设计为仅在开发环境中使用。

The following sections show how to configure a secret store.

以下部分说明如何配置机密存储。

Configuration

配置

You configure a secret store using a Dapr component configuration file. The typical structure of the file is shown below:

使用 Dapr 组件配置文件配置机密存储。 文件的典型结构如下所示:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: [component name]
  namespace: [namespace]
spec:
  type: secretstores.[secret store type]
  version: [secret store version]
  metadata:
  - name: [property name]
    value: [property value]

All Dapr component configuration files require a name along with an optional namespace value. Additionally, the type field in the spec section specifies the type of secret store component. The properties in the metadata section differ per secret store.

所有 Dapr 组件配置文件都需要指定 name 值和可选的 namespace 值。 另外,  spec 节中的type 字段指定了机密存储组件的类型。  metadata 节中的属性因机密存储的不同而不同。

Indirectly consume Dapr secrets

间接使用 Dapr 机密

As mentioned earlier in this chapter, applications can also consume secrets by referencing them in component configuration files. Consider a state management component that uses Redis cache for storing state:

如本章前面所述,应用程序还可以通过在组件配置文件中引用机密来使用机密。 请思考使用 Redis 缓存来存储状态的 状态管理组件 :

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-basket-statestore
  namespace: eshop
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: e$h0p0nD@pr

The above configuration file contains a clear-text password for connecting to the Redis server. Hardcoded passwords are always a bad idea. Pushing this configuration file to a public repository would expose the password. Storing the password in a secret store would dramatically improve this scenario.

上述配置文件包含用于连接到 Redis 服务的 明文 密码。 硬编码 密码始终是个坏主意。 将此配置文件推送到公共存储库将泄露密码。 将密码存储在机密存储中会显著改善这种情况。

The following examples demonstrate this using several different secret stores.

下面的示例使用几个不同的机密存储对此进行了演示。

Local file

本地文件

The local file component is designed for development scenarios. It stores secrets on the local filesystem inside a JSON file. Here's an example named eshop-secrets.json. It contains a single secret - a password for Redis:

本地文件组件被设计用于开发场景。 它将机密存储在本地文件系统上的 JSON 文件中。 下面是一个名为 eshop-secrets.json 的示例。 它包含单个机密——Redis 的密码:

{
  "eShopRedisPassword": "e$h0p0nD@pr"
}

You place this file in a components folder that you specify when running the Dapr application.

将此文件放置在运行 Dapr 应用程序时指定的 components 文件夹中。

The following secret store configuration file consumes the JSON file as a secret store. It's also placed in the components folder:

以下机密存储配置文件使用 JSON 文件作为机密存储。 它放置在 components 文件夹中:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-local-secret-store
  namespace: eshop
spec:
  type: secretstores.local.file
  version: v1
  metadata:
  - name: secretsFile
    value: ./components/eshop-secrets.json
  - name: nestedSeparator
    value: ":"

The component type is secretstore.local.file. The secretsFile metadata element specifies the path to the secrets file.

组件类型为 secretstore.local.file 。 Metadata节中的secretsFile元素指定机密文件的路径。

Important

The path to a secrets file can be a absolute or relative path. The relative path is based on the folder in which the application starts. In the example, the components folder is a sub-folder of the directory that contains the .NET application.

重要

机密文件的路径可以是绝对路径或相对路径。 相对路径基于应用程序的启动文件夹。 在此示例中, components 文件夹是包含 .net 应用程序的目录的子文件夹。

From the application folder, start the Dapr application specifying the components path as a command-line argument:

从应用程序文件夹中,启动 Dapr 应用程序,并将 components 的路径指定为命令行参数:

dapr run --app-id basket-api --components-path ./components dotnet run

Note

This above example applies to running Dapr in self-hosted mode. For Kubernetes hosting, consider using volume mounts.

备注

上面的示例适用于在自承载模式下运行 Dapr。 对于 Kubernetes 托管,请考虑使用卷装载。

The nestedSeparator in a Dapr configuration file specifies a character to flatten a JSON hierarchy. Consider the following snippet:

Dapr 配置文件中的nestedSeparator指定一个字符来展开 JSON 层次结构。 请考虑以下代码片段:

{
    "redisPassword": "some password",
    "connectionStrings": {
        "customerdb": "some connection string",
        "productdb": "some connection string"
    }
}

Using a colon as a separator, you can retrieve the customerdb connection-string using the key connectionStrings:customerdb.

使用冒号作为分隔符,可以使用 connectionStrings:customerdb 键来检索 customerdb 连接字符串。

Note

The colon : is the default separator value.

备注

冒号 : 为默认分隔符值。

In the next example, a state management configuration file references the local secret store component to obtain the password for connecting to the Redis server:

在下一个示例中,状态管理配置文件引用本地机密存储组件以获取用于连接到 Redis 服务的密码:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-basket-statestore
  namespace: eshop
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    secretKeyRef:
      name: eShopRedisPassword
      key: eShopRedisPassword
auth:
  secretStore: eshop-local-secret-store

The secretKeyRef element references the secret containing the password. It replaces the earlier clear-text value. The secret name and the key name, eShopRedisPassword, reference the secret. The name of the secret management component eshop-local-secret-store is found in the auth metadata element.

secretKeyRef元素引用包含密码的机密。 它将替换前面的 明文 值。 机密名称和键名 eShopRedisPassword 引用机密。 可在 auth 结中的secretStore元素中找到机密管理组件的名称 eshop-local-secret-store 。

You might wonder why eShopRedisPassword is identical for both the name and key in the secret reference. In the local file secret store, secrets aren't identified with a separate name. The scenario will be different in the next example using Kubernetes secrets.

您可能想知道为什么secretKeyRef中名称和键是相同的,都是 eShopRedisPassword 。 在本地文件机密存储中,不会使用单独的名称标识机密。 在下一个示例中,使用 Kubernetes 机密的情况将会不同。

Kubernetes secret

Kubernetes 机密

This second example focuses on a Dapr application running in Kubernetes. It uses the standard secrets mechanism that Kubernetes offers. Use the Kubernetes CLI (kubectl) to create a secret named eshop-redis-secret that contains the password:

此第二个示例重点介绍在 Kubernetes 中运行的 Dapr 应用程序。 它使用 Kubernetes 提供的标准机密机制。 使用 Kubernetes CLI (kubectl) 创建一个包含密码的名为 eshop-redis-secret 的机密:

kubectl create secret generic eshopsecrets --from-literal=redisPassword=e$h0p0nD@pr -n eshop

Once created, you can reference the secret in the component configuration file for state management:

创建后,可以在 "状态管理" 的组件配置文件中引用该机密:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-basket-statestore
  namespace: eshop
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis:6379
  - name: redisPassword
    secretKeyRef:
      name: eshopsecrets
      key: redisPassword
auth:
  secretStore: kubernetes

The secretKeyRef element specifies the name of the Kubernetes secret and the secret's key, eshopsecrets, and redisPassword respectively. The auth metadata section instructs Dapr to use the Kubernetes secrets management component.

secretKeyRef元素分别指定 Kubernetes 机密的名称(eshopsecrets )和机密的键( redisPassword )。 auth节指示 Dapr 使用 Kubernetes 机密管理组件。

Note

Auth is the default value when using Kubernetes secrets and can be omitted.

备注

Auth是使用 Kubernetes 机密时的默认值,可以省略。

In a production setting, secrets are typically created as part of an automated CI/CD pipeline. Doing so ensures only people with sufficient permissions can access and change the secrets. Developers create configuration files without knowing the actual value of the secrets.

在生产设置中,通常会将机密作为自动 CI/CD 管道的一部分创建。 这样做可确保只有具有足够权限的人员才能访问和更改机密。 开发人员无需知道机密的实际值即可创建配置文件。

Azure Key Vault

The next example is geared toward a real-world production scenario. It uses Azure Key Vault as the secret store. Azure Key Vault is a managed Azure service that enables secrets to be stored securely in the cloud.

下一个示例适用于实际的生产场景。 它使用 Azure Key Vault 作为机密存储。 Azure Key Vault 是一种托管的 Azure 服务,可让机密安全地存储在云中。

For this example to work, the following prerequisites must be satisfied:

  • You've secured administrative access to an Azure subscription.
  • You've provisioned an Azure Key Vault named eshopkv that holds a secret named redisPassword that contains the password for connecting to the Redis server.
  • You've created service principal in Azure Active Directory.
  • You've installed an X509 certificate for this service principal (containing both the public and private key) on the local filesystem.

要使此示例正常工作,必须满足以下先决条件:

  • 已获得对 Azure 订阅的管理员访问权限。
  • 你预配了一个名为 eshopkv 的 Azure Key Vault,它包含一个名为 redisPassword 的机密,其中包含用于连接到 Redis 服务的密码。
  • 已在 Azure Active Directory 中创建服务主体 。
  • 在本地文件系统上已为此服务主体安装了 X509 证书(包含公钥和私钥) 。

Note

A service principal is an identity that can be used by an application to authenticate an Azure service. The service principal uses a X509 certificate. The application uses this certificate as a credential to authenticate itself.

备注

服务主体是应用程序可用于对 Azure 服务进行身份验证的标识。 服务主体使用 X509 证书。 应用程序使用此证书作为凭据对自己进行身份验证。

The Dapr Azure Key Vault secret store documentation provides step-by-step instructions to create and configure a Key Vault environment.

Dapr Azure Key Vault 机密存储文档提供了创建和配置 Key Vault 环境的分步说明。

Use Key Vault when running in self-hosted mode

在自承载模式下运行时使用 Key Vault

Consuming Azure Key Vault in Dapr self-hosted mode requires the following configuration file:

在 Dapr 自承载模式下使用 Azure Key Vault 需要以下配置文件:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-azurekv-secret-store
  namespace: eshop
spec:
  type: secretstores.azure.keyvault
  version: v1
  metadata:
  - name: vaultName
    value: eshopkv
  - name: spnTenantId
    value: "619926af-a7c3-4e95-93ed-4ecc4e3e652b"
  - name: spnClientId
    value: "6cf48032-6c38-43be-9d6f-2a43ce736b09"
  - name: spnCertificateFile
    value : "azurekv-spn-cert.pfx"

The secret store type is secretstores.azure.keyvault. The metadata element to configure access to Key Vault requires the following properties:

  • The vaultName contains the name of the Azure Key Vault.
  • The spnTenantId contains the tenant ID of the service principal used to authenticate against the Key Vault.
  • The spnClientId contains the app ID of the service principal used to authenticate against the Key Vault.
  • The spnCertificateFile contains the path to the certificate file for the service principal to authenticate against the Key Vault.

机密存储类型为 secretstores.azure.keyvault 。用于配置对 Key Vault 的访问权限的 metadata元素需要以下属性:

  • vaultName包含 Azure Key Vault 的名称。
  • spnTenantId包含用于对 Key Vault 进行身份验证的服务主体的 租户 ID 。
  • spnClientId包含用于对 Key Vault 进行身份验证的服务主体的 应用程序 ID 。
  • spnCertificateFile包含服务主体的证书文件路径,以对 Key Vault 进行身份验证。

Tip

You can copy the service principal information from the Azure portal or Azure CLI .

提示

可以从 Azure 门户或 Azure CLI 复制服务主体信息。

Now the application can retrieve the Redis password from the Azure Key Vault.

现在,应用程序可以从 Azure Key Vault 中检索 Redis 密码。

Use Key Vault when running on Kubernetes

在 Kubernetes 上运行时使用 Key Vault

Consuming Azure Key Vault with Dapr and Kubernetes also requires a service principal to authenticate against the Azure Key Vault.

和Dapr 和 Kubernetes 一起使用的 Azure Key Vault 也需要服务主体针对 Azure Key Vault 进行身份验证。

First, create a Kubernetes secret that contains a certificate file using the kubectl CLI tool:

首先,使用 kubectl CLI 工具创建包含证书文件的 Kubernetes 机密 :

kubectl create secret generic [k8s_spn_secret_name] --from-file=[pfx_certificate_file_local_path] -n eshop

The command requires two command-line arguments:

  • [k8s_spn_secret_name] is the secret name in Kubernetes secret store.
  • [pfx_certificate_file_local_path] is the path of X509 certificate file.

此命令需要两个命令行参数:

  • [k8s_spn_secret_name] Kubernetes 机密存储中的机密名称。
  • [pfx_certificate_file_local_path] 是 X509 证书文件的路径。

Once created, you can reference the Kubernetes secret in the secret store component configuration file:

创建后,可以在机密存储组件配置文件中引用 Kubernetes 机密:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-azurekv-secret-store
  namespace: eshop
spec:
  type: secretstores.azure.keyvault
  version: v1
  metadata:
  - name: vaultName
    value: [your_keyvault_name]
  - name: spnTenantId
    value: "619926af-a7c3-4e95-93ed-4ecc4e3e652b"
  - name: spnClientId
    value: "6cf48032-6c38-43be-9d6f-2a43ce736b09"
  - name: spnCertificate
    secretKeyRef:
      name: [k8s_spn_secret_name]
      key: [pfx_certificate_file_local_name]
auth:
    secretStore: kubernetes

At this point, an application running in Kubernetes can retrieve the Redis password from the Azure Key Vault.

此时,在 Kubernetes 中运行的应用程序可以从 Azure Key Vault 检索 Redis 密码。

Important

It's critical to keep the X509 certificate file for the service principal in a safe place. It's best to place it in a well-known folder outside the source-code repository. The configuration file can then reference the certificate file from this well-known folder. On a local development machine, you're responsible for copying the certificate to the folder. For automated deployments, the pipeline will copy the certificate to the machine where the application is deployed. It's a best practice to use a different service principal per environment. Doing so prevents the service principal from a DEVELOPMENT environment to access secrets in a PRODUCTION environment.

重要

将服务主体的 X509 证书文件保存在安全的位置至关重要。 最好将它放在源代码存储库外的已知文件夹中。 然后,配置文件可以引用此文件夹中的证书文件。 在本地开发计算机上,您负责将证书复制到文件夹。 对于自动部署,管道会将证书复制到部署该应用程序的计算机。 最佳做法是在各个环境中使用不同的服务主体。 这样做可以防止开发环境中的服务主体访问生产环境中的机密。

When running in Azure Kubernetes Service (AKS), it's preferable to use an Azure Managed Identity for authenticating against Azure Key Vault. Managed identities are outside of the scope of this book, but explained in the Azure Key Vault with managed identities documentation.

在 Azure Kubernetes Service (AKS) 中运行时,最好使用 Azure Managed Identity 对 Azure Key Vault 进行身份验证。 Managed identities超出了本书的范围,但在 Azure Key Vault with managed中进行了介绍。

Scope secrets

限定范围的机密

Secret scopes allow you to control which secrets your application can access. You configure scopes in a Dapr sidecar configuration file. The Dapr configuration documentation provides instructions for scoping secrets.

机密作用域允许您控制您的应用程序可以访问哪些机密。 在 Dapr 边车配置文件中配置作用域。 Dapr 配置文档提供了有关限定范围的机密的介绍。

Here's an example of a Dapr sidecar configuration file that contains secret scopes:

下面是包含机密作用域的 Dapr 边车配置文件的示例:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: dapr-config
  namespace: eshop
spec:
  tracing:
    samplingRate: "1"
  secrets:
    scopes:
      - storeName: eshop-azurekv-secret-store
        defaultAccess: allow
        deniedSecrets: ["redisPassword", "apiKey"]

You specify scopes per secret store. In the above example, the secret store is named eshop-azurekv-secret-store. You configure access to secrets using the following properties:
为每个机密存储指定作用域。 在上面的示例中,机密存储名为 eshop-azurekv-secret-store 。 使用以下属性配置对机密的访问:

SCOPE SECRETS
PropertyValueDescription
defaultAccess allow or deny Allows or denies access to all secrets in the specified secret store. This property is optional with a default value of allow.
allowedSecrets List of secret keys Secrets specified in the array will be accessible. This property is optional.
deniedSecrets List of secret keys Secrets specified in the array will NOT be accessible. This property is optional.
范围机密
属性说明
defaultAccess allow 或 deny 允许或拒绝对指定机密存储中 所有 机密的访问。 此属性是可选的,默认值为 allow 。
allowedSecrets 机密键列表 数组中指定的机密将可供访问。 此属性是可选的。
deniedSecrets 机密键列表 数组中指定的机密将不可访问。 此属性是可选的。

The allowedSecrets and deniedSecrets properties take precedence over the defaultAccess property. Imagine specifying defaultAccess: allowed and an allowedSecrets list. In this case, only the secrets in the allowedSecrets list would be accessible by the application.

allowedSecrets和 deniedSecrets 属性优先于 defaultAccess 属性。 假设指定 defaultAccess: allowed 和 allowedSecrets 列表。 在这种情况下, 应用程序只能访问allowedSecrets 列表中的机密。

Reference application: eShopOnDapr

参考应用程序: eShopOnDapr

The eShopOnDapr reference application uses the secrets building block for two secrets:

  • The password for connecting to the Redis cache.
  • The API-key for using the Twilio Sendgrid API. The application uses Twillio to send emails using a Dapr output binding (as described in the bindings building block chapter).

EShopOnDapr 参考应用程序为两个机密使用机密构建块:

  • 用于连接到 Redis 缓存的密码。
  • 用于使用 Twilio Sendgrid API 的 API 密钥。 应用程序通过 Dapr 输出绑定使用 Twillio 发送电子邮件,如 绑定构建块章节中所述。

When running the application using Docker Compose, the local file secret store is used. The component configuration file eshop-secretstore.yaml is found in the dapr/components folder of the eShopOnDapr repository:

使用 Docker Compose 运行应用程序时,将使用 本地文件机密存储。 组件配置文件 eshop-secretstore.yaml 位于eShopOnDapr 存储库的dapr/components 文件夹中:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: eshop-secretstore
  namespace: eshop
spec:
  type: secretstores.local.file
  version: v1
  metadata:
  - name: secretsFile
    value: ./components/eshop-secretstore.json

The configuration file references the local store file eshop-secretstore.json located in the same folder:

配置文件引用位于同一文件夹中的本地存储文件 eshop-secretstore.json :

{
    "redisPassword": "**********",
    "sendgridAPIKey": "**********"
}

The components folder is specified in the command-line and mounted as a local folder inside the Dapr sidecar container. Here's a snippet from the docker-compose.override.yml file in the repository root that specifies the volume mount:

在命令行中指定 components 文件夹,并将其作为本地文件夹装载到 Dapr 边车容器中。 下面是存储库根目录中的 docker-compose.override.yml 文件中用于指定卷装载的代码段:

ordering-backgroundtasks-dapr:
    command: ["./daprd",
      "-app-id", "ordering-backgroundtasks",
      "-app-port", "80",
      "-dapr-grpc-port", "50004",
      "-components-path", "/components",
      "-config", "/configuration/eshop-config.yaml"
      ]
    volumes:
      - "./dapr/components/:/components"
      - "./dapr/configuration/:/configuration"

Note

The Docker Compose override file contains environmental specific configuration values.

备注

Docker Compose 重载文件包含特定于环境的配置值。

The /components volume mount and --components-path command-line argument are passed into the daprd startup command.

/components卷装载和 --components-path 命令行参数会传递到 daprd 启动命令。

Once configured, other component configuration files can also reference the secrets. Here's an example of the Publish/Subscribe component configuration consuming secrets:

配置后,其他组件配置文件也可以引用该机密。 下面是发布/订阅组件配置使用机密的示例:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub
  namespace: eshop
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis:6379
  - name: redisPassword
    secretKeyRef:
      name: redisPassword
auth:
  secretStore: eshop-secretstore

In the preceding example, the local Redis store is used to reference secrets.

在前面的示例中,本地 Redis 存储用于引用机密。

Summary

总结

The Dapr secrets building block provides capabilities for storing and retrieving sensitive configuration settings like passwords and connection-strings. It keeps secrets private and prevents them from being accidentally disclosed.

Dapr 机密构建块提供了存储和检索敏感配置设置(例如密码和连接字符串)的功能。 它将机密保密,防止无意中泄露机密。

The building block supports several different secret stores and hides their complexity with the Dapr secrets API.

构建块支持多个不同的机密存储,并通过 Dapr 机密 API 隐藏其复杂性。

The Dapr .NET SDK provides a DaprClient object to retrieve secrets. It also includes a .NET configuration provider that adds secrets to the .NET Core configuration system. Once loaded, you can consume these secrets in your .NET code.

Dapr .NET SDK 提供了一个 DaprClient 用于检索机密的对象。 它还包括将机密添加到 .NET Core 配置系统的 .NET 配置提供程序。 加载后,可以在 .NET 代码中使用这些机密。

You can use secret scopes to control access to specific secrets.

可以使用机密作用域来控制对特定机密的访问。