Skip to content

feat(server): separate HTTPS from mTLS authentication#1351

Open
sjenning wants to merge 1 commit into
NVIDIA:mainfrom
sjenning:feat/separate-https-from-mtls
Open

feat(server): separate HTTPS from mTLS authentication#1351
sjenning wants to merge 1 commit into
NVIDIA:mainfrom
sjenning:feat/separate-https-from-mtls

Conversation

@sjenning
Copy link
Copy Markdown
Contributor

@sjenning sjenning commented May 13, 2026

Summary

  • Decouple HTTPS encryption from mTLS client certificate authentication by making --tls-client-ca optional
  • Client certificates are always optional when a CA is configured — validated when presented but never required
  • mTLS and OIDC bearer tokens coexist as parallel authentication mechanisms: if no bearer token is present but a valid client cert was, the peer is authenticated via mTLS
  • Enable HTTPS-only deployments (no client CA) for gateways that rely solely on OIDC

Related Issue

N/A

Changes

Core config

  • openshell-core/config.rs: TlsConfig.client_ca_path changed from PathBuf to Option<PathBuf>; allow_unauthenticated replaced with require_client_auth (inverted semantics)

TLS layer

  • openshell-server/tls.rs: TlsAcceptor::from_files takes Option<&Path> for client CA — Some builds a client cert verifier (optional or required), None uses with_no_client_auth()

Authentication routing

  • openshell-server/multiplex.rs: New serve_with_peer_identity() plumbs the mTLS Identity from the TLS handshake into the gRPC auth layer; AuthGrpcRouter falls back to mTLS identity when no bearer token is present and a client cert was presented; new extract_peer_identity() parses CN and OU fields from the peer's X.509 certificate
  • openshell-server/lib.rs: Connection handler calls extract_peer_identity() on the TLS stream and passes it to serve_with_peer_identity()

CLI / startup

  • openshell-server/cli.rs: --tls-client-ca is no longer required when TLS is enabled; --disable-gateway-auth flag removed; added mutual exclusion check (--disable-tls + --tls-client-ca); startup logs now distinguish HTTPS, mTLS, OIDC, and no-auth states
  • openshell-server/Cargo.toml: Added x509-parser dependency for peer cert extraction

Helm

  • deploy/helm/openshell/templates/statefulset.yaml: Conditionally include client-ca env var, volume mount, and volume only when clientCaSecretName is set
  • deploy/helm/openshell/values.yaml: Document that clientCaSecretName is optional

Docs / config references

  • deploy/man/openshell-gateway.8.md: Updated man page — --tls-client-ca marked optional, --disable-gateway-auth removed
  • deploy/man/openshell-gateway.env.5.md: OPENSHELL_TLS_CLIENT_CA marked optional, OPENSHELL_DISABLE_GATEWAY_AUTH removed
  • deploy/rpm/CONFIGURATION.md: Same updates for RPM config docs
  • deploy/kube/manifests/openshell-helmchart.yaml: Removed disableGatewayAuth field

Tests

  • edge_tunnel_auth.rs: Rewritten — old allow_unauthenticated matrix replaced with new model: valid cert accepted, no cert accepted (optional), bearer auth passthrough, rogue cert rejected, and new HTTPS-only mode test
  • multiplex_tls_integration.rs: Updated from_files calls to new Option<&Path> signature; added HTTPS-only (no client CA) test case

Testing

  • mise run pre-commit passes
  • 5 edge_tunnel_auth tests pass (rewritten test matrix)
  • 5 multiplex_tls_integration tests pass (including new HTTPS-only case)
  • Manual: start gateway with --tls-cert and --tls-key only, verify HTTPS-only mode works with OIDC

Checklist

  • Conventional commit format
  • No secrets committed
  • Backward compatible for --tls-client-ca users (certs are now optional instead of required — strictly more permissive)
  • Breaking: --disable-gateway-auth removed, allow_unauthenticated config field removed
  • Tests updated for new auth model

@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 13, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@sjenning sjenning force-pushed the feat/separate-https-from-mtls branch from 17b1e9c to 6793737 Compare May 13, 2026 19:24
@sjenning sjenning changed the title feat(server): separate HTTPS from mTLS authentication WIP: feat(server): separate HTTPS from mTLS authentication May 13, 2026
Comment thread crates/openshell-server/src/cli.rs Outdated
Comment thread crates/openshell-server/src/cli.rs Outdated
@sjenning sjenning force-pushed the feat/separate-https-from-mtls branch from 6793737 to 96e496b Compare May 14, 2026 16:40
@sjenning sjenning changed the title WIP: feat(server): separate HTTPS from mTLS authentication feat(server): separate HTTPS from mTLS authentication May 14, 2026
@TaylorMutch TaylorMutch added the test:e2e Requires end-to-end coverage label May 14, 2026
@github-actions
Copy link
Copy Markdown

Label test:e2e applied, but pull-request/1351 is at {"messa while the PR head is 96e496b. A maintainer needs to comment /ok to test 96e496bb87c82b46ef7a8740945d3f2d491b9255 to refresh the mirror. Once the mirror catches up, re-run Branch E2E Checks from the Actions tab.

@TaylorMutch
Copy link
Copy Markdown
Collaborator

/ok to test 96e496b

@sjenning sjenning force-pushed the feat/separate-https-from-mtls branch 2 times, most recently from 59d4465 to df32568 Compare May 14, 2026 20:04
.push(DnType::CommonName, "openshell-client");
client_params
.distinguished_name
.push(DnType::OrganizationalUnitName, "openshell-user");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@TaylorMutch I was hoping to make this change fully backward compatible but the mTLS client cert for the supervisor needs to have a role now to get through authz.

@TaylorMutch TaylorMutch self-assigned this May 14, 2026
Make --tls-client-ca optional and make client certificates always
optional when a CA is configured. This decouples HTTPS encryption
from mTLS authentication, allowing mTLS and OIDC bearer tokens to
coexist as parallel authentication mechanisms.

When --tls-client-ca is provided, client certificates are validated
against the CA when presented but never required. Clients may connect
with or without a certificate — authentication is handled at the
application layer (e.g. OIDC).

Two TLS modes are now supported:
- HTTPS with optional mTLS (--tls-client-ca provided)
- HTTPS-only (--tls-client-ca omitted)

The --disable-gateway-auth flag is preserved for backward
compatibility but is now a no-op. The allow_unauthenticated field
has been removed from TlsConfig. The Helm chart conditionally
includes the client-ca volume and env var based on whether
clientCaSecretName is configured.
@sjenning sjenning force-pushed the feat/separate-https-from-mtls branch from df32568 to 6e76f6d Compare May 14, 2026 21:10
@TaylorMutch
Copy link
Copy Markdown
Collaborator

/ok to test 6e76f6d

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants