Skip to content

Latest commit

 

History

History
127 lines (90 loc) · 11.1 KB

File metadata and controls

127 lines (90 loc) · 11.1 KB
title Console server

The console server (services/web, the oac-web process) serves the built console, signs the administrator in with the Core key and forwards the signed-in browser's /core/v1 requests to Core with that key. The browser never holds the Core key or any API key. Applications, nodes and self-hosted executors call Core directly; the console forwards none of their traffic.

Configuration owns its process settings and defaults.

Request boundary

flowchart LR
  browser["Administrator browser"]
  console["Console server"]
  core["Core"]
  database[("PostgreSQL")]
  application["Application / official SDK"]
  machine["Nodes and Runtime daemons"]
  installer["Installer domain service"]

  browser -->|"same origin: /console/*, /core/v1/*; session cookie"| console
  console -->|"/core/v1/* with the Core key"| core
  console -->|"domain setup, Unix socket"| installer
  application -->|"/v1 with a Project API key"| core
  machine -->|"/api/v1 with machine credentials"| core
  core <--> database
Loading

The deployment's reverse proxy routes /v1 and /api/v1 to Core and every other path to the console; the installation options gives the routes. The console handles each path as follows:

Path Sign-in Handling
/healthz No GET or HEAD answers 200 ok
/v1, /api/v1 and below — 404, whatever credential the request carries
/node-install/* No The node installation payload (see Node installation payload)
/console/auth, /console/auth/login, /console/auth/logout No Sign-in
/, /index.html, /favicon.svg, /oac-mark.svg, /assets/* No Static console assets
/console/config Yes Console configuration
/console/installation/domain Yes Domain setup
/core/v1/* Yes Forwarded to Core
/core and other paths under /core/ Yes 404
Any other path Yes Static assets; a path without a file extension falls back to index.html

Every request except /healthz, /v1 and /api/v1 must pass these checks first:

  1. Host and origin. The Host header must equal the host of OAC_WEB_ORIGIN. An Origin header, when present, must equal that origin, and Sec-Fetch-Site must be same-origin or none. A write that carries neither Origin nor Sec-Fetch-Site: same-origin needs a same-origin Referer. Otherwise the console answers 403. /node-install/* checks only the host and the path.
  2. Safe request. The path must start with / and contain no %, backslash, NUL, dot segment or empty segment. Absolute-form request targets, CONNECT, TRACE and any request with an Upgrade header get 400. A request can therefore never leave /core/v1 on Core, and the console carries no WebSocket.
  3. Sign-in. Paths that need sign-in answer 401 without a valid session cookie.

Under /core, these failures use the Core error envelope with the codes in console-generated failures; elsewhere they return {"error": "…"}, or plain text for an unsafe request. Every response carries Cache-Control: no-store, X-Content-Type-Options: nosniff, Referrer-Policy: no-referrer and Content-Security-Policy: frame-ancestors 'none'.

Forwarding to Core

The console forwards each signed-in /core/v1/* request by prefix to OAC_WEB_UPSTREAM, with its path and query unchanged. Core alone decides whether the route exists, and its responses and errors pass through unchanged. The console therefore needs no change when Core adds a /core/v1 route.

On the way to Core, the console:

  • removes the browser's Authorization, Proxy-Authorization, Cookie, Origin and Referer headers;
  • sends Authorization: Bearer <Core key>;
  • sets X-Core-Console-Actor: console, replacing any value the browser sent. Core records it as a display-only audit label (administrator API);
  • ignores ambient HTTP proxy settings, so the Core key reaches only the configured Core;
  • streams responses without buffering.

On the way back, it removes Set-Cookie, WWW-Authenticate, Location, Refresh and every Access-Control-* header. A redirect from Core, or a failed connection to Core, becomes 502 core_unreachable.

The console never retries a request. Browser code calls /core/v1 through the typed clients in packages/agents-client; console API usage lists what each page reads and writes.

Sign-in

Method and route Request Result
GET /console/auth No body 200 {"mode":"login"} or 200 {"mode":"authenticated"}
POST /console/auth/login Content-Type: application/json; body {"core_key":"…"} with no other member, at most 4 KiB 200 {"mode":"authenticated"} and the session cookie
POST /console/auth/logout No body 200 {"mode":"login"}; ends the session and clears the cookie

The administrator signs in with the deployment's Core key. There are no console accounts, usernames or setup step, and signing in grants the whole console.

  • The console compares SHA-256 digests of the submitted and configured keys in constant time. It never logs or returns the key.
  • The session cookie core_console_session is HttpOnly, SameSite=Strict, and Secure when OAC_WEB_ORIGIN is HTTPS. It lasts 12 hours.
  • Sessions live only in the console's memory, at most 64 at a time; the oldest is dropped first. A console restart or a Core key rotation signs everyone out.
  • At most two sign-in checks run at once; another attempt gets 429 with Retry-After: 1.
  • Failed attempts share a budget of 10 per minute; beyond it, a wrong key gets 429 with Retry-After: 60. The correct key always signs in, which is why the console refuses to start with a Core key shorter than 32 characters.

Sign-in errors: 400 for a malformed body, 401 Invalid Core key, 405 for a method other than POST, 415 for a body that is not JSON, 429 as above, and 503 when the console cannot create a session.

Console configuration

GET /console/config returns what the signed-in browser needs to add nodes:

Field Meaning
node_installer Whether the console serves a node installation payload
node_installer_sha256 SHA-256 of that payload's node-install.pyz; Add node commands verify it before running the installer
node_artifacts The providers (docker, microsandbox) whose node artifacts the payload holds, locally or as a pinned release download. Read on every request, so artifacts added by rerunning the installer appear without a restart

Node installation payload

With OAC_WEB_NODE_PAYLOAD_DIR set, the console serves the matched distribution's node payload at /node-install/ without sign-in: node-install.pyz, manifest.json, SHA256SUMS, runtime/seccomp.json, and the node artifacts the manifest declares under artifacts/. An artifact missing locally redirects (307) to its pinned release download. Node install and uninstall commands download from <public_url>/node-install/, so the reverse proxy must send that path to the console. Nodes verify every checksum themselves.

Domain setup

GET and POST /console/installation/domain let System → Domain and HTTPS configure a managed installation's domain. They are console routes, not Core routes. After the same origin and sign-in checks, the console passes the request body (at most 2 KiB) to the installer's Unix socket at OAC_WEB_INSTALLATION_SOCKET, authenticated with the Core key, and returns the installer's JSON answer and status. The request times out after 20 seconds.

Method Request Result
GET No body The domain status
POST {"hostname":"core.example.com"}, optionally with "confirm_public_url_change":"https://core.example.com" 202 and the status; the installer checks and applies the domain in the background

The status has supported, state (unconfigured, checking, applying, ready or failed), and nullable public_url, target_url and message. Installer errors use {"error":{"code":"…","message":"…"}}. Changing an address that nodes or executors already use returns 409 public_url_confirmation_required until the request confirms the new URL; pending config.json edits, an installation that is not applied or not running, hand-edited generated files, and another installation operation holding the lock (installation_busy) also return 409.

Without OAC_WEB_INSTALLATION_SOCKET (external reverse proxy installations), GET reports supported: false and POST returns 400 domain_setup_unavailable. An unreachable installer or an invalid answer returns 502 installation_unreachable.

The System page submits a hostname once, polls the status every 2 seconds while it is checking or applying, and asks for confirmation when the installer requires it. During setup, network failures and HTTP 502/503/504 responses keep polling active. The page allows 30 seconds without a successful status response before showing the disconnected message, and recovers when a poll succeeds. It never retries a write. Applying the domain restarts the console, which ends every session; the page keeps a sign-in link to the new HTTPS address. Only the ready state confirms HTTPS; the browser does not probe the new origin. The installer owns certificates, locking and recovery (managed HTTPS).

OAC_WEB_BOOTSTRAP=1, which the installer sets while no public URL is configured, lets the console also accept plain HTTP requests addressed to a literal IP address, treating http://<that address> as the origin, so an operator can sign in through the server's IP address. Host names still require OAC_WEB_ORIGIN, so DNS rebinding cannot reach the console.

Verification

After installing or changing the console, check:

  1. GET /healthz on the console and on Core. Each proves only that the process answers.
  2. Sign in, then read GET /core/v1/projects in the browser. This proves the browser-to-console and console-to-Core path and the console's Core key.
  3. A Project API key works on /v1 and fails on /core/v1. The Core key fails on /v1, and /v1 sent to the console answers 404.
  4. A cross-origin write to the console is rejected, and a forged X-Core-Console-Actor header does not change the audit label.
  5. Neither sign-in nor the sandbox deployment read (GET /core/v1/sandbox/deployment) proves that a model or a sandbox is ready. Runtime observations and history report execution separately.

A sign-in failure belongs to the console. A 401 from Core on a signed-in request means the console's Core key does not match Core's digest, or the console reaches the wrong Core. The troubleshooting table covers the common symptoms.