Skip to content

fix(tui): correctly handle plaintext and cloudflare_jwt gateway auth#1876

Draft
alexclewontin wants to merge 4 commits into
NVIDIA:mainfrom
alexclewontin:tui-plaintext-jwt
Draft

fix(tui): correctly handle plaintext and cloudflare_jwt gateway auth#1876
alexclewontin wants to merge 4 commits into
NVIDIA:mainfrom
alexclewontin:tui-plaintext-jwt

Conversation

@alexclewontin

@alexclewontin alexclewontin commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix TUI gateway switching for non-mTLS gateways. This PR makes the TUI honor explicit plaintext
gateway metadata and adds a dedicated cloudflare_jwt path so edge-authenticated gateways no
longer fall through to the mTLS flow.

This was identified in the review process of #1625 but since it pre-dates that PR and is not really directly related to it, I wanted to split it out.

Related Issue

N/A — split from review feedback on system-gateway-dir.

Changes

  • honor auth_mode = "plaintext" when selecting the TUI transport instead of defaulting HTTPS
    endpoints to mTLS
  • add an explicit GatewayChannelMode::Edge path for auth_mode = "cloudflare_jwt"
  • load stored edge tokens and build the TUI client with EdgeAuthInterceptor for
    edge-authenticated gateways
  • add crates/openshell-tui/src/edge_tunnel.rs to bridge local gRPC traffic over the gateway
    /_ws_tunnel WebSocket endpoint for HTTPS edge gateways
  • add unit coverage for gateway mode selection across plaintext, edge, OIDC, and HTTP fallback
    cases
  • add tokio-tungstenite and futures to support the edge tunnel client

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Additional testing:

  • cargo test -p openshell-tui --lib
  • cargo clippy -p openshell-tui --all-targets -- -D warnings

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@copy-pr-bot

copy-pr-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

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.

Signed-off-by: Alex Lewontin <alex.lewontin@canonical.com>
Signed-off-by: Alex Lewontin <alex.lewontin@canonical.com>
@alexclewontin alexclewontin marked this pull request as ready for review June 19, 2026 18:50
Add harness::mock_gateway with MockGateway — a minimal stub implementing
the full OpenShell gRPC trait so tonic is satisfied. Only health and
list_providers do real work: counting calls and validating auth headers
(cf-access-jwt-assertion for edge tokens, Authorization: Bearer for
OIDC). Plaintext and mTLS modes need no header checks; authentication
is enforced at the TLS layer.

Add harness::certs with generate_test_certs() to produce a CA, server
cert (valid for localhost and 127.0.0.1), and client cert via rcgen.
Used by TLS and mTLS mock gateway variants.

Public API:
  start_gateway()                           plain HTTP
  start_gateway_with_edge_token(name, tok)  validates JWT header
  start_gateway_with_tls_and_bearer(...)    TLS + bearer token
  start_gateway_with_mtls(...)              mutual TLS

Signed-off-by: Alex Lewontin <alex.lewontin@canonical.com>
@alexclewontin alexclewontin marked this pull request as draft June 19, 2026 19:13
Add e2e tests verifying the TUI can authenticate and connect to gateways
using all four channel modes:

- plaintext (explicit auth_mode=plaintext)
- edge/Cloudflare JWT (auth_mode=cloudflare_jwt; mock validates the
  cf-access-jwt-assertion header)
- http endpoint fallback (no auth_mode, http:// URL)
- OIDC (auth_mode=oidc; TLS server, mock validates Authorization: Bearer)
- mTLS (default for https:// with no auth_mode; full mutual TLS handshake)

Each test starts the TUI pointed at the target gateway, waits 3 s for
refresh_data to complete (health + list_providers + sandboxes on startup,
before the event loop), then kills the process and asserts provider_calls
> 0.  Graceful exit via 'q' is avoided because crossterm's event::poll
is a blocking call that starves other tasks on a single-thread tokio
runtime, preventing the keystroke from being processed.

TLS tests use rcgen-generated self-signed certs valid for localhost and
127.0.0.1.

Signed-off-by: Alex Lewontin <alex.lewontin@canonical.com>
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