Local operations UI
Every Mesh Node embeds an optional, read-only web page at /ui/ for operators who need to check a node from inside the trust boundary — for example during an outage of the outbound connection. It reads the node's live in-process state; it is not a replacement for the Sectigo Edge console.
What it shows
| Area | Details |
|---|---|
| Node | Node ID, name, tenant, hardware key protection (tpm2, windows_cng, pkcs11 or software) and enrollment time |
| Trust | Status (healthy, degraded or blocked), active signed policy ID, version, exact SHA-256 digest, expiry and last sync time, number of workload profiles, audit sequence and head digest, and whether cloud fallback is configured |
| Trust activity | Issuance requests, allowed and denied decisions, certificates issued, transactions queued after transport loss, health-gated rotations promoted, and dependency observations delivered and queued |
| Integrations | Each installed or assigned adapter with its health, desired-state revision and error code |
The page refreshes every 15 seconds. It derives trust status from the active signed policy: a missing digest, a non-active policy, a malformed expiry or an expired policy is shown as Blocked. If the live state cannot be fetched or decoded, the page shows an explicit unverified error instead of stale data.
It cannot propose policy, approve issuance, rotate a certificate, claim a service or change an integration. Those actions stay on their signed, authorized and audited paths in the console.
Enable it
The UI is off unless local_ui_enabled is true. In production you must also authorize at least one dedicated operator SPIFFE path — do not reuse the general workload prefix used for issuance.
- Linux / Windows
- Kubernetes
Add to config.json, validate and restart (see Configuration reference):
{
"local_ui_enabled": true,
"local_ui_allowed_spiffe_prefixes": [
"spiffe://acme-corp.example/operators/pki/"
]
}
helm upgrade --install mesh ./edgepki-node \
--namespace edgepki --reuse-values \
--set config.localUiEnabled=true \
--set 'config.localUiAllowedSpiffePrefixes={spiffe://acme-corp.example/operators/pki/}'
Each prefix must start with spiffe://<workload_trust_domain>/, end with /, and contain no %, ? or #. Matching respects path boundaries: an identity under spiffe://acme-corp.example/operators-evil/ does not match spiffe://acme-corp.example/operators/.
Who can open it
For every page, asset and data request the node requires:
- a client certificate whose chain verifies against
workload_trust_bundle_file(the listener only accepts TLS 1.3); - exactly one canonical SPIFFE URI SAN;
- that SPIFFE ID in
workload_trust_domain; - a path-boundary match to one of
local_ui_allowed_spiffe_prefixes.
| Situation | Response |
|---|---|
local_ui_enabled is false | 404 Not Found |
| No client certificate, or an untrusted one | 401 with local_ui_access_denied |
A valid workload identity outside the operator prefixes (for example spiffe://acme-corp.example/workloads/payments) | 403 with local_ui_access_denied |
| A valid operator identity | The page |
Open it in a browser
- Obtain a short-lived client certificate for your own operator identity (for example
spiffe://acme-corp.example/operators/pki/alice) from the CA that issues your workload identities. Prefer a non-exportable key in a TPM, Windows CNG, Secure Enclave or smart card through your enterprise certificate flow. - Install it in your operating system or browser certificate store.
- Make sure your machine trusts the CA that issued the node's
local-api.crt. - Browse to the node's local API address followed by
/ui/, for examplehttps://127.0.0.1:9443/ui/on the host itself, and choose the operator certificate when the browser asks.
Do not export a SPIRE workload private key just to make it usable in a browser. Use a dedicated operator certificate.
Network exposure
- On a single host, keep
listen_addresson loopback (127.0.0.1:9443, the console default). - On Kubernetes, use
kubectl port-forwardto a specific pod, or a private internal route that preserves end-to-end client-certificate authentication. - Never publish the UI on a public ingress, and never rely on an identity header added by a TLS-terminating proxy — the node only trusts the client certificate it verifies itself.
Browser security
The page loads only same-origin resources and stores nothing in cookies, local storage, IndexedDB or service workers. Responses are sent with Cache-Control: no-store, a strict Content Security Policy (default-src 'none', same-origin scripts, styles and connections, no framing, forms, plugins or base-URI changes), same-origin opener and resource policies, Referrer-Policy: no-referrer, a restrictive Permissions Policy and X-Content-Type-Options: nosniff. Adapter data is rendered as text, never as HTML.
Development mode
With insecure_development: true the UI is available without a client certificate, but only when both listen_address and local_api_url are on loopback. Never use development mode on a shared or routed interface.