From ab215e6ca0529cef9cf22911b1a7f9c8a0d4f4ee Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 23 Mar 2026 08:08:53 +0800 Subject: [PATCH] Update dashboard configuration docs to match C# source code - dashboard/configuration.mdx: Add missing options (Api section, AI:Disabled, UI:DisableImport, Frontend:MaxConsoleLogCount, Frontend:OpenIdConnect:ClaimActions, Otlp:AllowedCertificates), fix OtlpAuthMode Certificate->ClientCertificate, fix RequireClaimType typo, update UNSECURED_ALLOW_ANONYMOUS to include Api - dashboard/security-considerations.mdx: Split telemetry endpoint section into incoming OTLP and outgoing telemetry API subsections, add standalone mode link - app-host/configuration.mdx: Add MCP endpoint URL, UNSECURED_ALLOW_ANONYMOUS, API_ENABLED, McpApiKey, DashboardApiKey, and auto-configured dashboard env vars (API auth, MCP auth, Kestrel certs) --- .../content/docs/app-host/configuration.mdx | 3 ++ .../content/docs/dashboard/configuration.mdx | 22 +++++++++-- .../dashboard/security-considerations.mdx | 37 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/content/docs/app-host/configuration.mdx b/src/frontend/src/content/docs/app-host/configuration.mdx index 8a6237e63..a0ebfecec 100644 --- a/src/frontend/src/content/docs/app-host/configuration.mdx +++ b/src/frontend/src/content/docs/app-host/configuration.mdx @@ -114,9 +114,11 @@ By default, the dashboard is automatically started by the AppHost. The dashboard | `ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL` | `http://localhost:18889` if no gRPC endpoint is configured. | Configures the dashboard OTLP gRPC address. Used by the dashboard to receive telemetry over OTLP. Set on resources as the `OTEL_EXPORTER_OTLP_ENDPOINT` env var. The `OTEL_EXPORTER_OTLP_PROTOCOL` env var is `grpc`. Automatically generated with _launchSettings.json_ to have a random port on localhost. | | `ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL` | `null` | Configures the dashboard OTLP HTTP address. Used by the dashboard to receive telemetry over OTLP. If only `ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL` is configured then it is set on resources as the `OTEL_EXPORTER_OTLP_ENDPOINT` env var. The `OTEL_EXPORTER_OTLP_PROTOCOL` env var is `http/protobuf`. | | `ASPIRE_DASHBOARD_CORS_ALLOWED_ORIGINS` | `null` | Overrides the CORS allowed origins configured in the dashboard. This setting replaces the default behavior of calculating allowed origins based on resource endpoints. | +| `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`| `false` | Configures the dashboard to not use authentication and accept anonymous access. Sets frontend, OTLP, MCP, and API auth modes to `Unsecured`. | | `ASPIRE_DASHBOARD_FRONTEND_BROWSERTOKEN` | Automatically generated 128-bit entropy token. | Configures the frontend browser token. This is the value that must be entered to access the dashboard when the auth mode is BrowserToken. If no browser token is specified then a new token is generated each time the AppHost is launched. | | `ASPIRE_DASHBOARD_TELEMETRY_OPTOUT` | `false` | Configures the dashboard to never send [usage telemetry](/dashboard/microsoft-collected-dashboard-telemetry/). | | `ASPIRE_DASHBOARD_AI_DISABLED` | `false` | [GitHub Copilot in the dashboard](/dashboard/copilot/) is available when the AppHost is launched by a supported IDE. When set to `true` Copilot is disabled in the dashboard and no Copilot UI is visible. | +| `ASPIRE_DASHBOARD_API_ENABLED` | `true` | Enables the dashboard [telemetry API](/dashboard/configuration/#api) (`/api/telemetry/*`) endpoints. The AppHost always sets this to `true`. | | `ASPIRE_DASHBOARD_FORWARDEDHEADERS_ENABLED` | `false` | Enables the Forwarded headers middleware that replaces the scheme and host values on the Request context with the values coming from the `X-Forwarded-Proto` and `X-Forwarded-Host` headers. | ## Internal @@ -129,6 +131,7 @@ Internal settings are used by the AppHost and integrations. Internal settings ar | `AppHost:Path` | The directory combined with the application name. | The path to the AppHost. It combines the directory with the application name. | | `AppHost:Sha256` | It is created from the AppHost name when the AppHost is in publish mode. Otherwise it is created from the AppHost path. | Hex encoded hash for the current application. The hash is based on the location of the app on the current machine so it is stable between launches of the AppHost. | | `AppHost:OtlpApiKey` | Automatically generated 128-bit entropy token. | The API key used to authenticate requests sent to the dashboard OTLP service. The value is present if needed: the AppHost is in run mode, the dashboard isn't disabled, and the dashboard isn't configured to allow anonymous access with `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`. | +| `AppHost:DashboardApiKey` | Automatically generated 128-bit entropy token. | The API key used to authenticate requests to the dashboard telemetry API. Also used as a fallback for MCP authentication if `AppHost:McpApiKey` is not set. The value is present if needed: the AppHost is in run mode, the dashboard isn't disabled, and the dashboard isn't configured to allow anonymous access. | | `AppHost:BrowserToken` | Automatically generated 128-bit entropy token. | The browser token used to authenticate browsing to the dashboard when it is launched by the AppHost. The browser token can be set by `ASPIRE_DASHBOARD_FRONTEND_BROWSERTOKEN`. The value is present if needed: the AppHost is in run mode, the dashboard isn't disabled, and the dashboard isn't configured to allow anonymous access with `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`. | | `AppHost:ResourceService:AuthMode` | `ApiKey`. If `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS` is true then the value is `Unsecured`. | The authentication mode used to access the resource service. The value is present if needed: the AppHost is in run mode and the dashboard isn't disabled. | | `AppHost:ResourceService:ApiKey` | Automatically generated 128-bit entropy token. | The API key used to authenticate requests made to the AppHost's resource service. The API key can be set by `ASPIRE_DASHBOARD_RESOURCESERVICE_APIKEY`. The value is present if needed: the AppHost is in run mode, the dashboard isn't disabled, and the dashboard isn't configured to allow anonymous access with `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`. | diff --git a/src/frontend/src/content/docs/dashboard/configuration.mdx b/src/frontend/src/content/docs/dashboard/configuration.mdx index 8b6a12a83..9bec472e9 100644 --- a/src/frontend/src/content/docs/dashboard/configuration.mdx +++ b/src/frontend/src/content/docs/dashboard/configuration.mdx @@ -107,7 +107,7 @@ Alternatively, these same values could be configured using a JSON configuration | `ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL`
Default: `http://localhost:18889` | The [OTLP/gRPC](https://opentelemetry.io/docs/specs/otlp/#otlpgrpc) endpoint. This endpoint hosts an OTLP service and receives telemetry using gRPC. When the dashboard is launched by the Aspire AppHost this address is secured with HTTPS. Securing the dashboard with HTTPS is recommended. | | `ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL`
Default: `http://localhost:18890` | The [OTLP/HTTP](https://opentelemetry.io/docs/specs/otlp/#otlphttp) endpoint. This endpoint hosts an OTLP service and receives telemetry using Protobuf over HTTP. When the dashboard is launched by the Aspire AppHost the OTLP/HTTP endpoint isn't configured by default. To configure an OTLP/HTTP endpoint with the AppHost, set an `ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL` env var value in _launchSettings.json_. Securing the dashboard with HTTPS is recommended. | | `ASPIRE_DASHBOARD_MCP_ENDPOINT_URL`
Default: `http://localhost:18891` | The [Aspire MCP](/dashboard/mcp-server/) endpoint. When this value isn't specified then the MCP server is hosted with an `ASPNETCORE_URLS` endpoint. The MCP server can be disabled by configuring `Dashboard:Mcp:Disabled` to `true`. When the dashboard is launched by the Aspire AppHost this address is secured with HTTPS. Securing the dashboard with HTTPS is recommended. | -| `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`
Default: `false` | Configures the dashboard to not use authentication and accepts anonymous access. This setting is a shortcut to configuring `Dashboard:Frontend:AuthMode`, `Dashboard:Otlp:AuthMode` and `Dashboard:Mcp:AuthMode` to `Unsecured`. | +| `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS`
Default: `false` | Configures the dashboard to not use authentication and accepts anonymous access. This setting is a shortcut to configuring `Dashboard:Frontend:AuthMode`, `Dashboard:Otlp:AuthMode`, `Dashboard:Mcp:AuthMode` and `Dashboard:Api:AuthMode` to `Unsecured`. | | `ASPIRE_DASHBOARD_CONFIG_FILE_PATH`
Default: `null` | The path for a JSON configuration file. If the dashboard is being run in a Docker container, then this is the path to the configuration file in a mounted volume. This value is optional. | | `ASPIRE_DASHBOARD_FILE_CONFIG_DIRECTORY`
Default: `null` | The directory where the dashboard looks for key-per-file configuration. This value is optional. | | `ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL`
Default: `null` | The gRPC endpoint to which the dashboard connects for its data. If this value is unspecified, the dashboard shows telemetry data but no resource list or console logs. This setting is a shortcut to `Dashboard:ResourceServiceClient:Url`. | @@ -123,11 +123,13 @@ Browser token authentication works by the frontend asking for a token. The token |--------|-------------| | `Dashboard:Frontend:AuthMode`
Default: `BrowserToken` | Can be set to `BrowserToken`, `OpenIdConnect` or `Unsecured`. `Unsecured` should only be used during local development. It's not recommended when hosting the dashboard publicly or in other settings. | | `Dashboard:Frontend:BrowserToken`
Default: `null` | Specifies the browser token. If the browser token isn't specified, then the dashboard generates one. Tooling that wants to automate logging in with browser token authentication can specify a token and open a browser with the token in the query string. A new token should be generated each time the dashboard is launched. | +| `Dashboard:Frontend:MaxConsoleLogCount`
Default: `10,000` | An optional limit on the number of console log messages to be retained in the viewer. When the limit is reached, the oldest messages are removed. | | `Dashboard:Frontend:PublicUrl`
Default: `null` | Specifies the public URL used to access the dashboard frontend. The public URL is used when constructing links to the dashboard frontend. If a public URL isn't specified, the frontend endpoint is used instead. This setting is important when the dashboard is accessed through a proxy and the dashboard endpoint isn't directly reachable. | | `Dashboard:Frontend:OpenIdConnect:NameClaimType`
Default: `name` | Specifies one or more claim types that should be used to display the authenticated user's full name. Can be a single claim type or a comma-delimited list of claim types. | | `Dashboard:Frontend:OpenIdConnect:UsernameClaimType`
Default: `preferred_username` | Specifies one or more claim types that should be used to display the authenticated user's username. Can be a single claim type or a comma-delimited list of claim types. | | `Dashboard:Frontend:OpenIdConnect:RequiredClaimType`
Default: `null` | Specifies the claim that must be present for authorized users. Authorization fails without this claim. This value is optional. | -| `Dashboard:Frontend:OpenIdConnect:RequiredClaimValue`
Default: `null` | Specifies the value of the required claim. Only used if `Dashboard:Frontend:OpenIdConnect:RequireClaimType` is also specified. This value is optional. | +| `Dashboard:Frontend:OpenIdConnect:RequiredClaimValue`
Default: `null` | Specifies the value of the required claim. Only used if `Dashboard:Frontend:OpenIdConnect:RequiredClaimType` is also specified. This value is optional. | +| `Dashboard:Frontend:OpenIdConnect:ClaimActions`
Default: `null` | An optional list of claim actions to configure on the OpenID Connect options. Each entry specifies a `ClaimType` and `JsonKey`, with optional `SubKey`, `IsUnique`, and `ValueType` properties. | | `Authentication:Schemes:OpenIdConnect:Authority`
Default: `null` | URL to the identity provider (IdP). | | `Authentication:Schemes:OpenIdConnect:ClientId`
Default: `null` | Identity of the relying party (RP). | | `Authentication:Schemes:OpenIdConnect:ClientSecret`
Default: `null` | A secret that only the real RP would know. | @@ -149,10 +151,11 @@ API key authentication works by requiring each OTLP request to have a valid `x-o | Option | Description | |--------|-------------| -| `Dashboard:Otlp:AuthMode`
Default: `Unsecured` | Can be set to `ApiKey`, `Certificate` or `Unsecured`. `Unsecured` should only be used during local development. It's not recommended when hosting the dashboard publicly or in other settings. | +| `Dashboard:Otlp:AuthMode`
Default: `Unsecured` | Can be set to `ApiKey`, `ClientCertificate` or `Unsecured`. `Unsecured` should only be used during local development. It's not recommended when hosting the dashboard publicly or in other settings. | | `Dashboard:Otlp:PrimaryApiKey`
Default: `null` | Specifies the primary API key. The API key can be any text, but a value with at least 128 bits of entropy is recommended. This value is required if auth mode is API key. | | `Dashboard:Otlp:SecondaryApiKey`
Default: `null` | Specifies the secondary API key. The API key can be any text, but a value with at least 128 bits of entropy is recommended. This value is optional. If a second API key is specified, then the incoming `x-otlp-api-key` header value can match either the primary or secondary key. | | `Dashboard:Otlp:SuppressUnsecuredMessage`
Default: `false` | Suppresses the unsecured message displayed in the dashboard when `Dashboard:Otlp:AuthMode` is `Unsecured`. This message should only be suppressed if an external frontdoor proxy is securing access to the endpoint. | +| `Dashboard:Otlp:AllowedCertificates`
Default: `null` | A list of allowed certificate rules for client certificate authentication. Each entry specifies a `Thumbprint` to match against. Only used when `Dashboard:Otlp:AuthMode` is `ClientCertificate`. | ## OTLP CORS @@ -198,6 +201,17 @@ API key authentication works by requiring each MCP request to have a valid `x-mc | `Dashboard:Mcp:PublicUrl`
Default: `null` | Specifies the public URL used to access the MCP server. The public URL is used when constructing links to the MCP server. If a public URL isn't specified, the MCP endpoint is used instead. This setting is important when the dashboard is accessed through a proxy and the dashboard endpoint isn't directly reachable. | | `Dashboard:Mcp:Disabled`
Default: `false` | Disables the MCP server and remove MCP UI in the dashboard. | +## API + +The API section configures authentication for the dashboard's HTTP API endpoints. + +| Option | Description | +|--------|-------------| +| `Dashboard:Api:Enabled`
Default: `false` | Enables the Telemetry HTTP API (`/api/telemetry/*`) endpoints. When `false`, the endpoints are not registered. | +| `Dashboard:Api:AuthMode`
Default: `Unsecured` | Can be set to `ApiKey` or `Unsecured`. `Unsecured` should only be used during local development. If an API key is configured and no auth mode is specified, defaults to `ApiKey`. | +| `Dashboard:Api:PrimaryApiKey`
Default: `null` | Specifies the primary API key. The API key can be any text, but a value with at least 128 bits of entropy is recommended. This value is required if auth mode is API key. | +| `Dashboard:Api:SecondaryApiKey`
Default: `null` | Specifies the secondary API key. The API key can be any text, but a value with at least 128 bits of entropy is recommended. This value is optional. | + ## Resources The dashboard connects to a resource service to load and display resource information. The client is configured in the dashboard for how to connect to the service. @@ -239,7 +253,9 @@ Telemetry limits have different scopes depending upon the telemetry type: | Option | Description | |--------|-------------| | `Dashboard:ApplicationName`
Default: `Aspire` | The application name to be displayed in the UI. This applies only when no resource service URL is specified. When a resource service exists, the service specifies the application name. | +| `Dashboard:AI:Disabled`
Default: `false` | Disables AI features in the dashboard. | | `Dashboard:UI:DisableResourceGraph`
Default: `false` | Disables displaying the resource graph UI in the dashboard. | +| `Dashboard:UI:DisableImport`
Default: `false` | Disables the telemetry import UI in the dashboard. | ## Next steps diff --git a/src/frontend/src/content/docs/dashboard/security-considerations.mdx b/src/frontend/src/content/docs/dashboard/security-considerations.mdx index 87a217bb3..8e6f50a83 100644 --- a/src/frontend/src/content/docs/dashboard/security-considerations.mdx +++ b/src/frontend/src/content/docs/dashboard/security-considerations.mdx @@ -43,6 +43,10 @@ For information about securing the telemetry when running the dashboard in stand The Aspire dashboard provides a variety of ways to view logs, traces, and metrics for your app. This information enables you to track the behavior and performance of your app and to diagnose any issues that arise. It's important that you can trust this information, and a warning is displayed in the dashboard UI if telemetry isn't secured. +When the dashboard is launched by an Aspire AppHost, the OTLP and telemetry API endpoints are both enabled and secured with API key authentication automatically. However, when the dashboard is run in [standalone mode](/dashboard/standalone/), additional configuration is required to enable and secure these endpoints. + +### Incoming OTLP endpoint + The dashboard collects telemetry through an [OTLP (OpenTelemetry protocol)](https://opentelemetry.io/docs/specs/otel/protocol/) endpoint. Apps send telemetry to this endpoint, and the dashboard stores the external information it receives in memory, which is then accessible via the UI. To prevent untrusted apps from sending telemetry to Aspire, the OTLP endpoint should be secured. The OTLP endpoint is automatically secured with an API key when the dashboard is started by Aspire tooling. Additional configuration is required for standalone mode. @@ -87,6 +91,39 @@ builder.Services.Configure( Other languages have different OpenTelemetry APIs. Passing the [`OTEL_EXPORTER_OTLP_HEADERS` environment variable](https://opentelemetry.io/docs/specs/otel/protocol/exporter/) to apps is a universal way to configure the header. +### Telemetry API endpoint + +The dashboard has an optional HTTP API that exposes collected telemetry data as JSON at `/api/telemetry/*` endpoints. The telemetry API allows programmatic access to spans, logs, traces, and resource information stored in the dashboard. Because telemetry data can contain sensitive runtime information, the API is disabled by default and must be explicitly enabled. + +When enabled, the telemetry API is served on the same endpoint as the dashboard frontend (`ASPNETCORE_URLS`). Enable and secure the API with the following configuration: + + +
+ +```bash +docker run --rm -it -d -p 18888:18888 -p 4317:18889 --name aspire-dashboard \ + -e DASHBOARD__API__ENABLED='true' \ + -e DASHBOARD__API__AUTHMODE='ApiKey' \ + -e DASHBOARD__API__PRIMARYAPIKEY='{MY_APIKEY}' \ + mcr.microsoft.com/dotnet/aspire-dashboard:latest +``` + +
+
+ +```powershell +docker run --rm -it -d -p 18888:18888 -p 4317:18889 --name aspire-dashboard ` + -e DASHBOARD__API__ENABLED='true' ` + -e DASHBOARD__API__AUTHMODE='ApiKey' ` + -e DASHBOARD__API__PRIMARYAPIKEY='{MY_APIKEY}' ` + mcr.microsoft.com/dotnet/aspire-dashboard:latest +``` + +
+
+ +When API key authentication is configured, each request to the telemetry API must include a valid `x-api-key` header. If the API is enabled without configuring an auth mode or API key, it defaults to `Unsecured` and a warning is logged at startup. + ## Memory exhaustion The dashboard stores external information it receives in memory, such as resource details and telemetry. While the number of resources the dashboard tracks are bounded, there isn't a limit to how much telemetry apps send to the dashboard. Limits must be placed on how much information is stored to prevent the dashboard using an excessive amount of memory and exhausting available memory on the current machine.