Skip to content

feat(router): add TLS support for NATS event source#2608

Closed
vatsalpatel wants to merge 3 commits intowundergraph:mainfrom
vatsalpatel:feat/nats-tls
Closed

feat(router): add TLS support for NATS event source#2608
vatsalpatel wants to merge 3 commits intowundergraph:mainfrom
vatsalpatel:feat/nats-tls

Conversation

@vatsalpatel
Copy link
Copy Markdown

@vatsalpatel vatsalpatel commented Mar 9, 2026

Add a tls block to NatsEventSource supporting four modes: no TLS (omit block), skip verify, custom CA (1-way TLS), and mTLS.

  • New NatsTLSConfiguration struct with insecure_skip_verify, ca_file, cert_file, and key_file fields
  • TLS option building in buildNatsOptions via nats.Secure(tlsCfg); cert/key pair validated together, missing CA file surfaced at startup
  • config.schema.json updated with tls object (additionalProperties: false)
  • Golden fixture updated
  • Tests for all modes and error paths in both config_events_nats_test.go and provider_builder_test.go

Closes #2582

Summary by CodeRabbit

  • New Features
    • NATS event sources now support TLS/mTLS: insecure-skip-verify, CA file, client cert and key, and will enable secure and mutual TLS connections to NATS servers (with warnings for insecure settings).
  • Schema
    • Configuration schema updated to accept a new TLS block for NATS providers.
  • Tests
    • Added validation and unit tests covering valid/invalid TLS configurations and related error cases.

Checklist

  • I have discussed my proposed changes in an issue and have received approval to proceed.
  • I have followed the coding standards of the project.
  • Tests or benchmarks have been added or updated.
  • Documentation has been updated on https://github.com/wundergraph/cosmo-docs.
  • I have read the Contributors Guide.

  Add a \`tls\` block to \`NatsEventSource\` supporting four modes: no TLS
  (omit block), skip verify, custom CA (1-way TLS), and mTLS.

  - New \`NatsTLSConfiguration\` struct with \`insecure_skip_verify\`,
    \`ca_file\`, \`cert_file\`, and \`key_file\` fields
  - TLS option building in \`buildNatsOptions\` via \`nats.Secure(tlsCfg)\`;
    cert/key pair validated together, missing CA file surfaced at startup
  - \`config.schema.json\` updated with \`tls\` object
    (\`additionalProperties: false\`)
  - Golden fixture updated
  - Tests for all modes and error paths in both \`config_events_nats_test.go\`
    and \`provider_builder_test.go\`

  Closes wundergraph#2582
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 9, 2026

Walkthrough

Adds TLS support for NATS event sources: new NatsTLSConfiguration type and optional TLS field on NatsEventSource, JSON schema and fixture updates, TLS-aware option construction in the NATS provider builder (skip-verify, custom CA, mTLS), and unit tests for TLS behaviors and validation.

Changes

Cohort / File(s) Summary
Config types & schema
router/pkg/config/config.go, router/pkg/config/config.schema.json
Added NatsTLSConfiguration and TLS *NatsTLSConfiguration on NatsEventSource; extended JSON schema with events.providers.nats[].tls properties (insecure_skip_verify, ca_file, cert_file, key_file).
Config tests & fixture
router/pkg/config/config_events_nats_test.go, router/pkg/config/testdata/config_full.json
Added tests for valid insecure-skip-verify, file-path TLS, and unknown TLS field validation; updated golden fixture to include TLS entries (null).
NATS provider TLS logic
router/pkg/pubsub/nats/provider_builder.go
Constructs tls.Config when eventSource.TLS present: handles InsecureSkipVerify, loads CA into RootCAs, loads cert/key pair for mTLS (validates presence), returns errors on file/parse failures, and appends nats.Secure(tlsCfg) to options.
NATS provider TLS tests & helpers
router/pkg/pubsub/nats/provider_builder_test.go
Added TestBuildNatsOptionsWithTLS with subtests covering insecure skip-verify, missing files, mTLS requirements, and success cases; added helpers to generate/write PEM certs for tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding TLS support to the NATS event source, which is the primary objective of this changeset.
Linked Issues check ✅ Passed All coding requirements from issue #2582 are met: NatsTLSConfiguration struct added, TLS field added to NatsEventSource, buildNatsOptions implements TLS with all four modes, schema updated, golden fixture updated, and comprehensive tests added.
Out of Scope Changes check ✅ Passed All changes directly support the TLS feature implementation; no unrelated modifications detected in config structs, schema, provider builder, test files, or golden fixtures.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vatsalpatel
Copy link
Copy Markdown
Author

Link to the docs PR - wundergraph/cosmo-docs#261

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
router/pkg/config/config.schema.json (1)

2584-2609: Consider adding dependencies constraint for cert_file/key_file mutual requirement.

Other TLS configurations in this schema (e.g., tls.client.all at lines 476-479 and tls.client.subgraphs at lines 509-512) enforce that cert_file and key_file must be provided together using a dependencies constraint. The new NATS TLS configuration is missing this, which could allow users to provide an incomplete mTLS configuration that would only be caught at runtime.

📋 Suggested schema addition for consistency
                     "key_file": {
                       "type": "string",
                       "description": "Path to the client private key file (PEM) for mTLS.",
                       "format": "file-path"
                     }
+                  },
+                  "dependencies": {
+                    "cert_file": ["key_file"],
+                    "key_file": ["cert_file"]
                   }
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router/pkg/config/config.schema.json` around lines 2584 - 2609, The tls
object for the NATS provider allows cert_file and key_file to be set
independently, which can lead to incomplete mTLS configs; update the tls schema
to enforce that cert_file and key_file are provided together by adding a
dependencies constraint (or dependentRequired) on the tls object so that
"cert_file" requires "key_file" and "key_file" requires "cert_file" (i.e., make
cert_file and key_file mutually required under the tls properties).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@router/pkg/pubsub/nats/provider_builder.go`:
- Around line 141-149: The TLS setup currently allows providing
cert_file/key_file without ca_file and silently uses the host trust store;
update the logic around eventSource.TLS handling in provider_builder.go so that
if eventSource.TLS.CertFile or KeyFile is set (i.e., mTLS is being configured)
you validate that eventSource.TLS.CAFile is also non-empty and return an error
(similar format to the existing fmt.Errorf messages) if it is missing; keep the
existing certificate loading (tls.LoadX509KeyPair) and assignment to
tlsCfg.Certificates but add the explicit CA file presence check before
proceeding to ensure private CA verification fails fast rather than during
handshake.

---

Nitpick comments:
In `@router/pkg/config/config.schema.json`:
- Around line 2584-2609: The tls object for the NATS provider allows cert_file
and key_file to be set independently, which can lead to incomplete mTLS configs;
update the tls schema to enforce that cert_file and key_file are provided
together by adding a dependencies constraint (or dependentRequired) on the tls
object so that "cert_file" requires "key_file" and "key_file" requires
"cert_file" (i.e., make cert_file and key_file mutually required under the tls
properties).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df8eafb0-cfac-43c1-8038-a6c7af8dce1e

📥 Commits

Reviewing files that changed from the base of the PR and between 26e20a2 and 06a14c7.

📒 Files selected for processing (6)
  • router/pkg/config/config.go
  • router/pkg/config/config.schema.json
  • router/pkg/config/config_events_nats_test.go
  • router/pkg/config/testdata/config_full.json
  • router/pkg/pubsub/nats/provider_builder.go
  • router/pkg/pubsub/nats/provider_builder_test.go

Comment thread router/pkg/pubsub/nats/provider_builder.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
router/pkg/pubsub/nats/provider_builder_test.go (1)

70-142: Good coverage for TLS validation error paths.

The tests effectively verify all failure modes: missing/unreadable CA file, mismatched cert/key, and mTLS without CA. This ensures configuration errors fail fast at startup.

Consider adding a positive test with real (or generated) test certificates to verify the happy path for CA loading and mTLS configuration. This would catch regressions in the certificate parsing logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router/pkg/pubsub/nats/provider_builder_test.go` around lines 70 - 142, Add a
positive integration test to TestBuildNatsOptionsWithTLS that generates
temporary test certificates (CA, server/client cert+key), writes them to temp
files, and calls buildNatsOptions with TLS configured to use the generated
ca_file, cert_file and key_file; assert no error is returned and that returned
opts include the TLS option (or that TLS handshake-related option is present) to
ensure CA loading and mTLS parsing succeed; use helper functions inside the test
to generate and cleanup the temp cert/key files and reference buildNatsOptions
and TestBuildNatsOptionsWithTLS to locate where to add the test.
router/pkg/pubsub/nats/provider_builder.go (1)

120-156: Set MinVersion on the TLS configuration.

The tls.Config omits MinVersion, allowing negotiation down to TLS 1.0 (server) or 1.2 (client). For a production-grade router, explicitly setting a minimum version hardens the connection against downgrade attacks.

Proposed fix
 	if eventSource.TLS != nil {
 		tlsCfg := &tls.Config{
 			InsecureSkipVerify: eventSource.TLS.InsecureSkipVerify,
+			MinVersion:         tls.VersionTLS12,
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router/pkg/pubsub/nats/provider_builder.go` around lines 120 - 156, The TLS
config created for NATS (tlsCfg in the eventSource.TLS handling) lacks a
MinVersion, so set tlsCfg.MinVersion = tls.VersionTLS12 (or tls.VersionTLS13 if
you want to require TLS1.3) before passing it to nats.Secure; update the block
that builds tlsCfg (the code creating tls.Config, adding RootCAs and
Certificates) to explicitly assign MinVersion to enforce a minimum TLS version
for the NATS provider.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@router/pkg/pubsub/nats/provider_builder_test.go`:
- Around line 70-142: Add a positive integration test to
TestBuildNatsOptionsWithTLS that generates temporary test certificates (CA,
server/client cert+key), writes them to temp files, and calls buildNatsOptions
with TLS configured to use the generated ca_file, cert_file and key_file; assert
no error is returned and that returned opts include the TLS option (or that TLS
handshake-related option is present) to ensure CA loading and mTLS parsing
succeed; use helper functions inside the test to generate and cleanup the temp
cert/key files and reference buildNatsOptions and TestBuildNatsOptionsWithTLS to
locate where to add the test.

In `@router/pkg/pubsub/nats/provider_builder.go`:
- Around line 120-156: The TLS config created for NATS (tlsCfg in the
eventSource.TLS handling) lacks a MinVersion, so set tlsCfg.MinVersion =
tls.VersionTLS12 (or tls.VersionTLS13 if you want to require TLS1.3) before
passing it to nats.Secure; update the block that builds tlsCfg (the code
creating tls.Config, adding RootCAs and Certificates) to explicitly assign
MinVersion to enforce a minimum TLS version for the NATS provider.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3107542d-24f7-4582-bc66-2a96cff032e4

📥 Commits

Reviewing files that changed from the base of the PR and between 06a14c7 and 526ab76.

📒 Files selected for processing (2)
  • router/pkg/pubsub/nats/provider_builder.go
  • router/pkg/pubsub/nats/provider_builder_test.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
router/pkg/pubsub/nats/provider_builder_test.go (1)

92-92: Consider documenting or extracting the magic number 7.

The len(opts) > 7 assertion appears in multiple tests (here and in the existing tests at lines 53 and 75). This value represents the count of base NATS options, but if buildNatsOptions adds or removes base options, these assertions become silently incorrect.

A small comment documenting what the 7 base options are would improve maintainability.

Also applies to: 165-165, 183-183

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router/pkg/pubsub/nats/provider_builder_test.go` at line 92, The test uses a
magic number 7 when asserting len(opts) > 7; replace that literal with a named
constant or computed expected count and document the base options so the
assertion stays correct when buildNatsOptions changes. Concretely, introduce a
constant like baseNatsOptionsCount (or a helper getBaseNatsOptionsCount()) and
use require.Greater(t, len(opts), baseNatsOptionsCount) (or require.Greater(t,
len(opts), baseNatsOptionsCount+1) for the TLS case), and add a brief comment
listing the base option names to explain what the constant represents; update
all occurrences that currently use the literal 7 and reference buildNatsOptions
and the opts variable when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@router/pkg/pubsub/nats/provider_builder_test.go`:
- Line 92: The test uses a magic number 7 when asserting len(opts) > 7; replace
that literal with a named constant or computed expected count and document the
base options so the assertion stays correct when buildNatsOptions changes.
Concretely, introduce a constant like baseNatsOptionsCount (or a helper
getBaseNatsOptionsCount()) and use require.Greater(t, len(opts),
baseNatsOptionsCount) (or require.Greater(t, len(opts), baseNatsOptionsCount+1)
for the TLS case), and add a brief comment listing the base option names to
explain what the constant represents; update all occurrences that currently use
the literal 7 and reference buildNatsOptions and the opts variable when making
the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2dfd87a2-499a-4968-b82b-6c8e58991a44

📥 Commits

Reviewing files that changed from the base of the PR and between 526ab76 and d5934d9.

📒 Files selected for processing (1)
  • router/pkg/pubsub/nats/provider_builder_test.go

@github-actions
Copy link
Copy Markdown

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions github-actions Bot added the Stale label Mar 24, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 7, 2026

Closed as inactive. Feel free to reopen if this PR is still being worked on.

@github-actions github-actions Bot closed this Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(router): add TLS support for NATS event source (skip verify, custom CA, mTLS)

1 participant