NVIDIA / NVIDIA/OpenShell

feat: gate platform-admin on a configurable role for mTLS-authenticated identities

Open
#3,071 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

state:triage-needed
Dominant language
Rust
Stars
8.7k
Forks
1.3k
Avg merge
2d 11h
Merged PRs (30d)
253

Description

User Story

As an operator running the gateway behind a trusted fronting service that creates workspaces and sandboxes on behalf of users, I want a platform-admin identity authenticated by an mTLS client certificate and gated by a configurable admin role, without running an OIDC provider, so that only my fronting service holds platform admin and presenting any valid client certificate does not make a caller an admin.

Problem Statement

The gateway only enforces platform-admin RBAC when OIDC is configured. Without an OIDC issuer there is no way to distinguish an admin from an ordinary authenticated caller, so every mTLS-authenticated caller is treated as a platform admin. There is no supported managed platform identity that avoids standing up OIDC.

Impact / Why This Matters

To give a fronting service admin while end users have none, an operator must deploy a full OIDC issuer purely for role separation — disproportionate for a deployment whose only authenticated caller is a certificate-holding backend, and it adds an external dependency with its own availability and rotation concerns.

On main today:

  • AuthzPolicy is built only from OIDC config and is None without an issuer (crates/openshell-server/src/multiplex.rs:282).
  • The role check runs only when that policy exists (crates/openshell-server/src/multiplex.rs:1153); with no policy, any Principal::User reaches platform-admin methods unchecked.
  • MtlsAuthConfig exposes only enabled (crates/openshell-core/src/config.rs:972-978), so an operator cannot declare which certificates are admin.
Proposed Design

mTLS authentication supports role-based authorization on its own, resolving admin/user roles from config when no OIDC issuer is present.

  • Configurable roles on the mTLS block. [openshell.gateway.mtls_auth] gains admin_role and user_role. A certificate carrying OU=<admin_role> is authorized for platform-admin methods; OU=<user_role> is a standard user subject to workspace-membership checks; neither is denied.
  • Fail closed. An empty admin_role never makes a CA-signed certificate an admin. When mTLS user auth is enabled with no resolvable admin role, the gateway refuses to start.
  • Reject the unsafe combination. mTLS user auth together with allow_unauthenticated_users is rejected (the local-dev principal carries platform-admin).
  • Deployment. Helm renders the new fields into gateway.toml and fails rendering on the same misconfigurations the binary rejects.

Observable outcome: an operator configures mTLS with an admin role, issues admin-OU certificates only to the fronting service, and that service can create workspaces/sandboxes while no other caller reaches platform-admin methods — with no OIDC anywhere.

Acceptance Criteria
  • With mTLS enabled, an admin_role set, and no OIDC, a cert carrying OU=<admin_role> is authorized for platform-admin methods; a CA-signed cert without it is denied.
  • With no OIDC and no admin role configured, an mTLS identity is not treated as platform-admin.
  • mTLS user auth enabled with no resolvable admin role fails at startup with a clear error.
  • mTLS user auth plus allow_unauthenticated_users fails at startup with a clear error.
  • Configuring both OIDC and mTLS user auth resolves per the Open Question (proposed: fail at startup).
  • Helm renders the mTLS role fields and fails rendering on the misconfigurations the binary rejects.
  • Sandbox supervisor calls continue to authenticate via gateway-minted sandbox JWTs, unchanged.
  • docs/reference/gateway-config.mdx and architecture/gateway.md document the path and its guardrails.
Open Question

What happens when both OIDC and mTLS user auth are configured? Proposed: fail at startup. Silently honoring one and ignoring the other hides a misconfiguration on the auth boundary, and an mTLS caller carries cert OUs, not OIDC claims — so "OIDC wins" would leave it authenticated but effectively role-less. Whether both can even be active on the same listener needs confirmation.

Alternatives Considered
  • Require OIDC for role separation (status quo). Forces an external identity provider onto a certificate-only deployment for no functional benefit.
  • Treat all mTLS callers as admin (implicit today). This is the gap — every authenticated caller becomes admin.
  • A dedicated admin-only client CA. Heavier operationally than a role OU and resolves to the same authorization question; possible follow-up, not the primary design.
Agent Investigation

The identity layer is already provider-agnostic (an Identity carries roles whether from OIDC or a cert), mTLS already extracts CN→subject and OU→roles (crates/openshell-server/src/multiplex.rs:1398-1409), and the role check is provider-neutral. The missing pieces are narrow: role fields on the mTLS config, a single resolver for the effective role names when there is no OIDC issuer, and having the authorization middleware consult it instead of only an OIDC-derived policy. The fail-closed and startup guards sit at existing config-validation and authorization sites. The sandbox JWT credential path is orthogonal and unchanged.

Checklist
  • I've reviewed existing issues and the architecture docs
  • This is a design proposal, not a "please build this" request

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with MtlsAuthConfig in crates/openshell-core/src/config.rs and the authorization and mTLS identity paths in crates/openshell-server/src/multiplex.rs, especially the cited sections. Review the Helm gateway configuration and the documentation files named in the acceptance criteria, then resolve the OIDC/mTLS behavior before implementation. Done means the startup guards, authorization outcomes, Helm rendering, and docs match the acceptance criteria without changing sandbox JWT authentication.

Written by the indexing model from the issue text.

Assessment

Tech stack
helm, rust
Domain
authentication, authorization, backend-api-design, devops, documentation
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.