1 - Dapr configuration

Overview of Dapr configuration

Dapr configurations are settings and policies that enable you to change both the behavior of individual Dapr applications, or the global behavior of the Dapr control plane system services.

for more information, read the configuration concept.

Application configuration

Set up application configuration

You can set up application configuration either in self-hosted or Kubernetes mode.

In self hosted mode, the Dapr configuration is a configuration file - for example, config.yaml. By default, the Dapr sidecar looks in the default Dapr folder for the runtime configuration:

  • Linux/MacOs: $HOME/.dapr/config.yaml
  • Windows: %USERPROFILE%\.dapr\config.yaml

An application can also apply a configuration by using a --config flag to the file path with dapr run CLI command.

In Kubernetes mode, the Dapr configuration is a Configuration resource, that is applied to the cluster. For example:

kubectl apply -f myappconfig.yaml

You can use the Dapr CLI to list the Configuration resources for applications.

dapr configurations -k

A Dapr sidecar can apply a specific configuration by using a dapr.io/config annotation. For example:

  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    dapr.io/app-port: "3000"
    dapr.io/config: "myappconfig"

Note: See all Kubernetes annotations available to configure the Dapr sidecar on activation by sidecar Injector system service.

Application configuration settings

The following menu includes all of the configuration settings you can set on the sidecar.

Tracing

Tracing configuration turns on tracing for an application.

The tracing section under the Configuration spec contains the following properties:

tracing:
  samplingRate: "1"
  otel: 
    endpointAddress: "otelcollector.observability.svc.cluster.local:4317"
  zipkin:
    endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

The following table lists the properties for tracing:

Property Type Description
samplingRate string Set sampling rate for tracing to be enabled or disabled.
stdout bool True write more verbose information to the traces
otel.endpointAddress string Set the Open Telemetry (OTEL) server address to send traces to. This may or may not require the https:// or http:// depending on your OTEL provider.
otel.isSecure bool Is the connection to the endpoint address encrypted
otel.protocol string Set to http or grpc protocol
zipkin.endpointAddress string Set the Zipkin server address to send traces to. This should include the protocol (http:// or https://) on the endpoint.
samplingRate

samplingRate is used to enable or disable the tracing. The valid range of samplingRate is between 0 and 1 inclusive. The sampling rate determines whether a trace span should be sampled or not based on value.

samplingRate : "1" samples all traces. By default, the sampling rate is (0.0001), or 1 in 10,000 traces.

To disable the sampling rate, set samplingRate : "0" in the configuration.

otel

The OpenTelemetry (otel) endpoint can also be configured via an environment variable. The presence of the OTEL_EXPORTER_OTLP_ENDPOINT environment variable turns on tracing for the sidecar.

Environment Variable Description
OTEL_EXPORTER_OTLP_ENDPOINT Sets the Open Telemetry (OTEL) server address, turns on tracing
OTEL_EXPORTER_OTLP_INSECURE Sets the connection to the endpoint as unencrypted (true/false)
OTEL_EXPORTER_OTLP_PROTOCOL Transport protocol (grpc, http/protobuf, http/json)

See Observability distributed tracing for more information.

Metrics

The metrics section under the Configuration spec can be used to enable or disable metrics for an application.

The metrics section contains the following properties:

metrics:
  enabled: true
  rules: []
  latencyDistributionBuckets: []
  http:
    increasedCardinality: true
    pathMatching:
      - /items
      - /orders/{orderID}
      - /orders/{orderID}/items/{itemID}
      - /payments/{paymentID}
      - /payments/{paymentID}/status
      - /payments/{paymentID}/refund
      - /payments/{paymentID}/details
    excludeVerbs: false
  recordErrorCodes: true

In the examples above, the path filter /orders/{orderID}/items/{itemID} would return a single metric count matching all the orderIDs and all the itemIDs, rather than multiple metrics for each itemID. For more information, see HTTP metrics path matching.

The above example also enables recording error code metrics, which is disabled by default.

The following table lists the properties for metrics:

Property Type Description
enabled boolean When set to true, the default, enables metrics collection and the metrics endpoint.
rules array Named rule to filter metrics. Each rule contains a set of labels to filter on and a regex expression to apply to the metrics path.
latencyDistributionBuckets array Array of latency distribution buckets in milliseconds for latency metrics histograms.
http.increasedCardinality boolean When set to true (default), in the Dapr HTTP server each request path causes the creation of a new “bucket” of metrics. This can cause issues, including excessive memory consumption, when there many different requested endpoints (such as when interacting with RESTful APIs).
To mitigate high memory usage and egress costs associated with high cardinality metrics with the HTTP server, you should set the metrics.http.increasedCardinality property to false.
http.pathMatching array Array of paths for path matching, allowing users to define matching paths to manage cardinality.
http.excludeVerbs boolean When set to true (default is false), the Dapr HTTP server ignores each request HTTP verb when building the method metric label.

To further help manage cardinality, path matching allows you to match specified paths according to defined patterns, reducing the number of unique metrics paths and thus controlling metric cardinality. This feature is particularly useful for applications with dynamic URLs, ensuring that metrics remain meaningful and manageable without excessive memory consumption.

Using rules, you can set regular expressions for every metric exposed by the Dapr sidecar. For example:

metrics:
  enabled: true
  rules:
    - name: dapr_runtime_service_invocation_req_sent_total
      labels:
      - name: method
        regex:
          "orders/": "orders/.+"

See metrics documentation for more information.

Logging

The logging section under the Configuration spec is used to configure how logging works in the Dapr Runtime.

The logging section contains the following properties:

logging:
  apiLogging:
    enabled: false
    obfuscateURLs: false
    omitHealthChecks: false

The following table lists the properties for logging:

Property Type Description
apiLogging.enabled boolean The default value for the --enable-api-logging flag for daprd (and the corresponding dapr.io/enable-api-logging annotation): the value set in the Configuration spec is used as default unless a true or false value is passed to each Dapr Runtime. Default: false.
apiLogging.obfuscateURLs boolean When enabled, obfuscates the values of URLs in HTTP API logs (if enabled), logging the abstract route name rather than the full path being invoked, which could contain Personal Identifiable Information (PII). Default: false.
apiLogging.omitHealthChecks boolean If true, calls to health check endpoints (e.g. /v1.0/healthz) are not logged when API logging is enabled. This is useful if those calls are adding a lot of noise in your logs. Default: false

See logging documentation for more information.

Middleware

Middleware configuration sets named HTTP pipeline middleware handlers. The httpPipeline and the appHttpPipeline section under the Configuration spec contain the following properties:

httpPipeline: # for incoming http calls
  handlers:
    - name: oauth2
      type: middleware.http.oauth2
    - name: uppercase
      type: middleware.http.uppercase
appHttpPipeline: # for outgoing http calls
  handlers:
    - name: oauth2
      type: middleware.http.oauth2
    - name: uppercase
      type: middleware.http.uppercase

The following table lists the properties for HTTP handlers:

Property Type Description
name string Name of the middleware component
type string Type of middleware component

See Middleware pipelines for more information.

Name resolution component

You can set name resolution components to use within the configuration file. For example, to set the spec.nameResolution.component property to "sqlite", pass configuration options in the spec.nameResolution.configuration dictionary as shown below.

This is a basic example of a configuration resource:

apiVersion: dapr.io/v1alpha1
kind: Configuration 
metadata:
  name: appconfig
spec:
  nameResolution:
    component: "sqlite"
    version: "v1"
    configuration:
      connectionString: "/home/user/.dapr/nr.db"

For more information, see:

Scope secret store access

See the Scoping secrets guide for information and examples on how to scope secrets to an application.

Access Control allow lists for building block APIs

See the guide for selectively enabling Dapr APIs on the Dapr sidecar for information and examples on how to set access control allow lists (ACLs) on the building block APIs lists.

Access Control allow lists for service invocation API

See the Allow lists for service invocation guide for information and examples on how to set allow lists with ACLs which use the service invocation API.

Disallow usage of certain component types

Using the components.deny property in the Configuration spec you can specify a denylist of component types that cannot be initialized.

For example, the configuration below disallows the initialization of components of type bindings.smtp and secretstores.local.file:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
spec: 
  components:
    deny:
      - bindings.smtp
      - secretstores.local.file

Optionally, you can specify a version to disallow by adding it at the end of the component name. For example, state.in-memory/v1 disables initializing components of type state.in-memory and version v1, but does not disable a (hypothetical) v2 version of the component.

Turning on preview features

See the preview features guide for information and examples on how to opt-in to preview features for a release.

Enabling preview features unlock new capabilities to be added for dev/test, since they still need more time before becoming generally available (GA) in the runtime.

Example sidecar configuration

The following YAML shows an example configuration file that can be applied to an applications’ Dapr sidecar.

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    stdout: true
    otel:
      endpointAddress: "localhost:4317"
      isSecure: false
      protocol: "grpc"
  httpPipeline:
    handlers:
      - name: oauth2
        type: middleware.http.oauth2
  secrets:
    scopes:
      - storeName: localstore
        defaultAccess: allow
        deniedSecrets: ["redis-password"]
  components:
    deny:
      - bindings.smtp
      - secretstores.local.file
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
      - appId: app1
        defaultAction: deny
        trustDomain: 'public'
        namespace: "default"
        operations:
          - name: /op1
            httpVerb: ['POST', 'GET']
            action: deny
          - name: /op2/*
            httpVerb: ["*"]
            action: allow

Control plane configuration

A single configuration file called daprsystem is installed with the Dapr control plane system services that applies global settings.

This is only set up when Dapr is deployed to Kubernetes.

Control plane configuration settings

A Dapr control plane configuration contains the following sections:

  • mtls for mTLS (Mutual TLS)

mTLS (Mutual TLS)

The mtls section contains properties for mTLS.

Property Type Description
enabled bool If true, enables mTLS for communication between services and apps in the cluster.
allowedClockSkew string Allowed tolerance when checking the expiration of TLS certificates, to allow for clock skew. Follows the format used by Go’s time.ParseDuration. Default is 15m (15 minutes).
workloadCertTTL string How long a certificate TLS issued by Dapr is valid for. Follows the format used by Go’s time.ParseDuration. Default is 24h (24 hours).
sentryAddress string Hostname port address for connecting to the Sentry server.
controlPlaneTrustDomain string Trust domain for the control plane. This is used to verify connection to control plane services.
tokenValidators array Additional Sentry token validators to use for authenticating certificate requests.

See the mTLS how-to and security concepts for more information.

Example control plane configuration

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

Next steps

Learn about concurrency and rate limits

2 - How-To: Control concurrency and rate limit applications

Learn how to control how many requests and events can invoke your application simultaneously

Typically, in distributed computing, you may only want to allow for a given number of requests to execute concurrently. Using Dapr’s app-max-concurrency, you can control how many requests and events can invoke your application simultaneously.

Default app-max-concurreny is set to -1, meaning no concurrency limit is enforced.

Different approaches

While this guide focuses on app-max-concurrency, you can also limit request rate per second using the middleware.http.ratelimit middleware. However, it’s important to understand the difference between the two approaches:

  • middleware.http.ratelimit: Time bound and limits the number of requests per second
  • app-max-concurrency: Specifies the max number of concurrent requests (and events) at any point of time.

See Rate limit middleware for more information about that approach.

Demo

Watch this video on how to control concurrency and rate limiting.

Configure app-max-concurrency

Without using Dapr, you would need to create some sort of a semaphore in the application and take care of acquiring and releasing it.

Using Dapr, you don’t need to make any code changes to your application.

Select how you’d like to configure app-max-concurrency.

To set concurrency limits with the Dapr CLI for running on your local dev machine, add the app-max-concurrency flag:

dapr run --app-max-concurrency 1 --app-port 5000 python ./app.py

The above example effectively turns your app into a sequential processing service.

To configure concurrency limits in Kubernetes, add the following annotation to your pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodesubscriber
  namespace: default
  labels:
    app: nodesubscriber
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodesubscriber
  template:
    metadata:
      labels:
        app: nodesubscriber
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodesubscriber"
        dapr.io/app-port: "3000"
        dapr.io/app-max-concurrency: "1"
#...

Limitations

Controlling concurrency on external requests

Rate limiting is guaranteed for every event coming from Dapr, including pub/sub events, direct invocation from other services, bindings events, etc. However, Dapr can’t enforce the concurrency policy on requests that are coming to your app externally.

Arguments and annotations

Next steps

Limit secret store access

3 - How-To: Limit the secrets that can be read from secret stores

Define secret scopes by augmenting the existing configuration resource with restrictive permissions.

In addition to scoping which applications can access a given component, you can also scope a named secret store component to one or more secrets for an application. By defining allowedSecrets and/or deniedSecrets lists, you restrict applications to access only specific secrets. In addition to scoping which applications can access a given component, you can also scope a named secret store component to one or more secrets for an application. By defining allowedSecrets and/or deniedSecrets lists, you restrict applications to access only specific secrets.

For more information about configuring a Configuration resource:

Configure secrets access

The secrets section under the Configuration spec contains the following properties:

secrets:
  scopes:
    - storeName: kubernetes
      defaultAccess: allow
      allowedSecrets: ["redis-password"]
    - storeName: localstore
      defaultAccess: allow
      deniedSecrets: ["redis-password"]

The following table lists the properties for secret scopes:

Property Type Description
storeName string Name of the secret store component. storeName must be unique within the list
defaultAccess string Access modifier. Accepted values “allow” (default) or “deny”
allowedSecrets list List of secret keys that can be accessed
deniedSecrets list List of secret keys that cannot be accessed

When an allowedSecrets list is present with at least one element, only those secrets defined in the list can be accessed by the application.

Permission priority

The allowedSecrets and deniedSecrets list values take priority over the defaultAccess. See how this works in the following example scenarios:

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 denied 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

Examples

Scenario 1: Deny access to all secrets for a secret store

In a Kubernetes cluster, the native Kubernetes secret store is added to your Dapr application by default. In some scenarios, it may be necessary to deny access to Dapr secrets for a given application. To add this configuration: In a Kubernetes cluster, the native Kubernetes secret store is added to your Dapr application by default. In some scenarios, it may be necessary to deny access to Dapr secrets for a given application. To add this configuration:

  1. Define the following appconfig.yaml.

  2. Define the following appconfig.yaml.

    apiVersion: dapr.io/v1alpha1
    kind: Configuration
    metadata:
      name: appconfig
    spec:
      secrets:
        scopes:
          - storeName: kubernetes
            defaultAccess: deny
    
    apiVersion: dapr.io/v1alpha1
    kind: Configuration
    metadata:
      name: appconfig
    spec:
      secrets:
        scopes:
          - storeName: kubernetes
            defaultAccess: deny
    
  3. Apply it to the Kubernetes cluster using the following command:

    kubectl apply -f appconfig.yaml`.
    

For applications that you need to deny access to the Kubernetes secret store, follow the Kubernetes instructions, adding the following annotation to the application pod.

  1. Apply it to the Kubernetes cluster using the following command:

    kubectl apply -f appconfig.yaml`.
    

For applications that you need to deny access to the Kubernetes secret store, follow the Kubernetes instructions, adding the following annotation to the application pod.

dapr.io/config: appconfig

With this defined, the application no longer has access to Kubernetes secret store.

Scenario 2: Allow access to only certain secrets in a secret store

Scenario 2: Allow access to only certain secrets in a secret store

To allow a Dapr application to have access to only certain secrets, define the following config.yaml:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  secrets:
    scopes:
      - storeName: vault
        defaultAccess: deny
        allowedSecrets: ["secret1", "secret2"]

This example defines configuration for secret store named vault. The default access to the secret store is deny. Meanwhile, some secrets are accessible by the application based on the allowedSecrets list. Follow the Sidecar configuration instructions to apply configuration to the sidecar. This example defines configuration for secret store named vault. The default access to the secret store is deny. Meanwhile, some secrets are accessible by the application based on the allowedSecrets list. Follow the Sidecar configuration instructions to apply configuration to the sidecar.

Scenario 3: Deny access to certain sensitive secrets in a secret store

Define the following config.yaml:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  secrets:
    scopes:
      - storeName: vault
        defaultAccess: allow # this is the default value, line can be omitted
        deniedSecrets: ["secret1", "secret2"]

This configuration explicitly denies access to secret1 and secret2 from the secret store named vault, while allowing access to all other secrets. Follow the Sidecar configuration instructions to apply configuration to the sidecar.

Next steps

Service invocation access control

This configuration explicitly denies access to secret1 and secret2 from the secret store named vault, while allowing access to all other secrets. Follow the Sidecar configuration instructions to apply configuration to the sidecar.

Next steps

Service invocation access control

4 - How-To: Apply access control list configuration for service invocation

Restrict what operations calling applications can perform

Using access control, you can configure policies that restrict what the operations calling applications can perform, via service invocation, on the called application. You can define an access control policy specification in the Configuration schema to limit access:

  • To a called application from specific operations, and
  • To HTTP verbs from the calling applications.

An access control policy is specified in Configuration and applied to the Dapr sidecar for the called application. Access to the called app is based on the matched policy action.

You can provide a default global action for all calling applications. If no access control policy is specified, the default behavior is to allow all calling applications to access to the called app.

See examples of access policies.

Terminology

trustDomain

A “trust domain” is a logical group that manages trust relationships. Every application is assigned a trust domain, which can be specified in the access control list policy spec. If no policy spec is defined or an empty trust domain is specified, then a default value “public” is used. This trust domain is used to generate the identity of the application in the TLS cert.

App Identity

Dapr requests the sentry service to generate a SPIFFE ID for all applications. This ID is attached in the TLS cert.

The SPIFFE ID is of the format: **spiffe://\<trustdomain>/ns/\<namespace\>/\<appid\>**.

For matching policies, the trust domain, namespace, and app ID values of the calling app are extracted from the SPIFFE ID in the TLS cert of the calling app. These values are matched against the trust domain, namespace, and app ID values specified in the policy spec. If all three of these match, then more specific policies are further matched.

Configuration properties

The following tables lists the different properties for access control, policies, and operations:

Access Control

Property Type Description
defaultAction string Global default action when no other policy is matched
trustDomain string Trust domain assigned to the application. Default is “public”.
policies string Policies to determine what operations the calling app can do on the called app

Policies

Property Type Description
app string AppId of the calling app to allow/deny service invocation from
namespace string Namespace value that needs to be matched with the namespace of the calling app
trustDomain string Trust domain that needs to be matched with the trust domain of the calling app. Default is “public”
defaultAction string App level default action in case the app is found but no specific operation is matched
operations string operations that are allowed from the calling app

Operations

Property Type Description
name string Path name of the operations allowed on the called app. Wildcard “*” can be used in a path to match. Wildcard “**” can be used to match under multiple paths.
httpVerb list List specific http verbs that can be used by the calling app. Wildcard “*” can be used to match any http verb. Unused for grpc invocation.
action string Access modifier. Accepted values “allow” (default) or “deny”

Policy rules

  1. If no access policy is specified, the default behavior is to allow all apps to access to all methods on the called app.
  2. If no global default action is specified and no app specific policies defined, the empty access policy is treated like no access policy is specified. The default behavior is to allow all apps to access to all methods on the called app.
  3. If no global default action is specified but some app specific policies have been defined, then we resort to a more secure option of assuming the global default action to deny access to all methods on the called app.
  4. If an access policy is defined and if the incoming app credentials cannot be verified, then the global default action takes effect.
  5. If either the trust domain or namespace of the incoming app do not match the values specified in the app policy, the app policy is ignored and the global default action takes effect.

Policy priority

The action corresponding to the most specific policy matched takes effect as ordered below:

  1. Specific HTTP verbs in the case of HTTP or the operation level action in the case of GRPC.
  2. The default action at the app level
  3. The default action at the global level

Example scenarios

Below are some example scenarios for using access control list for service invocation. See configuration guidance to understand the available configuration settings for an application sidecar.

Scenario 1:

Deny access to all apps except where trustDomain = public, namespace = default, appId = app1

With this configuration, all calling methods with appId = app1 are allowed. All other invocation requests from other applications are denied.

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"

Scenario 2:

Deny access to all apps except trustDomain = public, namespace = default, appId = app1, operation = op1

With this configuration, only the method op1 from appId = app1 is allowed. All other method requests from all other apps, including other methods on app1, are denied.

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1
        httpVerb: ['*']
        action: allow

Scenario 3:

Deny access to all apps except when a specific verb for HTTP and operation for GRPC is matched

With this configuration, only the scenarios below are allowed access. All other method requests from all other apps, including other methods on app1 or app2, are denied.

  • trustDomain = public, namespace = default, appID = app1, operation = op1, httpVerb = POST/PUT
  • trustDomain = "myDomain", namespace = "ns1", appID = app2, operation = op2 and application protocol is GRPC

Only the httpVerb POST/PUT on method op1 from appId = app1 are allowe. All other method requests from all other apps, including other methods on app1, are denied.

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1
        httpVerb: ['POST', 'PUT']
        action: allow
    - appId: app2
      defaultAction: deny
      trustDomain: 'myDomain'
      namespace: "ns1"
      operations:
      - name: /op2
        action: allow

Scenario 4:

Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/*, all httpVerb

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1/*
        httpVerb: ['*']
        action: deny

Scenario 5:

Allow access to all methods for trustDomain = public, namespace = ns1, appId = app1 and deny access to all methods for trustDomain = public, namespace = ns2, appId = app1

This scenario shows how applications with the same app ID while belonging to different namespaces can be specified.

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "ns1"
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "ns2"

Scenario 6:

Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/**/a, all httpVerb

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1/**/a
        httpVerb: ['*']
        action: deny

“hello world” examples

In these examples, you learn how to apply access control to the hello world tutorials.

Access control lists rely on the Dapr Sentry service to generate the TLS certificates with a SPIFFE ID for authentication. This means the Sentry service either has to be running locally or deployed to your hosting environment, such as a Kubernetes cluster.

The nodeappconfig example below shows how to deny access to the neworder method from the pythonapp, where the Python app is in the myDomain trust domain and default namespace. The Node.js app is in the public trust domain.

nodeappconfig.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: nodeappconfig
spec:
  tracing:
    samplingRate: "1"
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: pythonapp
      defaultAction: allow
      trustDomain: 'myDomain'
      namespace: "default"
      operations:
      - name: /neworder
        httpVerb: ['POST']
        action: deny

pythonappconfig.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pythonappconfig
spec:
  tracing:
    samplingRate: "1"
  accessControl:
    defaultAction: allow
    trustDomain: "myDomain"

Self-hosted mode

When walking through this tutorial, you:

  • Run the Sentry service locally with mTLS enabled
  • Set up necessary environment variables to access certificates
  • Launch both the Node app and Python app each referencing the Sentry service to apply the ACLs

Prerequisites

Run the Node.js app

  1. In a command prompt, set these environment variables:

      ```bash
      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
      ```
    
      ```powershell
      $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"
      ```
    
  2. Run daprd to launch a Dapr sidecar for the Node.js app with mTLS enabled, referencing the local Sentry service:

    daprd --app-id nodeapp --dapr-grpc-port 50002 -dapr-http-port 3501 --log-level debug --app-port 3000 --enable-mtls --sentry-address localhost:50001 --config nodeappconfig.yaml
    
  3. Run the Node.js app in a separate command prompt:

    node app.js
    

Run the Python app

  1. In another command prompt, set these environment variables:

    ```bash
    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"
    
  2. Run daprd to launch a Dapr sidecar for the Python app with mTLS enabled, referencing the local Sentry service:

    daprd --app-id pythonapp   --dapr-grpc-port 50003 --metrics-port 9092 --log-level debug --enable-mtls --sentry-address localhost:50001 --config pythonappconfig.yaml
    
  3. Run the Python app in a separate command prompt:

    python app.py
    

You should see the calls to the Node.js app fail in the Python app command prompt, due to the deny operation action in the nodeappconfig file. Change this action to allow and re-run the apps to see this call succeed.

Kubernetes mode

Prerequisites

Configure the Node.js and Python apps

You can create and apply the above nodeappconfig.yaml and pythonappconfig.yaml configuration files, as described in the configuration.

For example, the Kubernetes Deployment below is how the Python app is deployed to Kubernetes in the default namespace with this pythonappconfig configuration file.

Do the same for the Node.js deployment and look at the logs for the Python app to see the calls fail due to the deny operation action set in the nodeappconfig file.

Change this action to allow and re-deploy the apps to see this call succeed.

Deployment YAML example
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pythonapp
  namespace: default
  labels:
    app: python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python
  template:
    metadata:
      labels:
        app: python
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "pythonapp"
        dapr.io/config: "pythonappconfig"
    spec:
      containers:
      - name: python
        image: dapriosamples/hello-k8s-python:edge

Demo

Watch this video on how to apply access control list for service invocation.

Next steps

Dapr APIs allow list

5 - How-To: Selectively enable Dapr APIs on the Dapr sidecar

Choose which Dapr sidecar APIs are available to the app

In scenarios such as zero trust networks or when exposing the Dapr sidecar to external traffic through a frontend, it’s recommended to only enable the Dapr sidecar APIs being used by the app. Doing so reduces the attack surface and helps keep the Dapr APIs scoped to the actual needs of the application.

Dapr allows you to control which APIs are accessible to the application by setting an API allowlist or denylist using a Dapr Configuration.

Default behavior

If no API allowlist or denylist is specified, the default behavior is to allow access to all Dapr APIs.

  • If you’ve only defined a denylist, all Dapr APIs are allowed except those defined in the denylist
  • If you’ve only defined an allowlist, only the Dapr APIs listed in the allowlist are allowed
  • If you’ve defined both an allowlist and a denylist, the denylist overrides the allowlist for APIs that are defined in both.
  • If neither is defined, all APIs are allowed.

For example, the following configuration enables all APIs for both HTTP and gRPC:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"

Using an allowlist

Enabling specific HTTP APIs

The following example enables the state v1.0 HTTP API and blocks all other HTTP APIs:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    allowed:
      - name: state
        version: v1.0
        protocol: http

Enabling specific gRPC APIs

The following example enables the state v1 gRPC API and blocks all other gRPC APIs:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    allowed:
      - name: state
        version: v1
        protocol: grpc

Using a denylist

Disabling specific HTTP APIs

The following example disables the state v1.0 HTTP API, allowing all other HTTP APIs:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    denied:
      - name: state
        version: v1.0
        protocol: http

Disabling specific gRPC APIs

The following example disables the state v1 gRPC API, allowing all other gRPC APIs:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    denied:
      - name: state
        version: v1
        protocol: grpc

List of Dapr APIs

The name field takes the name of the Dapr API you would like to enable.

See this list of values corresponding to the different Dapr APIs:

API group HTTP API gRPC API
Service Invocation invoke (v1.0) invoke (v1)
State state (v1.0 and v1.0-alpha1) state (v1 and v1alpha1)
Pub/Sub publish (v1.0 and v1.0-alpha1) publish (v1 and v1alpha1)
Output Bindings bindings (v1.0) bindings (v1)
Subscribe n/a subscribe (v1alpha1)
Secrets secrets (v1.0) secrets (v1)
Actors actors (v1.0) actors (v1)
Metadata metadata (v1.0) metadata (v1)
Configuration configuration (v1.0 and v1.0-alpha1) configuration (v1 and v1alpha1)
Distributed Lock lock (v1.0-alpha1)
unlock (v1.0-alpha1)
lock (v1alpha1)
unlock (v1alpha1)
Cryptography crypto (v1.0-alpha1) crypto (v1alpha1)
Workflow workflows (v1.0) workflows (v1)
Conversation conversation (v1.0-alpha1) conversation (v1alpha1)
Health healthz (v1.0) n/a
Shutdown shutdown (v1.0) shutdown (v1)

Next steps

Configure Dapr to use gRPC

6 - How-To: Configure Dapr to use gRPC

Configure Dapr to use gRPC for low-latency, high performance scenarios

Dapr implements both an HTTP and a gRPC API for local calls. gRPC is useful for low-latency, high performance scenarios and has language integration using the proto clients. You can see the full list of auto-generated clients (Dapr SDKs).

The Dapr runtime implements a proto service that apps can communicate with via gRPC.

Not only can you call Dapr via gRPC, Dapr can communicate with an application via gRPC. To do that, the app needs to host a gRPC server and implement the Dapr appcallback service

Configuring Dapr to communicate with an app via gRPC

When running in self hosted mode, use the --app-protocol flag to tell Dapr to use gRPC to talk to the app:

dapr run --app-protocol grpc --app-port 5005 node app.js

This tells Dapr to communicate with your app via gRPC over port 5005.

On Kubernetes, set the following annotations in your deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-protocol: "grpc"
        dapr.io/app-port: "5005"
#...

Next steps

Handle large HTTP header sizes

7 - How-To: Handle large HTTP header size

Configure a larger HTTP read buffer size

Dapr has a default limit of 4KB for the HTTP header read buffer size. If you’re sending HTTP headers larger than the default 4KB, you may encounter a Too big request header service invocation error.

You can increase the HTTP header size by using:

  • The dapr.io/http-read-buffer-size annotation, or
  • The --dapr-http-read-buffer-size flag when using the CLI.

When running in self-hosted mode, use the --dapr-http-read-buffer-size flag to configure Dapr to use non-default http header size:

dapr run --dapr-http-read-buffer-size 16 node app.js

This tells Dapr to set maximum read buffer size to 16 KB.

On Kubernetes, set the following annotations in your deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/http-read-buffer-size: "16"
#...

Dapr Kubernetes pod annotations spec

Next steps

Handle large HTTP body requests

8 - How-To: Handle large http body requests

Configure http requests that are bigger than 4 MB

By default, Dapr has a limit for the request body size, set to 4MB. You can change this by defining:

  • The dapr.io/http-max-request-size annotation, or
  • The --dapr-http-max-request-size flag.

When running in self-hosted mode, use the --dapr-http-max-request-size flag to configure Dapr to use non-default request body size:

dapr run --dapr-http-max-request-size 16 node app.js

This tells Dapr to set maximum request body size to 16 MB.

On Kubernetes, set the following annotations in your deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/http-max-request-size: "16"
#...

Dapr Kubernetes pod annotations spec

Next steps

Install sidecar certificates

9 - How-To: Install certificates in the Dapr sidecar

Configure the Dapr sidecar container to trust certificates

The Dapr sidecar can be configured to trust certificates for communicating with external services. This is useful in scenarios where a self-signed certificate needs to be trusted, such as:

  • Using an HTTP binding
  • Configuring an outbound proxy for the sidecar

Both certificate authority (CA) certificates and leaf certificates are supported.

You can make the following configurations when the sidecar is running as a container.

  1. Configure certificates to be available to the sidecar container using volume mounts.
  2. Point the environment variable SSL_CERT_DIR in the sidecar container to the directory containing the certificates.

Note: For Windows containers, make sure the container is running with administrator privileges so it can install the certificates.

The following example uses Docker Compose to install certificates (present locally in the ./certificates directory) in the sidecar container:

version: '3'
services:
  dapr-sidecar:
    image: "daprio/daprd:edge" # dapr version must be at least v1.8
    command: [
      "./daprd",
     "-app-id", "myapp",
     "-app-port", "3000",
     ]
    volumes:
        - "./components/:/components"
        - "./certificates:/certificates" # (STEP 1) Mount the certificates folder to the sidecar container
    environment:
      - "SSL_CERT_DIR=/certificates" # (STEP 2) Set the environment variable to the path of the certificates folder
    # Uncomment the line below for Windows containers
    # user: ContainerAdministrator

Note: When the sidecar is not running inside a container, certificates must be directly installed on the host operating system.

On Kubernetes:

  1. Configure certificates to be available to the sidecar container using a volume mount.
  2. Point the environment variable SSL_CERT_DIR in the sidecar container to the directory containing the certificates.

The following example YAML shows a deployment that:

  • Attaches a pod volume to the sidecar
  • Sets SSL_CERT_DIR to install the certificates
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/volume-mounts: "certificates-vol:/tmp/certificates" # (STEP 1) Mount the certificates folder to the sidecar container
        dapr.io/env: "SSL_CERT_DIR=/tmp/certificates" # (STEP 2) Set the environment variable to the path of the certificates folder
    spec:
      volumes:
        - name: certificates-vol
          hostPath:
            path: /certificates
#...

Note: When using Windows containers, the sidecar container is started with admin privileges, which is required to install the certificates. This does not apply to Linux containers.

After following these steps, all the certificates in the directory pointed by SSL_CERT_DIR are installed.

Demo

Watch the demo on using installing SSL certificates and securely using the HTTP binding in community call 64:

Next steps

Enable preview features

10 - How-To: Enable preview features

How to specify and enable preview features

Preview features in Dapr are considered experimental when they are first released. These preview features require you to explicitly opt-in to use them. You specify this opt-in in Dapr’s Configuration file.

Preview features are enabled on a per application basis by setting configuration when running an application instance.

Configuration properties

The features section under the Configuration spec contains the following properties:

Property Type Description
name string The name of the preview feature that is enabled/disabled
enabled bool Boolean specifying if the feature is enabled or disabled

Enabling a preview feature

Preview features are specified in the configuration. Here is an example of a full configuration that contains multiple features:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: featureconfig
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
  features:
    - name: Feature1
      enabled: true
    - name: Feature2
      enabled: true

To enable preview features when running Dapr locally, either update the default configuration or specify a separate config file using dapr run.

The default Dapr config is created when you run dapr init, and is located at:

  • Windows: %USERPROFILE%\.dapr\config.yaml
  • Linux/macOS: ~/.dapr/config.yaml

Alternately, you can update preview features on all apps run locally by specifying the --config flag in dapr run and pointing to a separate Dapr config file:

dapr run --app-id myApp --config ./previewConfig.yaml ./app

In Kubernetes mode, the configuration must be provided via a configuration component. Using the same configuration as above, apply it via kubectl:

kubectl apply -f previewConfig.yaml

This configuration component can then be referenced in any application by modifying the application’s configuration to reference that specific configuration component via the dapr.io/config element. For example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  labels:
    app: node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/config: "featureconfig"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

Next steps

Configuration schema

11 - How-To: Configure Environment Variables from Secrets for Dapr sidecar

Inject Environment Variables from Kubernetes Secrets into Dapr sidecar

In special cases, the Dapr sidecar needs an environment variable injected into it. This use case may be required by a component, a 3rd party library, or a module that uses environment variables to configure the said component or customize its behavior. This can be useful for both production and non-production environments.

Overview

In Dapr 1.15, the new dapr.io/env-from-secret annotation was introduced, similar to dapr.io/env. With this annotation, you can inject an environment variable into the Dapr sidecar, with a value from a secret.

Annotation format

The values of this annotation are formatted like so:

  • Single key secret: <ENV_VAR_NAME>=<SECRET_NAME>
  • Multi key/value secret: <ENV_VAR_NAME>=<SECRET_NAME>:<SECRET_KEY>

<ENV_VAR_NAME> is required to follow the C_IDENTIFIER format and captured by the [A-Za-z_][A-Za-z0-9_]* regex:

  • Must start with a letter or underscore
  • The rest of the identifier contains letters, digits, or underscores

The name field is required due to the restriction of the secretKeyRef, so both name and key must be set. Learn more from the “env.valueFrom.secretKeyRef.name” section in this Kubernetes documentation. In this case, Dapr sets both to the same value.

Configuring single key secret environment variable

In the following example, the dapr.io/env-from-secret annotation is added to the Deployment.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/env-from-secret: "AUTH_TOKEN=auth-headers-secret"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

The dapr.io/env-from-secret annotation with a value of "AUTH_TOKEN=auth-headers-secret" is injected as:

env:
- name: AUTH_TOKEN
    valueFrom:
    secretKeyRef:
        name: auth-headers-secret
        key: auth-headers-secret

This requires the secret to have both name and key fields with the same value, “auth-headers-secret”.

Example secret

Note: The following example is for demo purposes only. It’s not recommended to store secrets in plain text.

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-headers-secret: "AUTH=mykey"

Configuring multi-key secret environment variable

In the following example, the dapr.io/env-from-secret annotation is added to the Deployment.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/env-from-secret: "AUTH_TOKEN=auth-headers-secret:auth-header-value"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

The dapr.io/env-from-secret annotation with a value of "AUTH_TOKEN=auth-headers-secret:auth-header-value" is injected as:

env:
- name: AUTH_TOKEN
    valueFrom:
    secretKeyRef:
        name: auth-headers-secret
        key: auth-header-value

Example secret

Note: The following example is for demo purposes only. It’s not recommended to store secrets in plain text.

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-header-value: "AUTH=mykey"