Skip to content

Latest commit

 

History

History
264 lines (184 loc) · 13.4 KB

File metadata and controls

264 lines (184 loc) · 13.4 KB

Web Interface

Ze provides an HTTPS web interface for browsing configuration, editing values, and running commands through a browser. The web UI uses the same YANG schemas, user database, and command grammar as the SSH CLI.

Starting the Web Server

Command Line

ze start --web 8443                              # Start daemon + web on port 8443
ze start --web 8443 --insecure-web               # No authentication (forces 127.0.0.1)

When no certificate is configured, ze generates an ECDSA P-256 self-signed certificate automatically. The certificate includes SANs for localhost, 127.0.0.1, ::1, and the listen address.

Flag Description
--web <port> Start web interface on 0.0.0.0:<port>
--insecure-web Disable authentication (forces 127.0.0.1, requires --web)

Configuration

The web server listen address can also be set in the ze configuration file:

environment {
    web {
        enabled true;
        server main {
            ip 0.0.0.0;
            port 8443;
        }
    }
}

Authentication

The web interface uses the same user database as the SSH server. Users log in through a browser login page or authenticate API requests with HTTP Basic Auth.

Browser Sessions

  1. Navigate to https://<host>:8443/. Unauthenticated requests receive a login page.
  2. Enter username and password. On success, a ze-session cookie is set.
  3. The cookie is Secure, HttpOnly, and SameSite=Strict.
  4. Each user can have one active session. Logging in again invalidates the previous session.

JSON API

API clients that send Accept: application/json (or append ?format=json to the URL) can authenticate with HTTP Basic Auth instead of session cookies. No session is created for Basic Auth requests.

curl -k -u admin:password https://localhost:8443/show/bgp/?format=json

Security Headers

All authenticated responses include security headers: HSTS (max-age=63072000), Content-Security-Policy (default-src 'self'), X-Frame-Options DENY, X-Content-Type-Options nosniff, and Cache-Control: no-store.

Navigation

URL Scheme

URLs follow a verb-first three-tier pattern:

Tier URL Pattern Method Description
View /show/<yang-path> GET Read-only config tree view
View /monitor/<yang-path> GET View with auto-polling
Config /config/edit/<path> GET Editable config tree view
Config /config/set/<path> POST Set a leaf value
Config /config/add/<path> POST Create a list entry (with optional field values)
Config /config/add-form/<path> GET Fetch add-entry overlay form
Config /config/rename/<path> POST Rename a keyed list entry
Config /config/delete/<path> POST Delete a leaf value
Config /config/commit/ GET/POST View diff and commit changes
Config /config/discard/ POST Discard pending changes
Config /config/changes GET Commit bar state (pending change count)
Config /config/compare/ GET Compare pending vs committed
Admin /admin/<yang-path> GET/POST Administrative commands
Auth /login POST Login (no auth required)
Static /assets/ GET CSS, JS, images (no auth required)

The root URL / redirects to /show/.

Finder Navigation

The left panel uses a Finder-style column browser (similar to macOS Finder). It shows up to 3 columns, scrolling horizontally as you navigate deeper.

Named vs unnamed containers: Named containers (lists with YANG keys, like peer, group) appear above unnamed containers (global settings like local, timer), separated by a horizontal rule. This makes keyed sections easy to find.

Simple lists: Lists without unique constraints show as a flat column of clickable entries with a + new button.

Context Heading

When inside a list entry, the detail panel shows a context heading at the top with the list name and entry key (e.g., PEER london). This provides immediate context without checking the breadcrumb.

List Table View

Lists that have YANG unique constraints (e.g., peer with unique "remote/ip") display as an interactive table in the detail panel. The table shows the list key and all unique fields as columns.

Column Behavior
Rename button Opens a modal, normalizes the new key, and renames the entry without losing its subtree
Key column (e.g., name) Clickable link, navigates into the entry's config subtree
Unique field columns (e.g., remote/ip) Editable inline, saves on blur/Enter/auto-save (1s debounce)
Delete button Removes the entry after confirmation

The + new button below the table opens a server-rendered form (via HTMX) with inputs for the entry name and all unique fields. Field values are validated against YANG types before the entry is created.

Breadcrumb Navigation

Every page displays a breadcrumb trail from root to the current YANG path. Clicking any breadcrumb segment navigates to that level.

Content Negotiation

The response format is determined by:

  1. ?format=json query parameter (takes precedence)
  2. Accept: application/json header (when text/html is not also present)
  3. Default: HTML

Config Editing

Each authenticated user gets an independent editor session with its own working tree. Changes are tracked per-user and do not affect other users until committed.

Workflow

  1. Browse: Navigate to a list (e.g., /show/bgp/peer/) to see entries in a table.
  2. Add: Click + new to create an entry. Fill in the name and unique fields. Values are validated against YANG types (e.g., IP addresses must be valid).
  3. Rename: In table views, click the rename button to change an entry key. The new key is trimmed and lowercased, and the existing subtree stays attached to the renamed entry.
  4. Edit: Click an entry name to see its full config. Edit leaf values through inline fields.
  5. Review: The commit bar at the bottom shows pending change count. Click "Review & Commit" to see a diff.
  6. Commit: Apply changes. Conflicts with other users are detected and reported.
  7. Discard: Click "Discard" to abandon all pending changes.

Validation

Field values are validated server-side against YANG types before being accepted:

Type Validation
IP address Must be a valid IPv4 or IPv6 address
IPv4 Must be a valid IPv4 address
IPv6 Must be a valid IPv6 address
Prefix Must be a valid CIDR prefix
Uint16/Uint32 Must be a valid unsigned integer in range
Boolean Normalized to true/false

YANG unique constraints are enforced: duplicate values are rejected with an error naming the conflicting entry.

Entry key names are automatically lowercased and trimmed for both add and rename operations.

Duplicate entry keys are rejected. Validation runs before the entry is created, so invalid input never produces a partial entry.

Navigating to a non-existent list entry (e.g., /show/bgp/peer/london/ when london has not been created) redirects to the root view with an error notification.

Notifications

Error notifications appear as toasts in the top-right corner with a 30-second countdown. Click the countdown to pause (for screenshots). Click the close button to dismiss immediately.

Input Auto-Save

Text and number fields auto-save 1 second after the user stops typing, in addition to saving on blur and Enter. This prevents data loss when navigating away before a field loses focus.

Conflict Detection

When two users edit the same leaf concurrently, the commit reports which paths conflict, showing both the local and other user's values. The user must resolve conflicts before committing.

Session Limits

The editor manager allows up to 50 concurrent user sessions. Idle sessions (no activity for 1 hour) are evicted when capacity is reached.

CLI Bar

The web interface includes a CLI bar at the bottom of the page that accepts the same command grammar as the SSH CLI. The CLI bar sends the current URL path as context, so set and delete commands operate relative to the current view.

Integrated Mode

In integrated mode, CLI commands update the page content directly:

Command Effect
edit <path> Navigate to a config path
set <leaf> <value> Set a value at the current context path
delete <leaf> Delete a value at the current context path
show [path] Display config text at the current or specified path
top Navigate to root
up Navigate one level up
commit Commit pending changes
discard Discard pending changes
help List available commands

The prompt shows the current context path: ze[bgp peer]# .

Terminal Mode

Terminal mode provides a scrollback terminal in the browser. Commands produce plain text output identical to the SSH CLI, displayed in a scrollback area with prompt echo.

Tab Completion

The CLI bar provides tab completion via a JSON endpoint at /cli/complete. Completions are context-aware: when at /show/bgp/peer/london/, typing set + Tab suggests remote, local, timer (children of the peer entry), not root-level items. For YANG union types that include an enum (e.g., local/ip accepting an IP address or auto), the enum values are offered as completions.

Live Updates

The web interface uses Server-Sent Events (SSE) to notify connected browsers when configuration changes are committed by any user. A notification banner appears with the username and a "Refresh" button.

Connect to the SSE stream at /events (requires authentication). The broker supports up to 100 concurrent SSE clients. Slow clients that fall behind have events dropped rather than blocking other clients.

Event Format

Events use the standard SSE wire format:

event: config-change
data: <html-fragment>

The HTML fragment contains a notification banner with the change description and action buttons.

Admin Commands

The /admin/ tier provides a browsable tree of administrative commands. Container nodes display navigable links to sub-commands. Leaf commands display a parameter form with an "Execute" button.

Admin command results are displayed as titled cards showing the command name, output text, and success/error styling.

Resilience

Corrupt change files: If a per-user change file in the blob store is unparseable (e.g., from a previous bug), it is automatically discarded with a warning log. The user can continue editing without manual intervention.

Asset caching: Static assets (/assets/) are served with Cache-Control: no-cache, must-revalidate so browsers always pick up changes after binary updates without requiring a hard refresh.