From 91f08d7a39bbb8d6efc441d57ae3365e8b5412ae Mon Sep 17 00:00:00 2001 From: Aaron Crawfis Date: Fri, 9 Oct 2020 14:39:43 -0700 Subject: [PATCH 1/3] Update Operations (#853) * Enable robots, Update versions, add links * Update left column minimum width * Add Dapr docs image * Update spacing for list pages * Add home image * Update hosting references * Remove extra width * Add favicons --- .../{security.md => security-concept.md} | 0 .../en/docs/operations/hosting/_index.md | 2 +- .../kubernetes/kubernetes-annotations.md | 4 +-- .../kubernetes/kubernetes-hybrid-clusters.md | 6 ++-- .../hosting/kubernetes/kubernetes-overview.md | 2 +- .../kubernetes/kubernetes-production.md | 34 +++++++++--------- .../self-hosted/self-hosted-no-docker.md | 6 ++-- .../self-hosted/self-hosted-overview.md | 2 +- .../self-hosted/self-hosted-with-docker.md | 19 ++++------ .../en/docs/operations/security/api-token.md | 2 +- .../{tracing.md => setup-tracing.md} | 0 daprdocs/static/favicons/android-144x144.png | Bin 0 -> 3981 bytes daprdocs/static/favicons/android-192x192.png | Bin 0 -> 5972 bytes daprdocs/static/favicons/android-36x36.png | Bin 0 -> 798 bytes daprdocs/static/favicons/android-48x48.png | Bin 0 -> 1374 bytes daprdocs/static/favicons/android-72x72.png | Bin 0 -> 1713 bytes daprdocs/static/favicons/android-96x196.png | Bin 0 -> 2776 bytes .../favicons/apple-touch-icon-180x180.png | Bin 0 -> 4926 bytes daprdocs/static/favicons/favicon-16x16.png | Bin 0 -> 423 bytes daprdocs/static/favicons/favicon-32x32.png | Bin 0 -> 923 bytes daprdocs/static/favicons/favicon.ico | Bin 1150 -> 1150 bytes daprdocs/static/favicons/tile150x150.png | Bin 0 -> 8655 bytes daprdocs/static/favicons/tile310x150.png | Bin 0 -> 13330 bytes daprdocs/static/favicons/tile310x310.png | Bin 0 -> 17571 bytes daprdocs/static/favicons/tile70x70.png | Bin 0 -> 3777 bytes 25 files changed, 35 insertions(+), 42 deletions(-) rename daprdocs/content/en/docs/concepts/{security.md => security-concept.md} (100%) rename daprdocs/content/en/docs/operations/troubleshooting/{tracing.md => setup-tracing.md} (100%) create mode 100644 daprdocs/static/favicons/android-144x144.png create mode 100644 daprdocs/static/favicons/android-192x192.png create mode 100644 daprdocs/static/favicons/android-36x36.png create mode 100644 daprdocs/static/favicons/android-48x48.png create mode 100644 daprdocs/static/favicons/android-72x72.png create mode 100644 daprdocs/static/favicons/android-96x196.png create mode 100644 daprdocs/static/favicons/apple-touch-icon-180x180.png create mode 100644 daprdocs/static/favicons/favicon-16x16.png create mode 100644 daprdocs/static/favicons/favicon-32x32.png create mode 100644 daprdocs/static/favicons/tile150x150.png create mode 100644 daprdocs/static/favicons/tile310x150.png create mode 100644 daprdocs/static/favicons/tile310x310.png create mode 100644 daprdocs/static/favicons/tile70x70.png diff --git a/daprdocs/content/en/docs/concepts/security.md b/daprdocs/content/en/docs/concepts/security-concept.md similarity index 100% rename from daprdocs/content/en/docs/concepts/security.md rename to daprdocs/content/en/docs/concepts/security-concept.md diff --git a/daprdocs/content/en/docs/operations/hosting/_index.md b/daprdocs/content/en/docs/operations/hosting/_index.md index 5459bb69b..01ba8061d 100644 --- a/daprdocs/content/en/docs/operations/hosting/_index.md +++ b/daprdocs/content/en/docs/operations/hosting/_index.md @@ -1,6 +1,6 @@ --- title: "Hosting options for Dapr" -linkTitle: "Hosting Options" +linkTitle: "Hosting options" weight: 100 description: "How to deploy Dapr into your environment." --- \ No newline at end of file diff --git a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-annotations.md b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-annotations.md index 647c95dda..45a323bd4 100644 --- a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-annotations.md +++ b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-annotations.md @@ -7,8 +7,8 @@ description: "The available annotations available when configuring Dapr in your The following table shows all the supported pod Spec annotations supported by Dapr. -| Annotation | Description -|---------------------------------------------------|-------| +| Annotation | Description | +|---------------------------------------------------|-------------| | `dapr.io/enabled` | Setting this paramater to `true` injects the Dapr sidecar into the pod | `dapr.io/app-port` | This parameter tells Dapr which port your application is listening on | `dapr.io/app-id` | The unique ID of the application. Used for service discovery, state encapsulation and the pub/sub consumer ID diff --git a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-hybrid-clusters.md b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-hybrid-clusters.md index db8e27b87..c4f089518 100644 --- a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-hybrid-clusters.md +++ b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-hybrid-clusters.md @@ -33,7 +33,7 @@ akswin000001 Ready agent 6d v1.17.9 10.240.0. ## Installing the Dapr Control Plane If you are installing using the Dapr CLI or via a helm chart, simply follow the normal deployment procedures: -[Installing Dapr on a Kubernetes cluster](../../getting-started/environment-setup.md#installing-Dapr-on-a-kubernetes-cluster) +[Installing Dapr on a Kubernetes cluster]({{< ref "install-dapr.md#installing-Dapr-on-a-kubernetes-cluster" >}}) Affinity will be automatically set for kubernetes.io/os=linux. This will be sufficient for most users, as Kubernetes requires at least one Linux node pool. @@ -157,8 +157,8 @@ helm uninstall dapr ``` ## Related links - - See the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) for examples of more advanced configuration via node affinity - - [Get started: Prep Windows for containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment) +- See the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) for examples of more advanced configuration via node affinity +- [Get started: Prep Windows for containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment) - [Setting up a Windows enabled Kubernetes cluster on Azure AKS](https://docs.microsoft.com/en-us/azure/aks/windows-container-cli) - [Setting up a Windows enabled Kubernetes cluster on AWS EKS](https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html) - [Setting up Windows on Google Cloud GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-cluster-windows) diff --git a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-overview.md b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-overview.md index 7a07ce115..9ce48f257 100644 --- a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-overview.md +++ b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-overview.md @@ -7,7 +7,7 @@ description: "Overview of how to get Dapr running on your Kubernetes cluster" Dapr can be configured to run on any [Kubernetes cluster](https://github.com/dapr/quickstarts/tree/master/hello-kubernetes). In Kubernetes the `dapr-sidecar-injector` and `dapr-operator` services provide first class integration to launch Dapr as a sidecar container in the same pod as the service container and provide notifications of Dapr component updates provisioned into the cluster. Additionally, the `dapr-sidecar-injector` also injects the environment variables `DAPR_HTTP_PORT` and `DAPR_GRPC_PORT` into **all** the containers in the pod to enable user defined applications to easily communicate with Dapr without hardcoding Dapr port values. -The `dapr-sentry` service is a certificate authority that enables mutual TLS between Dapr sidecar instances for secure data encryption. For more information on the `Sentry` service read the [security overview](../security/README.md#dapr-to-dapr-communication) +The `dapr-sentry` service is a certificate authority that enables mutual TLS between Dapr sidecar instances for secure data encryption. For more information on the `Sentry` service read the [security overview]({{< ref "security-concept.md" >}}) diff --git a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-production.md b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-production.md index a52cf44a5..c5a6fbc7c 100644 --- a/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-production.md +++ b/daprdocs/content/en/docs/operations/hosting/kubernetes/kubernetes-production.md @@ -13,14 +13,14 @@ The Dapr control plane pods are designed to be lightweight and require the follo *Note: For more info on CPU and Memory resource units and their meaning, see [this](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes) link* | Deployment | CPU | Memory -| ------------| ---- | ------ -| Operator | Limit: 1, Request: 100m | Limit: 200Mi, Request: 20Mi +|-------------|-----|------- +| Operator | Limit: 1, Request: 100m | Limit: 200Mi, Request: 20Mi | Sidecar Injector | Limit: 1, Request: 100m | Limit: 200Mi, Request: 20Mi -| Sentry | Limit: 1, Request: 100m | Limit: 200Mi, Request: 20Mi -| Placement | Limit: 1, Request: 250m | Limit: 500Mi, Request: 100Mi -| Dashboard | Limit: 200m, Request: 50m | Limit: 200Mi, Request: 20Mi +| Sentry | Limit: 1, Request: 100m | Limit: 200Mi, Request: 20Mi +| Placement | Limit: 1, Request: 250m | Limit: 500Mi, Request: 100Mi +| Dashboard | Limit: 200m, Request: 50m | Limit: 200Mi, Request: 20Mi -To change the resource assignments for the Dapr sidecar, see the annotations [here](../configure-k8s/). +To change the resource assignments for the Dapr sidecar, see the annotations [here]({{< ref "kubernetes-annotations.md" >}}). The specific annotations related to resource constraints are: * `dapr.io/sidecar-cpu-limit` @@ -42,8 +42,8 @@ The following Dapr control plane deployments are optional: The Dapr sidecar requires the following resources in a production-ready setup: -| CPU | Memory -| --------- | --------- | +| CPU | Memory | +|-----|--------| | Limit: 4, Request: 100m | Limit: 4000Mi, Request: 250Mi *Note: Since Dapr is intended to do much of the I/O heavy lifting for your app, it's expected that the resources given to Dapr enable you to drastically reduce the resource allocations for the application* @@ -53,7 +53,7 @@ The CPU and memory limits above account for the fact that Dapr is intended to do ## Deploying Dapr with Helm When deploying to a production cluster, it's recommended to use Helm. The Dapr CLI installation into a Kubernetes cluster is for a development and test only setup. -You can find information [here](../../getting-started/environment-setup.md#using-helm-(advanced)) on how to deploy Dapr using Helm. +You can find information [here]({{< ref "install-dapr.md#using-helm-advanced" >}}) on how to deploy Dapr using Helm. When deploying Dapr in a production-ready configuration, it's recommended to deploy with a highly available configuration of the control plane: @@ -63,7 +63,7 @@ helm install dapr dapr/dapr --namespace dapr-system --set global.ha.enabled=true This command will run 3 replicas of each control plane pod with the exception of the Placement pod in the dapr-system namespace. -*Note: The Dapr Helm chart automatically deploys with affinity for nodes with the label `kubernetes.io/os=linux`. You can deploy the Dapr control plane to Windows nodes, but most users should not need to. For more information see [Deploying to a Hybrid Linux/Windows K8s Cluster](../windows-k8s/)* +*Note: The Dapr Helm chart automatically deploys with affinity for nodes with the label `kubernetes.io/os=linux`. You can deploy the Dapr control plane to Windows nodes, but most users should not need to. For more information see [Deploying to a Hybrid Linux/Windows K8s Cluster]({{< ref "kubernetes-hybrid-clusters.md" >}})* ## Upgrading Dapr with Helm @@ -73,7 +73,7 @@ Dapr supports zero downtime upgrades. The upgrade path includes the following st 2. Updating the Dapr control plane 3. Updating the data plane (Dapr sidecars) -### 1. Upgrading the CLI +### Upgrading the CLI To upgrade the Dapr CLI, [download a release version](https://github.com/dapr/cli/releases) of the CLI that matches the Dapr runtime version. For example, if upgrading to Dapr 0.9.0, download a CLI version of 0.9.x. @@ -198,24 +198,24 @@ Properly configured, Dapr not only be secured with regards to it's control plane It is recommended that a production-ready deployment includes the following settings: -1. Mutual Authentication (mTLS) should be enabled. Note that Dapr has mTLS on by default. For details on how to bring your own certificates, see [here](../configure-mtls/README.md#bringing-your-own-certificates) +1. Mutual Authentication (mTLS) should be enabled. Note that Dapr has mTLS on by default. For details on how to bring your own certificates, see [here]({{< ref "mtls.md#bringing-your-own-certificates" >}}) -2. Dapr API authentication is enabled (this is the between your application and the Dapr sidecar). To secure the Dapr API from unauthorized access, it is recommended to enable Dapr's token based auth. See [here](../enable-dapr-api-token-based-authentication/README.md) for details +2. Dapr API authentication is enabled (this is the between your application and the Dapr sidecar). To secure the Dapr API from unauthorized access, it is recommended to enable Dapr's token based auth. See [here]({{< ref "api-token.md" >}}) for details -3. All component YAMLs should have secret data configured in a secret store and not hard-coded in the YAML file. See [here](../../concepts/secrets/component-secrets.md) on how to use secrets with Dapr components +3. All component YAMLs should have secret data configured in a secret store and not hard-coded in the YAML file. See [here]({{< ref "component-secrets.md" >}}) on how to use secrets with Dapr components 4. The Dapr control plane is installed on a separate namespace such as `dapr-system`, and never into the `default` namespace -Dapr also supports scoping components for certain applications. This is not a required practice, and can be enabled according to your Sec-Ops needs. See [here](../components-scopes/README.md) for more info. +Dapr also supports scoping components for certain applications. This is not a required practice, and can be enabled according to your Sec-Ops needs. See [here]({{< ref "component-scopes.md" >}}) for more info. ## Tracing and metrics configuration Dapr has tracing and metrics enabled by default. -To configure a tracing backend for Dapr visit [this](../diagnose-with-tracing) link. +To configure a tracing backend for Dapr visit [this]({{< ref "setup-tracing.md" >}}) link. For metrics, Dapr exposes a Prometheus endpoint listening on port 9090 which can be scraped by Prometheus. It is *recommended* that you set up distributed tracing and metrics for your applications and the Dapr control plane in production. If you already have your own observability set-up, you can disable tracing and metrics for Dapr. -To setup Prometheus, Grafana and other monitoring tools with Dapr, visit [this](../setup-monitoring-tools) link. +To setup Prometheus, Grafana and other monitoring tools with Dapr, visit [this]({{< ref "monitoring" >}}) link. diff --git a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-no-docker.md b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-no-docker.md index b3146ee0f..6f2a8928b 100644 --- a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-no-docker.md +++ b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-no-docker.md @@ -19,9 +19,9 @@ The Dapr CLI provides an option to initialize Dapr using slim init, without the dapr init --slim ``` -In this mode two different binaries are installed `daprd` and `placement`. The `placement` binary is needed to enable [actors](../../concepts/actors/README.md) in a Dapr self-hosted installation. +In this mode two different binaries are installed `daprd` and `placement`. The `placement` binary is needed to enable [actors]({{< ref "actors-overview.md" >}}) in a Dapr self-hosted installation. -In this mode no default components such as Redis are installed for state management or pub/sub. This means, that aside from [Service Invocation](../../concepts/service-invocation/README.md), no other building block functionality is available on install out of the box. Users are free to setup their own environment and custom components. Furthermore, actor based service invocation is possible if a state store is configured as explained in the following sections. +In this mode no default components such as Redis are installed for state management or pub/sub. This means, that aside from [Service Invocation]({{< ref "service-invocation-overview.md" >}}), no other building block functionality is available on install out of the box. Users are free to setup their own environment and custom components. Furthermore, actor based service invocation is possible if a state store is configured as explained in the following sections. ## Service invocation See [this sample](https://github.com/dapr/samples/tree/master/hello-dapr-slim) for an example on how to perform service invocation in this mode. @@ -65,4 +65,4 @@ INFO[0450] host removed: 192.168.1.6 instance=host.localhost ## Cleanup -Follow the uninstall [instructions](../../getting-started/environment-setup.md#Uninstall-Dapr-in-self-hosted-mode-(without-docker)) to remove the binaries. +Follow the uninstall [instructions]({{< ref "install-dapr.md#uninstall-dapr-in-a-self-hosted-mode" >}}) to remove the binaries. diff --git a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-overview.md b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-overview.md index bc379d26b..774fa886f 100644 --- a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-overview.md +++ b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-overview.md @@ -9,7 +9,7 @@ Dapr can be configured to run on your local developer machine in self hosted mod In self hosted mode, Redis is running locally in a container and is configured to serve as both the default component for state store and for pub/sub. A Zipkin container is also configured for diagnostics and tracing. After running `dapr init`, see the `$HOME/.dapr/components` directory (Mac/Linux) or `%USERPROFILE%\.dapr\components` on Windows. -The `dapr-placement` service is responsible for managing the actor distribution scheme and key range settings. This service is only required if you are using Dapr actors. For more information on the actor `Placement` service read [actor overview](../actors). +The `dapr-placement` service is responsible for managing the actor distribution scheme and key range settings. This service is only required if you are using Dapr actors. For more information on the actor `Placement` service read [actor overview]({{< ref "actors-overview.md" >}}). diff --git a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-with-docker.md b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-with-docker.md index ae17c2bfa..23ca883db 100644 --- a/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-with-docker.md +++ b/daprdocs/content/en/docs/operations/hosting/self-hosted/self-hosted-with-docker.md @@ -5,7 +5,6 @@ weight: 20000 description: "How to deploy and run Dapr in self-hosted mode using Docker" --- -# Run with Docker This article provides guidance on running Dapr with Docker outside of Kubernetes. There are a number of different configurations in which you may wish to run Dapr with Docker that are documented below. ## Prerequisites @@ -35,7 +34,7 @@ There are published Docker images for each of the Dapr components available on [ - `major.minor.patch-arm`: A release version for ARM. - `major.minor.patch-rc.iteration-arm`: A release candidate for ARM. -## Run Dapr in a Docker container with an app as a process +## Run app as a process > For development purposes ONLY If you are running Dapr in a Docker container and your app as a process on the host machine, then you need to configure @@ -49,7 +48,7 @@ Then you can run your app on the host and they should connect over the localhost However, if you are not running your Docker daemon on a Linux host, it is recommended you follow the steps below to run both your app and the [Dapr runtime in Docker containers using Docker Compose](#run-dapr-in-a-docker-container-using-docker-compose). -## Run Dapr and an app in a single Docker container +## Run app and Dapr in a single Docker container > For development purposes ONLY It is not recommended to run both the Dapr runtime and an application inside the same container. However, it is possible to do so for local development scenarios. @@ -78,7 +77,7 @@ CMD ["run", "--app-id", "nodeapp", "--app-port", "3000", "node", "app.js"] Remember that if Dapr needs to communicate with other components i.e. Redis, these also need to be made accessible to it. -## Run Dapr in a Docker container on a Docker network +## Run on a Docker network If you have multiple instances of Dapr running in Docker containers and want them to be able to communicate with each other i.e. for service invocation, then you'll need to create a shared Docker network and make sure those Dapr containers are attached to it. @@ -93,7 +92,7 @@ docker run --net=my-dapr-network ... ``` Each container will receive a unique IP on that network and be able to communicate with other containers on that network. -## Run Dapr in a Docker container using Docker-Compose +## Run using Docker-Compose [Docker Compose](https://docs.docker.com/compose/) can be used to define multi-container application configurations. If you wish to run multiple apps with Dapr sidecars locally without Kubernetes then it is recommended to use a Docker Compose definition (`docker-compose.yml`). @@ -142,14 +141,8 @@ services: To further learn how to run Dapr with Docker Compose, see the [Docker-Compose Sample](https://github.com/dapr/samples/tree/master/hello-docker-compose). -## Run Dapr in a Docker container on Kubernetes +## Run on Kubernetes If your deployment target is Kubernetes then you're probably better of running your applicaiton and Dapr sidecars directly on a Kubernetes platform. Running Dapr on Kubernetes is a first class experience and is documented separately. Please refer to the -following references: -- [Setup Dapr on a Kubernetes cluster](https://github.com/dapr/docs/blob/ea5b1918778a47555dbdccff0ed6c5b987ed10cf/getting-started/environment-setup.md#installing-dapr-on-a-kubernetes-cluster) -- [Hello Kubernetes Sample](https://github.com/dapr/quickstarts/tree/master/hello-kubernetes) -- [Configuring the Dapr sidecar on Kubernetes](https://github.com/dapr/docs/blob/c88d247a2611d6824d41bb5b6adfeb38152dbbc6/howto/configure-k8s/README.md) -- [Running Dapr in Kubernetes mode](https://github.com/dapr/docs/blob/a7668cab5e16d12f364a42d2fe7d75933c6398e9/overview/README.md#running-dapr-in-kubernetes-mode) +[Dapr on Kubernetes docs]({{< ref "kubernetes-overview.md" >}}) -## Related links -- [Docker-Compose Sample](https://github.com/dapr/samples/hello-docker-compose) diff --git a/daprdocs/content/en/docs/operations/security/api-token.md b/daprdocs/content/en/docs/operations/security/api-token.md index 4f3d77f9f..e74f3dcef 100644 --- a/daprdocs/content/en/docs/operations/security/api-token.md +++ b/daprdocs/content/en/docs/operations/security/api-token.md @@ -1,6 +1,6 @@ --- title: "Enable API token based authentication" -linkTitle: "API Token Auth" +linkTitle: "API token auth" weight: 3000 description: "Require every incoming API request to include an authentication token before allowing that request to pass through" --- diff --git a/daprdocs/content/en/docs/operations/troubleshooting/tracing.md b/daprdocs/content/en/docs/operations/troubleshooting/setup-tracing.md similarity index 100% rename from daprdocs/content/en/docs/operations/troubleshooting/tracing.md rename to daprdocs/content/en/docs/operations/troubleshooting/setup-tracing.md diff --git a/daprdocs/static/favicons/android-144x144.png b/daprdocs/static/favicons/android-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f5b25f80d458a2ae408f2dbdf1018837ce38ad6c GIT binary patch literal 3981 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 ArT_o{ literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/android-192x192.png b/daprdocs/static/favicons/android-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..38dc117103a04110a086e4544fdae580ae69ff28 GIT binary patch literal 5972 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 CX$(RD literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/android-36x36.png b/daprdocs/static/favicons/android-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..429719459aedf2a05e42c6f2951bf4423989d5b7 GIT binary patch literal 798 zcmV+(1L6FMP)LsMJoC718FrI&XsiLq~Pv{JKSp#I3MBmohbguzJv%B@?Im`^OGqL14^ z?G9DXKzoLQq45#BE7?>m0WgJzrY_pgn0;4?&{rs!C^BPdX=Pm_G4TX3W-T}R=w)_3 zYW=RYYT8~=^``(NRKgJ2ahX7k+|Dz&)0r%tSq8H^Q!|QZvSRF^XF!pWyJxGDeOy>v zHcfX(ek#7sq+%)0fZX+=IaNbP)?6uf(Pbb-)gJ*k0^mECr$Kb6dWMvN_%Mom8NgAg zW9Iurbj&U#XRS1Q)+1(qMnoq8>;{lDgm%i-{-g6zKNukkNKthGAXK%7gcC>!PaFpO zX8yBJYxtdJD8)NNQijmfQcc?mb{+XRK|ys=C(!8Hmgp^G^%9Zq0zl_Vne0N(0Svp) z+3u7H?=cte5ISyvc+e^Vj%P(wQ&ims`oh30m|w_llcMS$0PF)`_}T2sq+*%g1J{&% zzUv)`_Sm*pRQ(5lUKhGGAm-13K}-Ko+I|L%X%NmkZQmW9e8o&dM4aRzo`C2yfL#D) zYT15WAa~bReU)QaVF<0^PvnLJ>LDqro(Is$KrSn^t@ZTP@4W{K>nmV%09Y}ER`F%v z2F`n+kiH6npTUK!hz8t1I5i#vJ@6~)*VVNGWEx^rcB-M}DbUWro59>4({~l+M*bZyCx|KJqMC`x9`;let**D8-=O37&j8U88MsEp=Lna cK=r!!7dvt9u@E>RE&u=k07*qoM6N<$f*B`r@c;k- literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/android-48x48.png b/daprdocs/static/favicons/android-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..190ae9e14e2a065a479cb065bb5efe22dbc32156 GIT binary patch literal 1374 zcmV-k1)=(hP)CF-C3#-j4#525hDb5 z8h(mI68ymgY@_)9Abs#RhDM2KXzb4NX3<#ejP17Fon!8FXF9vxZP#7IEZKRQJNNv3 z=R4=zyGtnZhsr#DQ~>6LHZ> zD0uVXDp-78|o zBldb}+o9Hp1b4W5j0KReS*#gAB9R0$V=R%H!vmin&=0N<@pmIJ^`k<2dd?=6740N| z)oFu$hOV}Y_r_Zeb`Yp1m!r|KNsJ|CJ%IDZM`S%a65G7zKL-$OdHw!*K51JnN2WQM zGDjz^LWA(iG4Z=*Ox<6oZqW=dbMfxTT_dn~`&yqg-aSJH z7-HrFMD(I#%g|NZkF027!rBir?;y|y5SlVeinkhiWS8?TTSp?giGc@Q8x0M6{Rw~S z69Bj7sZCQPFTLlEQ8}dbg0Z%cdd>x4Ha+H4yU27lXabHo!MgxtMSBUr3$8(?GYsoE z5v~JEt3bTmvYAyW?@6LR%Sv;g@P?Nb8oN-Lf=bajO{ zd$Q8?Gr%`y0T5Zc&voX*BJ)@E_h|rK-2gw~taAY%(8dux{MIx8Z9OyI@%Y|i=<4o_ z9su4pb#;R`KFUHqRx>)@Ff_FFZy~gB*(>t+#1-cOEbs#GhqOJ!Q}-U50Z+|}wXA5r z0l0cL0ATbOarFTgbg1iPFhB3CiSWosOg)<2#LivJm6H`sbo_H3RJ%EaH;7VoB>6hM zO#{I0fq)X-$e<%0ofEKlCskFQXHIEgh(2(i{7pPHapcBm2Z&zHm`EfoGh)vS%n3lu zSt6gfuod!5O`*lzHFEX%>6s%iw~2o{g#hd}bahLb&5Y4IgMqY=V8ETdSz(BAmg5}I zR{A9L=L*@L@pGI506y^cQ7*=20-)_?JiH^L2b@Kk2~jdD38-bpXCUe&@KagF?d!C7 z{7w58k(J!X;8p@;5c=5SAH^OK-R|ju_NziW>ylh^!TDwZM~GQZ%dG~}84$iQ^zbIH zzw}MO{=`guc>xqsKc&b7LeU$TX~40;z~`o}I@7Oc({o8(c(HEY8zcqBVt!w}ULfRT;d^jC2pEC4F zOW6SME8047oAd)UdS~3*?7dwNc+N+dM gsTnL)zw8N)h zJF6yuK!^`05FbpG2#VDZc>rS4gai1@{}+*(zp@-lufQ9P4uYxmU1 zgRuZqYdJ_LsLYHAKmw453}<616eJWR6y%S9P>?@n2` zxmXSE?;J@Ad!=od*r%SSOKF6PTYO1{3rLCjclqrarr@0*52oYsn+E(3c$^cb8k}2v? z0Q$dj&=gH*)!hmOc~ww2qC5)lD-2o;!eRiIK=_dv=QFB&-0d!w?>89Pvx2Dp1%O)t zv@&oK;9u%M=lWFnWH1sp9We9l^5?2j&qERARe;wr(L)3@GjNuGPC!4PsqL5TVlU+{ z-16xH==vHaUShOmJ$u-sppX=Q1EBqmP?-*aSOQS?plJ9o217*eJMW>q6HJek@@F?8 z06L7*dkNn?VBV#rVmqyUJ54av1x`WdGv)(ucI7QVp-AFe5I^l=k$1QO6qb~u46OC* z&k2xq40inx__MScd%N(NBOszS05fd?g`)9~z%=Q)#ae2FBFX^}UULD*)}+v%10dI~ z3H)+ejeU`C;Nb5nfCW~k%-NN6cT`ywV4Ny(lsv)AR{>f`z-l`?X4;lXwQV<^HA~8B z9r)hCUoQw9#N5T8Wk4>+6@A-!^iVItw$=M-~5@y!73Dw+*&Lf5D5$iGJq&;58NH`E^j@NDtSO%%UQ0a;Z$wi(nJ z`OcIdbG`|$Yf1TF89*t3cTk}I^ay2d)@A82@Mt%MrNjpe-fA6WAizrt;pCpr+1nIs z96Ce5!{)U*p`c(ieuS8wxA?oDsq)gIgxQjK+?p5-n{o}5$g4jvzSdH5E=D^=5^yZ7%Ioany(0iI<47hYzv!qS<~>>}w#gRI z9kIlK&H1YjuLs=_(Z?JI49Vc8S^Di00K)p>2L5 zXVl;}-_>~6;G&+(TeL|5$~E$RP@I_YoWB}6C>9-J$6h+PDwW1g2;-khml`2S=>{;{ zF7a8uD_OeuDK(6mO{>FGxGLZJU7vjpGEcC12QK)pT(N4*1`$0`JOlO}lr2`7wt#p| zDSwW|D$q%Q>^uRq4@A4QjT8g8CVV=lE3Z<1o*3> zL+-ePa{XDy@A<;a#geJ0Nhp%&0r4!0({4?bZ@ql1XonVOH4i8(DK{9n$24xnbuA^k z$#1^d)jXh(r1Sv@TM}n)T9s$`j^2fXngy zK$2oyidlbWbX`-$E|x2WLXx7}NMKMCOAMGZXK$0%IMi>qMl@Bfiu$Y4$z+p2XwfIL zFr@d`0vZ`@!e5&PC+pj7yP5_xy=C{jdcEPAZ7{=u+1lS5ue%L&vUW8M$OtMNjc;Qv zdVRfBQ{@jQ8?={pH4n%LCOALwBoQk_7-rICE!l2*hwdd{ueP@Zps}Ei)&c9P{!_i% z2$0vguZ+C_REDDfBmntaYC=ImK|(?P2nYrF<0o=Z8Gio(`m&8@aAGWU00000NkvXX Hu0mjfAFd_o literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/android-96x196.png b/daprdocs/static/favicons/android-96x196.png new file mode 100644 index 0000000000000000000000000000000000000000..5bb6187e564c9210b5489af0d30e4cc2af3cce63 GIT binary patch literal 2776 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 eNXg`#(fkP006*y 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 R>#6_%002ovPDHLkV1nSfycqxh literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/favicon-32x32.png b/daprdocs/static/favicons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..7b3bb04b5f7407f4fb508d2ec05e88620becd09a GIT binary patch literal 923 zcmV;M17!S(P)DY)cEvz0>G8cfOx|_s_KM+--L?cOmvZesk_Q=bqpB zeM8Lf!x`4c|I|S1{`t86?w!e`JLLr0Iu5@LK}SS>>#s_6tPmmh7L+TyZ`}Cc?}5{m1cKy>UK6_zq zYEI5Co=BSzt(Ch`VRG z#Ab+eg1jtB-62^YfyQK(9^4?JUMA5hN`4$oU2<}H-5VewfOiQ@z82w>JTXwd*8OYR zD0Bg-b%3JAH<`sAp>(jtC>S*+?J-^*07le-j8WVK%9$~kivYSrq)!uOOe^Sva1fN` zqp;tnIPb-(Dz7Ay7sB()06H~4o6P=00>0y4i-PR|2MQt3FJZ>8z5(%k&@XN#u^J*D zhFkHVffx+HeInkMbpygdQe9GDGc%@j6Tp)q_`Kv~U)Q8*!#Yi3OFaS8a`iDF-L9QG z?2p8>z5}qTA%PeSh_6J|K8Xxa)S3~e_gnv?Glumuh<3g5uAOZP$w#!tKO?AP&bfB> z)e!RwfW;!rmzLcceuT4* zF`!{lhx}JazM+&i9BUx>n&JQ;TO$*il$3mwK#NgmsWGW9qK%`9_IpsmF$oaIA$T+7 z8Wxcw!Il)d#x>xZcy`|+xtDy7b8A1jSKt35E|K}|hn}HVTU4&jyMp2Fa)eoE9(XE& z#Bagps*gO*ITeSCGlA@^+G8Aq_zU1Wk#u;hD@qc0<-DWLg5`*D*_PS2b z$J1)SzeyGKTIyS1zia2-n^prE(^?DQ>!9)2J~EU&Fs%lfP3t8EoDW5JxpsEXv>MQ2 xP3^^3R887SPIh3j;(lUN0Y47xtbrL%;6Cit&2j~|YfbVMM@V z@C3X-xG!#S2hyQi9i7kj=jZRNFt$Wr6fxQr>#i`i%^2G!qZDO)o*ZLTTeLMWn>*Hs zS7$bk=9%5L)?%wgkt*JuhtHZ~3q0A)f4tM;BGvMq?(f0S18=p=%G|Cz1Mf7q^p2;# ziqv$kRs5@p(KpcilKfkm@KeN8KQ6r%=c$psO3NvJ3oWYUUQb-3FH_=*X3G1DpHTc$ z@rc1=hEh+9F>=07zE~sgz?bu3R=T4!ukX*q(mOC;4t;pcfHl!8Xf02huZDftVXGku zrwN~r4w~`sFfL%O6&22iZ_+6$%Z%6yRQ+kx(c_19^2ZVXf$rxvYhz#zuJz@P!dKp~(AL>x#lFaYJy!Tvy$SU zE$LAQ7djigf@3FxSF=qNUl4=$lx5A{Ut6$bZG^`;5T0$S^lPSp?ElFs0{KpEc~vm wU7C7kW`7+BpPtrRcVa>t2EMX#VKQ=<4}CTRF#jVktbBOD&cJ{TBdZ0m0ow?sga7~l diff --git a/daprdocs/static/favicons/tile150x150.png b/daprdocs/static/favicons/tile150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..17941dae1d804a1687c1d68b90f0267a870e3ff0 GIT binary patch literal 8655 zcmeHtS2WyT_xETa1ks66Li83yjEELww2a=ukVFVkCrb1ZL<~kZB%{|L1krmLqYHjY zbfZP@ME`&DJZt^ede(a1oA>IycrLy-XP>j%*=L{6-rp0h1A|hM-ysKqK$PlgDtaIg z0oC7+>;^F6S$3KW0&#-WRg?@oEw)m9lGzMXN&_t2p9H#XbxD0l-h7+o>GqV=9gN+h ziHU$%FzZJ5fh=t3V-IJE-4&sCBR@%pxNU*RBhk80#n-pRxXDP65dlJq$gbk{deI1><=SY5QXTUQ~7{^nNrbYjX0iz zp${VQ;jj*E*Z>qhu%UBlI9=>F>1Dy|iv(eZxa047b~AA3U_%c^r=LYTx32Uzu0$+2^ z=hpb#<i?n+~xuR1^E3~>CyMkj4+KxlyM+?MZWkK`Eq z@7wbOScYpMr!k8~i2Y#h;$RsnZBcE`(Cdh`)PMYv+VNt8Yu2z^w&J1lY}U6Zvm0ju zxQ5L%BiNCLr}7)zqR`H}qzWjVE|>~S&~iaL`MB>(KUX<|ef=c^kxC$-)(zXbilP!S z9k3I&EWaoSk^F{Y5CR^4U1�AI6Pvk&kWRr1`78(&wGcB5vRc!7kVeiueD2ImmAS zjtJgWb9s$M>;c^x_)DL$=o0FQnXI_KzvvvE9eK=?!z zn?4LD5etE_CGXShQGpIYWO*6POq?G$HF#+%9|uggeU0}xa{INuKI7*+XPpKU)xQ5j zD@NG3>m8`qU@wqto3!fc%RPPSAD@eyHrB2NTo+T3R^9tgV{Wa{=*STMyu0?~Y z`IlJZDVQ!^9KiE0Jxa1H|AOyqYJt zOl+V{XtZp+a9&FAT@Js6gVqIcAgk)q!_?0grVak1+EL3s(ibgao3*QLd{lcKvc$>W z>?+4WzngTNIf9%%;%OA6`R@J226 zpPB~r5PW5VCL@!JLlrK#b-sw?1l4dW&z!QS1{Oa9;v5p7yn@23Nv`#MTt2L3&8?qhAST3Ar)JZsvHOpDX zzpJvTW6x$m+%guEH-G(m%-8mj5Km0Bwo3M@TaqiOOtTfj?u*0@ePrd=~+#=1B;9*7Z`Mqt`(}kDcOvpMM=Lwwzz{j^tv- zPmZdrx{BU|EbM~Dd~L@<;eLbV2h*Nhg>?5+h`II$m{)G_j5eO%?9NmaP6a%g&cpo?k5L;iZjDYd2%grBtxybC1PA2`U zIefu!IZTh~F4dWU6RP<;?sZ`QlPHLY}yAf zJ=?SSVMR70#4Rz3bTMT$%aFobwERe`?IA|2HC_MYxrl4l3AT*O`~jv*TV?djCNosu zxbr!7fz-;FaNijID}|6%74bT7qdUFxB=QQPyyT`f7}3sQhoKzRw%Kw~z?ydGetn2C z9O5|CzpgkA#oKCY1QzjSO-@ZgouYpGA&3`JL1|wq+fzFPb_0lO7}eP6_x#Z-de72s zdTKIwy2m81_GjAs-CGBTn;?a9Q`igP{abp(MZBHw&0`&_9x{ngg+6#bWZO?t zngSld^Or1~^%8sc0b5H7mztz*qag5YF>FeC3zvwTMs*Gc3$36oR@HBM9?2yp%mZJ4cWF^2UMXpCMp9lz&O*V#bAWN zIi^>h;S?v?+aRa|-T+dI-gt3Zoxxu4eLt0BFDIdx-bLF(gKC*-n<4|;x?p*GRzvDo zymg=ucT}&z=+RVLC}jyp$Xa>m^{~K~tzNVM>To(3)9w?oX)3&TzNIR?Jy5Tits^=Y#`(+B{1rDJUdBdn3sMP@@RFfsk=onT>88g`6U>)OK)g73WTeGm2WiN5Pg02skF zQ~m5yLp*mjWY~Vx+()l(ObxBjx=sGU9%db`%rIvwWgoEc`unOHo;0(rSUITjTfxIe zbNElyTHAnS)0^dDvY)bPL&WswSAorx#t!|)L|=P6pKA*9oeaQt%ke(ym(-WfhCGy+ z(Y9e9=reZ})C7Yh6xwFGF)kuhAn6X>t!D?qs3$wlT9!AD3L(QMRO}pSNZFKoQ|K*Y zM9qo{fP1Ik;|m_HW|;sHT+8*SF{L6xInbUrYx3GH*4|jg`&iGqyP`cfo@86JOahs` zDr)#IF^%3|L)k_9HTdt!UE@?WQ zY|x{eX3Wl;y;!S@-ud6oqpr%?c?pq~22wpZXdUEM@eOU7ByMi z{H~=jj-MC{PxI~;>CLqr1h573d9vd4j!)q`=rq{9PUVY&ga@wyrkO286|DK863VBB zY1*pa>fKF`H{*?-^qos-c0Z!zpt|GC@LQ^6zkg|s5OLUNe-t>)2F)I{lfKa?g!<+a zGCfoh>?O}MzY<=MBw8@Fw{W(%w#AyD3T}BjNPRp@_TmI3TcJ;g){bT5iTcqE=S2Nr zX)KGOcIj3zF#F|Ha##!*Mx84CX(qTp)WcTJ%=fT0rW>}@aT-6F4Q-Q)u5N{vhZ7YL zFN~5eO>+N$OPY6OtJ%55LWc9)E)E=qG)cJ@qjqK)asS4F_1&rGuB}Jv67B#R7o4IE z6*Fm^+U;zV=i*vjDUnrfE&iK4S7TRB_$n7}rqoh4%7)xqIoyH`-HI0qnC%kKi|FC2Pyy8v} z@}{7_CT|sytGlaT_hz%#^=R6{Hnq?n%_?C{SlvsRLaW3XlfAka{qry-Wr1=pjR}|G z1WBcG8vrZxChUdkIQwG6GMG_!}jv5U>)Op zU>!7MFV2W?kd-}`$k_Q^>F+UVf#jxZJ?YdHfoF=23^C#P_xT33=rzg9BNm611G@u6 zUPULy-F{t|gtrY=Up_~;9u7*hPBZ?)gjYM)TXM2y%s61NXTTkrLY1hq``)CISv>6#l zD&XgUxgKMP@+ZU6LZtXEArudH6q>hittugOhklNdNC~m|ir!#58N83OuMX>R$UWBp zkL)ws73+<*C7JAe6l>FB-A7uT#pV933kEFpHhASF9WxQR=Kk(AAUkGdN=j9@7LbC z$HxI+o;Ck7dFP{zq=Vr#>wj3yt#ctB_r9`eWS3&gj{3M8G=iQO!yamFmlAqU|Xj*n%yU#{s;LMS7&jr6U&0r$0S)^kb5dCbWcH{%j_5pMz;0t#r)$4h@PF7 z#Nm}_3{+FjPjw^htkgWxa4y2Chz+Q(?jPPHBcEaQI3^gf6rJ4KQ}A0FsK7fhLMM;0 zt)Fw1ckfs~d-rd=@wHEV%{$U&z=PcMTq>L3Uq}Vxqy=ALw%$A*Y0E=XJ>VD>+uGK| zq-w|=(LqR+bF~7kKRL3ZFY*_n`9_kNY`>2+Pvv6 zAfbxeEVoUuN~l&~3%AM}{?NpHQnbzxzI_$?tIE_xP9TCF+KL%Yef(agtQV6|g0nRa zP#042L=rmRxWCH&?O05`tS#AYuq73-`S^BXu$XDkJsFs4bTA%ruJ{aH^Ne%+8E-w@ zY^h0DW@;tJq)uewl<5p|~v47?m-d)C^FER?6Lu4j@D9392tTE19E474C z>0V$}DvqPzJX7|s`^&pKWOY^MN@5gxbk{;a(odH1xw@O(gvP;_?<_jHS#S>DG~TNR zyz6Bz9ap*1QT3y_rHnN$5EG0C1POXFb44re-GAUkJo~eBaWC<`%#JmhuUOa_OsY+- zN!*^bPSIf;R9Z-p_serXCg(b@!GPT;wV`6B=f%v=WexY@T&@UsB@d0?N#~w-UfAZx z5t14?uaYO|CvE|X$0vc8?i=iqWrEMSXo>C=z14hBD{j#&=%)|?y+Ifn&aFIiYt5Cg zU8zPrP|n<4-%#6LY9sx9Vzk#jT?S;o!m9fr@kQ(|f}gRLFc;}vWGdv4>tnnH4tY$E zE!Y&XD?mp zO*h_5?*McRB?(RP?2#x#ScP)n0Z{tkFg&lbriuAc)4xqzLQb~52FFaLi(zO;ctAaj)f*$f_dH3stWRd{wJ#s?X-*)*NoqEoV z`cz1<4xm`Yth_Ea2l$##m=v%PD44jC&0oH$hfJ-WB|-|DM~prWsou_jATxR}6RuvK zzhlCt;8{AcMb8(r`Re+*%};@r;%QBp0W0Cvep&l`cQpKi9@hO^B&$q)F}gMl7KooO z<_~H4R}*DVIltSmnL~Ob4?c_;8+@$|Xar#)zdKL*vQBZIQZ!!3MN_DdZCQfPb(vcc zv9#E!=SX&o)XJHzYZRswe#OsT+T3FY*Q20$y)w75J9;%L!+ExfyU*7=tjmg1Urp;1^Hae-J|Q#s(D^iUd+l-U z`W~X<%5l{zXWnxl=XQ!r3qklx_%NKa-F0W6^q>9pa}`T9}JSm~?;d7!L{d%k!iiQ%((LI2WRE1ScRt?uGQPT=3}ZK;>pe=utd{ zT3^Bqz+3`G{msCmD1LtF5u1C8h}Xo}@0-McRF=XT zh|f*UoQub(r>UjFHg*J71jyiu78xMWM%bo@Q>T%TnmsofgD4pRD(?FqtNFg)Ba2oK zyxnqlD?5sYivxv&Dp(6+U2uROaEd8TtU-U<=)YtWaXw&i(=ZkLy|XiI@UqosD!|8V zEmlLvf5loBW)Zw7Jszt6q|*p-8XN3`r;(%rTZrMdZcDwniP+^Cw8+rEOOG@A&F@lL zFjj*{hfZE}=z$N~Qz}6Pk;SID>+l51kN*8%o|{a$?3`cAnmx{5i3efD(|?#UB?()e z<2y8meK<;|Nl-Wfwy5m0#E#KMAQx=2eQ9z^v2-*C4Y6578_z$bDP@c<6@D!e-E`y8 zU}`pGg#}V{E*GRxi6}C4)&Kwi literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/tile310x150.png b/daprdocs/static/favicons/tile310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..74ee0c75936f753a58a2c4f9461a2a0ade5d5759 GIT binary patch literal 13330 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 literal 0 HcmV?d00001 diff --git a/daprdocs/static/favicons/tile70x70.png b/daprdocs/static/favicons/tile70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..e90849675a028f94a172ae3377c3bb7bcf35b1d1 GIT binary patch literal 3777 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 literal 0 HcmV?d00001 From 1502710ab1e3f070355a9cfd8639ef2ccb45ab70 Mon Sep 17 00:00:00 2001 From: Aaron Crawfis Date: Fri, 9 Oct 2020 15:21:09 -0700 Subject: [PATCH 2/3] Update configuration section (#854) * Enable robots, Update versions, add links * Update left column minimum width * Add Dapr docs image * Update spacing for list pages * Add home image * Update hosting references * Remove extra width * Add favicons * Update configuration section * Fix configuration reference --- OLD/howto/secrets-scopes/README.md | 88 ------ ...g-blocks.md => building-blocks-concept.md} | 0 .../{components.md => components-concept.md} | 0 .../en/docs/concepts/configuration-concept.md | 11 + .../content/en/docs/concepts/configuration.md | 263 ------------------ .../{middleware.md => middleware-concept.md} | 0 ...ervability.md => observability-concept.md} | 0 .../configuration/configuration-overview.md | 169 +++++++++++ .../configuration/control-concurrency.md | 2 +- .../en/docs/operations/configuration/grpc.md | 2 +- .../configuration/invoke-allowlist.md | 62 +++-- .../operations/configuration/secret-scope.md | 115 ++++++++ 12 files changed, 340 insertions(+), 372 deletions(-) delete mode 100644 OLD/howto/secrets-scopes/README.md rename daprdocs/content/en/docs/concepts/{building-blocks.md => building-blocks-concept.md} (100%) rename daprdocs/content/en/docs/concepts/{components.md => components-concept.md} (100%) create mode 100644 daprdocs/content/en/docs/concepts/configuration-concept.md delete mode 100644 daprdocs/content/en/docs/concepts/configuration.md rename daprdocs/content/en/docs/concepts/{middleware.md => middleware-concept.md} (100%) rename daprdocs/content/en/docs/concepts/{observability.md => observability-concept.md} (100%) create mode 100644 daprdocs/content/en/docs/operations/configuration/configuration-overview.md create mode 100644 daprdocs/content/en/docs/operations/configuration/secret-scope.md diff --git a/OLD/howto/secrets-scopes/README.md b/OLD/howto/secrets-scopes/README.md deleted file mode 100644 index ef1a307ef..000000000 --- a/OLD/howto/secrets-scopes/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# Limit the secrets that can be read from secret stores - -Follow [these instructions](../setup-secret-store) to configure secret store for an application. Once configured, any secret defined within that store will be accessible from the Dapr application. - -To limit the secrets to which the Dapr application has access, users can define secret scopes by augmenting existing configuration CRD with restrictive permissions. - -Follow [these instructions](../../concepts/configuration/README.md) to define a configuration CRD. - -## 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: - -Define the following `appconfig.yaml` and apply it to the Kubernetes cluster using the command `kubectl apply -f appconfig.yaml`. - -```yaml -apiVersion: dapr.io/v1alpha1 -kind: Configuration -metadata: - name: appconfig -spec: - secrets: - scopes: - - storeName: kubernetes - defaultAccess: deny -``` - -For applications that need to be deined access to the Kubernetes secret store, follow [these instructions](../configure-k8s/README.md), and add the following annotation to the application pod. - -```yaml -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 - -To allow a Dapr application to have access to only certain secrets, define the following `config.yaml`: - -```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`, whereas some secrets are accessible by the application based on the `allowedSecrets` list. Follow [these instructions](../../concepts/configuration/README.md) to apply configuration to the sidecar. - -## Scenario 3: Deny access to certain senstive secrets in a secret store - -Define the following `config.yaml`: - -```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"] -``` - -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](../../concepts/configuration/README.md) to apply configuration to the sidecar. - -## Permission priority - -The `allowedSecrets` and `deniedSecrets` list values take priorty over the `defaultAccess`. - -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 deneied 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 - - - - diff --git a/daprdocs/content/en/docs/concepts/building-blocks.md b/daprdocs/content/en/docs/concepts/building-blocks-concept.md similarity index 100% rename from daprdocs/content/en/docs/concepts/building-blocks.md rename to daprdocs/content/en/docs/concepts/building-blocks-concept.md diff --git a/daprdocs/content/en/docs/concepts/components.md b/daprdocs/content/en/docs/concepts/components-concept.md similarity index 100% rename from daprdocs/content/en/docs/concepts/components.md rename to daprdocs/content/en/docs/concepts/components-concept.md diff --git a/daprdocs/content/en/docs/concepts/configuration-concept.md b/daprdocs/content/en/docs/concepts/configuration-concept.md new file mode 100644 index 000000000..ab8fe61d3 --- /dev/null +++ b/daprdocs/content/en/docs/concepts/configuration-concept.md @@ -0,0 +1,11 @@ +--- +title: "Configuration" +linkTitle: "Configuration" +weight: 400 +description: "Change the behavior of Dapr sidecars or globally on Dapr system services" +--- + +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. + +Read [this page]({{< ref "configuration-overview.md" >}}) for a list of all configuration options. diff --git a/daprdocs/content/en/docs/concepts/configuration.md b/daprdocs/content/en/docs/concepts/configuration.md deleted file mode 100644 index fc3006fd6..000000000 --- a/daprdocs/content/en/docs/concepts/configuration.md +++ /dev/null @@ -1,263 +0,0 @@ ---- -title: "Configuration" -linkTitle: "Configuration" -weight: 400 -description: "Change the behavior of Dapr sidecars or globally on Dapr system services" ---- - -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. - -## 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. - -## Setting Kubernetes sidecar configuration -In Kubernetes mode the Dapr configuration is a Configuration CRD, that is applied to the cluster. For example; - -```cli -kubectl apply -f myappconfig.yaml -``` - -You can use the Dapr CLI to list the Configuration CRDs - -```cli -dapr configurations -k -``` - -A Dapr sidecar can apply a specific configuration by using a ```dapr.io/config``` annotation. For example: - -```yml - annotations: - dapr.io/enabled: "true" - dapr.io/app-id: "nodeapp" - dapr.io/app-port: "3000" - dapr.io/config: "myappconfig" -``` -Note: There are more [Kubernetes annotations](../../howto/configure-k8s/README.md) available to configure the Dapr sidecar on activation by sidecar Injector system service. - -## Sidecar configuration settings - -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) - -### Tracing - -Tracing configuration turns on tracing for an application. - -The `tracing` section under the `Configuration` spec contains the following properties: - -```yml -tracing: - samplingRate: "1" -``` - -The following table lists the properties for tracing: - -Property | Type | Description ----- | ------- | ----------- -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. - -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 -httpPipeline: - 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](../middleware/README.md) for more information - -### Scoping secrets for secret stores - -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: - -```yml -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. - -See the [Scoping secrets](../../howto/secrets-scopes/README.md) HowTo for examples on how to scope secrets to an application. - -### 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://\/ns/\/\**. 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: - -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 - -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 -kind: Configuration -metadata: - name: default - namespace: default -spec: - mtls: - enabled: true - allowedClockSkew: 15m - workloadCertTTL: 24h -``` - -## References -* [Distributed tracing](../observability/traces.md) -* [Middleware pipelines](../middleware/README.md) -* [Security](../security/README.md) -* [How-To: Configuring the Dapr sidecar on Kubernetes](../../howto/configure-k8s/README.md) diff --git a/daprdocs/content/en/docs/concepts/middleware.md b/daprdocs/content/en/docs/concepts/middleware-concept.md similarity index 100% rename from daprdocs/content/en/docs/concepts/middleware.md rename to daprdocs/content/en/docs/concepts/middleware-concept.md diff --git a/daprdocs/content/en/docs/concepts/observability.md b/daprdocs/content/en/docs/concepts/observability-concept.md similarity index 100% rename from daprdocs/content/en/docs/concepts/observability.md rename to daprdocs/content/en/docs/concepts/observability-concept.md diff --git a/daprdocs/content/en/docs/operations/configuration/configuration-overview.md b/daprdocs/content/en/docs/operations/configuration/configuration-overview.md new file mode 100644 index 000000000..733f4158a --- /dev/null +++ b/daprdocs/content/en/docs/operations/configuration/configuration-overview.md @@ -0,0 +1,169 @@ +--- +title: "Overview of Dapr configuration options" +linkTitle: "Overview" +weight: 100 +description: "Information on Dapr configuration and how to set options for your application" +--- + +## Sidecar configuration + +### Setup sidecar configuration + +#### Self-hosted sidecar +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 +In Kubernetes mode the Dapr configuration is a Configuration CRD, that is applied to the cluster. For example; + +```bash +kubectl apply -f myappconfig.yaml +``` + +You can use the Dapr CLI to list the Configuration CRDs + +```bash +dapr configurations -k +``` + +A Dapr sidecar can apply a specific configuration by using a ```dapr.io/config``` annotation. For example: + +```yml + annotations: + dapr.io/enabled: "true" + dapr.io/app-id: "nodeapp" + dapr.io/app-port: "3000" + dapr.io/config: "myappconfig" +``` +Note: There are more [Kubernetes annotations]({{< ref "kubernetes-annotations.md" >}}) available to configure the Dapr sidecar on activation by sidecar Injector system service. + +### Sidecar configuration settings + +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) + +#### Tracing + +Tracing configuration turns on tracing for an application. + +The `tracing` section under the `Configuration` spec contains the following properties: + +```yml +tracing: + samplingRate: "1" +``` + +The following table lists the properties for tracing: + +| Property | Type | Description | +|--------------|--------|-------------| +| 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. + +See [Observability distributed tracing]({{< ref "tracing.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 +httpPipeline: + 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]({{< ref "middleware-concept.md" >}}) for more information + +#### Scope secret store access + +See the [Scoping secrets]({{< ref "secret-scope.md" >}}) guide for information and examples on how to scope secrets to an application. + +#### Access Control allow lists for service invocation + +See the [Allow lists for service invocation]({{< ref "invoke-allowlist.md" >}}) guide for information and examples on how to set allow lists. + +### Example 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 +``` + +## 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 only set up when Dapr is deployed to Kubernetes. + +### Control-plane configuration settings +A Dapr control plane configuration can configure the following settings: + +| 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 + +See the [Mutual TLS]({{< ref "mtls.md" >}}) HowTo and [security concepts]({{< ref "security-concept.md" >}}) for more information. + +### Example control plane configuration + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Configuration +metadata: + name: default + namespace: default +spec: + mtls: + enabled: true + allowedClockSkew: 15m + workloadCertTTL: 24h +``` diff --git a/daprdocs/content/en/docs/operations/configuration/control-concurrency.md b/daprdocs/content/en/docs/operations/configuration/control-concurrency.md index 79ac056d5..be231ea7b 100644 --- a/daprdocs/content/en/docs/operations/configuration/control-concurrency.md +++ b/daprdocs/content/en/docs/operations/configuration/control-concurrency.md @@ -1,7 +1,7 @@ --- title: "Control concurrency and rate limit applications" linkTitle: "Concurrency & rate limits" -weight: 1000 +weight: 2000 description: "Control how many requests and events will invoke your application simultaneously" --- diff --git a/daprdocs/content/en/docs/operations/configuration/grpc.md b/daprdocs/content/en/docs/operations/configuration/grpc.md index 3f553f9b8..289505281 100644 --- a/daprdocs/content/en/docs/operations/configuration/grpc.md +++ b/daprdocs/content/en/docs/operations/configuration/grpc.md @@ -1,7 +1,7 @@ --- title: "Configure Dapr to use gRPC" linkTitle: "Use gRPC interface" -weight: 3000 +weight: 5000 description: "How to configure Dapr to use gRPC for low-latency, high performance scenarios" --- diff --git a/daprdocs/content/en/docs/operations/configuration/invoke-allowlist.md b/daprdocs/content/en/docs/operations/configuration/invoke-allowlist.md index 47f7d83c1..ac7c02f45 100644 --- a/daprdocs/content/en/docs/operations/configuration/invoke-allowlist.md +++ b/daprdocs/content/en/docs/operations/configuration/invoke-allowlist.md @@ -1,23 +1,49 @@ --- title: "Apply access control list configuration for service invocation" linkTitle: "Service Invocation access control" -weight: 2000 +weight: 4000 description: "Restrict what operations *calling* applications can perform, via service invocation, on the *called* application" --- 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) - +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://\/ns/\/\**. 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. +**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://\/ns/\/\**`. 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 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" ## Policy rules @@ -36,9 +62,10 @@ The action corresponding to the most specific policy matched takes effect as ord ## 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. +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. + +Scenario 1: Deny access to all apps except where trustDomain = public, namespace = default, appId = app1 -### 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 @@ -57,7 +84,8 @@ spec: namespace: "default" ``` -### Scenario 2 : Deny access to all apps except trustDomain = public, namespace = default, appId = app1, operation = op1 +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 @@ -80,7 +108,7 @@ spec: action: allow ``` -### Scenario 3 : Deny access to all apps except when a specific verb for HTTP and operation for GRPC is matched +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 @@ -114,7 +142,7 @@ spec: action: allow ``` -### Scenario 4 : Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/*, all http verbs +Scenario 4: Allow access to all methods except trustDomain = public, namespace = default, appId = app1, operation = /op1/*, all http verbs ```yaml apiVersion: dapr.io/v1alpha1 @@ -136,7 +164,7 @@ spec: 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 +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 @@ -161,7 +189,7 @@ spec: ``` ## 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. +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]({{< ref "configuration-concept.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. @@ -232,7 +260,3 @@ spec: - name: python image: dapriosamples/hello-k8s-python:edge ``` - -## Related Links - -* [Configuration concepts](../../concepts/configuration/README.md) diff --git a/daprdocs/content/en/docs/operations/configuration/secret-scope.md b/daprdocs/content/en/docs/operations/configuration/secret-scope.md new file mode 100644 index 000000000..8d7b68812 --- /dev/null +++ b/daprdocs/content/en/docs/operations/configuration/secret-scope.md @@ -0,0 +1,115 @@ +--- +title: "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 CRD 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. + +Follow [these instructions]({{< ref "configuration-overview.md" >}}) to define a configuration CRD. + +## Configure secrets access + +The `secrets` section under the `Configuration` spec contains the following properties: + +```yml +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 priorty over the `defaultAccess`. + +| 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 deneied 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 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: + +Define the following `appconfig.yaml` and apply it to the Kubernetes cluster using the command `kubectl apply -f appconfig.yaml`. + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Configuration +metadata: + name: appconfig +spec: + secrets: + scopes: + - storeName: kubernetes + defaultAccess: deny +``` + +For applications that need to be deined access to the Kubernetes secret store, follow [these instructions](../configure-k8s/README.md), and add the following annotation to the application pod. + +```yaml +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 + +To allow a Dapr application to have access to only certain secrets, define the following `config.yaml`: + +```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`, whereas some secrets are accessible by the application based on the `allowedSecrets` list. Follow [these instructions](../../concepts/configuration/README.md) to apply configuration to the sidecar. + +### Scenario 3: Deny access to certain senstive secrets in a secret store + +Define the following `config.yaml`: + +```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"] +``` + +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](../../concepts/configuration/README.md) to apply configuration to the sidecar. From d869373979de1bc1cd253932902107b40d868d2b Mon Sep 17 00:00:00 2001 From: Aaron Crawfis Date: Fri, 9 Oct 2020 15:47:28 -0700 Subject: [PATCH 3/3] Complete operations section (#856) * Enable robots, Update versions, add links * Update left column minimum width * Add Dapr docs image * Update spacing for list pages * Add home image * Update hosting references * Remove extra width * Add favicons * Update configuration section * Fix configuration reference * Complete operations section --- .../operations/components/component-scopes.md | 5 +- .../components/component-secrets.md | 4 +- .../operations/monitoring/azure-monitor.md | 12 +-- .../en/docs/operations/monitoring/fluentd.md | 83 +++++++++---------- .../en/docs/operations/security/mtls.md | 2 +- .../en/docs/operations/security/oauth.md | 10 +-- .../troubleshooting/common_issues.md | 22 ++--- ...ng_debugging.md => profiling-debugging.md} | 0 .../reference/api/{README.md => _index.md} | 5 +- 9 files changed, 70 insertions(+), 73 deletions(-) rename daprdocs/content/en/docs/operations/troubleshooting/{profiling_debugging.md => profiling-debugging.md} (100%) rename daprdocs/content/en/docs/reference/api/{README.md => _index.md} (87%) diff --git a/daprdocs/content/en/docs/operations/components/component-scopes.md b/daprdocs/content/en/docs/operations/components/component-scopes.md index 199d22ec5..b4fef96b0 100644 --- a/daprdocs/content/en/docs/operations/components/component-scopes.md +++ b/daprdocs/content/en/docs/operations/components/component-scopes.md @@ -77,4 +77,7 @@ scopes: - app1 - app2 ``` -Watch this [video](https://www.youtube.com/watch?v=8W-iBDNvCUM&feature=youtu.be&t=1765) for an example on how to component scopes with secret components and the secrets API. \ No newline at end of file + +## Example + + \ No newline at end of file diff --git a/daprdocs/content/en/docs/operations/components/component-secrets.md b/daprdocs/content/en/docs/operations/components/component-secrets.md index 6b4cf872f..b281f9fc6 100644 --- a/daprdocs/content/en/docs/operations/components/component-secrets.md +++ b/daprdocs/content/en/docs/operations/components/component-secrets.md @@ -5,6 +5,8 @@ weight: 2000 description: "How to securly reference secrets from a component definition" --- +## Overview + Components can reference secrets for the `spec.metadata` section within the components definition. In order to reference a secret, you need to set the `auth.secretStore` field to specify the name of the secret store that holds the secrets. @@ -13,7 +15,7 @@ When running in Kubernetes, if the `auth.secretStore` is empty, the Kubernetes s ### Supported secret stores -Go to [this](../../howto/setup-secret-store/README.md) link to see all the secret stores supported by Dapr, along with information on how to configure and use them. +Go to [this]({{< ref "howto-secrets.md" >}}) link to see all the secret stores supported by Dapr, along with information on how to configure and use them. ## Non default namespaces diff --git a/daprdocs/content/en/docs/operations/monitoring/azure-monitor.md b/daprdocs/content/en/docs/operations/monitoring/azure-monitor.md index c972c25a2..f26699cba 100644 --- a/daprdocs/content/en/docs/operations/monitoring/azure-monitor.md +++ b/daprdocs/content/en/docs/operations/monitoring/azure-monitor.md @@ -12,12 +12,6 @@ description: "Enable Dapr metrics and logs with Azure Monitor for Azure Kubernet - [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) - [Helm 3](https://helm.sh/) -## Contents - - - [Enable Prometheus metric scrape using config map](#enable-prometheus-metric-scrape-using-config-map) - - [Install Dapr with JSON formatted logs](#install-dapr-with-json-formatted-logs) - - [Search metrics and logs with Azure Monitor](#Search-metrics-and-logs-with-azure-monitor) - ## Enable Prometheus metric scrape using config map 1. Make sure that omsagnets are running @@ -35,9 +29,9 @@ omsagent-smtk7 1/1 Runnin 2. Apply config map to enable Prometheus metrics endpoint scrape. -You can use [azm-config-map.yaml](./azm-config-map.yaml) to enable prometheus metrics endpoint scrape. +You can use [azm-config-map.yaml](/docs/azm-config-map.yaml) to enable prometheus metrics endpoint scrape. -If you installed Dapr to the different namespace, you need to change the `monitor_kubernetes_pod_namespaces` array values. For example; +If you installed Dapr to the different namespace, you need to change the `monitor_kubernetes_pod_namespaces` array values. For example: ```yaml ... @@ -53,7 +47,7 @@ If you installed Dapr to the different namespace, you need to change the `monito Apply config map: -``` +```bash kubectl apply -f ./azm-config.map.yaml ``` diff --git a/daprdocs/content/en/docs/operations/monitoring/fluentd.md b/daprdocs/content/en/docs/operations/monitoring/fluentd.md index f0e99c79b..5d4746e37 100644 --- a/daprdocs/content/en/docs/operations/monitoring/fluentd.md +++ b/daprdocs/content/en/docs/operations/monitoring/fluentd.md @@ -11,33 +11,27 @@ description: "How to install Fluentd, Elastic Search, and Kibana to search logs - [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) - [Helm 3](https://helm.sh/) -## Contents - - - [Install Fluentd, Elastic Search, and Kibana](#install-fluentd-elastic-search-and-kibana) - - [Install Fluentd](#install-fluentd) - - [Install Dapr with JSON formatted logs](#install-dapr-with-json-formatted-logs) - - [Search logs](#search-logs) ## Install Elastic search and Kibana 1. Create namespace for monitoring tool and add Helm repo for Elastic Search -```bash -kubectl create namespace dapr-monitoring -``` + ```bash + kubectl create namespace dapr-monitoring + ``` 2. Add Elastic helm repo -```bash -helm repo add elastic https://helm.elastic.co -helm repo update -``` + ```bash + helm repo add elastic https://helm.elastic.co + helm repo update + ``` 3. Install Elastic Search using Helm By default the chart creates 3 replicas which must be on different nodes. If your cluster has less than 3 nodes, specify a lower number of replicas. For example, this sets it to 1: -``` +```bash helm install elasticsearch elastic/elasticsearch -n dapr-monitoring --set replicas=1 ``` @@ -47,40 +41,41 @@ Otherwise: helm install elasticsearch elastic/elasticsearch -n dapr-monitoring ``` -If you are using minikube or want to disable persistent volumes for development purposes, you can disable it by using the following command. +If you are using minikube or want to disable persistent volumes for development purposes, you can disable it by using the following command: + ```bash helm install elasticsearch elastic/elasticsearch -n dapr-monitoring --set persistence.enabled=false --replicas=1 ``` 4. Install Kibana -```bash -helm install kibana elastic/kibana -n dapr-monitoring -``` + ```bash + helm install kibana elastic/kibana -n dapr-monitoring + ``` 5. Validation -Ensure Elastic Search and Kibana are running in your Kubernetes cluster. - -```bash -kubectl get pods -n dapr-monitoring -NAME READY STATUS RESTARTS AGE -elasticsearch-master-0 1/1 Running 0 6m58s -kibana-kibana-95bc54b89-zqdrk 1/1 Running 0 4m21s -``` + Ensure Elastic Search and Kibana are running in your Kubernetes cluster. + + ```bash + kubectl get pods -n dapr-monitoring + NAME READY STATUS RESTARTS AGE + elasticsearch-master-0 1/1 Running 0 6m58s + kibana-kibana-95bc54b89-zqdrk 1/1 Running 0 4m21s + ``` ## Install Fluentd 1. Install config map and Fluentd as a daemonset -Navigate to the following path if you're not already there (the one this document is in): - -``` -docs/howto/setup-monitoring-tools -``` +Download these config files: +- [fluentd-config-map.yaml](/docs/fluentd-config-map.yaml) +- [fluentd-dapr-with-rbac.yaml](/docs/fluentd-dapr-with-rbac.yaml) > Note: If you already have Fluentd running in your cluster, please enable the nested json parser to parse JSON formatted log from Dapr. +Apply the configurations to your cluster: + ```bash kubectl apply -f ./fluentd-config-map.yaml kubectl apply -f ./fluentd-dapr-with-rbac.yaml @@ -102,11 +97,11 @@ fluentd-sdrld 1/1 Running 0 14s 1. Install Dapr with enabling JSON-formatted logs -```bash -helm repo add dapr https://dapr.github.io/helm-charts/ -helm repo update -helm install dapr dapr/dapr --namespace dapr-system --set global.logAsJson=true -``` + ```bash + helm repo add dapr https://dapr.github.io/helm-charts/ + helm repo update + helm install dapr dapr/dapr --namespace dapr-system --set global.logAsJson=true + ``` 2. Enable JSON formatted log in Dapr sidecar @@ -155,37 +150,37 @@ Handling connection for 5601 3. Click Management -> Index Management -![kibana management](./img/kibana-1.png) +![kibana management](/images/kibana-1.png) 4. Wait until dapr-* is indexed. -![index log](./img/kibana-2.png) +![index log](/images/kibana-2.png) 5. Once dapr-* indexed, click Kibana->Index Patterns and Create Index Pattern -![create index pattern](./img/kibana-3.png) +![create index pattern](/images/kibana-3.png) 6. Define index pattern - type `dapr*` in index pattern -![define index pattern](./img/kibana-4.png) +![define index pattern](/images/kibana-4.png) 7. Select time stamp filed: `@timestamp` -![timestamp](./img/kibana-5.png) +![timestamp](/images/kibana-5.png) 8. Confirm that `scope`, `type`, `app_id`, `level`, etc are being indexed. > Note: if you cannot find the indexed field, please wait. it depends on the volume of data and resource size where elastic search is running. -![indexing](./img/kibana-6.png) +![indexing](/images/kibana-6.png) 9. Click `discover` icon and search `scope:*` > Note: it would take some time to make log searchable based on the data volume and resource. -![discover](./img/kibana-7.png) +![discover](/images/kibana-7.png) -# References +## References * [Fluentd for Kubernetes](https://docs.fluentd.org/v/0.12/articles/kubernetes-fluentd) * [Elastic search helm chart](https://github.com/elastic/helm-charts/tree/master/elasticsearch) diff --git a/daprdocs/content/en/docs/operations/security/mtls.md b/daprdocs/content/en/docs/operations/security/mtls.md index bbdca414f..862a86cd3 100644 --- a/daprdocs/content/en/docs/operations/security/mtls.md +++ b/daprdocs/content/en/docs/operations/security/mtls.md @@ -9,7 +9,7 @@ Dapr supports in-transit encryption of communication between Dapr instances usin Dapr allows operators and developers to bring in their own certificates, or let Dapr automatically create and persist self signed root and issuer certificates. -For detailed information on mTLS, go to the concepts section [here](../../concepts/security/README.md). +For detailed information on mTLS, go to the concepts section [here]({{< ref "security-concept.md" >}}). If custom certificates have not been provided, Dapr will automatically create and persist self signed certs valid for one year. In Kubernetes, the certs are persisted to a secret that resides in the namespace of the Dapr system pods, accessible only to them. diff --git a/daprdocs/content/en/docs/operations/security/oauth.md b/daprdocs/content/en/docs/operations/security/oauth.md index 34bc37614..a56d7453f 100644 --- a/daprdocs/content/en/docs/operations/security/oauth.md +++ b/daprdocs/content/en/docs/operations/security/oauth.md @@ -5,7 +5,7 @@ weight: 2000 description: "Enable OAUTH authorization on Dapr endpoints for your web APIs" --- -Dapr OAuth 2.0 [middleware](../../concepts/middleware/README.md) allows you to enable [OAuth](https://oauth.net/2/) authorization on Dapr endpoints for your web APIs using the [Authorization Code Grant flow](https://tools.ietf.org/html/rfc6749#section-4.1). +Dapr OAuth 2.0 [middleware]({{< ref "middleware-concept.md" >}}) allows you to enable [OAuth](https://oauth.net/2/) authorization on Dapr endpoints for your web APIs using the [Authorization Code Grant flow](https://tools.ietf.org/html/rfc6749#section-4.1). You can also inject authorization tokens into your APIs which can be used for authorization towards external APIs called by your APIs using the [Client Credentials Grant flow](https://tools.ietf.org/html/rfc6749#section-4.4). When the middleware is enabled any method invocation through Dapr needs to be authorized before getting passed to the user code. @@ -73,8 +73,8 @@ spec: ### Define a custom pipeline for an Authorization Code Grant -To use the OAuth middleware (Authorization Code), you should create a [custom pipeline](../../concepts/middleware/README.md) -using [Dapr configuration](../../concepts/configuration/README.md), as shown in the following sample: +To use the OAuth middleware (Authorization Code), you should create a [custom pipeline]({{< ref "middleware-concept.md" >}}) +using [Dapr configuration]({{< ref "configuration-overview" >}}), as shown in the following sample: ```yaml apiVersion: dapr.io/v1alpha1 @@ -130,8 +130,8 @@ spec: ### Define a custom pipeline for a Client Credentials Grant -To use the OAuth middleware (Client Credentials), you should create a [custom pipeline](../../concepts/middleware/README.md) -using [Dapr configuration](../../concepts/configuration/README.md), as shown in the following sample: +To use the OAuth middleware (Client Credentials), you should create a [custom pipeline]({{< ref "middleware-concept.md" >}}) +using [Dapr configuration]({{< ref "configuration-overview.md" >}}), as shown in the following sample: ```yaml apiVersion: dapr.io/v1alpha1 diff --git a/daprdocs/content/en/docs/operations/troubleshooting/common_issues.md b/daprdocs/content/en/docs/operations/troubleshooting/common_issues.md index df2419422..1e7d74bd5 100644 --- a/daprdocs/content/en/docs/operations/troubleshooting/common_issues.md +++ b/daprdocs/content/en/docs/operations/troubleshooting/common_issues.md @@ -81,11 +81,11 @@ The most common cause of this failure is that a component (such as a state store To diagnose the root cause: -- Significantly increase the liveness probe delay - [link](../../howto/configure-k8s/README.md) -- Set the log level of the sidecar to debug - [link](./logs.md#setting-the-sidecar-log-level) -- Watch the logs for meaningful information - [link](./logs.md#viewing-logs-on-kubernetes) +- Significantly increase the liveness probe delay - [link]{{< ref "kubernetes-overview.md" >}}) +- Set the log level of the sidecar to debug - [link]({{< ref "logs.md#setting-the-sidecar-log-level" >}}) +- Watch the logs for meaningful information - [link]({{< ref "logs.md#viewing-logs-on-kubernetes" >}}) -> :bulb: Remember to configure the liveness check delay and log level back to your desired values after solving the problem. +> Remember to configure the liveness check delay and log level back to your desired values after solving the problem. ## I am unable to save state or get state @@ -98,7 +98,7 @@ kubectl get components ``` If there isn't a state store component, it means you need to set one up. -Visit [here](../../howto/setup-state-store/setup-redis.md) for more details. +Visit [here]({{< ref "state-management" >}}) for more details. If everything's set up correctly, make sure you got the credentials right. Search the Dapr runtime logs and look for any state store errors: @@ -118,7 +118,7 @@ kubectl get components ``` If there isn't a pub/sub component, it means you need to set one up. -Visit [here](../../howto/setup-pub-sub-message-broker/README.md) for more details. +Visit [here]({{< ref "pubsub" >}}) for more details. If everything is set up correctly, make sure you got the credentials right. Search the Dapr runtime logs and look for any pub/sub errors: @@ -150,26 +150,26 @@ kubectl logs daprd ## I'm getting 404 Not Found responses when calling Dapr This means you're trying to call an Dapr API endpoint that either doesn't exist or the URL is malformed. -Look at the Dapr API reference [here](../../reference/api/README.md) and make sure you're calling the right endpoint. +Look at the Dapr API reference [here]({{< ref "api" >}}) and make sure you're calling the right endpoint. ## I don't see any incoming events or calls from other services Have you specified the port your app is listening on? In Kubernetes, make sure the `dapr.io/app-port` annotation is specified: -
+```yaml
 annotations:
     dapr.io/enabled: "true"
     dapr.io/app-id: "nodeapp"
-    dapr.io/app-port: "3000"
-
+ dapr.io/app-port: "3000" +``` If using Dapr Standalone and the Dapr CLI, make sure you pass the `--app-port` flag to the `dapr run` command. ## My Dapr-enabled app isn't behaving correctly The first thing to do is inspect the HTTP error code returned from the Dapr API, if any. -If you still can't find the issue, try enabling `debug` log levels for the Dapr runtime. See [here](logs.md) how to do so. +If you still can't find the issue, try enabling `debug` log levels for the Dapr runtime. See [here]({{< ref "logs.md" >}}) how to do so. You might also want to look at error logs from your own process. If running on Kubernetes, find the pod containing your app, and execute the following: diff --git a/daprdocs/content/en/docs/operations/troubleshooting/profiling_debugging.md b/daprdocs/content/en/docs/operations/troubleshooting/profiling-debugging.md similarity index 100% rename from daprdocs/content/en/docs/operations/troubleshooting/profiling_debugging.md rename to daprdocs/content/en/docs/operations/troubleshooting/profiling-debugging.md diff --git a/daprdocs/content/en/docs/reference/api/README.md b/daprdocs/content/en/docs/reference/api/_index.md similarity index 87% rename from daprdocs/content/en/docs/reference/api/README.md rename to daprdocs/content/en/docs/reference/api/_index.md index 978db69ac..03d5ff66d 100644 --- a/daprdocs/content/en/docs/reference/api/README.md +++ b/daprdocs/content/en/docs/reference/api/_index.md @@ -1,4 +1,7 @@ -# Dapr API reference +--- +title: Dapr API reference +linkTitle: "Dapr API" +--- Dapr is language agnostic and provides a RESTful HTTP & gRPC API.