Enable RavenDB secured mode for filtered Hub/Sink pull replication#4
Enable RavenDB secured mode for filtered Hub/Sink pull replication#4Mateosssss wants to merge 5 commits into
Conversation
WithFiltering = true on Hub Pull Replication requires a secured (TLS) RavenDB server, so the AppHost now runs RavenDB in secured mode: - Generate a self-signed server certificate (<=4 months, per Developer license limits) and a sink replication certificate; both are mounted into the RavenDB container and injected into clients via Aspire__RavenDB__Client__CertificatePath - Bind RavenDB on a single host-mapped port (9534) reachable from both host and container, overriding Aspire's hardcoded 443 endpoint - Accept the self-signed cert in all .NET clients via RequestExecutor.RemoteCertificateValidationCallback - Guard Enterprise-only features (Remote Attachments, Time Series, AI Agent, GenAI tasks, Queue ETL) with try/catch, since secured mode now enforces license checks previously skipped silently - Pass the server cert to the Sink database client in 005_ConfigureHubSink for authenticated database creation - Fix a pre-existing build error in VerityAgentApi (body.UserId does not exist on GenerateAuditRequest) - Document installing the client certificate for RavenDB Studio access in README
…o English Replace inline env var name string literals in AppHost.cs with named consts (matching the existing envXxx pattern) and translate Polish migration comments in 005_ConfigureHubSink.cs to English.
License-guard catches were added defensively but the project requires a Developer license, so these operations always succeed. Letting failures propagate makes startup failures visible rather than silently skipped.
There was a problem hiding this comment.
Pull request overview
Enables RavenDB secured (TLS) mode in the Aspire AppHost so Hub → Sink pull replication can run with WithFiltering = true, and wires certificates/config needed for end-to-end filtered replication.
Changes:
- Switch RavenDB from unsecured to secured mode in the AppHost, generating/mounting certificates and overriding the secured endpoint port mapping to
9534. - Extend the setup/migrations flow to register Hub access + configure the Sink pull replication task with certificate-based authentication and allowed paths.
- Apply self-signed cert acceptance for RavenDB client calls across services; fix a pre-existing
VerityAgentApilogging/build issue; update README with Studio certificate steps.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/RavenDB.Samples.Verity.Setup/Program.cs | Adds RavenDB TLS cert-chain acceptance and passes new cert-related env vars into migration context. |
| src/RavenDB.Samples.Verity.Setup/Migrations/MigrationContext.cs | Extends migration context with sink certs + server cert path. |
| src/RavenDB.Samples.Verity.Setup/Migrations/005_ConfigureHubSink.cs | Creates Hub with filtering, registers Hub access, creates sink DB, configures sink pull replication with cert + allowed paths. |
| src/RavenDB.Samples.Verity.Setup/Migrations/004_ConfigureQueueEtl.cs | Minor whitespace-only change. |
| src/RavenDB.Samples.Verity.Setup/Migrations/003_ConfigureAi.cs | Formatting/whitespace-only changes. |
| src/RavenDB.Samples.Verity.Setup/Migrations/001_ConfigureDatabase.cs | Wraps Remote Attachments configuration in try/catch with warning output. |
| src/RavenDB.Samples.Verity.Setup/Constants.cs | Adds env var names for sink certs + server cert path. |
| src/RavenDB.Samples.Verity.Model/HubSinks/VerityReplicationSink.cs | Adds access name + allowed paths; removes old Create() helper. |
| src/RavenDB.Samples.Verity.Model/HubSinks/VerityReplicationHub.cs | Enables WithFiltering = true. |
| src/RavenDB.Samples.Verity.IdentityServer/Program.cs | Adds RavenDB TLS cert-chain acceptance. |
| src/RavenDB.Samples.Verity.DataSubscriptionsApp/Program.cs | Adds RavenDB TLS cert-chain acceptance. |
| src/RavenDB.Samples.Verity.AppHost/AppHost.cs | Generates certs, configures secured RavenDB + port override, injects cert path into dependent services. |
| src/RavenDB.Samples.Verity.App/Program.cs | Adds RavenDB TLS cert-chain acceptance. |
| src/RavenDB.Samples.Verity.App/Infrastructure/VerityAgentApi.cs | Fixes logging to use user.Id instead of nonexistent body.UserId. |
| README.md | Documents importing the generated PFX for RavenDB Studio access. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Accept self-signed server certs — chain errors only; name and revocation checks still apply. | ||
| RequestExecutor.RemoteCertificateValidationCallback += | ||
| (_, _, _, errors) => (errors & ~SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.None; |
There was a problem hiding this comment.
Fixed in 677aff6 — gated behind DOTNET_ENVIRONMENT == "Development".
| // HubServerInternalUrl: how the Sink (inside the RavenDB container) reaches the Hub. | ||
| // Hub and Sink share the same RavenDB container, so the Hub is reachable at the | ||
| // container's own loopback on the target port (8080 for unsecured RavenDB). | ||
| // Hub and Sink share the same RavenDB container on port 443 in secured mode. |
There was a problem hiding this comment.
Fixed in 677aff6 — updated the comment to say port 9534 and reference the EndpointAnnotation TargetPort override above instead of the toolkit's default 443.
…o dev, fix port comment - 005_ConfigureHubSink: guard RegisterReplicationHubAccessOperation with the same kind of try/catch already used for hub/database creation, so rerunning the migration against an existing access entry doesn't fail - Gate RequestExecutor.RemoteCertificateValidationCallback behind a Development check in all 5 entry points (Setup, App, DataSubscriptionsApp, IdentityServer, AppHost) so TLS chain validation is never relaxed outside local dev - Fix a stale comment in AppHost.cs claiming Hub/Sink share port 443 — the actual port is overridden to 9534 via the EndpointAnnotation TargetPort above
| // 2) Certificate injected by AppHost | ||
| var publicCertBase64 = context.SinkCertPublicBase64; | ||
| var pfxBase64 = context.SinkCertPfxBase64; | ||
|
|
There was a problem hiding this comment.
Fixed in 5053520. Added explicit InvalidOperationException throws at the top of Up() for both SinkCertPublicBase64 and SinkCertPfxBase64 before they're consumed, with messages pointing to the AppHost as the injection source.
| // 4) Create Sink database (if it doesn't exist) | ||
| var serverCert = !string.IsNullOrEmpty(context.ServerCertPath) && File.Exists(context.ServerCertPath) | ||
| ? X509CertificateLoader.LoadPkcs12FromFile(context.ServerCertPath, null) | ||
| : null; | ||
|
|
There was a problem hiding this comment.
Fixed in 5053520. Replaced the null-returning conditional with a mandatory path validation — throws InvalidOperationException if ServerCertPath is missing or the file doesn't exist, then loads the cert unconditionally. The sinkStore always gets a non-null Certificate in secured mode.
…emove unused using - 005_ConfigureHubSink: throw on empty SinkCertPublicBase64/SinkCertPfxBase64 - 005_ConfigureHubSink: make ServerCertPath mandatory in secured mode - Setup/Program.cs: remove unused X509Certificates using
Summary
WithFiltering = trueon Hub Pull Replication (VerityReplicationHub) requires a secured (TLS) RavenDB server. This PR switches the AppHost from unsecured to secured mode and wires up everything needed for the filtered Hub → Sink pull replication to work end-to-end.Aspire__RavenDB__Client__CertificatePath9534) reachable from both host and container, overriding Aspire's hardcoded443endpointRequestExecutor.RemoteCertificateValidationCallback, restricted to Development (chain errors only)005_ConfigureHubSinkfor authenticated database creationVerityAgentApi(body.UserIddoes not exist onGenerateAuditRequest)This is a focused split-out of the replication/secured-mode work from #3, which mixed in unrelated
identitychanges. Base isidentityso the diff only shows replication-related changes; once #1 merges this can be retargeted tomain.Test plan
dotnet buildsucceedsaspire run— verify RavenDB starts in secured mode, hub/sink replication transfersCompanies/Reportsdocuments, and RavenDB Studio is reachable after importingserver.pfx