Skip to content

fix(security): NATS account boundaries and JetStream API prefixes [GNICFD-5354]#180

Open
dmathur0 wants to merge 1 commit into
mainfrom
davesh/nats-account-auth-gnicfd-5354
Open

fix(security): NATS account boundaries and JetStream API prefixes [GNICFD-5354]#180
dmathur0 wants to merge 1 commit into
mainfrom
davesh/nats-account-auth-gnicfd-5354

Conversation

@dmathur0

@dmathur0 dmathur0 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Cherry-picks c8845e1 onto main so GitLab MR image builds can publish test images.
  • Adds configurable JetStream API prefixes per stream so render consumers/admin APIs can reach account-scoped / imported streams (e.g. Nautobot via $JS.CEREBRO.API).
  • Wires the prefixes through Helm values, vault/kubernetes secret ini generation, config helpers, pull consumers, and admin consumer APIs.

Test plan

  • Confirm GitLab MR pipeline runs docker-build-mr-amd64 / docker-build-mr-arm64 / docker-manifest-mr
  • Verify images tagged with $CI_COMMIT_SHORT_SHA land in the internal registry
  • Unit tests for pull consumer + admin API prefix selection pass
  • In a multi-account NATS env, set externalServices.nats.streams.nautobot.apiPrefix to $JS.CEREBRO.API and confirm Nautobot consumer connects; kiwi streams remain on $JS.API

Summary by CodeRabbit

  • New Features
    • Added per-stream JetStream API prefix configuration for config-manager, render-change, device-change, archive, and Nautobot.
    • Updated consumer operations and administrative endpoints to use the correct configured JetStream prefix per consumer type.
    • Added sensible defaults and fallback behavior when custom prefixes aren’t set.
  • Documentation
    • Updated Helm/Vault/INI templates and values to render the new *_api_prefix settings.
  • Tests
    • Expanded unit tests to validate prefix propagation for consumer management and pull consumers.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The change adds per-stream JetStream API prefix configuration to Helm-generated INI files, resolves prefixes with fallback defaults, and applies them to admin and pull consumer JetStream contexts. Tests cover configured prefixes for Nautobot and device-change consumers.

JetStream API Prefixes

Layer / File(s) Summary
Helm prefix configuration
deploy/helm/values.yaml, deploy/helm/templates/*, deploy/helm/sample-nv-config-manager.ini
Adds per-stream apiPrefix values and renders corresponding NATS configuration entries.
Configuration prefix resolution
src/nv_config_manager/common/config.py, src/tests/conftest.py
Adds default and stream-specific API prefix helpers with fallback behavior and shared test configuration.
Admin consumer JetStream contexts
src/nv_config_manager/render/api/admin_v1.py, src/tests/render/api/test_admin_v1.py
Associates consumer types with prefixes and uses prefixed JetStream contexts for consumer operations.
Pull consumer prefix propagation
src/nv_config_manager/render/pull_consumer.py, src/tests/render/test_pull_consumer.py
Passes configured prefixes into pull consumers and verifies prefixed JetStream initialization.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Config as NATS configuration
  participant Consumer as Config manager consumer
  participant NATS as NATS connection
  participant JetStream as JetStream context
  Config->>Consumer: resolve stream API prefix
  Consumer->>NATS: jetstream(prefix=api_prefix)
  NATS->>JetStream: create prefixed context
  Consumer->>JetStream: consume or manage consumer
Loading

Suggested reviewers: polarweasel, zsblevins, ryanheffernan

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: tightening NATS account boundaries and adding configurable JetStream API prefixes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch davesh/nats-account-auth-gnicfd-5354

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

…rcement [GNICFD-5354]

Signed-off-by: Davesh Mathur <daveshm@nvidia.com>
@dmathur0
dmathur0 force-pushed the davesh/nats-account-auth-gnicfd-5354 branch from 902c681 to 8af2e18 Compare July 24, 2026 18:18

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
src/tests/render/api/test_admin_v1.py (1)

104-105: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Make the prefix assertions consumer-specific.

These assertions only prove that both prefixes were requested. Because both calls return the same mock_js, a reversed Nautobot/device mapping would still pass. Use distinct JetStream mocks, or assert the ordered prefix calls together with the corresponding consumer calls.

Minimal assertion improvement
-        mock_conn.jetstream.assert_any_call(prefix="$JS.CEREBRO.API")
-        mock_conn.jetstream.assert_any_call(prefix="$JS.API")
+        assert [
+            call.kwargs["prefix"] for call in mock_conn.jetstream.call_args_list
+        ] == ["$JS.CEREBRO.API", "$JS.API"]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tests/render/api/test_admin_v1.py` around lines 104 - 105, Update the
JetStream assertions in the admin API test to verify prefix-to-consumer mapping
rather than merely checking that both prefixes were requested. Use distinct
JetStream mocks for the Nautobot and device prefixes, or assert the ordered
prefix calls together with their corresponding consumer calls, so a reversed
mapping fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/tests/render/api/test_admin_v1.py`:
- Around line 104-105: Update the JetStream assertions in the admin API test to
verify prefix-to-consumer mapping rather than merely checking that both prefixes
were requested. Use distinct JetStream mocks for the Nautobot and device
prefixes, or assert the ordered prefix calls together with their corresponding
consumer calls, so a reversed mapping fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 14631edc-9630-4fb7-8301-e6e3771173a6

📥 Commits

Reviewing files that changed from the base of the PR and between 5f3ee8d and 902c681.

📒 Files selected for processing (11)
  • deploy/helm/sample-nv-config-manager.ini
  • deploy/helm/templates/_vault-agent.tpl
  • deploy/helm/templates/kubernetes-secrets.yaml
  • deploy/helm/templates/vault-secrets.yaml
  • deploy/helm/values.yaml
  • src/nv_config_manager/common/config.py
  • src/nv_config_manager/render/api/admin_v1.py
  • src/nv_config_manager/render/pull_consumer.py
  • src/tests/conftest.py
  • src/tests/render/api/test_admin_v1.py
  • src/tests/render/test_pull_consumer.py

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/nv_config_manager/common/config.py`:
- Around line 222-225: Update nats_nautobot_api_prefix to fall back to the
shared config_manager_api_prefix value before DEFAULT_NATS_API_PREFIX, matching
the fallback chain used by the other NATS API-prefix helpers. Add a regression
case in test_admin_v1.py covering a missing nautobot_api_prefix with a
configured config_manager_api_prefix and assert the configured shared prefix is
used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 373323af-459b-4bf4-a0ed-38d288dfb1af

📥 Commits

Reviewing files that changed from the base of the PR and between 902c681 and 8af2e18.

📒 Files selected for processing (11)
  • deploy/helm/sample-nv-config-manager.ini
  • deploy/helm/templates/_vault-agent.tpl
  • deploy/helm/templates/kubernetes-secrets.yaml
  • deploy/helm/templates/vault-secrets.yaml
  • deploy/helm/values.yaml
  • src/nv_config_manager/common/config.py
  • src/nv_config_manager/render/api/admin_v1.py
  • src/nv_config_manager/render/pull_consumer.py
  • src/tests/conftest.py
  • src/tests/render/api/test_admin_v1.py
  • src/tests/render/test_pull_consumer.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • deploy/helm/values.yaml
  • src/tests/conftest.py
  • deploy/helm/templates/kubernetes-secrets.yaml
  • deploy/helm/templates/_vault-agent.tpl
  • src/tests/render/api/test_admin_v1.py
  • src/tests/render/test_pull_consumer.py
  • deploy/helm/templates/vault-secrets.yaml
  • src/nv_config_manager/render/api/admin_v1.py
  • src/nv_config_manager/render/pull_consumer.py

Comment on lines +222 to +225
def nats_nautobot_api_prefix(config: ConfigParser | None = None) -> str:
"""Return the JetStream API prefix for Nautobot changelog events."""
nats_config = _nats_section(config)
return nats_config.get("nautobot_api_prefix", DEFAULT_NATS_API_PREFIX)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve the shared API-prefix fallback for Nautobot.

When nautobot_api_prefix is absent, this helper ignores a configured config_manager_api_prefix and returns $JS.API. For example, an account-scoped configuration using $JS.CEREBRO.API will make Nautobot consumers target the wrong JetStream API/account. Match the fallback chain used by the other helpers and add a regression case for the missing Nautobot-specific key in src/tests/render/api/test_admin_v1.py.

Proposed fix
-    return nats_config.get("nautobot_api_prefix", DEFAULT_NATS_API_PREFIX)
+    return nats_config.get(
+        "nautobot_api_prefix",
+        nats_config.get("config_manager_api_prefix", DEFAULT_NATS_API_PREFIX),
+    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def nats_nautobot_api_prefix(config: ConfigParser | None = None) -> str:
"""Return the JetStream API prefix for Nautobot changelog events."""
nats_config = _nats_section(config)
return nats_config.get("nautobot_api_prefix", DEFAULT_NATS_API_PREFIX)
def nats_nautobot_api_prefix(config: ConfigParser | None = None) -> str:
"""Return the JetStream API prefix for Nautobot changelog events."""
nats_config = _nats_section(config)
return nats_config.get(
"nautobot_api_prefix",
nats_config.get("config_manager_api_prefix", DEFAULT_NATS_API_PREFIX),
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nv_config_manager/common/config.py` around lines 222 - 225, Update
nats_nautobot_api_prefix to fall back to the shared config_manager_api_prefix
value before DEFAULT_NATS_API_PREFIX, matching the fallback chain used by the
other NATS API-prefix helpers. Add a regression case in test_admin_v1.py
covering a missing nautobot_api_prefix with a configured
config_manager_api_prefix and assert the configured shared prefix is used.

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.

2 participants