Skip to content

feat(nautobot): YAML-driven group-mapping RBAC for JWT-authenticated users#24

Open
dmathur0 wants to merge 3 commits into
mainfrom
port/nautobot-rbac-group-mapping-mr238
Open

feat(nautobot): YAML-driven group-mapping RBAC for JWT-authenticated users#24
dmathur0 wants to merge 3 commits into
mainfrom
port/nautobot-rbac-group-mapping-mr238

Conversation

@dmathur0

@dmathur0 dmathur0 commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Description

Validation

  • Standard CI passes.
  • Kind integration passes, or this PR explains why it was not run.

The kind integration test is manual due to taking ~30 min to complete. When the PR is ready for review,
run Actions -> Kind Integration -> Run workflow against the copy-pr-bot generated
pull-request/<PR_NUMBER> branch. Use the default test_path for the full suite,
or narrow it only while debugging.

Passing Kind Integration run:

Checklist

  • I am familiar with the contributing guidelines in CONTRIBUTING.md.
  • Commits are signed off for DCO compliance.
  • New or existing tests cover these changes, or the PR explains why tests are not needed.
  • Documentation is updated for user-facing behavior changes.
  • Generated artifacts are updated when applicable, such as OpenAPI specs,
    docs screenshots, or Helm/rendered outputs.

Summary by CodeRabbit

  • New Features
    • Added YAML-driven group mapping to synchronize JWT claim groups into Nautobot/Django groups and per-action object permissions at login.
    • Mapping-based superuser reconciliation plus optional auto-creation of referenced groups via Helm config.
  • Behavior Changes
    • Fail-closed mapping loading: parse/load errors are logged and treated as empty, with managed permissions still revoked/pruned on next login.
    • Mapping empty vs omitted is handled distinctly to control reconciliation and demotion behavior.
  • Helm & Configuration
    • Conditionally renders and mounts the group-mapping ConfigMap, including checksum-based rollout triggering.
  • Tests
    • Expanded coverage for mapping states, permission/group sync, and superuser reconciliation.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 113c4093-96ab-4819-87a0-4a9342e4f488

📥 Commits

Reviewing files that changed from the base of the PR and between e39912a and 9ba851e.

📒 Files selected for processing (9)
  • components/nautobot/nv_config_manager_auth/jwt_authentication.py
  • components/nautobot/nv_config_manager_auth/rbac.py
  • components/nautobot/tests/conftest.py
  • components/nautobot/tests/test_jwt_authentication.py
  • components/nautobot/tests/test_rbac.py
  • deploy/helm/templates/_nautobot-configmap-data.tpl
  • deploy/helm/templates/nautobot.yaml
  • deploy/helm/values-local-azure-sso.yaml
  • deploy/helm/values.yaml
💤 Files with no reviewable changes (9)
  • deploy/helm/templates/_nautobot-configmap-data.tpl
  • deploy/helm/values-local-azure-sso.yaml
  • components/nautobot/tests/conftest.py
  • deploy/helm/values.yaml
  • components/nautobot/nv_config_manager_auth/jwt_authentication.py
  • deploy/helm/templates/nautobot.yaml
  • components/nautobot/nv_config_manager_auth/rbac.py
  • components/nautobot/tests/test_jwt_authentication.py
  • components/nautobot/tests/test_rbac.py

📝 Walkthrough

Walkthrough

This PR adds YAML-driven JWT RBAC reconciliation for Nautobot, including mapping load/validation, login-time group and permission sync, superuser reconciliation changes, Helm wiring for config injection, and tests covering the new flows.

Changes

JWT-driven Group Mapping RBAC

Layer / File(s) Summary
RBAC module foundation: configuration, error handling, and content-type resolution
components/nautobot/nv_config_manager_auth/rbac.py
Adds mapping configuration gating, dedicated mapping read/parse exceptions, YAML loading and validation, and content-type resolution for mapping-defined permission specs.
RBAC group and permission synchronization orchestration
components/nautobot/nv_config_manager_auth/rbac.py
Implements atomic reconciliation for mapped permissions, mapped group memberships, and revocation of retired mapping entries, including superuser-specific permission pruning.
JWT authentication integration with RBAC sync
components/nautobot/nv_config_manager_auth/jwt_authentication.py
Updates JWT login handling to load mapping state when configured, fail closed on load errors, reconcile superuser status with mapping-derived matches, and trigger RBAC sync.
Test infrastructure and RBAC behavior tests
components/nautobot/tests/conftest.py, components/nautobot/tests/test_jwt_authentication.py, components/nautobot/tests/test_rbac.py
Expands test stubs and adds coverage for mapping gating, YAML parsing, content-type resolution, sync orchestration, superuser reconciliation, and revoke behavior.
Helm templates, values, and integration docs
deploy/helm/templates/_nautobot-configmap-data.tpl, deploy/helm/templates/nautobot.yaml, deploy/helm/values.yaml, deploy/helm/values-local-azure-sso.yaml, docs/nautobot/nautobot-integration.mdx
Adds Helm values and templates for mapping config injection, rollout checksums, directory mounts, a local Azure SSO overlay, and updated RBAC documentation.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 67.71% 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 summarizes the main change: YAML-driven RBAC group mapping for JWT-authenticated Nautobot users.
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 port/nautobot-rbac-group-mapping-mr238

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

@dmathur0 dmathur0 force-pushed the port/nautobot-rbac-group-mapping-mr238 branch from 91ca8ad to 3b934e2 Compare June 1, 2026 22:59
@dmathur0 dmathur0 changed the title Port/nautobot rbac group mapping mr238 Port/nautobot rbac group mapping Jun 1, 2026

@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: 2

🤖 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 `@deploy/helm/templates/_nautobot-configmap-data.tpl`:
- Around line 79-90: The group-mapping ConfigMap and mounts are being rendered
unconditionally so nv_config_manager_auth.rbac (mapping_is_configured() /
DEFAULT_MAPPING_PATH) treats RBAC as configured even when
Values.nautobot.rbac.groupMapping is empty; update
deploy/helm/templates/nautobot.yaml to wrap the ConfigMap, volume, and
volumeMount blocks with a guard that checks for the presence of the key (e.g.,
{{ if hasKey .Values.nautobot.rbac "groupMapping" }} ) so an absent key means
“unconfigured”, and update deploy/helm/values.yaml to remove the default
groupMapping: [] (or set it to null) so the chart will not render the
ConfigMap/mount unless the operator explicitly provides groupMapping.

In `@deploy/helm/values.yaml`:
- Line 2454: The default empty array for groupMapping causes unintended
revoke-all behavior; change the default in values.yaml from "groupMapping: []"
to either remove the key or set "groupMapping: null" (or comment it out) and
update the Helm templates (the ConfigMap/volume creation in nautobot.yaml that
mounts the RBAC file) to be conditional on groupMapping being defined and
non-null so the ConfigMap is only created when the user explicitly configures
groupMapping (this preserves the documented semantics that null/omitted means
"do not touch", while an explicit [] still triggers the revoke-all behavior).
🪄 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: 7557663c-2858-4da0-8809-605501b8542b

📥 Commits

Reviewing files that changed from the base of the PR and between 6bec6d7 and 91ca8ad.

📒 Files selected for processing (9)
  • components/nautobot/nv_config_manager_auth/jwt_authentication.py
  • components/nautobot/nv_config_manager_auth/rbac.py
  • components/nautobot/tests/conftest.py
  • components/nautobot/tests/test_jwt_authentication.py
  • components/nautobot/tests/test_rbac.py
  • deploy/helm/templates/_nautobot-configmap-data.tpl
  • deploy/helm/templates/nautobot.yaml
  • deploy/helm/values-local-azure-sso.yaml
  • deploy/helm/values.yaml

Comment thread deploy/helm/templates/_nautobot-configmap-data.tpl Outdated
Comment thread deploy/helm/values.yaml Outdated
@dmathur0 dmathur0 changed the title Port/nautobot rbac group mapping feat(nautobot): YAML-driven group-mapping RBAC for JWT-authenticated users Jul 6, 2026

@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)
docs/nautobot/nautobot-integration.mdx (1)

214-214: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Terminology mismatch: "empty" vs. the chart's actual gating semantics.

This doc describes superuserGroups as disabled "when empty," which is consistent with the Helm template's {{- with .Values.nautobot.rbac.superuserGroups }} (falsy/empty skips rendering). No issue here, but worth double-checking phrasing consistency against groupMapping's very different "presence, not truthiness" semantics described a few lines below (Line 238) — a reader could conflate the two gating models since they're documented back-to-back with different rules.

🤖 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 `@docs/nautobot/nautobot-integration.mdx` at line 214, Clarify the
documentation wording around `superuserGroups` versus `groupMapping` so readers
do not conflate their gating behavior. Keep the `superuserGroups` description
aligned with the `with .Values.nautobot.rbac.superuserGroups` truthiness-based
behavior, and explicitly distinguish it from `groupMapping`, which is enabled by
key presence rather than value truthiness. Use the existing `superuserGroups`
and `groupMapping` sections in the Nautobot integration docs to make the
contrast obvious and consistent.
🤖 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 `@docs/nautobot/nautobot-integration.mdx`:
- Line 214: Clarify the documentation wording around `superuserGroups` versus
`groupMapping` so readers do not conflate their gating behavior. Keep the
`superuserGroups` description aligned with the `with
.Values.nautobot.rbac.superuserGroups` truthiness-based behavior, and explicitly
distinguish it from `groupMapping`, which is enabled by key presence rather than
value truthiness. Use the existing `superuserGroups` and `groupMapping` sections
in the Nautobot integration docs to make the contrast obvious and consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 31e4bdaa-361a-406c-aa93-ae8705b77448

📥 Commits

Reviewing files that changed from the base of the PR and between 3b934e2 and e39912a.

📒 Files selected for processing (6)
  • components/nautobot/nv_config_manager_auth/jwt_authentication.py
  • components/nautobot/nv_config_manager_auth/rbac.py
  • deploy/helm/templates/_nautobot-configmap-data.tpl
  • deploy/helm/templates/nautobot.yaml
  • deploy/helm/values.yaml
  • docs/nautobot/nautobot-integration.mdx
🚧 Files skipped from review as they are similar to previous changes (5)
  • deploy/helm/values.yaml
  • deploy/helm/templates/nautobot.yaml
  • deploy/helm/templates/_nautobot-configmap-data.tpl
  • components/nautobot/nv_config_manager_auth/rbac.py
  • components/nautobot/nv_config_manager_auth/jwt_authentication.py

dmathur0 added 3 commits July 6, 2026 16:20
Adds nv_config_manager_auth.rbac, which reads a YAML group-mapping file on
every JWT login to reconcile Django Group membership and per-action
ObjectPermissions (with optional constraints and is_superuser shortcut)
against the JWT roles claim. Group lifecycle is operator-managed by default;
NV_CONFIG_MANAGER_AUTO_CREATE_GROUPS opts into auto-creation.
_sync_superuser_status now decouples mapping-enabled from per-user-match so
revocation/demotion runs even with an empty or failed-to-parse mapping
(fail-closed). Helm renders the mapping into a directory-mounted ConfigMap
with a pod-template checksum.

Signed-off-by: Davesh Mathur <daveshm@nvidia.com>
Adds values-local-azure-sso.yaml as a generic, scrubbed example: all
tenant/client IDs, secrets, internal hostnames, and cluster contexts are
replaced with <placeholder>s. Shows how to exercise the
nautobot.rbac.groupMapping path against a real Entra ID OIDC provider on a
local kind cluster.

Signed-off-by: Davesh Mathur <daveshm@nvidia.com>
…fault revoke-all

The group-mapping ConfigMap, volume, volumeMount, and env var rendered
unconditionally, so /app/config/group-mapping.yaml always existed and
rbac.mapping_is_configured() treated the feature as configured-but-empty
by default (groupMapping: []). That ran the revoke-everyone / demotion
path on every JWT login even when operators never opted in.

Guard the ConfigMap, checksum annotation, volume, volumeMount, and the
GROUP_MAPPING_PATH env var on `hasKey nautobot.rbac "groupMapping"`, and
default the key to omitted (commented out) in values.yaml. The three
states are now: omitted = unconfigured (privileges untouched),
[] = configured-empty (deliberate revoke-all), [...] = configured.

Document the semantics in values.yaml, the templates, the
mapping_is_configured docstring, and a new Authentication and RBAC
section in the Nautobot integration docs. Also add docstrings to the
previously-undocumented JWT auth helpers to satisfy docstring coverage.

Signed-off-by: Davesh Mathur <daveshm@nvidia.com>
@dmathur0 dmathur0 force-pushed the port/nautobot-rbac-group-mapping-mr238 branch from e39912a to 9ba851e Compare July 6, 2026 21:22
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

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.

1 participant