This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

保护 Dapr 部署

关于如何保护您的 Dapr 应用程序的最佳实践和说明

在使用 Dapr 部署应用程序时,确保安全性至关重要。Dapr 提供了一系列功能和最佳实践,帮助开发者保护他们的应用程序。这些功能包括身份验证、授权、数据加密以及安全的通信协议。

首先,身份验证是确保只有授权用户和服务可以访问您的 Dapr 应用程序的关键步骤。Dapr 支持多种身份验证机制,包括 OAuth 和 API 密钥。通过配置这些机制,您可以有效地控制对应用程序的访问。

其次,授权是在用户或服务通过身份验证后,确定其可以执行哪些操作。Dapr 提供了详细的权限控制,允许您定义不同角色和权限,以确保用户只能访问他们被授权的资源。

数据加密是保护敏感信息的另一重要措施。Dapr 支持在传输和存储过程中对数据进行加密。即使数据被截获,未授权用户也无法读取。

最后,Dapr 使用安全的通信协议来保护数据在网络中的传输。通过采用 HTTPS 和其他加密协议,Dapr 确保数据在传输过程中不会被窃听或篡改。

通过遵循这些最佳实践,您可以显著提高 Dapr 应用程序的安全性,保护您的数据和服务免受潜在威胁。

1 - 设置和配置 mTLS 证书

使用自签名或用户提供的 x.509 证书加密应用程序之间的通信

Dapr 支持通过 Dapr 控制平面的 Sentry 服务对 Dapr 实例之间的通信进行传输加密。Sentry 服务是一个中央证书颁发机构 (CA)。

Dapr 允许操作员和开发人员使用自己的证书,或者让 Dapr 自动创建并保存自签名的根证书和颁发者证书。

有关 mTLS 的详细信息,请阅读安全概念部分

如果没有提供自定义证书,Dapr 会自动创建并保存有效期为一年的自签名证书。 在 Kubernetes 中,证书会保存到 Dapr 系统 pod 所在命名空间的 secret 中,仅对它们可访问。 在自托管模式中,证书会保存到磁盘。

控制平面 Sentry 服务配置

mTLS 设置位于 Dapr 控制平面配置文件中。例如,当您将 Dapr 控制平面部署到 Kubernetes 时,此配置文件会自动创建,然后您可以编辑它。以下文件显示了在 daprsystem 命名空间中部署的配置资源中可用的 mTLS 设置:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: default
spec:
  mtls:
    enabled: true
    workloadCertTTL: "24h"
    allowedClockSkew: "15m"

此文件显示了默认的 daprsystem 配置设置。下面的示例向您展示如何在 Kubernetes 和自托管模式下更改和应用此配置到控制平面 Sentry 服务。

Kubernetes

使用配置资源设置 mTLS

在 Kubernetes 中,Dapr 创建了一个启用 mTLS 的默认控制平面配置资源。 Sentry 服务,即证书颁发机构系统 pod,可以通过 Helm 和 Dapr CLI 使用 dapr init --kubernetes 安装。

您可以使用以下命令查看控制平面配置资源:

kubectl get configurations/daprsystem --namespace <DAPR_NAMESPACE> -o yaml

要对控制平面配置资源进行更改,请运行以下命令进行编辑:

kubectl edit configurations/daprsystem --namespace <DAPR_NAMESPACE>

保存更改后,对控制平面执行滚动更新:

kubectl rollout restart deploy/dapr-sentry -n <DAPR_NAMESPACE>
kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>

注意:控制平面 sidecar 注入器服务不需要重新部署

使用 Helm 禁用 mTLS

控制平面将继续使用 mTLS

kubectl create ns dapr-system

helm install \
  --set global.mtls.enabled=false \
  --namespace dapr-system \
  dapr \
  dapr/dapr

使用 CLI 禁用 mTLS

控制平面将继续使用 mTLS

dapr init --kubernetes --enable-mtls=false

查看日志

要查看 Sentry 服务日志,请运行以下命令:

kubectl logs --selector=app=dapr-sentry --namespace <DAPR_NAMESPACE>

使用您自己的证书

使用 Helm,您可以提供 PEM 编码的根证书、颁发者证书和私钥,这些将被填充到 Sentry 服务使用的 Kubernetes secret 中。

注意:此示例使用 OpenSSL 命令行工具,这是一个广泛分发的软件包,可以通过包管理器轻松安装在 Linux 上。在 Windows 上可以使用 chocolatey 安装 OpenSSL。在 MacOS 上可以使用 brew 安装 brew install openssl

创建用于生成证书的配置文件,这是生成带有 SAN(主题备用名称)扩展字段的 v3 证书所必需的。首先将以下内容保存到名为 root.conf 的文件中:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = Daprville
O = dapr.io/sentry
OU = dapr.io/sentry
CN = cluster.local
[v3_req]
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = cluster.local

issuer.conf 重复此操作,将相同的内容粘贴到文件中,但在 basicConstraints 行的末尾添加 pathlen:0,如下所示:

basicConstraints = critical, CA:true, pathlen:0

运行以下命令生成根证书和密钥

# 跳过以下行以重用现有的根密钥,这是轮换过期证书所需的
openssl ecparam -genkey -name prime256v1 | openssl ec -out root.key
openssl req -new -nodes -sha256 -key root.key -out root.csr -config root.conf -extensions v3_req
openssl x509 -req -sha256 -days 365 -in root.csr -signkey root.key -outform PEM -out root.pem -extfile root.conf -extensions v3_req

接下来运行以下命令生成颁发者证书和密钥:

# 跳过以下行以重用现有的颁发者密钥,这是轮换过期证书所需的
openssl ecparam -genkey -name prime256v1 | openssl ec -out issuer.key
openssl req -new -sha256 -key issuer.key -out issuer.csr -config issuer.conf -extensions v3_req
openssl x509 -req -in issuer.csr -CA root.pem -CAkey root.key -CAcreateserial -outform PEM -out issuer.pem -days 365 -sha256 -extfile issuer.conf -extensions v3_req

安装 Helm 并通过配置将根证书、颁发者证书和颁发者密钥传递给 Sentry:

kubectl create ns dapr-system

helm install \
  --set-file dapr_sentry.tls.issuer.certPEM=issuer.pem \
  --set-file dapr_sentry.tls.issuer.keyPEM=issuer.key \
  --set-file dapr_sentry.tls.root.certPEM=root.pem \
  --namespace dapr-system \
  dapr \
  dapr/dapr

使用 CLI 升级根和颁发者证书(推荐)

以下 CLI 命令可用于更新 Kubernetes 集群中的根和颁发者证书。

生成全新的证书

  1. 下面的命令生成全新的根和颁发者证书,由新生成的私有根密钥签名。

注意:必须重启 Dapr sentry 服务 以及其余的控制平面服务,以便它们能够读取新证书。这可以通过向命令提供 --restart 标志来完成。

dapr mtls renew-certificate -k --valid-until <days> --restart
  1. 下面的命令生成全新的根和颁发者证书,由提供的私有根密钥签名。

注意:如果您现有的已部署证书是由此相同的私有根密钥签名的,则 Dapr Sentry 服务 可以在不重启的情况下读取这些新证书。

dapr mtls renew-certificate -k --private-key <private_key_file_path> --valid-until <days>

使用提供的自定义证书更新证书

要更新 Kubernetes 集群中提供的证书,可以使用以下 CLI 命令。

注意 - 它不支持 valid-until 标志来指定新证书的有效期。

dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.crt> --restart

推荐的方法是对您的部署执行滚动重启:

kubectl rollout restart deploy/myapp

使用 Kubectl 更新根或颁发者证书

如果根或颁发者证书即将过期,您可以更新它们并重启所需的系统服务。

Dapr 生成的自签名证书

  1. 清除现有的 Dapr 信任包 secret,将以下 YAML 保存到文件(例如 clear-trust-bundle.yaml)并应用此 secret。
apiVersion: v1
kind: Secret
metadata:
  name: dapr-trust-bundle
  labels:
    app: dapr-sentry
data:
kubectl apply -f `clear-trust-bundle.yaml` -n <DAPR_NAMESPACE>
  1. 重启 Dapr Sentry 服务。这将生成一个新的证书包并更新 dapr-trust-bundle Kubernetes secret。
kubectl rollout restart -n <DAPR_NAMESPACE> deployment/dapr-sentry
  1. 一旦 Sentry 服务已重启,重启其余的 Dapr 控制平面以获取新的 Dapr 信任包。
kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>
  1. 重启您的 Dapr 应用程序以获取最新的信任包。
kubectl rollout restart deployment/mydaprservice1 kubectl deployment/myotherdaprservice2

自定义证书(自带)

首先,使用上面使用您自己的证书中的步骤颁发新证书。

现在您有了新证书,使用 Helm 升级证书:

helm upgrade \
  --set-file dapr_sentry.tls.issuer.certPEM=issuer.pem \
  --set-file dapr_sentry.tls.issuer.keyPEM=issuer.key \
  --set-file dapr_sentry.tls.root.certPEM=root.pem \
  --namespace dapr-system \
  dapr \
  dapr/dapr

或者,您可以更新保存它们的 Kubernetes secret:

kubectl edit secret dapr-trust-bundle -n <DAPR_NAMESPACE>

用新证书的相应值替换 Kubernetes secret 中的 ca.crtissuer.crtissuer.key 键。 注意:这些值必须是 base64 编码的

如果您使用相同的私有密钥签署了新的证书根,Dapr Sentry 服务将自动获取新证书。您可以使用 kubectl rollout restart 重启您的应用程序部署而不会停机。无需一次性重启所有部署,只要在原始证书过期之前重启即可。

如果您使用不同的私有密钥签署了新的证书根,您必须重启 Dapr Sentry 服务,然后是其余的 Dapr 控制平面服务。

kubectl rollout restart deploy/dapr-sentry -n <DAPR_NAMESPACE>

一旦 Sentry 完全重启,运行:

kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>

接下来,您必须重启所有 Dapr 启用的 pod。 推荐的方法是对您的部署执行滚动重启:

kubectl rollout restart deploy/myapp

由于证书不匹配,您将经历潜在的停机,直到所有部署成功重启(从而加载新的 Dapr 证书)。

Kubernetes 视频演示

观看此视频以了解如何在 Kubernetes 上更新 mTLS 证书

设置 Dapr 控制平面 mTLS 证书过期的监控

从 mTLS 根证书过期前 30 天开始,Dapr sentry 服务将每小时发出警告级别日志,指示根证书即将过期。

作为在生产中运行 Dapr 的操作最佳实践,我们建议为这些特定的 sentry 服务日志配置监控,以便您了解即将到来的证书过期。

"Dapr root certificate expiration warning: certificate expires in 2 days and 15 hours"

一旦证书过期,您将看到以下消息:

"Dapr root certificate expiration warning: certificate has expired."

在 Kubernetes 中,您可以这样查看 sentry 服务日志:

kubectl logs deployment/dapr-sentry -n dapr-system

日志输出将如下所示:"

{"instance":"dapr-sentry-68cbf79bb9-gdqdv","level":"warning","msg":"Dapr root certificate expiration warning: certificate expires in 2 days and 15 hours","scope":"dapr.sentry","time":"2022-04-01T23:43:35.931825236Z","type":"log","ver":"1.6.0"}

作为提醒您即将到来的证书过期的额外工具,从 1.7.0 版本开始,CLI 现在在您与基于 Kubernetes 的部署交互时打印证书过期状态。

示例:

dapr status -k

  NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION   AGE  CREATED
  dapr-sentry            dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-dashboard         dapr-system  True     Running  1         0.9.0     17d  2022-03-15 09:29.45
  dapr-sidecar-injector  dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-operator          dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-placement-server  dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
⚠  Dapr root certificate of your Kubernetes cluster expires in 2 days. Expiry date: Mon, 04 Apr 2022 15:01:03 UTC.
 请参阅 docs.dapr.io 以获取证书更新说明,以避免服务中断。

自托管

运行控制平面 Sentry 服务

为了运行 Sentry 服务,您可以从这里下载源代码或发布的二进制文件。

在从源代码构建时,请参考指南了解如何构建 Dapr。

其次,为 Sentry 服务创建一个目录以创建自签名的根证书:

mkdir -p $HOME/.dapr/certs

使用以下命令在本地运行 Sentry 服务:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local

如果成功,Sentry 服务将运行并在给定目录中创建根证书。 此命令使用默认配置值,因为没有给定自定义配置文件。请参阅下文了解如何使用自定义配置启动 Sentry 服务。

使用配置资源设置 mTLS

Dapr 实例配置

在自托管模式下运行 Dapr 时,默认情况下禁用 mTLS。您可以通过创建以下配置文件来启用它:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: default
spec:
  mtls:
    enabled: true

除了 Dapr 配置,您还需要为每个 Dapr sidecar 实例提供 TLS 证书。您可以在运行 Dapr 实例之前设置以下环境变量来实现:

export DAPR_TRUST_ANCHORS=`cat $HOME/.dapr/certs/ca.crt`
export DAPR_CERT_CHAIN=`cat $HOME/.dapr/certs/issuer.crt`
export DAPR_CERT_KEY=`cat $HOME/.dapr/certs/issuer.key`
export NAMESPACE=default
$env:DAPR_TRUST_ANCHORS=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\ca.crt)
$env:DAPR_CERT_CHAIN=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.crt)
$env:DAPR_CERT_KEY=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.key)
$env:NAMESPACE="default"

如果使用 Dapr CLI,请将 Dapr 指向上面的配置文件以启用 mTLS 运行 Dapr 实例:

dapr run --app-id myapp --config ./config.yaml node myapp.js

如果直接使用 daprd,请使用以下标志启用 mTLS:

daprd --app-id myapp --enable-mtls --sentry-address localhost:50001 --config=./config.yaml

Sentry 服务配置

以下是一个 Sentry 配置示例,将工作负载证书 TTL 更改为 25 秒:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: default
spec:
  mtls:
    enabled: true
    workloadCertTTL: "25s"

为了使用自定义配置启动 Sentry 服务,请使用以下标志:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local --config=./config.yaml

使用您自己的证书

为了提供您自己的凭据,请创建 ECDSA PEM 编码的根和颁发者证书并将它们放置在文件系统上。 使用 --issuer-credentials 标志告诉 Sentry 服务从哪里加载证书。

下一个示例创建根和颁发者证书并将它们加载到 Sentry 服务中。

注意:此示例使用 step 工具创建证书。您可以从这里安装 step 工具。Windows 二进制文件可从这里获得

创建根证书:

step certificate create cluster.local ca.crt ca.key --profile root-ca --no-password --insecure

创建颁发者证书:

step certificate create cluster.local issuer.crt issuer.key --ca ca.crt --ca-key ca.key --profile intermediate-ca --not-after 8760h --no-password --insecure

这将创建根和颁发者证书和密钥。 将 ca.crtissuer.crtissuer.key 放在所需路径中(以下示例中为 $HOME/.dapr/certs),并启动 Sentry:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local

更新根或颁发者证书

如果根或颁发者证书即将过期,您可以更新它们并重启所需的系统服务。

要让 Dapr 生成新证书,请删除现有的 $HOME/.dapr/certs 证书并重启 sentry 服务以生成新证书。

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local --config=./config.yaml

要替换为您自己的证书,请首先使用上面使用您自己的证书中的步骤生成新证书。

ca.crtissuer.crtissuer.key 复制到每个配置的系统服务的文件系统路径,并重启进程或容器。 默认情况下,系统服务将在 /var/run/dapr/credentials 中查找凭据。上面的示例使用 $HOME/.dapr/certs 作为自定义位置。

注意:如果您使用不同的私有密钥签署了证书根,请重启 Dapr 实例。

社区通话视频关于证书轮换

观看此视频以了解如何在证书即将过期时执行证书轮换。

Sentry 令牌验证器

令牌通常用于身份验证和授权目的。 令牌验证器是负责验证这些令牌的有效性和真实性的组件。 例如,在 Kubernetes 环境中,一种常见的令牌验证方法是通过 Kubernetes 绑定服务帐户机制。 此验证器检查绑定服务帐户令牌以确保其合法性。

Sentry 服务可以配置为:

  • 启用除 Kubernetes 绑定服务帐户验证器之外的额外令牌验证器
  • 替换自托管模式下默认启用的 insecure 验证器

Sentry 令牌验证器用于将额外的非 Kubernetes 客户端加入到以 Kubernetes 模式运行的 Dapr 集群中,或替换自托管模式下的不安全“允许所有”验证器以启用适当的身份验证。 除非您使用的是特殊的部署场景,否则不需要配置令牌验证器。

当前唯一支持的令牌验证器是 jwks 验证器。

JWKS

jwks 验证器使 Sentry 服务能够使用 JWKS 端点验证 JWT 令牌。 令牌的内容_必须_包含与 Dapr 客户端的 SPIFFE 身份匹配的 sub 声明,格式为 spiffe://<trust-domain>/ns/<namespace>/<app-id>。 令牌的受众必须是 Sentry 身份的 SPIFFE ID,例如 spiffe://cluster.local/ns/dapr-system/dapr-sentry。 其他基本的 JWT 规则,如签名、过期等也适用。

jwks 验证器可以接受远程源以获取公钥列表或公钥的静态数组。

以下配置启用具有远程源的 jwks 令牌验证器。 此远程源使用 HTTPS,因此 caCertificate 字段包含远程源的信任根。

kind: Configuration
apiVersion: dapr.io/v1alpha1
metadata:
  name: sentryconfig
spec:
  mtls:
    enabled: true
    tokenValidators:
      - name: jwks
        options:
          minRefreshInterval: 2m
          requestTimeout: 1m
          source: "https://localhost:1234/"
          caCertificate: "<optional ca certificate bundle string>"

以下配置启用具有公钥静态数组的 jwks 令牌验证器。

kind: Configuration
apiVersion: dapr.io/v1alpha1
metadata:
  name: sentryconfig
spec:
  mtls:
    enabled: true
    tokenValidators:
      - name: jwks
        options:
          minRefreshInterval: 2m
          requestTimeout: 1m
          source: |
            {"keys":[ "12345.." ]}

2 - 使用 OAuth 配置端点授权

为您的 Web API 启用应用程序端点的 OAuth 授权

Dapr 的 OAuth 2.0 中间件允许您在 Dapr 端点上为 Web API 启用 OAuth 授权,支持 授权码模式。您还可以将授权令牌注入到端点 API 中,这些令牌可用于通过 客户端凭证模式对 API 调用的外部 API 进行授权。启用中间件后,所有通过 Dapr 的方法调用在传递给用户代码之前都需要进行授权。

这两种模式的主要区别在于,授权码模式需要用户交互并授权用户,而客户端凭证模式不需要用户交互,授权的是服务或应用程序。

在授权服务器上注册您的应用程序

不同的授权服务器提供不同的应用程序注册体验。以下是一些示例:

要配置 Dapr OAuth 中间件,您需要收集以下信息:

  • 客户端 ID (参见 这里)
  • 客户端密钥 (参见 这里)
  • 范围 (参见 这里)
  • 授权 URL
  • 令牌 URL

一些流行的授权服务器的授权/令牌 URL:

服务器授权 URL令牌 URL
Microsoft Entra IDhttps://login.microsoftonline.com/{tenant}/oauth2/authorizehttps://login.microsoftonline.com/{tenant}/oauth2/token
GitHubhttps://github.com/login/oauth/authorizehttps://github.com/login/oauth/access_token
Googlehttps://accounts.google.com/o/oauth2/v2/authhttps://accounts.google.com/o/oauth2/token https://www.googleapis.com/oauth2/v4/token
Twitterhttps://api.twitter.com/oauth/authorizehttps://api.twitter.com/oauth2/token

定义中间件组件

定义授权码模式组件

OAuth 中间件(授权码模式)由以下组件定义:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2
  namespace: default
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "<comma-separated scope names>"
  - name: authURL
    value: "<authorization URL>"
  - name: tokenURL
    value: "<token exchange URL>"
  - name: redirectURL
    value: "<redirect URL>"
  - name: authHeaderName
    value: "<header name under which the secret token is saved>"
  - name: forceHTTPS
    value: "<set to true if you invoke an API method through Dapr from https origin>"

为授权码模式定义自定义管道

要使用 OAuth 中间件(授权码模式),您需要使用 Dapr 配置 创建一个 自定义管道,如下所示:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pipeline
  namespace: default
spec:
  httpPipeline:
    handlers:
    - name: oauth2
      type: middleware.http.oauth2

定义客户端凭证模式组件

OAuth(客户端凭证模式)中间件由以下组件定义:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: myComponent
spec:
  type: middleware.http.oauth2clientcredentials
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "<comma-separated scope names>"
  - name: tokenURL
    value: "<token issuing URL>"
  - name: headerName
    value: "<header name under which the secret token is saved>"
  - name: endpointParamsQuery
    value: "<list of additional key=value settings separated by ampersands or semicolons forwarded to the token issuing service>"
  - name: authStyle
    value: "<see comment>"

为客户端凭证模式定义自定义管道

要使用 OAuth 中间件(客户端凭证模式),您需要使用 Dapr 配置 创建一个 自定义管道,如下所示:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pipeline
  namespace: default
spec:
  httpPipeline:
    handlers:
    - name: myComponent
      type: middleware.http.oauth2clientcredentials

应用配置

要将上述配置(无论授权类型)应用到您的 Dapr sidecar,请在您的 pod 规范中添加一个 dapr.io/config 注释:

apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        ...
        dapr.io/config: "pipeline"
...

访问访问令牌

授权码模式

配置完成后,每当客户端尝试通过 Dapr sidecar 调用 API 方法时(例如调用 v1.0/invoke/ 端点),如果未找到访问令牌,客户端将被重定向到授权同意页面。否则,访问令牌将写入 authHeaderName 头中,供应用程序代码使用。

客户端凭证模式

配置完成后,每当客户端尝试通过 Dapr sidecar 调用 API 方法时(例如调用 v1.0/invoke/ 端点),如果未找到现有的有效令牌,将检索一个新的访问令牌。访问令牌将写入 headerName 头中,供应用程序代码使用。这样,应用程序可以在调用请求该令牌的外部 API 时在授权头中转发令牌。

3 - 在 Dapr 中启用 API 令牌认证

要求每个传入的 Dapr API 请求在通过之前包含一个认证令牌

默认情况下,Dapr 通过网络边界限制对其公共 API 的访问。如果您计划在该边界之外公开 Dapr API,或者您的部署需要额外的安全级别,请考虑为 Dapr API 启用令牌认证。这意味着 Dapr 将要求每个传入的 gRPC 和 HTTP 请求在通过之前包含认证令牌。

创建令牌

Dapr 通过共享令牌进行 API 认证。您可以自由定义要使用的 API 令牌。

虽然 Dapr 对共享令牌的格式没有具体要求,但一个好的做法是生成一个随机字节序列并将其编码为 Base64。例如,以下命令生成一个随机的 32 字节密钥并将其编码为 Base64:

openssl rand 16 | base64

在 Dapr 中配置 API 令牌认证

对于 Kubernetes 或自托管 Dapr 部署,令牌认证配置略有不同:

自托管

在自托管场景中,Dapr 会检查 DAPR_API_TOKEN 环境变量是否存在。如果在 daprd 进程启动时设置了该环境变量,Dapr 将对其公共 API 强制执行认证:

export DAPR_API_TOKEN=<token>

要更新配置的令牌,请将 DAPR_API_TOKEN 环境变量更新为新值并重新启动 daprd 进程。

Kubernetes

在 Kubernetes 部署中,Dapr 使用 Kubernetes secret 存储来保存共享令牌。要配置 Dapr API 认证,首先创建一个新的 secret:

kubectl create secret generic dapr-api-token --from-literal=token=<token>

注意,您需要在每个希望启用 Dapr 令牌认证的命名空间中创建上述 secret。

要指示 Dapr 使用该 secret 来保护其公共 API,请在您的 Deployment 模板规范中添加一个注释:

annotations:
  dapr.io/enabled: "true"
  dapr.io/api-token-secret: "dapr-api-token" # Kubernetes secret 的名称

部署时,Dapr sidecar 注入器将自动创建一个 secret 引用并将实际值注入 DAPR_API_TOKEN 环境变量。

更新令牌

自托管

要在自托管中更新配置的令牌,请将 DAPR_API_TOKEN 环境变量更新为新值并重新启动 daprd 进程。

Kubernetes

要在 Kubernetes 中更新配置的令牌,请在每个命名空间中使用新令牌更新先前创建的 secret。您可以使用 kubectl patch 命令执行此操作,但在每个命名空间中更新这些的更简单方法是使用清单:

apiVersion: v1
kind: Secret
metadata:
  name: dapr-api-token
type: Opaque
data:
  token: <your-new-token>

然后将其应用到每个命名空间:

kubectl apply --file token-secret.yaml --namespace <namespace-name>

要让 Dapr 开始使用新令牌,请触发对每个部署的滚动升级:

kubectl rollout restart deployment/<deployment-name> --namespace <namespace-name>

假设您的服务配置了多个副本,密钥更新过程不会导致任何停机时间。

向客户端 API 调用添加 API 令牌

一旦在 Dapr 中配置了令牌认证,所有调用 Dapr API 的客户端都需要在每个请求中附加 dapr-api-token 令牌。

注意: Dapr SDK 会读取 DAPR_API_TOKEN 环境变量并默认为您设置。

HTTP

在 HTTP 的情况下,Dapr 要求在 dapr-api-token 头中提供 API 令牌。例如:

GET http://<daprAddress>/v1.0/metadata
dapr-api-token: <token>

使用 curl,您可以使用 --header(或 -H)选项传递头。例如:

curl http://localhost:3500/v1.0/metadata \
  --header "dapr-api-token: my-token"

gRPC

使用 gRPC 协议时,Dapr 将在 gRPC 元数据中检查传入调用的 API 令牌:

dapr-api-token[0].

从应用访问令牌

Kubernetes

在 Kubernetes 中,建议将 secret 挂载到您的 pod 作为环境变量,如下例所示,其中名为 dapr-api-token 的 Kubernetes secret 用于保存令牌。

containers:
  - name: mycontainer
    image: myregistry/myapp
    envFrom:
    - secretRef:
      name: dapr-api-token

自托管

在自托管模式下,您可以将令牌设置为应用的环境变量:

export DAPR_API_TOKEN=<my-dapr-token>

相关链接

4 - 使用令牌认证对Dapr请求进行身份验证

要求每个来自Dapr的API请求都包含一个认证令牌

对于一些构建块,例如pubsub、service-invocation和输入bindings,Dapr与应用程序通过HTTP或gRPC进行通信。 为了让应用程序能够验证来自Dapr sidecar的请求,您可以配置Dapr在HTTP请求的头部或gRPC请求的元数据中发送一个API令牌。

创建令牌

Dapr使用共享令牌进行API认证。您可以自由定义API令牌。

虽然Dapr对共享令牌没有强制格式,但一个好的做法是生成一个随机字节序列并将其编码为Base64。例如,这个命令生成一个随机的32字节密钥并将其编码为Base64:

openssl rand 16 | base64

在Dapr中配置应用API令牌认证

令牌认证配置在Kubernetes或selfhosted Dapr部署中略有不同:

Selfhosted

在selfhosted场景中,Dapr会检查APP_API_TOKEN环境变量是否存在。如果在daprd进程启动时设置了该环境变量,Dapr在调用应用程序时会包含该令牌:

export APP_API_TOKEN=<token>

要更新配置的令牌,修改APP_API_TOKEN环境变量为新值并重启daprd进程。

Kubernetes

在Kubernetes部署中,Dapr使用Kubernetes secrets存储来保存共享令牌。首先,创建一个新的secret:

kubectl create secret generic app-api-token --from-literal=token=<token>

注意,您需要在每个希望启用应用令牌认证的命名空间中创建上述secret

要指示Dapr在向应用程序发送请求时使用secret中的令牌,请在您的Deployment模板规范中添加一个注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-token-secret: "app-api-token" # Kubernetes secret的名称

部署时,Dapr Sidecar Injector会自动创建一个secret引用并将实际值注入到APP_API_TOKEN环境变量中。

轮换令牌

Selfhosted

要在selfhosted中更新配置的令牌,修改APP_API_TOKEN环境变量为新值并重启daprd进程。

Kubernetes

要在Kubernetes中更新配置的令牌,修改之前创建的secret中的新令牌在每个命名空间中。您可以使用kubectl patch命令来完成此操作,但更简单的方法是使用清单更新这些:

apiVersion: v1
kind: Secret
metadata:
  name: app-api-token
type: Opaque
data:
  token: <your-new-token>

然后将其应用到每个命名空间:

kubectl apply --file token-secret.yaml --namespace <namespace-name>

要让Dapr开始使用新令牌,请触发对每个部署的滚动升级:

kubectl rollout restart deployment/<deployment-name> --namespace <namespace-name>

假设您的服务配置了多个副本,密钥轮换过程不会导致任何停机。

验证来自Dapr的请求

一旦使用环境变量或Kubernetes secret app-api-token配置了应用令牌认证,Dapr sidecar在调用应用程序时总是会在HTTP头部或gRPC元数据中包含dapr-api-token: <token>。从应用程序端,确保您使用dapr-api-token值进行认证,该值使用您设置的app-api-token来验证来自Dapr的请求。

HTTP

在您的代码中,查找传入请求中的HTTP头部dapr-api-token

dapr-api-token: <token>

gRPC

使用gRPC协议时,检查传入调用中的gRPC元数据中的API令牌:

dapr-api-token[0].

从应用程序访问令牌

Kubernetes

在Kubernetes中,建议将secret挂载到您的pod作为环境变量。 假设我们创建了一个名为app-api-token的secret来保存令牌:

containers:
  - name: mycontainer
    image: myregistry/myapp
    envFrom:
    - secretRef:
      name: app-api-token

Selfhosted

在selfhosted模式中,您可以将令牌设置为应用程序的环境变量:

export APP_API_TOKEN=<my-app-token>

相关链接