mirror of https://github.com/dapr/docs.git
Add documentation - allow lists for service invocation (#809)
* Add documentation - allow lists for service invocation * Update README.md * Update README.md * more changes * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Change app id annotation * Update README.md * Update README.md * fix appId annotation Co-authored-by: Mark Fussell <mfussell@microsoft.com> Co-authored-by: Yaron Schneider <yaronsc@microsoft.com> Co-authored-by: Mukundan Sundararajan <musundar@microsoft.com>
This commit is contained in:
parent
38f4569741
commit
86400a00bc
|
@ -1,20 +1,19 @@
|
|||
# Configurations
|
||||
Dapr configurations are settings that enable you to change the behavior of individual Dapr sidecars or globally on the system services in the Dapr control plane.
|
||||
Dapr configurations are settings that enable you to change the behavior of individual Dapr application sidecars or globally on the system services in the Dapr control plane.
|
||||
An example of a per Dapr application sidecar setting is configuring trace settings. An example of a Dapr control plane setting is mutual TLS which is a global setting on the Sentry system service.
|
||||
|
||||
An example of a per Dapr sidecar setting is configuring trace settings. An example of a control plane setting is mutual TLS which is a global setting on the Sentry system service.
|
||||
|
||||
- [Self hosted sidecar configuration](#self-hosted-sidecar-configuration)
|
||||
- [Kubernetes sidecar configuration](#kubernetes-sidecar-configuration)
|
||||
- [Sidecar Configuration settings](#sidecar-configuration-settings)
|
||||
- [Kubernetes control plane configuration](#kubernetes-control-plane-configuration)
|
||||
- [Setting self hosted sidecar configuration](#setting-self-hosted-sidecar-configuration)
|
||||
- [Setting Kubernetes sidecar configuration](#setting-kubernetes-sidecar-configuration)
|
||||
- [Sidecar configuration settings](#sidecar-configuration-settings)
|
||||
- [Setting Kubernetes control plane configuration](#kubernetes-control-plane-configuration)
|
||||
- [Control plane configuration settings](#control-plane-configuration-settings)
|
||||
|
||||
## Self hosted sidecar configuration
|
||||
In self hosted mode the Dapr configuration is a configuration file, for example `config.yaml`. By default Dapr sidecar looks in the default Dapr folder for the runtime configuration eg: `$HOME/.dapr/config.yaml` in Linux/MacOS and `%USERPROFILE%\.dapr\config.yaml` in Windows.
|
||||
## Setting self hosted sidecar configuration
|
||||
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 eg: `$HOME/.dapr/config.yaml` in Linux/MacOS and `%USERPROFILE%\.dapr\config.yaml` in Windows.
|
||||
|
||||
A Dapr sidecar can also apply a configuration by using a ```--config``` flag to the file path with ```dapr run``` CLI command.
|
||||
|
||||
## Kubernetes sidecar configuration
|
||||
## Setting Kubernetes sidecar configuration
|
||||
In Kubernetes mode the Dapr configuration is a Configuration CRD, that is applied to the cluster. For example;
|
||||
|
||||
```cli
|
||||
|
@ -40,13 +39,16 @@ Note: There are more [Kubernetes annotations](../../howto/configure-k8s/README.m
|
|||
|
||||
## Sidecar configuration settings
|
||||
|
||||
The following configuration settings can be applied to Dapr sidecars;
|
||||
The following configuration settings can be applied to Dapr application sidecars;
|
||||
- [Tracing](#tracing)
|
||||
- [Middleware](#middleware)
|
||||
- [Scoping secrets for secret stores](#scoping-secrets-for-secret-stores)
|
||||
- [Access control allow lists for service invocation](#access-control-allow-lists-for-service-invocation)
|
||||
- [Example application sidecar configuration](#example-application-sidecar-configuration)
|
||||
|
||||
* [Observability distributed tracing](../observability/traces.md)
|
||||
* [Middleware pipelines](../middleware/README.md)
|
||||
* [Scoping secrets](../../howto/secrets-scopes/README.md)
|
||||
### Tracing
|
||||
|
||||
### Tracing configuration
|
||||
Tracing configuration turns on tracing for an application.
|
||||
|
||||
The `tracing` section under the `Configuration` spec contains the following properties:
|
||||
|
||||
|
@ -55,7 +57,7 @@ tracing:
|
|||
samplingRate: "1"
|
||||
```
|
||||
|
||||
The following table lists the different properties.
|
||||
The following table lists the properties for tracing:
|
||||
|
||||
Property | Type | Description
|
||||
---- | ------- | -----------
|
||||
|
@ -65,8 +67,11 @@ samplingRate | string | Set sampling rate for tracing to be enabled or disabled
|
|||
`samplingRate` is used to enable or disable the tracing. To disable the sampling rate ,
|
||||
set `samplingRate : "0"` in the configuration. 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.
|
||||
|
||||
### Middleware configuration
|
||||
See [Observability distributed tracing](../observability/traces.md) for more information
|
||||
|
||||
### Middleware
|
||||
|
||||
Middleware configuration set named Http pipeline middleware handlers
|
||||
The `httpPipeline` section under the `Configuration` spec contains the following properties:
|
||||
|
||||
```yml
|
||||
|
@ -78,34 +83,18 @@ httpPipeline:
|
|||
type: middleware.http.uppercase
|
||||
```
|
||||
|
||||
The following table lists the different properties.
|
||||
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](../middleware/README.md) for more information
|
||||
|
||||
### Scoping secrets for secret stores
|
||||
|
||||
Example sidecar configuration
|
||||
|
||||
```yml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: myappconfig
|
||||
namespace: default
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
httpPipeline:
|
||||
- name: oauth2
|
||||
type: middleware.http.oauth2
|
||||
```
|
||||
|
||||
### Scoping secrets
|
||||
|
||||
In addition to scoping which application can access given secret store component, the secret store component itself can be scoped to one or more secrets. By defining `allowedSecrets` and/or `deniedSecrets` list, applications can be restricted access to specific secrets.
|
||||
In addition to scoping which applications can access a given component, for example a secret store component (see [Scoping components](../../howto/components-scopes)), a named secret store component itself can be scoped to one or more secrets for an application. By defining `allowedSecrets` and/or `deniedSecrets` list, applications can be restricted to access only specific secrets.
|
||||
|
||||
The `secrets` section under the `Configuration` spec contains the following properties:
|
||||
|
||||
|
@ -120,35 +109,139 @@ secrets:
|
|||
deniedSecrets: ["redis-password"]
|
||||
```
|
||||
|
||||
The following table lists the different properties.
|
||||
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.
|
||||
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.
|
||||
|
||||
See the [Scoping secrets](../../howto/secrets-scopes/README.md) HowTo for examples on how to scope secrets to an application.
|
||||
|
||||
## Kubernetes control plane configuration
|
||||
There is a single configuration file called `default` installed with the control plane system services that applies global settings.
|
||||
### Access Control allow lists for service invocation
|
||||
Access control enables the configuration of policies that restrict what operations *calling* applications can perform, via service invocation, on the *called* application.
|
||||
An access control policy is specified in configuration and be applied to Dapr sidecar for the *called* application. Example access policies are shown below and access to the called app is based on the matched policy action. You can provide a default global action for all calling applications and if no access control policy is specified, the default behavior is to allow all calling applicatons to access to the called app.
|
||||
|
||||
## Concepts
|
||||
**TrustDomain** - A "trust domain" is a logical group to manage 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 generates a [SPIFFE](https://spiffe.io/) id for all applications which 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.
|
||||
|
||||
```
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
accessControl:
|
||||
defaultAction: deny --> Global default action in case no other policy is matched
|
||||
trustDomain: "public" --> The called application is assigned a trust domain and is used to generate the identity of this app in the TLS certificate.
|
||||
policies:
|
||||
- appId: app1 --> AppId of the calling app to allow/deny service invocation from
|
||||
defaultAction: deny --> App level default action in case the app is found but no specific operation is matched
|
||||
trustDomain: 'public' --> Trust domain of the calling app is matched against the specified value here.
|
||||
namespace: "default" --> Namespace of the calling app is matched against the specified value here.
|
||||
operations:
|
||||
- name: /op1 --> operation name on the called app
|
||||
httpVerb: ['POST', 'GET'] --> specific http verbs, unused for grpc invocation
|
||||
action: deny --> allow/deny access
|
||||
- name: /op2/* --> operation name with a postfix
|
||||
httpVerb: ["*"] --> wildcards can be used to match any http verb
|
||||
action: allow
|
||||
- appId: app2
|
||||
defaultAction: allow
|
||||
trustDomain: "public"
|
||||
namespace: "default"
|
||||
operations:
|
||||
- name: /op3
|
||||
httpVerb: ['POST', 'PUT']
|
||||
action: deny
|
||||
```
|
||||
|
||||
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 to under a path to match
|
||||
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"
|
||||
|
||||
See the [Allow lists for service invocation](../../howto/allowlists-serviceinvocation/README.md) HowTo for examples on how to set allow lists.
|
||||
|
||||
### Example application sidecar configuration
|
||||
The following yaml shows an example configuration file that can be applied to an applications' Dapr sidecar.
|
||||
|
||||
```yml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: myappconfig
|
||||
namespace: default
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
httpPipeline:
|
||||
handlers:
|
||||
- name: oauth2
|
||||
type: middleware.http.oauth2
|
||||
secrets:
|
||||
scopes:
|
||||
- storeName: localstore
|
||||
defaultAccess: allow
|
||||
deniedSecrets: ["redis-password"]
|
||||
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
|
||||
```
|
||||
|
||||
## Setting Kubernetes control plane configuration
|
||||
There is a single configuration file called `default` installed with the Dapr control plane system services that applies global settings. This is set up when Dapr is deployed to Kubernetes
|
||||
|
||||
## Control plane configuration settings
|
||||
|
||||
A Dapr control plane configuration can configure the following settings:
|
||||
|
||||
* [Mutual TLS](../../howto/configure-mtls/README.md). Also see [security concepts](../security/README.md)
|
||||
|
||||
|
||||
Property | Type | Description
|
||||
---- | ------- | -----------
|
||||
enabled | bool | Set mtls to be enabled or disabled
|
||||
allowedClockSkew | string | The extra time to give for certificate expiry based on possible clock skew on a machine. Default is 15 minutes.
|
||||
workloadCertTTL | string | Time a certificate is valid for. Default is 24 hours
|
||||
|
||||
Example control plane configuration
|
||||
See the [Mutual TLS](../../howto/configure-mtls/README.md) HowTo and [security concepts](../security/README.md) for more information.
|
||||
|
||||
### Example control plane configuration
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
# Apply access control list for service invocation
|
||||
|
||||
Access control enables the configuration of policies that restrict what operations *calling* applications can perform, via service invocation, on the *called* application. To limit access to a called applications from specific operations and HTTP verbs from the calling applications, you can define an access control policy specification in configuration.
|
||||
|
||||
- [Concepts](#concepts)
|
||||
- [Policy rules](#policy-rules)
|
||||
- [Policy priority](#policy-priority)
|
||||
- [Example scenarios](#example-scenarios)
|
||||
- [Hello world example](#hello-world-example)
|
||||
|
||||
|
||||
## Concepts
|
||||
**TrustDomain** - A "trust domain" is a logical group to manage 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 generates a [SPIFFE](https://spiffe.io/) id for all applications which 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.
|
||||
|
||||
## 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 specified and 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](../../concepts/configuration/README.md) 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 and all other invocation requests from other applications are denied
|
||||
|
||||
```yaml
|
||||
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 method op1 from appId = app1 is allowed and all other method requests from all other apps, including other methods on app1, are denied
|
||||
|
||||
```yaml
|
||||
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, the only scenarios below are allowed access and and 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, http verb = POST/PUT
|
||||
* trustDomain = "myDomain", namespace = "ns1", appID = app2, operation = op2 and application protocol is GRPC
|
||||
, only HTTP verbs POST/PUT on method op1 from appId = app1 are allowed and all other method requests from all other apps, including other methods on app1, are denied
|
||||
|
||||
```yaml
|
||||
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 http verbs
|
||||
|
||||
```yaml
|
||||
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 but belonging to different namespaces can be specified
|
||||
|
||||
```yaml
|
||||
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"
|
||||
```
|
||||
|
||||
## Hello world example
|
||||
This scenario shows how to apply access control to the [hello world](https://github.com/dapr/quickstarts/blob/master/hello-world/README.md) or [hello kubernetes](https://github.com/dapr/quickstarts/blob/master/hello-world/README.md) samples where a python app invokes a node.js app. You can create and apply these configuration files `nodeappconfig.yaml` and `pythonappconfig.yaml` as described in the [configuration](../../concepts/configuration/README.md) article.
|
||||
|
||||
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 nodeapp is in the `public` trust domain.
|
||||
|
||||
**nodeappconfig.yaml**
|
||||
|
||||
```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**
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: pythonappconfig
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
accessControl:
|
||||
defaultAction: allow
|
||||
trustDomain: "myDomain"
|
||||
```
|
||||
|
||||
For example, this is how the pythonapp is deployed to Kubernetes in the default namespace with this configuration file.
|
||||
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
|
||||
## Related Links
|
||||
|
||||
* [Configuration concepts](../../concepts/configuration/README.md)
|
Loading…
Reference in New Issue