Skip to content

feat(auth): govern workspace creation through RBAC - #531

Merged
ironcommit merged 1 commit into
mainfrom
auth-workspace-creator
Jul 3, 2026
Merged

feat(auth): govern workspace creation through RBAC#531
ironcommit merged 1 commit into
mainfrom
auth-workspace-creator

Conversation

@ironcommit

@ironcommit ironcommit commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Moves workspace creation from a hardcoded policy exception (any authenticated user can create) to a proper RBAC-controlled permission, while preserving the current default behavior through seeding.

What changed

  • New WorkspaceCreator role with workspaces.create permission added to the static authz config
  • OPA policy generalized: the IAM-specific system-workspace fallback rule now applies to any workspace-less endpoint with required permissions, removing the /apis/auth/v2/iam/ path prefix check
  • Workspace creation endpoint (POST /apis/entities/v2/workspaces) now requires workspaces.create permission and entities:write/platform:write scopes instead of empty permissions/scopes
  • Platform seed creates a wildcard WorkspaceCreator binding in the system workspace, preserving open workspace creation by default
  • Operators can restrict workspace creation by rebinding the system workspace: remove the wildcard WorkspaceCreator and grant it only to specific users/groups

Why

Previously, workspace creation was a special-cased policy exception — the endpoint had empty permissions, so any authenticated user could create workspaces with no way for operators to restrict it. This change brings workspace creation under the same RBAC model as every other operation, giving operators a knob to control who can create workspaces while keeping the default behavior unchanged.

Files changed

  • services/core/auth/src/nmp/core/auth/assets/static-authz.yaml — new role, permission, and endpoint config
  • services/core/auth/src/nmp/core/auth/app/policies/authz.rego — generalized system-workspace fallback rule
  • services/core/auth/src/nmp/core/auth/app/seeding.py — new seed_workspace_creator() function
  • services/core/auth/scripts/auth-tools.py — updated permission/scope inference
  • services/core/auth/src/nmp/core/auth/app/policy_tests/ — updated Rego tests
  • services/core/auth/tests/test_embedded_pdp.py — new system-scoped permission test
  • services/core/auth/tests/test_seeding.py — tests for WorkspaceCreator seeding
  • services/core/entities/tests/integration/test_workspaces_crud_with_auth.py — integration tests for default-open and restricted creation
  • docs/ — updated documentation across auth concepts, roles/permissions, OIDC setup, configuration, workspaces, and setup pages

Test plan

  • make test-unit passes (Rego policy tests, seeding tests, embedded PDP tests)
  • Integration test test_workspaces_crud_with_auth.py covers both default-open and restricted creation flows
  • Verify existing workspace creation still works without any configuration changes
  • Verify operators can restrict creation by rebinding the system workspace roles

Summary by CodeRabbit

  • New Features
    • Introduced a dedicated workspaces.create permission via a WorkspaceCreator role; the creator is granted Admin access in the newly created workspace.
    • Workspace creation now requires system-scoped authorization plus entities:write and platform:write scopes.
    • Default platform seeding enables open workspace creation for authenticated users via a wildcard WorkspaceCreator binding in the system workspace; operators can restrict it by removing/rebinding that wildcard.
  • Documentation
    • Updated setup and permission/workspace creation docs to reflect the new WorkspaceCreator behavior and restriction steps.
  • Bug Fixes
    • Authorization and permission-suggestion behavior were tightened to fail closed for unconfigured endpoints and correctly model workspace-creation requirements.

@ironcommit
ironcommit requested review from a team as code owners June 30, 2026 23:55
@github-actions github-actions Bot added the feat label Jun 30, 2026
@ironcommit
ironcommit requested a review from maxdubrinsky June 30, 2026 23:55
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 22529/29649 76.0% 60.9%
Integration Tests 13015/28329 45.9% 19.4%

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

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: 4eed3097-1e8b-4963-b0f8-7d589f072c7d

📥 Commits

Reviewing files that changed from the base of the PR and between 8989f3a and 326905c.

📒 Files selected for processing (18)
  • docs/auth/authentication/oidc.mdx
  • docs/auth/authorization/permissions-reference.mdx
  • docs/auth/authorization/roles-and-permissions.mdx
  • docs/auth/concepts.mdx
  • docs/auth/deployment/configuration.mdx
  • docs/get-started/concepts/workspaces.mdx
  • docs/get-started/setup.mdx
  • services/core/auth/scripts/auth-tools.py
  • services/core/auth/src/nmp/core/auth/app/policies/authz.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_access_test.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_creation_test.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/unknown_endpoint_test.rego
  • services/core/auth/src/nmp/core/auth/app/seeding.py
  • services/core/auth/src/nmp/core/auth/assets/static-authz.yaml
  • services/core/auth/tests/test_embedded_pdp.py
  • services/core/auth/tests/test_seeding.py
  • services/core/entities/tests/integration/test_workspaces_crud_with_auth.py
  • services/platform-seed/README.md
✅ Files skipped from review due to trivial changes (6)
  • docs/auth/deployment/configuration.mdx
  • services/platform-seed/README.md
  • docs/auth/authorization/permissions-reference.mdx
  • docs/auth/concepts.mdx
  • docs/auth/authentication/oidc.mdx
  • docs/get-started/setup.mdx
🚧 Files skipped from review as they are similar to previous changes (10)
  • services/core/auth/tests/test_embedded_pdp.py
  • services/core/auth/scripts/auth-tools.py
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_access_test.rego
  • services/core/auth/src/nmp/core/auth/assets/static-authz.yaml
  • docs/auth/authorization/roles-and-permissions.mdx
  • docs/get-started/concepts/workspaces.mdx
  • services/core/auth/src/nmp/core/auth/app/policy_tests/unknown_endpoint_test.rego
  • services/core/entities/tests/integration/test_workspaces_crud_with_auth.py
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_creation_test.rego
  • services/core/auth/src/nmp/core/auth/app/policies/authz.rego

📝 Walkthrough

Walkthrough

Adds WorkspaceCreator as a dedicated workspace-creation role, seeds it for the wildcard principal in system, updates authz policy and tests for scoped workspace creation, and revises docs to describe the new default binding and restriction flow.

Changes

WorkspaceCreator RBAC rollout

Layer / File(s) Summary
Permission and endpoint mapping
services/core/auth/src/nmp/core/auth/assets/static-authz.yaml, services/core/auth/scripts/auth-tools.py
Adds workspaces.create, WorkspaceCreator, and updates POST workspace mappings plus CLI inference for permissions and scopes.
Seed wildcard WorkspaceCreator binding
services/core/auth/src/nmp/core/auth/app/seeding.py, services/core/auth/tests/test_seeding.py
Adds the seeding helper and wires it into run_seeding, with tests for creating the wildcard system binding and existing-binding behavior.
Authz rule and Rego tests
services/core/auth/src/nmp/core/auth/app/policies/authz.rego, services/core/auth/src/nmp/core/auth/app/policy_tests/*.rego
Broadens the workspace-less allow rule and updates Rego fixtures/tests to require WorkspaceCreator and write scopes for workspace creation.
Embedded PDP tests
services/core/auth/tests/test_embedded_pdp.py
Updates embedded PDP coverage for system-scoped WorkspaceCreator authorization and the new POST workspace permission/scope requirements.
Workspace creation integration test
services/core/entities/tests/integration/test_workspaces_crud_with_auth.py
Adds helpers for rebinding system membership and polling authz, then updates integration coverage for default-open and restricted workspace creation.
Docs and README updates
docs/auth/..., docs/get-started/..., services/platform-seed/README.md
Updates auth and setup docs to describe the seeded WorkspaceCreator binding and how to restrict workspace creation.

Sequence Diagram(s)

sequenceDiagram
  participant Seeder as platform-seed
  participant EntityClient as EntityClient
  participant PDP as authz.rego
  participant Client as API caller

  Seeder->>EntityClient: seed_workspace_creator(*, system, WorkspaceCreator)
  Client->>PDP: POST /apis/entities/v2/workspaces
  PDP->>PDP: require workspaces.create and write scopes
  PDP->>PDP: check system WorkspaceCreator binding
  PDP-->>Client: allow or deny
Loading

Possibly related PRs

Suggested reviewers: mckornfield

🚥 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 clearly matches the main change: workspace creation is now governed by RBAC.
Docstring Coverage ✅ Passed Docstring coverage is 96.15% 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 auth-workspace-creator

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (2)
services/platform-seed/README.md (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the doc substitution and spell out the bindings.

NeMo Platform is hardcoded here, and wildcard default/system/workspace-creator is too compressed to be useful reference text. Use the configured product substitution and name the exact bindings, like Line 22 does. As per coding guidelines, "Avoid marketing language ('powerful', 'flexible', 'easy', 'robust') and vague terms ('many', 'various', 'different approaches'); use concrete, specific terminology instead" and "Never hardcode product names; use substitutions in Sphinx configuration to maintain consistency across documentation".

🤖 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 `@services/platform-seed/README.md` at line 3, Update the README summary text
to use the configured product substitution instead of hardcoding NeMo Platform,
and replace the compressed “wildcard default/system/workspace-creator” wording
with the explicit binding names. Keep the wording concrete and specific, and
align the phrasing with the existing seed-job description referenced elsewhere
in the document.

Source: Coding guidelines

docs/get-started/concepts/workspaces.mdx (1)

63-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move this procedure out of the concepts page.

Lines 63-91 are a task workflow with commands, so they read as HOW-TO content inside a concepts page. Split this into a dedicated how-to and link to it from here; if the procedure stays, add Python SDK and CLI examples in tabs instead of CLI only. As per coding guidelines, "Each documentation page should fit ONE Diataxis quadrant; do not mix tutorials with reference tables or how-tos with architecture explanations; use cross-links instead" and "Provide both Python SDK and CLI examples in tab-sets for consistency and to support multiple user workflows".

🤖 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/get-started/concepts/workspaces.mdx` around lines 63 - 91, The “Restrict
Workspace Creation” section in the concepts page is a how-to workflow, so move
it out of this page and into a dedicated how-to doc, then add a cross-link from
the concepts content. If any part must remain here, refactor the procedure in
this area into tabbed Python SDK and CLI examples instead of CLI-only, using the
existing workspace/RBAC guidance and the “WorkspaceCreator” binding example as
the anchor to relocate.

Source: Coding guidelines

🤖 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 `@docs/auth/authentication/oidc.mdx`:
- Line 74: Broaden the 403 warning in the OIDC docs so it reflects the full
impact of missing platform seeding: if platform-seed never ran, the seeded
Editor, Viewer, and WorkspaceCreator bindings are also absent, so workspace
creation and default workspace access can fail with 403 as well. Update the
sentence around auth.admin_email and the PlatformAdmin/WorkspaceCreator bindings
to mention these additional seeded bindings and avoid limiting the warning to
admin operations only.

In `@docs/auth/authorization/roles-and-permissions.mdx`:
- Around line 76-84: The workspace permissions matrix in
roles-and-permissions.mdx conflicts with the explanatory note about creation
access. Update the “Create workspace” row in the permissions table to match the
`WorkspaceCreator` rule described in the note, or remove that row entirely if
the table cannot express the `system` workspace binding; make sure the table no
longer implies only `PlatformAdmin` can create workspaces. Use the
`WorkspaceCreator` note and the permissions matrix near “Create workspace” as
the place to align the documentation.

In
`@services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_creation_test.rego`:
- Line 27: The endpoint fixture for the POST case is missing the required
scopes, so the allow/deny policy tests are not covering the new
entities:write/platform:write contract. Update the fixture in
namespace_creation_test.rego alongside the existing permissions entry to include
the appropriate scopes for the endpoint, using the same test data structure used
by the namespace creation policy tests.

In
`@services/core/auth/src/nmp/core/auth/app/policy_tests/unknown_endpoint_test.rego`:
- Line 29: The scoped creation test fixture is not actually requiring the write
scopes it is supposed to validate, so the permission check can be bypassed.
Update the Rego test cases in unknown_endpoint_test and the related scoped
creation fixtures to explicitly require the needed write scope before asserting
workspace creation, and make sure the request permissions align with the
expected enforcement path.

In `@services/core/auth/src/nmp/core/auth/app/seeding.py`:
- Around line 288-300: The bootstrap in seed_workspace_creator() is reapplying
the wildcard WorkspaceCreator binding via _seed_wildcard_binding(), which blocks
operators from keeping workspace creation restricted. Update this seeding path
so a deleted or revoked wildcard binding is treated as an intentional override
rather than being recreated or causing failure, or gate the behavior behind a
one-time/opt-in flag; make the same adjustment for the other affected seeding
call referenced in the review.

In `@services/core/entities/tests/integration/test_workspaces_crud_with_auth.py`:
- Around line 204-229: The test mutates shared RBAC on the system workspace by
changing the wildcard member’s roles but never restores the seeded wildcard
WorkspaceCreator binding, which makes later workspace-creation tests
order-dependent. Update this test around
restrict_workspace_creation_to_named_users, sdk.workspaces.members.create, and
the final sdk.workspaces.create call to re-add or reset the wildcard principal’s
original roles before exiting the test, ideally in a cleanup/finally path so the
shared system membership is restored even if the test fails.

---

Nitpick comments:
In `@docs/get-started/concepts/workspaces.mdx`:
- Around line 63-91: The “Restrict Workspace Creation” section in the concepts
page is a how-to workflow, so move it out of this page and into a dedicated
how-to doc, then add a cross-link from the concepts content. If any part must
remain here, refactor the procedure in this area into tabbed Python SDK and CLI
examples instead of CLI-only, using the existing workspace/RBAC guidance and the
“WorkspaceCreator” binding example as the anchor to relocate.

In `@services/platform-seed/README.md`:
- Line 3: Update the README summary text to use the configured product
substitution instead of hardcoding NeMo Platform, and replace the compressed
“wildcard default/system/workspace-creator” wording with the explicit binding
names. Keep the wording concrete and specific, and align the phrasing with the
existing seed-job description referenced elsewhere in the document.
🪄 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: 7ee01af0-fc74-4e96-b4d3-ab47e69b1aa1

📥 Commits

Reviewing files that changed from the base of the PR and between d18be8e and 84500eb.

📒 Files selected for processing (17)
  • docs/auth/authentication/oidc.mdx
  • docs/auth/authorization/roles-and-permissions.mdx
  • docs/auth/concepts.mdx
  • docs/auth/deployment/configuration.mdx
  • docs/get-started/concepts/workspaces.mdx
  • docs/get-started/setup.mdx
  • services/core/auth/scripts/auth-tools.py
  • services/core/auth/src/nmp/core/auth/app/policies/authz.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_access_test.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/namespace_creation_test.rego
  • services/core/auth/src/nmp/core/auth/app/policy_tests/unknown_endpoint_test.rego
  • services/core/auth/src/nmp/core/auth/app/seeding.py
  • services/core/auth/src/nmp/core/auth/assets/static-authz.yaml
  • services/core/auth/tests/test_embedded_pdp.py
  • services/core/auth/tests/test_seeding.py
  • services/core/entities/tests/integration/test_workspaces_crud_with_auth.py
  • services/platform-seed/README.md

Comment thread docs/auth/authentication/oidc.mdx Outdated
Comment thread docs/auth/authorization/roles-and-permissions.mdx Outdated
Comment thread services/core/auth/src/nmp/core/auth/app/policy_tests/unknown_endpoint_test.rego Outdated
Comment thread services/core/auth/src/nmp/core/auth/app/seeding.py
Comment thread services/core/entities/tests/integration/test_workspaces_crud_with_auth.py Outdated
@ironcommit
ironcommit force-pushed the auth-workspace-creator branch from 84500eb to 8989f3a Compare July 2, 2026 18:44
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
@ironcommit
ironcommit force-pushed the auth-workspace-creator branch from 8989f3a to 326905c Compare July 2, 2026 22:48

@mckornfield mckornfield left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

some minor things, max might have more, I wonder about the default create though (I remember that being a no no for certain customers/larger orgs when anyone with an email could onboard)

Comment thread docs/auth/concepts.mdx
Comment thread services/core/auth/scripts/auth-tools.py

@drazvan drazvan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LTGM

@ironcommit
ironcommit added this pull request to the merge queue Jul 3, 2026
Merged via the queue into main with commit 2cc1011 Jul 3, 2026
57 checks passed
@ironcommit
ironcommit deleted the auth-workspace-creator branch July 3, 2026 16:42
arpitsardhana pushed a commit that referenced this pull request Jul 9, 2026
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants