Skip to content

Enable RavenDB secured mode for filtered Hub/Sink pull replication#4

Open
Mateosssss wants to merge 5 commits into
identityfrom
secured-replication
Open

Enable RavenDB secured mode for filtered Hub/Sink pull replication#4
Mateosssss wants to merge 5 commits into
identityfrom
secured-replication

Conversation

@Mateosssss

@Mateosssss Mateosssss commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

WithFiltering = true on 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.

  • Generate a self-signed server certificate (≤4 months, per Developer license limits) and a sink replication certificate; mount both into the RavenDB container and inject the server cert into all .NET 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, restricted to Development (chain errors only)
  • Guard Remote Attachments with try/catch — secured mode enforces a license check on it that was previously skipped silently. (An earlier license-loading bug also caused 003/004 to need similar guards; that bug is now fixed and they were reverted to fail loudly instead.)
  • 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)
  • README: document installing the generated client certificate into the Windows certificate store for RavenDB Studio access

This is a focused split-out of the replication/secured-mode work from #3, which mixed in unrelated identity changes. Base is identity so the diff only shows replication-related changes; once #1 merges this can be retargeted to main.

Test plan

  • dotnet build succeeds
  • aspire run — verify RavenDB starts in secured mode, hub/sink replication transfers Companies/Reports documents, and RavenDB Studio is reachable after importing server.pfx

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
Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/003_ConfigureAi.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/003_ConfigureAi.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/004_ConfigureQueueEtl.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/005_ConfigureHubSink.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/005_ConfigureHubSink.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Program.cs Outdated
Comment thread src/RavenDB.Samples.Verity.AppHost/AppHost.cs Outdated
Comment thread src/RavenDB.Samples.Verity.AppHost/AppHost.cs Outdated
…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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 VerityAgentApi logging/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.

Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/005_ConfigureHubSink.cs Outdated
Comment thread src/RavenDB.Samples.Verity.Setup/Program.cs Outdated
Comment thread src/RavenDB.Samples.Verity.App/Program.cs Outdated
Comment on lines +9 to +11
// Accept self-signed server certs — chain errors only; name and revocation checks still apply.
RequestExecutor.RemoteCertificateValidationCallback +=
(_, _, _, errors) => (errors & ~SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.None;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 677aff6 — gated behind DOTNET_ENVIRONMENT == "Development".

Comment thread src/RavenDB.Samples.Verity.IdentityServer/Program.cs
Comment thread src/RavenDB.Samples.Verity.AppHost/AppHost.cs Outdated
Comment on lines +159 to +160
// 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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 677aff6 — updated the comment to say port 9534 and reference the EndpointAnnotation TargetPort override above instead of the toolkit's default 443.

Comment thread src/RavenDB.Samples.Verity.Setup/Migrations/003_ConfigureAi.cs
…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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Comment on lines +25 to +28
// 2) Certificate injected by AppHost
var publicCertBase64 = context.SinkCertPublicBase64;
var pfxBase64 = context.SinkCertPfxBase64;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +43 to +47
// 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;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/RavenDB.Samples.Verity.Setup/Program.cs Outdated
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants