Imported from stolostron/console (
backend/AGENTS.md). Install upstream withnpx skills add stolostron/console --skill backend. Copyright stays with the author.
Backend
Node.js ESM proxy server. Sits between the browser and the hub cluster API server, handling authentication, RBAC enforcement, resource watching, and API proxying.
Key Technologies
- Runtime: Node.js with native ESM (
"type": "module") - Router:
find-my-wayfor HTTP/2 route matching - Proxy:
node:https+pipelinefor main API proxy;http2-proxyfor managed cluster proxy - Logging: Pino with structured JSON output (use
pino-zenfor dev formatting) - Metrics: Prometheus metrics proxied via
metricsProxyroute - HTTP Client:
gotfor outbound requests - WebSocket: upgrade handler routes to search (bidirectional relay via
wswith token injection) and managed cluster proxy (viahttp2-proxy)
Source Layout
| Directory | Purpose |
|---|---|
src/lib/ |
Core server: main.ts entry, server.ts, auth, cookies, CORS, proxy, search, SSE, logging, config |
src/routes/ |
HTTP route handlers: proxy, OAuth, search, events, hub, serve, metrics, managed cluster proxy, etc. |
src/resources/ |
Backend resource watchers and handlers |
test/ |
Jest test files |
config/ |
Runtime configuration |
certs/ |
TLS certificates (auto-generated on npm install) |
Commands
Run from the backend/ directory, or use the npm run *:backend variants from the repo root.
| Command | Purpose |
|---|---|
npm start |
Start dev server with nodemon + inspector |
npm test |
Run Jest tests |
npm run lint |
ESLint check |
npm run tsc |
TypeScript type check |
npm run check |
Run lint + prettier + tsc together |
npm run build |
Production build via tsc + rollup → backend.mjs |
npm run clean |
Remove build artifacts |
npm run generate-certs |
Regenerate TLS certificates |
Architecture
Browser → Backend (HTTP/2 proxy) → Hub Cluster API Server
↓
Watches resources via service account
Enforces RBAC via user token + SubjectAccessReview
Streams events to frontend via SSE
Route Handlers
- Route handler signature:
(req: Http2ServerRequest, res: Http2ServerResponse): Promise<void> - Router uses
maxParamLength: 500for long Kubernetes resource names - URL rewriting:
/multicloudprefix is stripped before routing inapp.tsfor HTTP andserver.tsfor WebSocket upgrades (e.g.,/multicloud/proxy/search→/proxy/search) - Use
pipeline()fromnode:streamfor proxy and streaming operations to ensure proper backpressure and cleanup - Use
getEncodeStream()for SSE compression
Security
- Never log sensitive data (tokens, passwords, credentials)
- Validate and sanitize all inputs
- Guard against injection vulnerabilities (command injection, path traversal)
- Ensure proper authentication and authorization checks on all routes
- Use
SelfSubjectAccessReviewfor permission checks - Log at appropriate levels with Pino (error, warn, info, debug) — include relevant context but never sensitive data
Configuration
Environment Variables (.env)
Generated by npm run setup from the repo root. These are cluster-specific and should not be set manually unless overriding for special cases:
| Variable | Purpose |
|---|---|
PORT |
Backend server port (defaults via port-defaults.sh) |
NODE_ENV |
development or production — controls CORS, caching, logging, cert behavior |
CLUSTER_API_URL |
Hub cluster API server URL — used extensively for all K8s API calls |
TOKEN |
Service account token for backend-initiated cluster requests |
CA_CERT / SERVICE_CA_CERT |
Cluster CA certificates for TLS verification |
OAUTH2_CLIENT_ID / OAUTH2_CLIENT_SECRET |
OAuth client credentials for login flow |
OAUTH2_REDIRECT_URL |
OAuth callback URL |
OIDC_ISSUER_URL |
OIDC issuer URL (when using external OIDC instead of OpenShift OAuth) |
FRONTEND_URL |
Frontend URL for post-login redirect |
SEARCH_API_URL |
Search API route URL |
PLACEMENT_DEBUG_URL |
Placement debug service route URL |
CLUSTER_PROXY_ADDON_USER_HOST / CLUSTER_PROXY_ADDON_USER_ROUTE |
Managed cluster proxy endpoint |
OBSERVABILITY_ROUTE |
Observability query proxy route (requires ACM Observability) |
PROMETHEUS_ROUTE |
Prometheus route for metrics proxy |
Optional development/debug variables (not in .env by default):
| Variable | Purpose |
|---|---|
HTTPS_PROXY |
HTTP proxy for outbound requests |
DELAY / RANDOM_DELAY |
Artificial delay for dev testing (development mode only) |
MOCK_CLUSTERS |
Number of mock clusters to generate for testing |
DISABLE_EVENTS |
Set to true to disable SSE event streams |
DISABLE_STREAM_COMPRESSION |
Set to true to disable SSE compression |
PUBLIC_FOLDER |
Override static file serving path (default ./public) |
Settings (config/ directory)
Files in config/ are loaded at startup and watched for dynamic updates. Changes are pushed to the frontend via SSE SETTINGS events. Only specific keys are promoted to process.env:
LOG_*keys (LOG_LEVEL,LOG_ACCESS,LOG_EVENTS,LOG_MEMORY,LOG_WATCH) — control logging behaviorAPP_SEARCH_*keys (APP_SEARCH_INTERVAL,APP_SEARCH_LIMIT) — application search tuningglobalSearchFeatureFlag— enables federated search endpointUPGRADE_RISKS_PREDICTION_URL— override for upgrade risk prediction service
Other config files (e.g., singleNodeOpenshift, ansibleIntegration, awsPrivateWizardStep) are sent to the frontend as settings but not promoted to backend env vars. The frontend uses these to toggle UI features like single-node cluster creation and Ansible automation options.
Feature Flags
Feature flags come from two mechanisms:
- MultiClusterHub components — the
/multiclusterhub/componentsroute exposes MCH component status, used by the frontend to determine which features are installed - Config settings — files in
config/act as feature toggles (e.g.,singleNodeOpenshift,ansibleIntegration), pushed to the frontend via SSE and checked withsettings.<flag> === 'enabled'
Testing
- Test files are in
test/ - Tests should meaningfully cover behavior, not just achieve coverage metrics
- Properly mock and isolate dependencies
- Async tests must handle promises correctly
Environment
The backend requires a .env file for cluster connection. Generate it with npm run setup from the repo root. Key variables include the cluster API URL, OAuth credentials, and service account token.