Skip to main content

Policies

Reference for the declarative manifests that define Diagrid policies. For the conceptual story see Policies. For end-to-end usage see IDs.

Policies are applied with the diagrid CLI. The target project is provided by the --project flag, not by a field in the manifest:

diagrid configuration create -f configuration.yaml --project my-project
diagrid workflow access-policy create -f workflow-access-policy.yaml --project my-project

Manifest envelope​

Every policy manifest shares the same top-level shape:

apiVersion: dapr.io/v1alpha1
kind: <Configuration | WorkflowAccessPolicy>
metadata:
name: <policy-name>
scopes:
- <app-id-1>
- <app-id-2>
spec:
# ...kind-specific spec below
FieldTypeRequiredDescription
apiVersionstringyesMust be dapr.io/v1alpha1.
kindstringyesConfiguration or WorkflowAccessPolicy.
metadata.namestringyesUnique policy name within the project.
scopesstring[]noWorkloads the policy applies to. Top-level (sibling of spec). Omit to leave the policy unbound — except for WorkflowAccessPolicy, where omitting scopes applies the policy to every app in the project.

Configuration​

A configuration sets app-level runtime behaviour: access control lists, HTTP pipelines, distributed tracing (private regions only), and workflow runtime parameters. For the access-control rules model and the CLI commands to manage them, see Secure service invocation with access control.

Spec​

spec:
accessControl:
defaultAction: allow | deny
trustDomain: <trust-domain> # ignored: set by the platform
policies:
- appId: <caller-app-id>
defaultAction: allow | deny
trustDomain: <trust-domain>
namespace: <namespace> # ignored: set by the platform
operations:
- name: <operation-name>
httpVerb: ["GET", "POST", ...]
action: allow | deny
appHttpPipeline:
handlers:
- name: <middleware-name>
type: <middleware-type>
httpPipeline:
handlers:
- name: <middleware-name>
type: <middleware-type>
tracing: # private regions only
samplingRate: "<float-as-string>"
otel:
endpointAddress: <url>
isSecure: <bool>
protocol: <http | grpc>
timeout: <duration>
headers:
- name: <header-name>
value: <header-value>
- name: <header-name>
secretKeyRef:
name: <secret-name>
key: <field-in-secret>
workflow:
maxConcurrentWorkflowInvocations: <int> # private regions only
maxConcurrentActivityInvocations: <int> # private regions only
globalMaxConcurrentWorkflowInvocations: <int> # accepted, not yet enforced
globalMaxConcurrentActivityInvocations: <int> # accepted, not yet enforced
workflowConcurrencyLimits:
- name: <workflow-name>
maxConcurrent: <int>
activityConcurrencyLimits:
- name: <activity-name>
maxConcurrent: <int>
stateRetentionPolicy:
completed: <duration>
failed: <duration>
terminated: <duration>
anyTerminal: <duration>

Field reference​

FieldNotes
accessControlService-invocation ACLs. The top-level defaultAction applies when no per-caller policy matches. Per-caller policies[] can refine to specific operations and HTTP verbs. defaultAction and action accept only allow or deny; httpVerb accepts only the nine standard HTTP methods; a policies[] entry must set appId and every operations[] entry must set name.
accessControl.trustDomainTop-level only. Set by the platform: a value you supply is accepted and then discarded, on create and on update alike.
accessControl.policies[].trustDomainYours to set, and kept. Leave it out and it defaults to your organization's trust domain, which is what you want unless you are naming a caller from somewhere else.
accessControl.policies[].namespaceSet by the platform. Whatever you supply is replaced with your project's namespace, prj-<project-namespace>, because that is the namespace the access-control decision is actually made against.
appHttpPipelineMiddleware applied to traffic from the data plane to your application (inbound to the app).
httpPipelineMiddleware applied to traffic from your application out through the data plane (outbound).
tracingDistributed tracing config. Only honored on projects in private regions. samplingRate is a string between "0" and "1".
tracing.otel.headersHeaders added to every OTLP exporter request. Give each entry a name and then one of value (plaintext), secretKeyRef (a name/key pair naming a secret and the field in it), or envRef (an environment variable to read the value from).
tracing.otel.timeoutDuration string bounding each OTLP exporter request.
workflow.maxConcurrentWorkflowInvocations
workflow.maxConcurrentActivityInvocations
Per-sidecar ceilings: the most a single Dapr instance schedules at once. Invocations beyond the ceiling queue rather than fail. These are never unlimited — omit them and Diagrid applies its own ceilings of 5000 concurrent workflows and 10000 concurrent activities per sidecar. You can lower them but not raise them: a value above the ceiling is ignored and the ceiling stands, with no error. Honored in private regions only — see the note below.
workflow.globalMaxConcurrentWorkflowInvocations
workflow.globalMaxConcurrentActivityInvocations
The same ceilings across every replica rather than per sidecar. Not enforced yet: Diagrid accepts and stores both fields and does not pass them to the workflow engine, so setting one changes nothing today. Use the per-name limits below to bound concurrency across replicas.
workflow.workflowConcurrencyLimits
workflow.activityConcurrencyLimits
Per-name ceilings, enforced across every replica by the scheduler. Each entry takes a name (the workflow or activity name to limit) and a maxConcurrent. Names must be non-empty and unique within a list, and maxConcurrent must be non-negative.
workflow.stateRetentionPolicyHow long a workflow instance's state is kept after it reaches a terminal state, after which it is purged automatically. Set completed, failed or terminated per state, or anyTerminal for all of them; a specific state wins over anyTerminal. Values are duration strings such as 72h or 30m, including 0s to purge immediately. Omit the whole block and instances are never purged automatically.
warning

Some of this spec is accepted and then overwritten, with no error to tell you so. accessControl.trustDomain is always cleared and accessControl.policies[].namespace is always replaced, because the platform owns both. On a project in a public region, workflow.maxConcurrentWorkflowInvocations and workflow.maxConcurrentActivityInvocations are cleared too — read them back with diagrid configuration get and they are gone, and Diagrid's own per-sidecar ceilings apply instead. The per-name limits and stateRetentionPolicy are kept and honored in every region. The global... ceilings are also kept, but nothing reads them yet. To bound concurrency in a public region, use the per-name limits.

Worked example​

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: order-service-config
spec:
accessControl:
defaultAction: deny
policies:
- appId: api-gateway
defaultAction: deny
operations:
- name: /orders
httpVerb: ["POST"]
action: allow
workflow:
workflowConcurrencyLimits:
- name: OrderProcess
maxConcurrent: 20
activityConcurrencyLimits:
- name: ChargePayment
maxConcurrent: 5
stateRetentionPolicy:
completed: 24h
anyTerminal: 72h

The top-level accessControl.trustDomain and the per-caller namespace are left out because the platform sets both, and policies[].trustDomain is left out so it defaults to your organization's. The limits and the retention policy above are honored in every region. Add maxConcurrentWorkflowInvocations and maxConcurrentActivityInvocations only for a project in a private region, where they are not dropped, and only to lower Diagrid's per-sidecar ceilings.

Workflow access policy​

A workflow access policy is an allow-list that controls which caller apps can schedule workflows and activities on the apps in scopes. Without a policy, all cross-app workflow calls are allowed; once a policy covers an app, every cross-app call must match a rule or it is denied. Self-calls are always allowed. For the conceptual story and CLI walkthrough see Secure workflows with access policies.

Spec​

spec:
rules:
- callers:
- appID: <caller-app-id>
workflows:
- name: <workflow-name or glob>
operations: [schedule]
activities:
- name: <activity-name or glob>

Field reference​

FieldTypeRequiredDescription
ruleslistnoAllow-list of rules; a call is permitted if any rule matches. An empty or omitted list denies every cross-app workflow call to the scoped apps.
rules[].callerslistyesCaller apps this rule grants access to. At least one entry.
rules[].callers[].appIDstringyesThe ID of the calling application.
rules[].workflowslistno*Workflow rules granted to the matched callers.
rules[].workflows[].namestringyesExact workflow name or glob pattern (*, ?, [abc]).
rules[].workflows[].operationsstring[]yesSet to [schedule]. The API also accepts terminate, raise, pause, resume, purge, get, and rerun for forward compatibility, but these operations don't route cross-app yet, so policies have no effect on them.
rules[].activitieslistno*Activity rules granted to the matched callers. Activities only support scheduling, so there is no operations field.
rules[].activities[].namestringyesExact activity name or glob pattern.

* At least one of workflows or activities must be present in each rule.

Worked example​

apiVersion: dapr.io/v1alpha1
kind: WorkflowAccessPolicy
metadata:
name: order-app-policy
scopes:
- order-app
spec:
rules:
- callers:
- appID: orchestrator-app
workflows:
- name: order-processing
operations: [schedule]
- name: "report-*"
operations: [schedule]
activities:
- name: charge-payment

Applying and inspecting policies​

# Apply or update
diagrid configuration create -f configuration.yaml --project <project>
diagrid configuration update <name> -f configuration.yaml --project <project>
diagrid apply -f configuration.yaml --project <project>
diagrid workflow access-policy create -f workflow-access-policy.yaml --project <project>
diagrid workflow access-policy update -f workflow-access-policy.yaml --project <project>

# Inspect
diagrid configuration list --project <project>
diagrid configuration get <name> --project <project>
diagrid workflow access-policy list --project <project>
diagrid workflow access-policy get <name> --project <project>

# Remove
diagrid configuration delete <name> --project <project>
diagrid workflow access-policy delete <name> --project <project>

A configuration can also be edited without a manifest. diagrid configuration create and diagrid configuration update take the same set of inline flags — --default-action, --policy, the --tracing-* flags, the --workflow-* and --activity-concurrency-limit flags, and the pipeline-handler flags — as an alternative to --file. On update, those flags merge section by section: a section is touched only when at least one of its flags is set, and fields you leave out keep their current value. To replace a configuration wholesale instead, pass --file or use diagrid apply -f.

See the diagrid configuration CLI reference for its full flag set.

See also​