feat(security): authenticate Orleans connections - #10496
Conversation
e4a8494 to
e704c8f
Compare
e704c8f to
583c1a8
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a provider-neutral, fail-closed authentication layer for Orleans connections, enabling workloads (silos and external clients) to prove identity before entering the cluster trust boundary, with Microsoft Entra support as a strict built-in provider. It extends the existing TLS transport security story with separate silo vs gateway TLS configuration, ALPN controls for protocol selection, bounded bearer-token handshakes, and related telemetry, tests, samples, and documentation.
Changes:
- Add authenticated-connection middleware, options/validators, hosting extensions, and telemetry for silo-to-silo and client-to-gateway authentication using a token exchange negotiated via ALPN.
- Add
Microsoft.Orleans.Connections.Security.Entrawith strict OpenID Connect metadata handling, signing-key rollover/last-known-good behavior, and Entra token acquisition/validation, plus a dedicated test project. - Update TLS configuration APIs (separate silo/gateway TLS, ALPN exposure, revocation checking on inbound/outbound) and add a maintained sample + production guidance docs.
Show a summary per file
| File | Description |
|---|---|
| test/Orleans.Connections.Security.Tests/TlsConnectionTests.cs | Adds coverage for separate silo vs gateway TLS configuration, ALPN negotiation, and revocation-check configuration behavior. |
| test/Orleans.Connections.Security.Tests/SiloConnectionAuthenticationContractsTests.cs | Adds unit tests for authentication contracts, options defaults, service registration isolation, and protocol identifiers. |
| test/Orleans.Connections.Security.Tests/ClientConnectionAuthenticationTests.cs | Adds cluster-level coverage for authenticated client-to-gateway connections. |
| test/Orleans.Connections.Security.Entra.Tests/Usings.cs | Adds global xUnit using for the Entra test project. |
| test/Orleans.Connections.Security.Entra.Tests/Orleans.Connections.Security.Entra.Tests.csproj | Introduces a new Entra-focused test project. |
| test/Orleans.Connections.Security.Entra.Tests/EntraTokenProviderTests.cs | Validates token acquisition behavior and secret non-leakage in failures. |
| test/Orleans.Connections.Security.Entra.Tests/EntraTestInfrastructure.cs | Adds test fixtures/utilities for Entra metadata and JWT generation. |
| test/Orleans.Connections.Security.Entra.Tests/EntraOptionsTests.cs | Adds validation tests for secure Entra option configurations and bounds. |
| test/Orleans.Connections.Security.Entra.Tests/EntraMetadataTests.cs | Adds tests for metadata refresh, rollover, throttling, LKG behavior, and bounded queueing. |
| test/Orleans.Connections.Security.Entra.Tests/EntraJwtValidatorTests.cs | Adds extensive JWT validation tests covering issuer/audience/role/caller binding and strict parsing. |
| src/Orleans.Connections.Security/Security/TlsServerAuthenticationOptions.cs | Exposes ALPN ApplicationProtocols on server TLS authentication options. |
| src/Orleans.Connections.Security/Security/TlsOptions.cs | Clarifies revocation-check semantics to apply to both client and server authentication paths. |
| src/Orleans.Connections.Security/Security/TlsClientConnectionMiddleware.cs | Applies certificate revocation mode to outbound TLS handshakes based on CheckCertificateRevocation. |
| src/Orleans.Connections.Security/Security/TlsClientAuthenticationOptions.cs | Exposes ALPN ApplicationProtocols on client TLS authentication options. |
| src/Orleans.Connections.Security/Security/OrleansApplicationProtocol.cs | Adds a typed ALPN constant for the token-authenticated protocol version. |
| src/Orleans.Connections.Security/Orleans.Connections.Security.csproj | Updates package metadata and adds InternalsVisibleTo for test access. |
| src/Orleans.Connections.Security/Hosting/HostingExtensions.SiloAuthentication.cs | Adds hosting extension to configure authenticated silo-to-silo connections (TLS + token auth). |
| src/Orleans.Connections.Security/Hosting/HostingExtensions.ISiloBuilder.cs | Splits TLS configuration into silo vs gateway variants and adds duplicate-configuration guards. |
| src/Orleans.Connections.Security/Hosting/HostingExtensions.IClientBuilder.cs | Adds duplicate-configuration guards for client TLS vs authenticated-client configuration. |
| src/Orleans.Connections.Security/Hosting/HostingExtensions.ClientAuthentication.cs | Adds hosting extensions for authenticated gateway and external client connections. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationTelemetry.cs | Adds bounded metrics and structured logs for connection authentication outcomes and latency. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationRegistration.cs | Introduces registration model, ALPN configuration, and service-key isolation for token auth. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationProtocol.cs | Defines the versioned ALPN identifier for the token-auth wire protocol. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationOptionsValidator.cs | Adds bounded validation (timeouts, sizes, concurrency, TLS policy constraints in Required). |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationOptions.cs | Adds core authentication configuration options (mode, bounds, target host, time provider). |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationMiddleware.cs | Implements inbound/outbound token exchange, framing, bounded work admission, and expiration recycling. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationFeature.cs | Adds a connection feature describing authentication state without leaking mutable principals. |
| src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationBuilder.cs | Adds a builder API for registering token providers/validators with keyed isolation. |
| src/Orleans.Connections.Security/Authentication/AuthenticationWorkLimiter.cs | Adds bounded concurrency/queue admission for authentication work. |
| src/Orleans.Connections.Security/Authentication/AuthenticationAbstractions.cs | Adds public contracts for providers/validators, contexts, failures, and validation results. |
| src/Orleans.Connections.Security.Entra/StrictHttpDocumentRetriever.cs | Adds strict, bounded, redirect-rejecting metadata retrieval restricted to trusted hosts. |
| src/Orleans.Connections.Security.Entra/README.md | Documents Entra package guarantees and operational behavior (LKG, rollover, throttling). |
| src/Orleans.Connections.Security.Entra/Orleans.Connections.Security.Entra.csproj | Introduces the Entra provider package and dependencies. |
| src/Orleans.Connections.Security.Entra/HostingExtensions.cs | Adds UseEntra extension to wire Entra token acquisition/validation into connection authentication. |
| src/Orleans.Connections.Security.Entra/EntraTokenProvider.cs | Implements credential-based token acquisition with minimum-lifetime enforcement. |
| src/Orleans.Connections.Security.Entra/EntraSiloConnectionTokenValidator.cs | Adapts Entra JWT validation errors into bounded Orleans connection-auth failures. |
| src/Orleans.Connections.Security.Entra/EntraSiloConnectionTokenProvider.cs | Adapts Entra access tokens into SiloConnectionToken for outbound connections. |
| src/Orleans.Connections.Security.Entra/EntraSiloConnectionOptionsValidator.cs | Validates Entra options for strict tenant/audience/caller binding and bounded refresh behavior. |
| src/Orleans.Connections.Security.Entra/EntraSiloConnectionOptions.cs | Adds configurable Entra policy surface (audiences, tenants, roles, refresh/backoff bounds). |
| src/Orleans.Connections.Security.Entra/EntraSigningKey.cs | Enforces key-usage and algorithm constraints for signing keys. |
| src/Orleans.Connections.Security.Entra/EntraOpenIdConfigurationProvider.cs | Adds single-flight metadata refresh, LKG, bounded outage behavior, and unknown-key throttling. |
| src/Orleans.Connections.Security.Entra/EntraJwtValidator.cs | Implements strict JWT parsing plus cryptographic validation with strong caller/cluster binding. |
| src/Orleans.Connections.Security.Entra/EntraAuthenticationException.cs | Defines bounded Entra error categories and non-secret-leaking exception messages. |
| src/api/Orleans.Connections.Security/Orleans.Connections.Security.cs | Updates public API surface for connection authentication and new TLS/hosting APIs. |
| src/api/Orleans.Connections.Security.Entra/Orleans.Connections.Security.Entra.cs | Adds generated public API surface for Entra options and hosting extensions. |
| samples/Samples.slnx | Adds the AuthenticatedSiloConnections sample to the samples solution. |
| samples/README.md | Documents the new sample in the samples index. |
| samples/gallery.json | Registers the new sample in the gallery manifest. |
| samples/AuthenticatedSiloConnections/SiloAuthentication.cs | Sample wiring for authenticated silo + authenticated client gateway policies. |
| samples/AuthenticatedSiloConnections/SampleOptions.cs | Sample configuration model and validation for TLS and Entra settings. |
| samples/AuthenticatedSiloConnections/README.md | Sample setup, rollout guidance, negative testing checklist, and operational guidance. |
| samples/AuthenticatedSiloConnections/Program.cs | Sample host bootstrapping with explicit workload credential and OTEL metrics. |
| samples/AuthenticatedSiloConnections/Directory.Packages.props | Central package versioning for the sample. |
| samples/AuthenticatedSiloConnections/ClientAuthentication.cs | Sample wiring for an external authenticated Orleans client. |
| samples/AuthenticatedSiloConnections/AuthenticatedSiloConnections.csproj | Adds the sample project (net10.0) and references required packages. |
| samples/AuthenticatedSiloConnections/appsettings.json | Provides a placeholder configuration template for the sample. |
| Orleans.slnx | Adds the new Entra project and Entra test project to the main solution. |
| docs/site/src/content/docs/tutorials-and-samples/index.md | Adds the new sample to the docs samples list. |
| docs/site/src/content/docs/toc.yml | Adds a new docs entry for authenticated Orleans connections. |
| docs/site/src/content/docs/host/transport-layer-security.md | Updates guidance to reflect revocation behavior and links to authenticated connections docs. |
| docs/site/src/content/docs/host/snippets/snippets.sln | Adds the new authenticated-connections snippets project to the snippets solution. |
| docs/site/src/content/docs/host/snippets/authenticated-silo-connections/csharp/AuthenticatedSiloConnections.Snippets.csproj | Adds a snippets project that compiles linked sample sources for docs. |
| docs/site/src/content/docs/host/authenticated-silo-connections.md | Adds production guidance for authenticated silo/client connections, rollout, and monitoring. |
| docs/site/src/content/docs/deployment/production-readiness.md | Updates production checklist to include workload authentication and negative testing. |
| docs/site/src/content/docs/deployment/networking.md | Updates networking guidance to reference authenticated connections when needed. |
| Directory.Packages.props | Adds identity model package versions required by the Entra implementation. |
Review details
Tip
Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Suppressed comments (1)
src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationMiddleware.cs:733
- This path disposes
admission,linked, andtimeoutinside ausing (admission)/using (timeout)scope right before callingRunAcceptedAsync. That pattern is easy to misread and could become unsafe if the limiter ever returns a disposable which is not idempotent. Consider refactoring so theusingscopes end before the call toRunAcceptedAsync, allowing normal scope-based disposal (and avoiding the need for manualDispose()calls).
- Files reviewed: 66/66 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
Review details
Suppressed comments (1)
src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationMiddleware.cs:202
- Telemetry in Abort() always tags the attempted protocol as Version2, even when the connection didn't negotiate the auth ALPN (e.g., missing/unknown ALPN or baseline). This can misattribute failures/latency to the auth protocol and makes the "protocol.version" dimension less reliable for monitoring/rollout decisions.
Consider deriving a bounded protocol tag from the negotiated ALPN (Version2/Orleans1//) and using that for RecordAttempt/RecordEvent.
- Files reviewed: 66/66 changed files
- Comments generated: 0 new
- Review effort level: Lite
0e70416 to
6edaee8
Compare
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Connections.Security.Entra/EntraJwtValidator.cs:241
- ValidateUntrustedClaims is invoked twice for the same token: once before signature validation (ValidateAsync) and again in ValidateTrustedClaims. This duplicates work and can introduce a small time-of-check/time-of-use edge case for the remaining-lifetime check (a token near the MinimumRemainingTokenLifetime threshold could pass the first check and fail the second after signature validation latency). Consider removing the second call and keeping ValidateTrustedClaims focused on issuer/tenant binding, since the other claim invariants were already checked.
throw new EntraAuthenticationException(EntraAuthenticationError.InvalidToken);
}
ValidateUntrustedClaims(document, clusterId);
}
- Files reviewed: 67/67 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Connections.Security/Hosting/HostingExtensions.ISiloBuilder.cs:202
- The exception message thrown when no certificate is configured is missing a trailing period and is ambiguous now that silo and gateway TLS can be configured independently. Consider making the message more descriptive (e.g., “No TLS certificate was specified.”) to help users diagnose which configuration is missing.
- Files reviewed: 72/72 changed files
- Comments generated: 0 new
- Review effort level: Lite
|
The retried Documentation workflow still fails in the link audit because both newly introduced targets return 404: the |
3ee0724 to
d70ea30
Compare
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
docs/site/src/content/docs/resources/nuget-packages.md:32
- This table presents
Microsoft.Orleans.Connections.Security.Entraas an installable NuGet package, but it is not available on nuget.org yet (the linked page will 404). To avoid misleading readers, please note that it's not yet published (or remove it from the NuGet table until publication).
| [Microsoft.Orleans.Connections.Security.Entra](https://www.nuget.org/packages/Microsoft.Orleans.Connections.Security.Entra) | Microsoft Entra workload authentication for Orleans connections. |
- Files reviewed: 71/71 changed files
- Comments generated: 0 new
- Review effort level: Lite
b77ba83 to
bbac81f
Compare
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Connections.Security/Authentication/SiloConnectionAuthenticationFeature.cs:73
ClonePrincipalenumeratesprincipal.Identitiestwice (Count()+foreach). Besides extra work, this can also produce incorrect sizing if the identities enumerable were ever non-repeatable. Prefer cloning in a single pass (e.g.,Select(...).ToArray()).
- Files reviewed: 74/74 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Add a bounded bearer-token handshake for silo-to-silo connections and an Entra workload identity provider with strict JWT and metadata validation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1a69ae4d-a036-4ccd-9a33-1e97fd1378cf
Use the finalized bounded authentication options, configure cluster audience binding and the security meter, and keep Required mode on built-in certificate validation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Include the source-backed authenticated silo example in the aggregate host snippets solution. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Add independent gateway and external-client TLS plus bearer-token authentication using the existing generic and Entra mechanisms. Preserve silo registration compatibility, isolate client policies, and extend samples, docs, telemetry, API surfaces, and integration coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Apply CheckCertificateRevocation consistently to TLS client and server authentication, cover both silo and external-client outbound paths, and align the TLS guidance. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Document secure topology planning, Entra and certificate provisioning, silo and client configuration, fail-closed test cases, staged rollout, monitoring, rotation, incident recovery, and production readiness. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
State that authenticated silos and clients are admitted into the same coarse-grained trust boundary, that Orleans does not sandbox clients per grain call, and that configured storage and providers are trusted cluster infrastructure. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Use package references and sample-local central package versions so the authenticated connections sample satisfies the standalone sample validation introduced on main. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Register and localize the compiled connection-security snippets, document the Entra package, and account for sample and package URLs which become available after publication. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Reference the shared test infrastructure and assign the Entra test classes to the standard BVT, provider, category, and security-area traits used by filtered CI runs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
Remove redundant namespace imports from the authenticated connection sample and its compiled documentation snippet. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e71c4ddd-5362-4204-910f-9a742ddd63de
e3a68c2 to
3d1ebc3
Compare
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It introduces a large, security-critical transport authentication surface area (runtime, hosting APIs, provider package, docs, and samples) that warrants final human review for threat-model correctness and compatibility impact.
Review tier: Lite
Findings: None
Orleans TLS encrypted transport but did not provide a built-in way for silos and external clients to prove workload identity before entering the cluster trust boundary. This adds a fail-closed, provider-neutral authentication layer so deployments can admit only explicitly authorized workloads.
The change:
Disabled,Audit, andRequiredrollout modes without unauthenticated fallback inRequiredThe trust model is intentionally coarse-grained: an authenticated silo or Orleans client is admitted into the same trusted cluster boundary and is not sandboxed per grain call. Configured membership, storage, reminder, and stream providers and their data are trusted infrastructure. The documentation makes these assumptions explicit.
Microsoft Reviewers: Open in CodeFlow