mirror of https://github.com/dapr/docs.git
continue freshness pass
Signed-off-by: Hannah Hunter <hannahhunter@microsoft.com>
This commit is contained in:
parent
c490da5873
commit
bbdf25a1dd
|
|
@ -3,15 +3,21 @@ type: docs
|
|||
title: "How-To: Control concurrency and rate limit applications"
|
||||
linkTitle: "Concurrency & rate limits"
|
||||
weight: 2000
|
||||
description: "Control how many requests and events will invoke your application simultaneously"
|
||||
description: "Learn how to control how many requests and events can invoke your application simultaneously"
|
||||
---
|
||||
|
||||
A common scenario in distributed computing is to only allow for a given number of requests to execute concurrently.
|
||||
Using Dapr, you can control how many requests and events will 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.
|
||||
|
||||
*Note that this rate limiting is guaranteed for every event that's coming from Dapr, meaning Pub/Sub events, direct invocation from other services, bindings events etc. Dapr can't enforce the concurrency policy on requests that are coming to your app externally.*
|
||||
## Different approaches
|
||||
|
||||
*Note that rate limiting per second can be achieved by using the **middleware.http.ratelimit** middleware. However, there is an important difference between the two approaches. The rate limit middleware is time bound and limits the number of requests per second, while the `app-max-concurrency` flag specifies the number of concurrent requests (and events) at any point of time. See [Rate limit middleware]({{< ref middleware-rate-limit.md >}}). *
|
||||
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 number of concurrent requests (and events) at any point of time.
|
||||
|
||||
See [Rate limit middleware]({{< ref middleware-rate-limit.md >}}) for more information about that approach.
|
||||
|
||||
## Demo
|
||||
|
||||
Watch this [video](https://youtu.be/yRI5g6o_jp8?t=1710) on how to control concurrency and rate limiting ".
|
||||
|
||||
|
|
@ -19,14 +25,33 @@ Watch this [video](https://youtu.be/yRI5g6o_jp8?t=1710) on how to control concur
|
|||
<iframe width="764" height="430" src="https://www.youtube-nocookie.com/embed/yRI5g6o_jp8?t=1710" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
## Setting app-max-concurrency
|
||||
## Configure `app-max-concurrency`
|
||||
|
||||
Without using Dapr, a developer would need to create some sort of a semaphore in the application and take care of acquiring and releasing it.
|
||||
Using Dapr, there are no code changes needed to an app.
|
||||
Without using Dapr, you would need to create some sort of a semaphore in the application and take care of acquiring and releasing it.
|
||||
|
||||
### Setting app-max-concurrency in Kubernetes
|
||||
Using Dapr, you don't need to make any code changes to your application.
|
||||
|
||||
To set app-max-concurrency in Kubernetes, add the following annotation to your pod:
|
||||
Select how you'd like to configure `app-max-concurrency`.
|
||||
|
||||
{{< tabs "CLI" Kubernetes >}}
|
||||
|
||||
<!-- CLI -->
|
||||
{{% codetab %}}
|
||||
|
||||
To set concurrency limits with the Dapr CLI for running on your local dev machine, add the `app-max-concurrency` flag:
|
||||
|
||||
```bash
|
||||
dapr run --app-max-concurrency 1 --app-port 5000 python ./app.py
|
||||
```
|
||||
|
||||
The above example effectively turns your app into a single concurrent service.
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
<!-- Kubernetes -->
|
||||
{{% codetab %}}
|
||||
|
||||
To configure concurrency limits in Kubernetes, add the following annotation to your pod:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
|
|
@ -50,15 +75,18 @@ spec:
|
|||
dapr.io/app-id: "nodesubscriber"
|
||||
dapr.io/app-port: "3000"
|
||||
dapr.io/app-max-concurrency: "1"
|
||||
...
|
||||
#...
|
||||
```
|
||||
|
||||
### Setting app-max-concurrency using the Dapr CLI
|
||||
{{% /codetab %}}
|
||||
|
||||
To set app-max-concurrency with the Dapr CLI for running on your local dev machine, add the `app-max-concurrency` flag:
|
||||
{{< /tabs >}}
|
||||
|
||||
```bash
|
||||
dapr run --app-max-concurrency 1 --app-port 5000 python ./app.py
|
||||
```
|
||||
## Limitations
|
||||
|
||||
The above examples will effectively turn your app into a single concurrent service.
|
||||
### 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.
|
||||
|
||||
## Next steps
|
||||
|
||||
{{< button text="Limit secret store access" page="secret-scope" >}}
|
||||
|
|
|
|||
|
|
@ -3,71 +3,87 @@ type: docs
|
|||
title: "How-To: Apply access control list configuration for service invocation"
|
||||
linkTitle: "Service Invocation access control"
|
||||
weight: 4000
|
||||
description: "Restrict what operations *calling* applications can perform, via service invocation, on the *called* application"
|
||||
description: "Restrict what operations calling applications can perform"
|
||||
---
|
||||
|
||||
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.
|
||||
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 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 applications to access to the called app.
|
||||
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.
|
||||
|
||||
## Concepts
|
||||
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.
|
||||
|
||||
**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.
|
||||
[See examples of access policies.](#example-scenarios)
|
||||
|
||||
**App Identity** - Dapr requests the sentry service to generate a [SPIFFE](https://spiffe.io/) id for all applications and 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.
|
||||
## 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](https://spiffe.io/) 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:
|
||||
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
|
||||
| `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
|
||||
| `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" |
|
||||
| `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 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.
|
||||
1. If no access policy is specified, the default behavior is to allow all apps to access to all methods on the called app.
|
||||
1. 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.
|
||||
1. 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.
|
||||
1. If an access policy is defined and if the incoming app credentials cannot be verified, then the global default action takes effect.
|
||||
1. 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
|
||||
1. The default action at the app level
|
||||
1. 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]({{< ref "configuration-concept.md" >}}) to understand the available configuration settings for an application sidecar.
|
||||
|
||||
<font size=5>Scenario 1: Deny access to all apps except where trustDomain = public, namespace = default, appId = app1</font>
|
||||
### Scenario 1:
|
||||
|
||||
With this configuration, all calling methods with appId = app1 are allowed and all other invocation requests from other applications are denied
|
||||
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.
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -85,9 +101,11 @@ spec:
|
|||
namespace: "default"
|
||||
```
|
||||
|
||||
<font size=5>Scenario 2: Deny access to all apps except trustDomain = public, namespace = default, appId = app1, operation = op1</font>
|
||||
### Scenario 2:
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -109,12 +127,16 @@ spec:
|
|||
action: allow
|
||||
```
|
||||
|
||||
<font size=5>Scenario 3: Deny access to all apps except when a specific verb for HTTP and operation for GRPC is matched</font>
|
||||
### Scenario 3:
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -143,7 +165,9 @@ spec:
|
|||
action: allow
|
||||
```
|
||||
|
||||
<font size=5>Scenario 4: Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/*, all http verbs</font>
|
||||
### Scenario 4:
|
||||
|
||||
Allow access to all methods except `trustDomain` = `public`, `namespace` = `default`, `appId` = `app1`, `operation` = `/op1/*`, all `httpVerb`
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -165,9 +189,11 @@ spec:
|
|||
action: deny
|
||||
```
|
||||
|
||||
<font size=5>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</font>
|
||||
### Scenario 5:
|
||||
|
||||
This scenario shows how applications with the same app ID but belonging to different namespaces can be specified
|
||||
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.
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -189,7 +215,9 @@ spec:
|
|||
namespace: "ns2"
|
||||
```
|
||||
|
||||
<font size=5>Scenario 6: Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/**/a, all http verbs</font>
|
||||
### Scenario 6:
|
||||
|
||||
Allow access to all methods except `trustDomain` = `public`, `namespace` = `default`, `appId` = `app1`, `operation` = `/op1/**/a`, all `httpVerb`
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -211,14 +239,15 @@ spec:
|
|||
action: deny
|
||||
```
|
||||
|
||||
## Hello world examples
|
||||
## "hello world" examples
|
||||
|
||||
These examples show how to apply access control to the [hello world](https://github.com/dapr/quickstarts#quickstarts) quickstart samples where a python app invokes a node.js app.
|
||||
Access control lists rely on the Dapr [Sentry service]({{< ref "security-concept.md" >}}) to generate the TLS certificates with a SPIFFE id for authentication, which means the Sentry service either has to be running locally or deployed to your hosting environment such as a Kubernetes cluster.
|
||||
In these examples, you learn how to apply access control to the [hello world](https://github.com/dapr/quickstarts/tree/master/tutorials) tutorials.
|
||||
|
||||
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.
|
||||
Access control lists rely on the Dapr [Sentry service]({{< ref "security-concept.md" >}}) 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.
|
||||
|
||||
**nodeappconfig.yaml**
|
||||
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
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -242,7 +271,7 @@ spec:
|
|||
action: deny
|
||||
```
|
||||
|
||||
**pythonappconfig.yaml**
|
||||
### pythonappconfig.yaml
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
|
|
@ -258,95 +287,119 @@ spec:
|
|||
```
|
||||
|
||||
### Self-hosted mode
|
||||
This example uses the [hello world](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-world/README.md) quickstart.
|
||||
|
||||
The following steps run the Sentry service locally with mTLS enabled, set up necessary environment variables to access certificates, and then launch both the node app and python app each referencing the Sentry service to apply the ACLs.
|
||||
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
|
||||
|
||||
1. Follow these steps to run the [Sentry service in self-hosted mode]({{< ref "mtls.md" >}}) with mTLS enabled
|
||||
#### Prerequisites
|
||||
|
||||
2. In a command prompt, set these environment variables:
|
||||
- Become familiar with running [Sentry service in self-hosted mode]({{< ref "mtls.md" >}}) with mTLS enabled
|
||||
- Clone the [hello world](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-world/README.md) tutorial
|
||||
|
||||
#### Run the Node.js app
|
||||
|
||||
1. In a command prompt, set these environment variables:
|
||||
|
||||
{{< tabs "Linux/MacOS" Windows >}}
|
||||
|
||||
{{% codetab %}}
|
||||
```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
|
||||
```
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
{{% codetab %}}
|
||||
```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"
|
||||
```
|
||||
{{% codetab %}}
|
||||
|
||||
```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"
|
||||
```
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
{{< /tabs >}}
|
||||
|
||||
3. Run daprd to launch a Dapr sidecar for the node.js app with mTLS enabled, referencing the local Sentry service:
|
||||
1. Run daprd to launch a Dapr sidecar for the Node.js app with mTLS enabled, referencing the local Sentry service:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
4. Run the node app in a separate command prompt:
|
||||
1. Run the Node.js app in a separate command prompt:
|
||||
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
|
||||
5. In another command prompt, set these environment variables:
|
||||
#### Run the Python app
|
||||
|
||||
1. In another command prompt, set these environment variables:
|
||||
|
||||
{{< tabs "Linux/MacOS" Windows >}}
|
||||
|
||||
{{% codetab %}}
|
||||
```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
|
||||
```
|
||||
|
||||
```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
|
||||
```
|
||||
{{% /codetab %}}
|
||||
|
||||
{{% codetab %}}
|
||||
|
||||
```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"
|
||||
```
|
||||
```
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
{{< /tabs >}}
|
||||
|
||||
6. Run daprd to launch a Dapr sidecar for the python app with mTLS enabled, referencing the local Sentry service:
|
||||
1. Run daprd to launch a Dapr sidecar for the Python app with mTLS enabled, referencing the local Sentry service:
|
||||
|
||||
```bash
|
||||
daprd --app-id pythonapp --dapr-grpc-port 50003 --metrics-port 9092 --log-level debug --enable-mtls --sentry-address localhost:50001 --config pythonappconfig.yaml
|
||||
```
|
||||
|
||||
7. Run the python app in a separate command prompt:
|
||||
1. Run the Python app in a separate command prompt:
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
8. You should see the calls to the node app fail in the python app command prompt based due to the **deny** operation action in the nodeappconfig file. Change this action to **allow** and re-run the apps and you should then see this call succeed.
|
||||
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
|
||||
This example uses the [hello kubernetes](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-kubernetes/README.md) quickstart.
|
||||
|
||||
You can create and apply the above configuration files `nodeappconfig.yaml` and `pythonappconfig.yaml` as described in the [configuration]({{< ref "configuration-concept.md" >}}) to the Kubernetes deployments.
|
||||
#### Prerequisites
|
||||
|
||||
For example, below is how the pythonapp is deployed to Kubernetes in the default namespace with this pythonappconfig configuration file.
|
||||
Do the same for the nodeapp deployment and then look at the logs for the pythonapp 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 and you should then see this call succeed.
|
||||
- Become familiar with running [Sentry service in self-hosted mode]({{< ref "mtls.md" >}}) with mTLS enabled
|
||||
- Clone the [hello world](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-world/README.md) tutorial
|
||||
|
||||
#### Configure the Node.js and Python apps
|
||||
|
||||
You can create and apply the above [`nodeappconfig.yaml`](#nodeappconfigyaml) and [`pythonappconfig.yaml`](#pythonappconfigyaml) configuration files, as described in the [configuration]({{< ref "configuration-concept.md" >}}).
|
||||
|
||||
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
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
|
|
@ -375,9 +428,14 @@ spec:
|
|||
image: dapriosamples/hello-k8s-python:edge
|
||||
```
|
||||
|
||||
## Community call demo
|
||||
## Demo
|
||||
|
||||
Watch this [video](https://youtu.be/j99RN_nxExA?t=1108) on how to apply access control list for service invocation.
|
||||
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<iframe width="688" height="430" src="https://www.youtube-nocookie.com/embed/j99RN_nxExA?start=1108" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Next steps
|
||||
|
||||
{{< button text="Dapr APIs allow list" page="api-allowlist" >}}
|
||||
|
|
@ -3,12 +3,14 @@ type: docs
|
|||
title: "How-To: Limit the secrets that can be read from secret stores"
|
||||
linkTitle: "Limit secret store access"
|
||||
weight: 3000
|
||||
description: "To limit the secrets to which the Dapr application has access, users can define secret scopes by augmenting existing configuration resource with restrictive permissions."
|
||||
description: "Define secret scopes by augmenting the existing configuration resource with restrictive permissions."
|
||||
---
|
||||
|
||||
In addition to scoping which applications can access a given component, for example a secret store component (see [Scoping components]({{< ref "component-scopes.md">}})), 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.
|
||||
In addition to [scoping which applications can access a given component]({{< ref "component-scopes.md">}}), you can also scop 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.
|
||||
|
||||
Follow [these instructions]({{< ref "configuration-overview.md" >}}) to define a configuration resource.
|
||||
For more information about configuring a Configuration resource:
|
||||
- [Configuration overview]({{< ref configuration-overview.md >}})
|
||||
- [Configuration schema]({{< ref configuration-schema.md >}})
|
||||
|
||||
## Configure secrets access
|
||||
|
||||
|
|
@ -38,38 +40,44 @@ When an `allowedSecrets` list is present with at least one element, only those s
|
|||
|
||||
## Permission priority
|
||||
|
||||
The `allowedSecrets` and `deniedSecrets` list values take priorty over the `defaultAccess`.
|
||||
The `allowedSecrets` and `deniedSecrets` list values take priorty 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
|
||||
| | 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
|
||||
### Scenario 1: Deny access to all secrets for a secret store
|
||||
|
||||
In Kubernetes cluster, the native Kubernetes secret store is added to 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 follow the steps below:
|
||||
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:
|
||||
|
||||
Define the following `appconfig.yaml` and apply it to the Kubernetes cluster using the command `kubectl apply -f appconfig.yaml`.
|
||||
1. Define the following `appconfig.yaml`.
|
||||
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
secrets:
|
||||
scopes:
|
||||
- storeName: kubernetes
|
||||
defaultAccess: deny
|
||||
```
|
||||
```yaml
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
secrets:
|
||||
scopes:
|
||||
- storeName: kubernetes
|
||||
defaultAccess: deny
|
||||
```
|
||||
|
||||
For applications that need to be denied access to the Kubernetes secret store, follow [these instructions]({{< ref kubernetes-overview >}}), and add the following annotation to the application pod.
|
||||
1. Apply it to the Kubernetes cluster using the following command:
|
||||
|
||||
```bash
|
||||
kubectl apply -f appconfig.yaml`.
|
||||
```
|
||||
|
||||
For applications that you need to deny access to the Kubernetes secret store, follow [the Kubernetes instructions]({{< ref kubernetes-overview >}}), adding the following annotation to the application pod.
|
||||
|
||||
```yaml
|
||||
dapr.io/config: appconfig
|
||||
|
|
@ -77,7 +85,7 @@ 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`:
|
||||
|
||||
|
|
@ -94,7 +102,7 @@ spec:
|
|||
allowedSecrets: ["secret1", "secret2"]
|
||||
```
|
||||
|
||||
This example defines configuration for secret store named vault. The default access to the secret store is `deny`, whereas some secrets are accessible by the application based on the `allowedSecrets` list. Follow [these instructions]({{< ref configuration-overview.md >}}) 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]({{< ref "configuration-overview.md#sidecar-configuration" >}}) to apply configuration to the sidecar.
|
||||
|
||||
### Scenario 3: Deny access to certain sensitive secrets in a secret store
|
||||
|
||||
|
|
@ -113,4 +121,8 @@ spec:
|
|||
deniedSecrets: ["secret1", "secret2"]
|
||||
```
|
||||
|
||||
The above configuration explicitly denies access to `secret1` and `secret2` from the secret store named vault while allowing access to all other secrets. Follow [these instructions]({{< ref configuration-overview.md >}}) to apply configuration to the sidecar.
|
||||
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]({{< ref "configuration-overview.md#sidecar-configuration" >}}) to apply configuration to the sidecar.
|
||||
|
||||
## Next steps
|
||||
|
||||
{{< button text="Service invocation access control" page="invoke-allowlist" >}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue