-
Notifications
You must be signed in to change notification settings - Fork 32
Device Management Toolkit Architecture Deep Dive
A comprehensive technical guide covering microservice deployment, device lifecycle, CIRA connectivity, command execution flows, WSMAN protocol, and E2E TLS activation.
- Deployment Models & Component Overview
- System Overview & Deployment Architecture
- Microservice Roles & Responsibilities
- How RPC Operates Internally on the Device
- RPC-Go to RPS Communication
- Device Lifecycle: Activation to Remote Manageability
- CIRA Connection: Establishment & Maintenance
- MPS Router: Scaled Deployment & Connection Routing
- Command Execution: API Request to Device Action
- WSMAN Protocol
- APF Protocol Overview
- KVM, SOL & IDER: Redirection Features
- Data Storage: Vault vs Database
- Production Integration Guide
- Security Architecture
- Appendix: Port & Protocol Reference
DMT provides two deployment models: a cloud deployment (current, production-ready) and an enterprise on-premises deployment (work in progress).
-
Cloud Deployment — the
v2branch of thedeploymentrepo. Microservice-based, Docker Compose orchestrated, designed for remote management of distributed AMT devices over the internet. - Enterprise Deployment — On-premises focused, uses two standalone binaries: Console (server) and RPC-Go in local mode. No cloud infrastructure needed — communicates with AMT directly on the LAN.
flowchart TB
DMT["Device Management Toolkit"]
DMT --> Cloud["Cloud Deployment"]
DMT --> Enterprise["Enterprise Deployment"]
flowchart TB
Cloud["Cloud Deployment - v2 (Current Deployment)"]
Cloud --> MPSRouter["MPS Router"]
Cloud --> MPS["MPS"]
Cloud --> RPS["RPS"]
Cloud --> RPC["RPC-Go"]
Cloud --> SWUI["Sample Web UI"]
Cloud --> EA["Enterprise Assistant"]
SWUI --> UITAngular["UI Toolkit Angular"]
UITAngular --> UIT["UI Toolkit"]
MPS --> WSMAN["WSMAN-Messages"]
RPS --> WSMAN
RPC --> GoWSMAN["Go-WSMAN-Messages"]
| Component | Repo | Role |
|---|---|---|
| MPS | mps |
Management Presence Server — maintains CIRA connections, REST API, WebSocket relay |
| RPS | rps |
Remote Provisioning Server — activates devices, applies profiles |
| MPS Router | mps-router |
Device-affinity TCP proxy for horizontal MPS scaling |
| RPC-Go | rpc-go |
Agent on managed device — communicates with AMT via MEI |
| Sample Web UI | sample-web-ui |
Angular reference management console |
| Enterprise Assistant | — | Assists with enterprise integration workflows |
| UI Toolkit Angular | ui-toolkit-angular |
Reusable KVM/SOL/IDER Angular components |
| UI Toolkit | ui-toolkit |
Core rendering logic (framework-agnostic) |
| WSMAN-Messages | wsman-messages |
TypeScript SOAP/XML message construction for AMT |
| Go-WSMAN-Messages | go-wsman-messages |
Go WSMAN message construction + transport + digest auth |
flowchart TB
Enterprise["Enterprise Deployment"]
Enterprise --> Console["Console"]
Enterprise --> RPC["RPC-Go"]
Enterprise --> SWUI["Sample Web UI"]
Enterprise --> EA["Enterprise Assistant"]
SWUI --> UITAngular["UI Toolkit Angular"]
UITAngular --> UIT["UI Toolkit"]
Console --> GoWSMAN["Go-WSMAN-Messages"]
RPC --> GoWSMAN
The enterprise model replaces MPS/RPS/Router with a single Console binary (Go) that manages devices directly on the LAN. No CIRA tunnel needed — Console communicates with AMT over local WSMAN (ports 16992/16993) using go-wsman-messages.
DMT Cloud deployment is composed of the following core microservices, deployable via Kubernetes (EKS, AKS) for production or Docker Compose for quick setups:
graph TB
subgraph External["External Network"]
Client[API Client / Browser]
end
subgraph Device["Client Machine (vPro/ISM)"]
RPC["RPC-Go<br/>(OS Layer)"]
AMT["Intel AMT<br/>(Firmware Layer)"]
end
subgraph Cloud["Cloud Services"]
Kong["Kong API Gateway<br/>:443 HTTPS<br/>JWT · CORS · TLS termination"]
subgraph Core["Core Services"]
MPS["MPS<br/>Management Presence Server<br/>:4433 CIRA (TLS+APF)<br/>:3000 REST API + WS Relay"]
RPS["RPS<br/>Remote Provisioning Server<br/>:8081 REST API<br/>:8080 WebSocket (activation)"]
Router["MPS Router<br/>:8003<br/>Device-affinity TCP proxy"]
end
subgraph Backing["Backing Services (3rd Party)"]
PG["PostgreSQL :5432<br/>rpsdb + mpsdb"]
Vault["Vault :8200<br/>Secrets & Certs"]
end
WebUI["Sample Web UI<br/>nginx :80"]
end
RPC -->|"LMS (APF) :16992/16993"| AMT
Client -->|HTTPS :443| Kong
RPC -->|"WSS :443 /activate"| Kong
AMT -->|"TLS :4433 (CIRA)"| Kong
Kong -->|/mps/*| Router
Kong -->|/mps/login, /mps/ws/*| MPS
Kong -->|/rps/*| RPS
Kong -->|/activate, /deactivate| RPS
Kong -->|/| WebUI
Kong -->|":4433 TCP passthrough"| MPS
Router -->|Route to correct instance| MPS
RPS -->|POST /api/v1/devices| MPS
RPS --> PG
RPS --> Vault
MPS --> PG
MPS --> Vault
%% DMT-owned components - Blue
style MPS fill:#1565C0,color:#fff
style RPS fill:#1976D2,color:#fff
style Router fill:#1E88E5,color:#fff
style WebUI fill:#2196F3,color:#fff
style RPC fill:#42A5F5,color:#fff
%% 3rd party / external - Gray
style Kong fill:#616161,color:#fff
style PG fill:#616161,color:#fff
style Vault fill:#616161,color:#fff
style Client fill:#616161,color:#fff
style AMT fill:#616161,color:#fff
%% Device context
style Device fill:#EEEEEE,color:#000
style Cloud fill:#ffffff,color:#000,stroke:#1565C0
style Core fill:#E3F2FD,color:#000
style Backing fill:#FAFAFA,color:#000
style External fill:#FAFAFA,color:#000
graph LR
Client[Client / Browser] -->|":443 HTTPS"| Kong
RPC[RPC-Go] -.->|":443 WSS /activate"| Kong
AMT[Intel AMT] ==>|":4433 TLS (CIRA)"| Kong
Kong -->|":8003 HTTP"| Router[MPS Router]
Kong -->|":3000 HTTP"| MPS
Kong -->|":8081 HTTP"| RPS
Kong -->|":80 HTTP"| WebUI[Sample Web UI]
Kong ==>|":4433 TCP passthrough"| MPS
Router -->|":3000 HTTP"| MPS
RPS -->|":3000 HTTP"| MPS
MPS --> PG[PostgreSQL :5432]
RPS --> PG
MPS --> Vault[Vault :8200]
RPS --> Vault
style MPS fill:#1565C0,color:#fff
style RPS fill:#1976D2,color:#fff
style Router fill:#1E88E5,color:#fff
style WebUI fill:#2196F3,color:#fff
style RPC fill:#42A5F5,color:#fff
style Kong fill:#616161,color:#fff
style PG fill:#616161,color:#fff
style Vault fill:#616161,color:#fff
style Client fill:#616161,color:#fff
style AMT fill:#616161,color:#fff
| Port | Protocol | From | To | Purpose |
|---|---|---|---|---|
| 443 | HTTPS | Client / Browser | Kong | All API calls, WebSocket relay, UI — Kong terminates TLS |
| 443 | WSS | RPC-Go (OS) | Kong → RPS :8080 | Activation/deactivation via /activate, /deactivate — Kong terminates TLS
|
| 4433 | TLS + APF | Intel AMT (firmware) | Kong → MPS | Persistent CIRA connection — Kong passes TCP through, MPS handles TLS |
| Port | Protocol | From | To | Purpose |
|---|---|---|---|---|
| 4433 | TCP passthrough | Kong | MPS | Forward CIRA TLS connections as-is — MPS handles TLS termination |
| 8003 | HTTP | Kong | MPS Router | Route device-specific API requests to correct MPS instance |
| 3000 | HTTP | Kong | MPS | Auth endpoints (/mps/login), WebSocket relay (/mps/ws/*) |
| 8081 | HTTP | Kong | RPS | Profile/config management API (/rps/*) |
| 8080 | HTTP/WS | Kong | RPS | Activation/deactivation WebSocket — routed from /activate, /deactivate on :443 |
| 80 | HTTP | Kong | Sample Web UI | Serve Angular SPA |
| Port | Protocol | From | To | Purpose |
|---|---|---|---|---|
| 3000 | HTTP | MPS Router | MPS | Forward device-affinity routed requests |
| 3000 | HTTP | RPS | MPS | Register device after activation (POST /api/v1/devices) |
| Port | Protocol | From | To | Purpose |
|---|---|---|---|---|
| 5432 | TCP | MPS | PostgreSQL | Device inventory, connection state (mpsdb) |
| 5432 | TCP | RPS | PostgreSQL | Profiles, CIRA configs, domains (rpsdb) |
| 8200 | HTTP | MPS | Vault | Device MPS passwords, AMT credentials |
| 8200 | HTTP | RPS | Vault | Provisioning certs, device passwords |
| Port | Protocol | From | To | Purpose |
|---|---|---|---|---|
| 443 | WSS | RPC-Go | Kong (cloud) | Outbound activation/deactivation connection to cloud |
| 16992/16993 | APF (LMS) | RPC-Go | Intel AMT (firmware) | Local MEI communication on the client machine |
Two separate PostgreSQL databases share the same server:
| Database | Owner | Key Tables |
|---|---|---|
| rpsdb | RPS |
profiles, ciraconfigs, domains, wirelessconfigs, ieee8021xconfigs, proxyconfigs
|
| mpsdb | MPS, MPS Router |
devices (GUID, status, mpsInstance, tags, tenantId, lastSeen, deviceInfo) |
Purpose: Activates (provisions) AMT devices and applies configuration profiles.
| Capability | Details |
|---|---|
| Activation | CCM (Client Control Mode) and ACM (Admin Control Mode) |
| Configuration | CIRA, TLS, WiFi, 802.1x, proxy, KVM/SOL/IDER features |
| Deactivation | Unprovision devices remotely |
| Maintenance | Sync clock, hostname, IP, password rotation, device info |
| Profile Management | CRUD for AMT profiles, CIRA configs, domains, wireless profiles |
| Device Registration | After activation, RPS calls POST /api/v1/devices on MPS to add the device |
Runtime behavior: RPS runs an Express REST API (port 8081) for profile management and a WebSocket server (port 8080) for RPC client connections. The activation logic is driven by XState v5 state machines that orchestrate dozens of WSMAN calls against the device.
Key interaction with MPS:
- Fetches MPS root CA certificate from Vault (path
MPSCerts) for CIRA configuration -
Adds the device to MPS via
POST /api/v1/devices(sends GUID, hostname, mpsusername, tags, tenantId, deviceInfo) - Checks tenant access on already-activated devices via
GET /api/v1/devices/{uuid}
Purpose: Maintains persistent connections to AMT devices and provides the management API.
| Capability | Details |
|---|---|
| CIRA Connections | Accepts and manages persistent TLS connections from devices via APF protocol |
| REST API | Power control, feature management, certificates, audit/event logs, hardware info |
| WebSocket Relay | Bridges browser WebSocket connections to AMT redirection channels (KVM/SOL/IDER) |
| Device Inventory | Tracks connection status, last seen timestamps, device metadata in PostgreSQL |
| Multi-Instance | Supports horizontal scaling via MPS Router for connection routing |
Two servers in one process:
| Server | Port | Clients |
|---|---|---|
| MPS Server | 4433 | AMT devices (CIRA over TLS) |
| Web Server | 3000 | API clients, Web UI, MPS Router |
Purpose: Routes API requests to the correct MPS instance in multi-instance deployments. See Section 8 for the detailed scaling mechanism.
RPC-Go is a command-line tool (or shared library) that runs on the managed device. In remote mode, it acts as a transparent byte bridge — one WSS connection to the cloud, one TCP connection to AMT via LMS. It decodes base64 payloads from JSON messages and forwards the raw bytes to LMS. In local mode, it constructs WSMAN messages itself using go-wsman-messages and sends them to AMT via the same LMS or LME paths.
graph TB
subgraph Cloud["Cloud"]
Kong["Kong :443"]
RPS["RPS :8080"]
end
subgraph Device["Managed Device (OS)"]
subgraph RPC["RPC-Go Process"]
CLI["CLI Parser<br/>(cobra)"]
Exec["Command Executor<br/>activate / deactivate /<br/>configure / maintenance / amtinfo"]
subgraph RemoteMode["Remote Mode (-u wss://...)"]
WS["WebSocket Client<br/>(gorilla/websocket)"]
Decode["Decode base64 payload<br/>to raw bytes"]
end
subgraph LocalMode["Local Mode (-local)"]
WSMANLib["go-wsman-messages<br/>(HTTP/SOAP client,<br/>constructs WSMAN XML)"]
end
subgraph LMLayer["Local Management Interface"]
LMS_Conn["LMS Connection<br/>(TCP socket to LMS daemon)<br/>preferred"]
LME_Conn["LME Connection<br/>(APF over MEI)<br/>fallback when LMS not running"]
end
PTHI_Cmd["PTHI Commands<br/>(binary: UUID, version,<br/>cert hashes, control mode)"]
end
LMS["Intel LMS Daemon<br/>(separate system service)<br/>TCP listener on localhost"]
HECI["HECI / MEI Driver<br/>(kernel)"]
end
subgraph ME["Intel Management Engine (Hardware)"]
AMT["Intel AMT Firmware<br/>:16992 · :16993 (WSMAN)<br/>:16994 (KVM) · :16995 (SOL) · :16996 (IDER)"]
end
%% Cloud connections
WS <-->|"JSON over WSS"| Kong
Kong <-->|"JSON over WS"| RPS
%% CLI flow
CLI --> Exec
Exec --> RemoteMode
Exec --> LocalMode
Exec --> PTHI_Cmd
%% Remote mode: decode then forward
WS -->|"base64 payload<br/>from JSON"| Decode
Decode -->|"raw bytes"| LMLayer
%% Local mode: WSMAN HTTP to LMS or LME
WSMANLib -->|"HTTP POST<br/>/wsman"| LMLayer
%% LM connections
LMS_Conn -->|"TCP"| LMS
LME_Conn -->|"APF bytes"| HECI
%% PTHI (common to both modes, direct to driver)
PTHI_Cmd -->|"IOCTL"| HECI
%% LMS daemon to ME
LMS --> HECI
%% ME
HECI --> AMT
%% Styling
style RPC fill:#FAFAF0,color:#000
style ME fill:#616161,color:#fff
style Cloud fill:#FAFAF0,color:#000
style LMS fill:#616161,color:#fff
Key points:
- In remote mode, rpc-go maintains two simultaneous connections: WSS to cloud (left) and TCP to LMS (right). It decodes base64 from JSON messages and forwards raw bytes to LMS, and base64-encodes LMS responses back into JSON for the cloud.
- In local mode, rpc-go constructs WSMAN HTTP/SOAP messages using
go-wsman-messagesand sends them to LMS over HTTP, or directly via LME/MEI if LMS isn't running. - PTHI commands are common to both modes — used at startup to gather device info (UUID, version, cert hashes, control mode). They call the HECI/MEI driver directly.
- LMS (Intel Local Management Service) is a separate OS daemon — not part of rpc-go. It provides the TCP socket interface on localhost that proxies into AMT firmware.
- LME (via MEI) is the fallback path when LMS is not installed or not running. RPC-Go speaks APF protocol directly over the HECI driver.
| Layer | Interface | Protocol | Purpose |
|---|---|---|---|
| HECI | pkg/heci/ |
IOCTLs to MEI device | Raw byte transport to Management Engine |
| PTHI | pkg/pthi/ |
Binary commands over HECI | AMT host commands (UUID, version, control mode, cert hashes, unprovision) |
| WSMAN | go-wsman-messages |
HTTP/SOAP over LMS or LME | Full AMT configuration (activation, CIRA, TLS, WiFi, etc.) |
Three MEI client GUIDs are used:
| Client | GUID | Purpose |
|---|---|---|
| PTHI | {12F80028-...} |
Primary provisioning commands |
| LME | {6733A4DB-...} |
Local Manageability Engine (APF protocol for WSMAN) |
| Watchdog | {05B79A6F-...} |
AMT operational state, TLS enforcement check |
RPC-Go connects to RPS over a secure WebSocket (WSS) through Kong on port 443. The connection path is:
RPC-Go → WSS :443 → Kong (TLS termination) → WS :8080 → RPS
Authentication model: The RPC-Go to RPS WebSocket connection itself does not carry API key or mutual TLS credentials. ISVs are expected to authenticate the device through their own agent before initiating the RPC-Go activation flow. The ISV agent establishes trust and authorization first, then connects RPC-Go to RPS over the already-authenticated session.
TLS certificate verification (-n flag):
| Flag | Behavior | Use Case |
|---|---|---|
Without -n |
RPC-Go verifies Kong's TLS certificate against system trust store | Production — ISV provides a valid certificate on Kong |
With -n |
RPC-Go skips certificate verification (InsecureSkipVerify=true) |
Reference/dev setup — Kong uses a self-signed certificate |
Note for ISVs: The reference deployment uses
-nbecause Kong ships with a self-signed certificate. In production, replace Kong's certificate with your own CA-signed certificate and remove the-nflag. See Kong documentation for configuring custom certificates.
The entire ACM activation is a single /activate WebSocket session. The device cannot be activated directly to ACM — it must first be activated to CCM, then TLS certificates are added to AMT (which enables TLS and makes AMT listen on :16993), then rpc-go switches to port 16993 for E2E TLS communication, and finally ACM elevation occurs over the encrypted channel.
sequenceDiagram
autonumber
box Client Machine
participant AMT as AMT<br/>LMS :16992
participant RPC as RPC-Go<br/>Byte-forwarding proxy
end
box Cloud
participant Kong as Kong<br/>API Gateway :443
participant RPS as RPS<br/>:8080
end
Note over RPC,Kong: RPC-Go to Kong is JSON over WSS
Note over Kong,RPS: Kong to RPS is JSON (WSS terminated at Kong)
Note over AMT,RPC: RPC-Go to AMT is non-TLS (via LMS on port 16992)
RPC->>Kong: JSON activate message over WSS (with --tls-tunnel)
Kong->>RPS: Forward JSON activate message
Note left of RPS: method=activate
Note left of RPS: payload.tlsTunnel=true
Note left of RPS: payload.profile=acm
RPS->>RPS: Resolve ACM profile, start XState machine
Note over AMT,RPS: Phase 1 — CCM Activation (non-TLS :16992)
loop WSMAN round-trips over non-TLS LMS :16992
RPS->>Kong: JSON {method:"wsman", payload: base64(WSMAN)}
Kong->>RPC: Forward JSON over WSS
RPC->>AMT: Decode base64, forward to LMS :16992
AMT-->>RPC: WSMAN response
RPC-->>Kong: JSON {method:"response", payload: base64(response)} over WSS
Kong-->>RPS: Forward JSON
end
Note over RPS: CCM activation complete
Note over AMT,RPS: Phase 2 — Add TLS Certs to AMT (still over non-TLS :16992)
loop Add TLS certificates and enable TLS via WSMAN
RPS->>Kong: JSON {method:"wsman", payload: base64(TLS cert WSMAN)}
Kong->>RPC: Forward JSON over WSS
RPC->>AMT: Decode base64, forward to LMS :16992
AMT-->>RPC: WSMAN response
RPC-->>Kong: JSON {method:"response", payload: base64(response)} over WSS
Kong-->>RPS: Forward JSON
end
Note over AMT: TLS configured. AMT now listens on :16993.
Note over AMT,RPS: Phase 3 — Port Switch (rpc-go switches to :16993)
RPS->>Kong: JSON {method:"port_switch", payload:{port:"16993"}}
Kong->>RPC: Forward JSON over WSS
RPC->>RPC: Reconnect LMS to port 16993
RPC-->>Kong: JSON {method:"port_switch_ack"} over WSS
Kong-->>RPS: Forward JSON
Note over AMT,RPS: Phase 4 — E2E TLS Handshake + ACM Activation
RPS->>Kong: JSON {method:"tls_data", payload: base64(TLS ClientHello)}
Kong->>RPC: Forward JSON over WSS
RPC->>AMT: Decode base64, forward TLS bytes to LMS :16993
AMT-->>RPC: TLS ServerHello + handshake
RPC-->>Kong: JSON {method:"tls_data", payload: base64(TLS response)} over WSS
Kong-->>RPS: Forward JSON
Note over AMT,RPS: E2E TLS tunnel established (RPS ↔ AMT)
loop ACM activation WSMAN over E2E TLS
RPS->>Kong: JSON {method:"tls_data", payload: base64(encrypted WSMAN)}
Kong->>RPC: Forward JSON over WSS
RPC->>AMT: Decode base64, forward encrypted bytes to LMS :16993
AMT-->>RPC: Encrypted WSMAN response
RPC-->>Kong: JSON {method:"tls_data", payload: base64(response)} over WSS
Kong-->>RPS: Forward JSON
end
Note over RPS: ACM activation complete
AMT version behavior:
| AMT Version |
--tls-tunnel Flag |
Behavior |
|---|---|---|
| 11–18 | Not provided | All WSMAN over non-TLS LMS :16992. CCM-only activation. |
| 11–18 | Provided | CCM over :16992 → add TLS certs over :16992 → port switch to :16993 → E2E TLS → ACM |
| 19+ | Not needed | AMT enforces TLS — TLS tunnel is used automatically regardless of flag |
Deprecation notice: With RPC-Go v3 (planned before end of 2025),
--tls-tunnelwill be enabled by default and non-TLS local connections will be deprecated.
AMT 19+ devices enforce TLS on port 16993 — there is no non-TLS 16992 endpoint. The activation uses a multi-phase approach: CCM first (over a TLS tunnel), then TLS certificate provisioning, and finally ACM upgrade (over a new TLS tunnel with the provisioned cert).
RPC-Go supports end-to-end TLS where RPS performs the actual TLS handshake directly with AMT firmware, and RPC-Go acts as a transparent byte relay — it doesn't do any TLS processing.
graph RL
subgraph Cloud
RPS["RPS Service<br/>tls.TLSSocket<br/>(encrypt/decrypt)"]
Kong["Kong<br/>WSS TLS termination"]
end
subgraph Device["Client Machine"]
AMT["Intel AMT 19<br/>TLS server :16993"]
LMS["LMS<br/>Local AMT interface"]
RPC["rpc-go<br/>WebSocket client<br/>Byte-forwarding proxy<br/>(no TLS processing)"]
end
RPS -->|"JSON tls_data<br/>over WS"| Kong
Kong -->|"JSON tls_data<br/>over WSS"| RPC
RPC -->|"Decode base64<br/>raw TLS bytes"| LMS
LMS -->|"Forward to<br/>port 16993"| AMT
AMT -->|"TLS bytes"| LMS
LMS -->|"Raw bytes"| RPC
RPC -->|"base64 encode<br/>JSON tls_data"| Kong
Kong -->|"Forward WS"| RPS
style RPS fill:#0068B5,color:#fff
style AMT fill:#6c3483,color:#fff
style RPC fill:#B43232,color:#fff
Key insight: Kong, rpc-go, and LMS forward payload bytes but cannot decrypt the WSMAN HTTP/XML content. The TLS tunnel is truly end-to-end between RPS and AMT.
sequenceDiagram
autonumber
box Client Machine
participant AMT as Intel AMT 19<br/>TLS server
participant LMS as LMS<br/>Local AMT interface
participant RPC as rpc-go<br/>WebSocket client<br/>Byte-forwarding proxy
end
box Cloud
participant Kong as API Gateway<br/>Kong<br/>WSS TLS termination
participant RPS as RPS Service<br/>TLS client
participant Vault as Vault<br/>Secrets and Certs
participant DB as DB<br/>Non-secret config
end
Note over AMT,RPC: AMT, LMS, and rpc-go are on the client machine.
Note over Kong,DB: Kong, RPS, Vault, and DB are running in the cloud.
Note over AMT,LMS: AMT 19 local TLS path uses 16993 only. 16992 is not used in this flow.
Note over RPC,RPS: All tunnel traffic uses JSON tls_data messages. The payload field carries base64 encoded TLS bytes.
RPC->>Kong: Open WSS connection
Note left of Kong: Kong presents WebSocket TLS cert
Kong-->>RPC: Complete WSS TLS handshake
Kong->>RPS: Forward WebSocket connection to RPS
Note left of Kong: Kong terminates WSS TLS and forwards WS traffic to RPS
RPC->>Kong: JSON activate message over WSS
Kong->>RPS: Forward JSON activate message over WS
Note right of RPS: method=activate
Note right of RPS: protocolVersion=4.0.0
Note right of RPS: payload.ver=19.0.5
Note right of RPS: payload.uuid=device uuid
Note right of RPS: payload.tlsEnforced=true
Note right of RPS: payload.profile=acm
RPS->>DB: Read AMT profile and CIRA config
DB-->>RPS: Profile, TLS mode, non-secret config
RPS->>Vault: Read AMT and MEBx password
Vault-->>RPS: Secrets
RPS->>RPS: tlsEnforced=true. Enable TLS tunnel mode.
Note over AMT,RPS: Phase 1: Pre-activation TLS validation uses Intel ODCA trust only.
RPS->>Kong: JSON tls_data over WS. payload=base64 TLS ClientHello bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 TLS ClientHello bytes
RPC->>LMS: Decode base64 payload and forward raw TLS bytes
LMS->>AMT: Forward TLS bytes to 16993
AMT-->>LMS: TLS ServerHello and AMT ODCA cert chain
LMS-->>RPC: Forward TLS bytes
RPC-->>Kong: JSON tls_data over WSS. payload=base64 TLS response bytes
Kong-->>RPS: JSON tls_data over WS. payload=base64 TLS response bytes
RPS->>RPS: Capture and parse AMT cert chain from TLS handshake
RPS->>RPS: Validate ODCA chain
Note right of RPS: 1. Ensure peer certificate chain exists
Note right of RPS: 2. Check validity period for every cert in chain
Note right of RPS: 3. Verify each cert is signed by the next cert in chain
Note right of RPS: 4. Load trusted Intel ODCA root certificates
Note right of RPS: 5. Verify top cert fingerprint matches trusted ODCA root
Note right of RPS: 6. Or verify top cert is signed by trusted ODCA root
Note right of RPS: 7. Skip EKU validation intentionally
Note over RPS: CRL and revocation checking are not implemented.
RPS->>RPS: Complete TLS handshake. TLS tunnel established.
Note over AMT,RPS: WSMAN HTTP/XML is encrypted inside RPS to AMT TLS.
Note over LMS,Kong: Kong, rpc-go, and LMS forward payload bytes but cannot decrypt HTTPS/XML.
RPS->>Kong: JSON tls_data over WS. payload=base64 encrypted WSMAN TLS bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 encrypted WSMAN TLS bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes to 16993
AMT-->>LMS: HTTP 401 challenge inside encrypted TLS
LMS-->>RPC: Forward encrypted TLS response bytes
RPC-->>Kong: JSON tls_data over WSS. payload=base64 encrypted TLS response bytes
Kong-->>RPS: JSON tls_data over WS. payload=base64 encrypted TLS response bytes
RPS->>RPS: Close and reset tunnel after 401
RPS->>Kong: JSON tls_data over WS. payload=base64 new TLS tunnel bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 new TLS tunnel bytes
RPC->>LMS: Decode base64 payload and forward TLS bytes
LMS->>AMT: Forward TLS bytes to 16993
AMT-->>RPS: TLS established again through Kong, rpc-go, and LMS
RPS->>Kong: JSON tls_data over WS. payload=base64 WSMAN digest auth bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 WSMAN digest auth bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: AMT_GeneralSettings response over TLS
RPS->>Kong: JSON tls_data over WS. payload=base64 WSMAN Setup bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 WSMAN Setup bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: SetupResponse ReturnValue=0
RPS->>Kong: JSON tls_data over WS. payload=base64 WSMAN CommitChanges bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 WSMAN CommitChanges bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: CommitChangesResponse ReturnValue=0
Note over AMT,RPS: Device is now activated in CCM.
Note over AMT,RPS: Phase 2: TLS cert provisioning (over E2E TLS)
RPS->>Kong: JSON tls_data over WS. payload=base64 TLS handshake bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 TLS handshake bytes
RPC->>LMS: Decode base64 payload and forward TLS bytes
LMS->>AMT: Forward TLS bytes to 16993
AMT-->>RPS: TLS handshake using temporary self-signed AMT cert
RPS->>RPS: Temporarily allow self-signed AMT cert only during post-CCM transition.
RPS->>Vault: Fetch MPS root key and MPS root cert
Vault-->>RPS: MPS root key and MPS root cert
RPS->>Kong: JSON tls_data over WS. payload=base64 Enumerate AMT_PublicPrivateKeyPair bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 Enumerate AMT_PublicPrivateKeyPair bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: Existing AMT key pair inventory
RPS->>Kong: JSON tls_data over WS. payload=base64 GenerateKeyPair bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 GenerateKeyPair bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Generate key pair internally
AMT-->>RPS: Public key returned
Note over AMT: Private key never leaves AMT.
RPS->>RPS: Generate AMT TLS leaf cert signed by MPS root CA using AMT-generated public key.
RPS->>Kong: JSON tls_data over WS. payload=base64 Add MPS root cert bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 Add MPS root cert bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: ReturnValue=0
RPS->>Kong: JSON tls_data over WS. payload=base64 AddCertificate bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 AddCertificate bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: ReturnValue=0
RPS->>Kong: JSON tls_data over WS. payload=base64 Associate cert with AMT key bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 Associate cert with AMT key bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Bind cert to internal private key
AMT-->>RPS: ReturnValue=0
RPS->>Kong: JSON tls_data over WS. payload=base64 Configure AMT local TLS bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 Configure AMT local TLS bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: ReturnValue=0
RPS->>Vault: Store AMT TLS leaf cert for future verification
Vault-->>RPS: Stored
RPS->>RPS: Wait for AMT TLS rollover
Note over AMT,RPS: Phase 3: ACM activation (over E2E TLS with new cert)
RPS->>Kong: JSON tls_data over WS. payload=base64 TLS handshake bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 TLS handshake bytes
RPC->>LMS: Decode base64 payload and forward TLS bytes
LMS->>AMT: Forward TLS bytes to 16993
AMT-->>RPS: TLS handshake using AMT TLS cert signed by MPS root
RPS->>RPS: Validate AMT leaf cert
Note right of RPS: 1. Check AMT leaf cert validity period
Note right of RPS: 2. Load configured MPS root CA
Note right of RPS: 3. Verify AMT leaf signature using MPS root public key
Note right of RPS: 4. Validate issuer relationship with MPS root
Note right of RPS: 5. Allow issuer formatting mismatch if signature is valid
Note over RPS: CRL and revocation checking are not implemented.
RPS->>Kong: JSON tls_data over WS. payload=base64 ACM activation WSMAN bytes
Kong->>RPC: JSON tls_data over WSS. payload=base64 ACM activation WSMAN bytes
RPC->>LMS: Decode base64 payload and forward encrypted TLS bytes
LMS->>AMT: Forward encrypted TLS bytes
AMT-->>RPS: ACM activation WSMAN responses over TLS
For simple CCM activation without --tls-tunnel:
sequenceDiagram
autonumber
box Client Machine
participant AMT as AMT<br/>LMS :16992
participant RPC as RPC-Go
end
box Cloud
participant Kong as Kong<br/>API Gateway :443
participant RPS as RPS<br/>:8080
end
Note over RPC: Gather from MEI:<br/>UUID, version, SKU,<br/>cert hashes, control mode
RPC->>Kong: JSON activate message over WSS
Kong->>RPS: Forward JSON activate message
Note left of RPS: Resolve profile,<br/>start XState machine
loop WSMAN round-trips (dozens)
RPS->>Kong: JSON {method:"wsman", payload: base64(WSMAN)}
Kong->>RPC: Forward JSON over WSS
RPC->>AMT: Decode base64, forward to LMS :16992
AMT-->>RPC: WSMAN response
RPC-->>Kong: JSON {method:"response", payload: base64(response)} over WSS
Kong-->>RPS: Forward JSON
end
RPS->>Kong: JSON {method:"success"}
Kong->>RPC: Forward JSON over WSS
RPC->>Kong: WebSocket Close
Envelope (all messages):
{
"method": "activation",
"apiKey": "",
"appVersion": "v2.50.6",
"protocolVersion": "4.0.0",
"status": "ok",
"message": "",
"fqdn": "",
"payload": "<base64-encoded or JSON string>",
"tenantId": ""
}Initial activation payload (decoded from payload field):
{
"ver": "16.1.2",
"build": "1234",
"sku": "16392",
"features": "AMT Pro",
"uuid": "4c4c4544-0042-3210-8030-b4c04f564433",
"username": "",
"password": "",
"currentMode": 0,
"hostname": "DEVICE-01",
"fqdn": "device-01.corp.local",
"client": "RPC",
"certHashes": ["e7685634...", "a4310d50..."],
"ipConfiguration": { "ipAddress": "192.168.1.100" },
"hostnameInfo": { "dnsSuffix": "corp.local" },
"tlsEnforced": false,
"tlsTunnel": false
}| Method | Direction | Purpose |
|---|---|---|
activation |
RPC → RPS | Initial request to activate device (includes device payload) |
deactivation |
RPC → RPS | Request to unprovision device |
maintenance |
RPC → RPS | Sync clock, change password, update hostname, etc. |
response |
RPC → RPS | WSMAN HTTP response from AMT (base64-encoded) |
wsman |
RPS → RPC | WSMAN HTTP request to forward to AMT (base64-encoded) |
success |
RPS → RPC | Operation completed successfully |
error |
RPS → RPC | Operation failed with error message |
tls_data |
Both | Raw TLS bytes for E2E TLS tunnel (base64) |
port_switch |
RPS → RPC | Instruct RPC to reconnect LMS to different port (16992→16993) |
port_switch_ack |
RPC → RPS | Confirm port switch completed |
connection_reset |
RPC → RPS | LMS connection died, RPS should re-establish state |
| Mode | Flag | Deployment | How It Works |
|---|---|---|---|
| Remote Mode | -u wss://... |
Cloud deployment | RPC is a transparent byte proxy. RPS orchestrates everything — sends WSMAN commands, RPC forwards them to AMT via LMS, sends responses back. RPC does zero protocol interpretation. |
| Local Mode | -local |
Enterprise / on-prem | RPC is the orchestrator. It directly constructs WSMAN calls using go-wsman-messages, sends them to AMT via LMS/LME, and handles the activation flow locally without RPS. |
This flowchart shows how RPS decides the TLS path based on device state and AMT version:
flowchart TD
Start([AMT Provisioning]) --> ModeCheck{Device Mode?}
%% ============================================================
%% PATH 1: Already Activated (ACM/CCM)
%% ============================================================
ModeCheck -->|Activated - ACM / CCM| TLSConfigured{TLS already<br>configured?}
%% TLS not configured
TLSConfigured -->|No| GenCert[RPS generates cert<br>from MPS root and<br>adds it to AMT]
GenCert --> Done1[Connect on port 16993<br>RPS: amt_post_tls_reject = true]
%% TLS already configured
TLSConfigured -->|Yes| GetCerts[Get AMT_PublicKeyCertificate<br>and AMT_TLSCredentialsContext]
GetCerts --> IdentifyCert[Identify cert AMT<br>is currently using]
IdentifyCert --> SignedByMPS{Cert signed by<br>MPS Root?}
SignedByMPS -->|Yes| Reuse[Switch to port 16993<br>and reconfigure]
Reuse --> Done2[RPS: amt_post_tls_reject = true<br>MPS root cert is trusted]
SignedByMPS -->|No| RegenCert[RPS generates new cert<br>from MPS root and<br>configures it in AMT]
RegenCert --> Done3[Connect on port 16993<br>RPS: amt_post_tls_reject = true]
%% ============================================================
%% PATH 2: Pre-Provisioning
%% ============================================================
ModeCheck -->|Not Activated| PreProv{AMT Version?}
%% AMT 19+
PreProv -->|19+| ODCA[ODCA cert present<br>and validatable]
ODCA --> Act19[Activates to CCM<br>over e2e TLS on port 16993<br>RPS: amt_pre_tls_reject = true]
Act19 -->|Post-Activation| Self19[AMT generates its own<br>self-signed cert]
Self19 --> DMT19[RPS adds DMT self-signed cert<br>to AMT]
DMT19 --> RPS19[RPS: amt_post_tls_reject = true<br>RPS owns the DMT root cert]
%% AMT 18 and below
PreProv -->|18 and below| TLSCheck{--tls-tunnel<br>flag set?}
TLSCheck -->|Yes| NoODCA[No ODCA cert available]
NoODCA --> Act18TLS[Activates to CCM<br>over non-TLS port 16992]
Act18TLS -->|Post-Activation| VersionCheck2{AMT Version?}
VersionCheck2 -->|16 - 18| Self16[AMT generates its own<br>self-signed cert]
Self16 --> DMT16[RPS adds DMT self-signed cert<br>to AMT]
DMT16 --> RPS16[RPS: amt_post_tls_reject = true<br>RPS owns the DMT root cert]
VersionCheck2 -->|15 and below| DMT[RPS generates DMT<br>self-signed cert and<br>adds it to AMT]
DMT --> RPS15[RPS: amt_post_tls_reject = true<br>RPS owns the DMT root cert]
TLSCheck -->|No| Act18Plain[Activates to CCM<br>over non-TLS port 16992]
Act18Plain -->|Post-Activation| NoTLS[No certs used or added<br>remains on port 16992]
NoTLS --> RPS18Plain[Both RPS TLS configs<br>not applicable]
%% Styling
classDef version19 fill:#2563eb,stroke:#1e40af,color:#fff
classDef version18tls fill:#7c3aed,stroke:#5b21b6,color:#fff
classDef version15 fill:#0891b2,stroke:#0e7490,color:#fff
classDef version18plain fill:#64748b,stroke:#475569,color:#fff
classDef decision fill:#f59e0b,stroke:#d97706,color:#000
classDef rps fill:#dc2626,stroke:#b91c1c,color:#fff
classDef rpsok fill:#16a34a,stroke:#15803d,color:#fff
classDef acm fill:#0d9488,stroke:#0f766e,color:#fff
classDef query fill:#6366f1,stroke:#4f46e5,color:#fff
class ODCA,Self19 version19
class Act19 rpsok
class NoODCA,Act18TLS,Self16 version18tls
class DMT,DMT16,DMT19 version15
class Act18Plain,NoTLS version18plain
class ModeCheck,TLSConfigured,SignedByMPS,PreProv,TLSCheck,VersionCheck2 decision
class RPS18Plain rps
class RPS15,RPS19,RPS16,Done1,Done2,Done3 rpsok
class GenCert,RegenCert acm
class GetCerts,IdentifyCert query
class Reuse query
| Concept | Details |
|---|---|
| OnDie CA (ODCA) | AMT's factory-installed certificate chain. RPS validates against Intel ODCA root certificates during Phase 1 to verify it's talking to genuine AMT firmware. CRL/revocation checking is not implemented. |
| Self-signed transition | After CCM activation, AMT may temporarily present a self-signed cert. RPS temporarily allows this only during the post-CCM transition window. |
| Private key isolation | When RPS calls GenerateKeyPair(), AMT generates the key pair internally. The private key never leaves AMT. RPS only receives the public key to sign. |
| Cert binding | RPS signs a leaf cert using MPS root CA + AMT's public key, then calls AddCertificate and associates it with the internal private key. AMT then uses this cert for TLS. |
| amt_pre_tls_reject | RPS config that controls whether to reject untrusted certs before activation (Phase 1). Set true for AMT 19+ (ODCA validation). |
| amt_post_tls_reject | RPS config that controls whether to reject untrusted certs after activation (Phase 2+). Set true when RPS owns the MPS root cert used to sign the AMT leaf. |
| CCM-then-ACM | AMT 19+ requires CCM activation first over the TLS tunnel, then TLS cert provisioning, then ACM upgrade. ACM requires cert chain injection which needs the device to be in at least CCM. |
| RPC-Go as transparent relay | RPC-Go does zero TLS processing. It passes raw bytes between the WebSocket and local TCP. The TLS handshake is truly end-to-end between RPS and AMT. |
| # | Requirement | Details |
|---|---|---|
| 1 | Wired LAN connection | Device connected via ethernet, receiving IP from DHCP |
| 2 | DHCP Option 15 | DNS Suffix / domain must be configured on the DHCP server |
| 3 | Provisioning certificate | Purchased from a supported CA vendor. CN must match DNS suffix from DHCP Option 15 |
| 4 | Intel MEI driver | Linux: upstreamed to kernel. Windows: installer available |
Why DHCP Option 15? AMT firmware reads the domain suffix from DHCP Option 15 and verifies it matches the CN on the provisioning certificate. This is the zero-touch trust anchor.
flowchart LR
DHCP["DHCP Server<br/>Option 15: corp.local"] -->|"DNS suffix"| AMT["AMT Firmware"]
ProvCert["Provisioning Cert<br/>CN: corp.local"] -->|"uploaded to"| RPS
AMT -->|"Verifies CN matches<br/>DHCP Option 15"| Match{Match?}
Match -->|Yes| ACM["ACM Activation Proceeds"]
Match -->|No| Fail["Activation Rejected"]
style Match fill:#FFA000,color:#000
style ACM fill:#2E7D32,color:#fff
style Fail fill:#C62828,color:#fff
Wi-Fi: DNS suffix must be manually configured in MEBx, negating zero-touch. Uncommon in practice.
stateDiagram-v2
[*] --> Unprovisioned: Factory state
Unprovisioned --> Activating: RPC connects to RPS
Activating --> Provisioned: Activation + CIRA configured
Provisioned --> Managed: AMT CIRA connects to MPS
Managed --> Operational: Ready for management
state Activating {
[*] --> ProfileResolution
ProfileResolution --> WSMANActivation: ACM or CCM
WSMANActivation --> SaveCredentials: To Vault
SaveCredentials --> RegisterDevice: POST /api/v1/devices to MPS
RegisterDevice --> ConfigureCIRA: WSMAN AddMPS, PolicyRules
ConfigureCIRA --> [*]
}
Before any device can be activated, an administrator must configure:
- AMT Profile (in RPS via API or Web UI) — Defines activation mode (ACM/CCM), random password generation, TLS mode, features (KVM/SOL/IDER), CIRA config name, WiFi profiles
- CIRA Configuration (in RPS) — MPS server address, port (4433), authentication method, MPS root certificate
- Domain (for ACM only, in RPS) — DNS suffix that matches the device's network, plus the provisioning certificate (PFX) that chains to a root hash trusted by AMT
This is the most complex phase. The XState state machine in RPS orchestrates the following:
sequenceDiagram
autonumber
participant RPS as RPS
participant AMT as AMT (via RPC relay)
Note over RPS,AMT: ACM Activation Flow
RPS->>AMT: AMT_GeneralSettings.Get()
AMT-->>RPS: DigestRealm, hostname
RPS->>AMT: IPS_HostBasedSetupService.Get()
AMT-->>RPS: ConfigurationNonce, allowedControlModes
loop For each cert in provisioning chain
RPS->>AMT: AddNextCertInChain(cert[i])
AMT-->>RPS: ReturnValue=0
end
RPS->>AMT: AdminSetup(passwordHash, nonce, signature)
AMT-->>RPS: ReturnValue=0
RPS->>AMT: SetMEBXPassword(hash)
AMT-->>RPS: ReturnValue=0
Note over RPS,AMT: Device activated in ACM
ACM vs CCM Comparison:
| Aspect | CCM (Client Control Mode) | ACM (Admin Control Mode) |
|---|---|---|
| Provisioning Cert | Not required | Required (must match AMT trusted root hash) |
| User Consent | Required for KVM/SOL | Can be disabled |
| MEBx Password | Not set | Set during activation |
| Features | Limited | Full control |
| Certificate Chain | Not injected | Injected via AddNextCertInChain |
| Signature | Not used | SHA-256 signed with provisioning cert private key |
After successful activation, RPS applies the profile configuration:
sequenceDiagram
autonumber
participant RPS
participant Vault
participant MPS
participant AMT as AMT (via RPC relay)
RPS->>Vault: Save AMT_PASSWORD, MEBX_PASSWORD
RPS->>Vault: Save MPS_PASSWORD
RPS->>MPS: POST /api/v1/devices<br/>(GUID, hostname, mpsusername, tags, tenantId, deviceInfo)
MPS-->>RPS: 201 Created
RPS->>AMT: Network config (EthernetPortSettings, WiFi)
RPS->>AMT: Feature config (RedirectionService, OptInService)
RPS->>AMT: CIRA config (AddTrustedRootCert, AddMPS, PolicyRules)
RPS->>RPC: Success message
Note over RPS: WebSocket closed. Activation complete.
Note: The POST /api/v1/devices call to MPS is how RPS registers the device. This creates the device record in the mpsdb.devices table so MPS knows about the device before it connects via CIRA.
After RPC completes and CIRA is configured, AMT firmware autonomously initiates an outbound TLS connection to MPS (see Section 7).
CIRA (Client-Initiated Remote Access) is an Intel AMT feature where the device's AMT firmware establishes an outbound TLS connection to a Management Presence Server. This eliminates the need for inbound firewall rules — the device "calls home" to the cloud.
The CIRA state machine in RPS configures AMT firmware with these WSMAN calls (in order):
| Step | WSMAN Call | Purpose |
|---|---|---|
| 1 | AMT_PublicKeyManagementService.AddTrustedRootCertificate(mpsRootCert) |
Install MPS server's root CA so AMT trusts the TLS connection |
| 2 | Save MPS password to Vault | devices/{uuid}/MPS_PASSWORD |
| 3 | POST /api/v1/devices to MPS |
Add/register the device in MPS database |
| 4 | AMT_RemoteAccessService.AddMPS(server, port, username, password) |
Register MPS server address/credentials in AMT firmware |
| 5 | AMT_RemoteAccessService.AddRemoteAccessPolicyRule(trigger=2) |
Periodic connection policy (connect on schedule) |
| 6 | AMT_RemoteAccessService.AddRemoteAccessPolicyRule(trigger=0) |
User-initiated connection policy |
| 7 | AMT_RemoteAccessPolicyAppliesToMPS.Put() |
Bind policies to MPS (type=Both) |
| 8 | AMT_EnvironmentDetectionSettingData.Put() |
Set detection domain (prevents CIRA on corporate LAN) |
| 9 | AMT_UserInitiatedConnectionService.RequestStateChange(32771) |
Enable all CIRA connection types |
After configuration, AMT firmware handles the connection autonomously:
sequenceDiagram
autonumber
participant AMT as AMT Firmware
participant MPS as MPS Server (:4433)
participant Vault
participant DB as PostgreSQL
AMT->>MPS: TLS ClientHello
MPS-->>AMT: TLS ServerHello + MPS TLS Certificate
AMT->>MPS: TLS Finished (verifies cert against installed MPS root CA)
MPS-->>AMT: TLS Finished
Note over AMT,MPS: TLS Tunnel Established
AMT->>MPS: APF PROTOCOL_VERSION (includes SystemId = device UUID)
MPS-->>AMT: APF PROTOCOL_VERSION
AMT->>MPS: APF SERVICE_REQUEST("auth")
MPS-->>AMT: APF SERVICE_ACCEPT("auth")
AMT->>MPS: APF USERAUTH_REQUEST (username + password)
MPS->>Vault: Verify: devices/{uuid}/MPS_PASSWORD
Vault-->>MPS: Stored password
MPS->>MPS: Verify password match + username matches DB
MPS->>DB: UPDATE devices SET mpsInstance=this, connectionStatus=true, lastConnected=now()
MPS-->>AMT: APF USERAUTH_SUCCESS
Note over AMT,MPS: CIRA Session Active
AMT->>MPS: APF GLOBAL_REQUEST (bind ports 16992, 16994, 16995, 16996)
MPS-->>AMT: APF REQUEST_SUCCESS
Note over AMT,MPS: Device Ready for Remote Management
CIRA connections are in-memory only — each connection lives as a ConnectedDevice object in a Record<string, ConnectedDevice> map inside the MPS process. There is no persistent connection state on disk. If the MPS process restarts, all connections are lost and devices must reconnect. The database only tracks metadata about the connection (which instance owns it, last seen timestamp, connection status) for routing and monitoring purposes — it does not store the actual socket or session.
This means:
- Scaling requires sticky routing (MPS Router) because the connection object only exists in one MPS instance's memory
- Process crashes cause all connected devices on that instance to appear disconnected until AMT firmware re-establishes CIRA
-
Graceful shutdown (SIGINT/SIGTERM) triggers
clearInstanceStatus()which nulls outmpsInstanceand setsconnectionStatus=falsefor all devices owned by that instance
| Mechanism | Details |
|---|---|
| In-memory storage | Each authenticated CIRA connection is stored as a ConnectedDevice object (holds the TLS socket, AMT credentials, HTTP handler, rate limiter) in a process-level devices map keyed by device GUID. |
| Keepalive | AMT sends APF: KEEPALIVE_REQUEST every ~30 seconds (CIRA_KEEPALIVE_INTERVAL). MPS replies with KEEPALIVE_REPLY and updates lastSeen timestamp in DB. |
| Idle Timeout | MPS sets socket.setTimeout(90s) (CIRA_MAX_IDLE_TIME). If no data received within 90 seconds, socket is closed and the device record is cleaned up. |
| DB metadata sync | On connect: sets connectionStatus=true, mpsInstance=<instance_name>, lastConnected=now(). On keepalive: updates lastSeen. On disconnect: sets connectionStatus=false, mpsInstance=null, lastDisconnected=now(). |
| Duplicate connection handling | If a device connects while an existing connection exists (same GUID), MPS closes the old socket first (ciraSocket.end()), cleans up the old record, then stores the new connection. |
| Reconnection | If connection drops, AMT firmware automatically reconnects based on the CIRA periodic policy. This is handled entirely by the ME firmware — no OS/RPC involvement needed. |
| Environment Detection | AMT checks if it's on the corporate network (by DNS suffix). If detected, CIRA connection is not established (device is already locally reachable). |
| Graceful shutdown | On SIGINT/SIGTERM/exit, MPS calls db.devices.clearInstanceStatus(instance_name) which sets mpsInstance=null and connectionStatus=false for all devices owned by this instance. |
In a scaled deployment, you run multiple MPS instances. Each AMT device connects via CIRA to exactly one MPS instance, and that connection is held in-memory as a ConnectedDevice object. When an API request arrives for a device, it must be routed to the specific MPS instance holding that device's CIRA connection.
sequenceDiagram
autonumber
participant Client as API Client
participant Router as MPS Router :8003
participant DB as PostgreSQL<br/>(mpsdb.devices)
participant MPS1 as MPS Instance "mps.1"
participant MPS2 as MPS Instance "mps.2"
Note over MPS1: In-memory CIRA connections:<br/>device-guid-123<br/>device-guid-456
Note over MPS2: In-memory CIRA connections:<br/>device-guid-789<br/>device-guid-012
Client->>Router: GET /api/v1/amt/power/state/device-guid-123
Router->>Router: Parse GUID from URL (regex)
Router->>DB: SELECT mpsinstance FROM devices WHERE guid='device-guid-123'
DB-->>Router: mpsinstance = "mps.1"
Router->>MPS1: TCP proxy to mps.1:3000
MPS1-->>Router: Response (device is connected here)
Router-->>Client: 200 OK {powerstate: ...}
Step 1: Device connects to an MPS instance via CIRA
When a device's CIRA connection is authenticated, MPS calls handleDeviceConnect() which:
// mps/src/server/mpsserver.ts
async handleDeviceConnect(guid: string): Promise<void> {
const device = await this.db.devices.getById(guid)
device.connectionStatus = true
device.mpsInstance = Environment.Config.instance_name // e.g., "mps.1"
device.lastConnected = new Date()
await this.db.devices.update(device)
}The instance_name comes from the MPS_INSTANCE_NAME environment variable. In Docker Swarm, this is set to {{.Task.Name}} which auto-expands to a unique name like mps.1, mps.2, etc. If not in Swarm, it defaults to "mps".
Step 2: API request arrives at MPS Router
MPS Router is a raw TCP proxy. On each incoming connection:
// mps-router/internal/proxy/proxy.go
guid := s.parseGuid(string(b)) // Extract GUID from URL using regex
if guid != "" {
instance := s.DB.Query(guid) // SELECT mpsinstance FROM devices WHERE guid = $1
if instance != "" {
parts := strings.Split(destination, ":")
parts[0] = instance // Replace hostname with MPS instance name
destination = parts[0] + ":" + parts[1]
}
}
dst, err = net.Dial("tcp", destination) // Connect to the correct MPS instanceStep 3: Request is proxied to the correct MPS instance
The Router dials a raw TCP connection to the resolved MPS instance (e.g., mps.1:3000) and bidirectionally copies all bytes. It does NOT interpret HTTP — it's a transparent TCP proxy.
Step 4: Cleanup on disconnect
When a device disconnects or an MPS instance shuts down:
-
handleDeviceDisconnect()clearsconnectionStatusandmpsInstancein the DB - SIGINT/SIGTERM handlers clean up all device records owned by that instance
- Next CIRA reconnect from the device may land on a different MPS instance
- The
mpsInstancefield in the DB still points to the dead instance - MPS Router queries DB, gets the dead instance name, and tries to connect — connection fails
- The SIGTERM handler on the dying instance should have cleared the
mpsInstancefield - If ungraceful shutdown, stale entries remain until the device reconnects to a healthy instance
- When the device's CIRA reconnect lands on a new instance,
handleDeviceConnect()updatesmpsInstanceto the new instance name
When an API request like "Power Off" arrives, the WSMAN XML message is constructed inside MPS using the @device-management-toolkit/wsman-messages library. Here's the exact code path:
API Request: POST /api/v1/amt/power/action/{guid} {action: 8}
│
▼
Express Route Handler: powerAction.ts
│ req.deviceAction.sendPowerAction(8)
▼
DeviceAction class (src/amt/DeviceAction.ts)
│ this.cim = new CIM.Messages() // <── wsman-messages library
│ this.amt = new AMT.Messages()
│ this.ips = new IPS.Messages()
│
│ xmlRequestBody = this.cim.PowerManagementService
│ .RequestPowerStateChange(powerState, managedElement)
│
│ // This produces SOAP XML like:
│ // <s:Envelope>
│ // <s:Header>
│ // <a:Action>RequestPowerStateChange</a:Action>
│ // <w:ResourceURI>CIM_PowerManagementService</w:ResourceURI>
│ // </s:Header>
│ // <s:Body>
│ // <PowerState>8</PowerState>
│ // </s:Body>
│ // </s:Envelope>
▼
CIRAHandler.Send(socket, xmlRequestBody)
│ Rate limited: max 3 concurrent, 250ms min interval
▼
HttpHandler.wrapIt(xml)
│ Wraps SOAP XML in HTTP POST request:
│ POST /wsman HTTP/1.1
│ Authorization: Digest username=admin, ...
│ Content-Type: application/soap+xml; charset=UTF-8
│ <SOAP XML body>
▼
CIRAChannel.writeData(httpBytes)
│ Sends via APF CHANNEL_DATA frame on the CIRA connection
│ APF frame: [type=94][channelId][dataLength][httpBytes]
▼
AMT Firmware (port 16992 through CIRA tunnel)
│ Receives HTTP POST on /wsman
│ Digest auth challenge → MPS retries with credentials
│ Processes WSMAN command
│ Returns SOAP response via CHANNEL_DATA
▼
Response flows back: AMT → APF CHANNEL_DATA → CIRAHandler → DeviceAction → Express → Kong → Client
sequenceDiagram
autonumber
participant Client as API Client
participant Kong as Kong :443
participant Router as MPS Router :8003
participant DB as PostgreSQL
participant MPS as MPS :3000
participant AMT as AMT Device<br/>(via CIRA)
Client->>Kong: POST /mps/api/v1/amt/power/action/{guid}<br/>{action: 8}
Kong->>Kong: JWT validation, strip /mps prefix
Kong->>Router: Forward to MPS Router
Router->>DB: SELECT mpsinstance FROM devices WHERE guid={guid}
DB-->>Router: mpsinstance = "mps.1"
Router->>MPS: TCP proxy to mps.1:3000
MPS->>MPS: Verify JWT, check CIRA connection in memory
MPS->>MPS: DeviceAction builds WSMAN XML<br/>(using wsman-messages library)
MPS->>MPS: CIRAHandler wraps in HTTP POST /wsman
MPS->>AMT: APF CHANNEL_OPEN (port 16992)
AMT-->>MPS: APF CHANNEL_OPEN_CONFIRMATION
MPS->>AMT: APF CHANNEL_DATA (HTTP + WSMAN XML)
AMT-->>MPS: APF CHANNEL_DATA (HTTP 401 Digest challenge)
MPS->>AMT: APF CHANNEL_DATA (HTTP + Digest auth + WSMAN)
AMT-->>MPS: APF CHANNEL_DATA (HTTP 200 + SOAP response)
MPS-->>Router: 200 {ReturnValue: 0, ReturnValueStr: "SUCCESS"}
Router-->>Kong: Forward response
Kong-->>Client: 200 OK
For interactive sessions, MPS uses WebSocket relay — no WSMAN involved, just raw byte streaming:
sequenceDiagram
autonumber
participant Browser
participant MPS as MPS Web Server :3000
participant AMT as AMT Device<br/>(via CIRA channel)
Browser->>MPS: GET /api/v1/authorize/redirection/{guid}
MPS-->>Browser: Short-lived JWT (scoped to device + expiry)
Browser->>MPS: WebSocket Upgrade<br/>/relay/webrelay.ashx?host={guid}&port=16994&mode=kvm<br/>Sec-WebSocket-Protocol: {short-lived-JWT}
MPS->>MPS: Verify JWT (host claim matches, not expired)
MPS->>AMT: APF CHANNEL_OPEN (port 16994)
AMT-->>MPS: APF CHANNEL_OPEN_CONFIRMATION
loop Bidirectional raw byte relay
Browser->>MPS: WebSocket binary frame (RFB/VNC data)
MPS->>AMT: APF CHANNEL_DATA
AMT-->>MPS: APF CHANNEL_DATA
MPS-->>Browser: WebSocket binary frame
end
WS-Management (WSMAN) is a SOAP-based protocol used by Intel AMT for device management. Every management action (power control, feature toggle, certificate operation, etc.) is performed via WSMAN requests.
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
<s:Header>
<a:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action>
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
<w:ResourceURI>
http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings
</w:ResourceURI>
<a:MessageID>uuid:unique-id-here</a:MessageID>
</s:Header>
<s:Body>
<!-- Operation-specific content -->
</s:Body>
</s:Envelope>| Context | Transport |
|---|---|
| MPS → AMT (remote via CIRA) | HTTP POST tunneled through APF CHANNEL_DATA on port 16992 |
| RPC → AMT (local) | HTTP POST to localhost:16992/wsman or :16993/wsman (TLS) |
| Authentication | HTTP Digest authentication (username: admin, password: AMT admin password) |
| Library | Language | Package | Used By | Scope |
|---|---|---|---|---|
wsman-messages |
TypeScript | @device-management-toolkit/wsman-messages |
MPS, RPS | Message construction only |
go-wsman-messages |
Go | github.com/device-management-toolkit/go-wsman-messages/v2 |
RPC-Go | Message construction + transport + digest auth |
In MPS, the DeviceAction class instantiates message builders:
this.cim = new CIM.Messages() // CIM class messages
this.amt = new AMT.Messages() // AMT class messages
this.ips = new IPS.Messages() // IPS class messagesThese build the SOAP XML string, which is then wrapped in an HTTP POST request by HttpHandler and sent through the CIRA channel.
The DMT codebase implements 80+ WSMAN classes across three namespaces. These are implemented in wsman-messages (TypeScript) and go-wsman-messages (Go).
| Class | Purpose |
|---|---|
AMT_GeneralSettings |
Hostname, digest realm, network settings |
AMT_SetupAndConfigurationService |
Provisioning mode, unprovision, commit changes |
AMT_AuthorizationService |
User/ACL authorization management |
AMT_TimeSynchronizationService |
Time sync between OS and AMT |
AMT_PublicKeyCertificate |
Public key certificate store |
AMT_PublicKeyManagementService |
Add/remove certificates and keys |
AMT_PublicPrivateKeyPair |
RSA key pair store |
AMT_TLSSettingData |
TLS configuration (mutual auth, ports) |
AMT_TLSCredentialContext |
Certificate-to-TLS-setting association |
AMT_TLSProtocolEndpointCollection |
TLS endpoint collection |
AMT_RemoteAccessService |
Register MPS, add CIRA policies |
AMT_RemoteAccessPolicyRule |
CIRA policy rules (periodic, alert, etc.) |
AMT_RemoteAccessPolicyAppliesToMPS |
Policy-to-MPS association |
AMT_ManagementPresenceRemoteSAP |
MPS server connection endpoint |
AMT_MPSUsernamePassword |
MPS connection credentials |
AMT_RemoteAccessCapabilities |
Remote access capability info |
AMT_UserInitiatedConnectionService |
User-initiated CIRA connection |
AMT_EnvironmentDetectionSettingData |
Domain detection settings (corporate vs. remote) |
AMT_RedirectionService |
KVM/SOL/IDER enable/disable |
AMT_BootSettingData |
Boot configuration settings |
AMT_BootCapabilities |
Boot capability enumeration |
AMT_EthernetPortSettings |
Wired/wireless NIC configuration |
AMT_WiFiPortConfigurationService |
WiFi profile configuration |
AMT_8021XProfile |
802.1x authentication profile |
AMT_8021xCredentialContext |
802.1x credential context |
AMT_AlarmClockService |
Alarm clock/wake timer management |
AMT_AuditLog |
Security audit log access |
AMT_MessageLog |
AMT message log |
AMT_SystemPowerScheme |
Power scheme management |
AMT_KerberosSettingData |
Kerberos authentication settings |
| Class | Purpose |
|---|---|
CIM_PowerManagementService |
Power on/off/reset/cycle |
CIM_PowerManagementCapabilities |
Supported power states |
CIM_AssociatedPowerManagementService |
Power service association |
CIM_SoftwareIdentity |
AMT firmware version |
CIM_ComputerSystemPackage |
Computer-to-chassis association |
CIM_Processor |
CPU info |
CIM_PhysicalMemory |
RAM module info |
CIM_MediaAccessDevice |
Storage device info |
CIM_Card |
System board info |
CIM_Chassis |
Chassis/enclosure info |
CIM_Chip |
Chipset info |
CIM_PhysicalPackage |
Physical package container |
CIM_Battery |
Battery status |
CIM_Fan |
Fan/cooling info |
CIM_Sensor |
Hardware sensor readings |
CIM_BIOSElement |
BIOS information |
CIM_BootConfigSetting |
Boot configuration |
CIM_BootService |
Boot service operations |
CIM_BootSourceSetting |
Boot source/device setting |
CIM_EthernetPort |
Ethernet port hardware info |
CIM_KVMRedirectionSAP |
KVM redirection service access point |
CIM_RedirectionService |
Redirection service status |
CIM_IEEE8021xSettings |
802.1x authentication settings |
CIM_WiFiEndpoint |
WiFi endpoint status |
CIM_WiFiEndpointSettings |
WiFi profile settings |
CIM_WiFiPort |
WiFi port hardware info |
CIM_WiFiPortCapabilities |
WiFi port capabilities |
CIM_CredentialContext |
Credential context association |
CIM_ConcreteDependency |
Concrete dependency association |
CIM_ServiceAvailableToElement |
Service-to-element association |
| Class | Purpose |
|---|---|
IPS_HostBasedSetupService |
Host-based activation (Setup, AdminSetup) |
IPS_OptInService |
User consent configuration |
IPS_KVMRedirectionSettingData |
KVM settings (consent, port) |
IPS_AlarmClockOccurrence |
Individual alarm occurrence instance |
IPS_HostIPSettings |
Host IP configuration |
IPS_IEEE8021xSettings |
IPS-specific 802.1x settings |
IPS_8021xCredentialContext |
IPS 802.1x credential context |
IPS_IPv6PortSettings |
IPv6 port configuration |
IPS_HTTPProxyService |
HTTP proxy service management |
IPS_HTTPProxyAccessPoint |
HTTP proxy access point |
IPS_LANEndpoint |
LAN endpoint status |
IPS_PowerManagementService |
OS power saving state |
IPS_ProvisioningRecordLog |
Provisioning record log |
IPS_ScreenSettingData |
Screen/display settings |
IPS_SecIOService |
Secure IO service |
IPS_HostBootReason |
Host boot reason information |
APF (AMT Port Forwarding Protocol) is the multiplexing protocol used inside the CIRA TLS tunnel. Based on SSH's channel architecture, it allows multiple logical channels over a single TCP connection.
Reference: Intel AMT Port Forwarding Protocol Reference Manual
| Code | Name | Direction | Purpose |
|---|---|---|---|
| 192 | PROTOCOL_VERSION |
Both | Version negotiation, carries SystemId (device UUID) |
| 5/6 | SERVICE_REQUEST/ACCEPT |
Both | Authentication service negotiation |
| 50/52 | USERAUTH_REQUEST/SUCCESS |
Both | Username + password authentication |
| 80/81 | GLOBAL_REQUEST/SUCCESS |
Both | Bind port forwarding (tcpip-forward) |
| 90/91 | CHANNEL_OPEN/CONFIRMATION |
Both | Open channel to specific AMT port |
| 94 | CHANNEL_DATA |
Both | Data transfer on channel (carries HTTP+WSMAN) |
| 93 | CHANNEL_WINDOW_ADJUST |
Both | Flow control (sliding window) |
| 97 | CHANNEL_CLOSE |
Both | Close channel |
| 208/209 | KEEPALIVE_REQUEST/REPLY |
Both | Connection heartbeat |
Multiple AMT services are accessed through different channels on the same CIRA connection:
graph LR
subgraph CIRA["CIRA TLS Connection (single TCP socket)"]
CH0["Channel 0<br/>Port 16992<br/>WSMAN commands"]
CH1["Channel 1<br/>Port 16994<br/>KVM (RFB/VNC)"]
CH2["Channel 2<br/>Port 16995<br/>SOL (serial)"]
CH3["Channel 3<br/>Port 16996<br/>IDER (boot media)"]
end
MPS["MPS Server"] --> CH0
MPS --> CH1
MPS --> CH2
MPS --> CH3
CH0 --> AMT_WSMAN["AMT WSMAN<br/>HTTP POST /wsman<br/>Digest auth + SOAP XML<br/>(built by wsman-messages)"]
CH1 --> AMT_KVM["AMT KVM<br/>Raw RFB/VNC bytes"]
CH2 --> AMT_SOL["AMT SOL<br/>Raw serial bytes"]
CH3 --> AMT_IDER["AMT IDER<br/>Raw IDE bytes"]
style CIRA fill:#1a2744,color:#fff
style MPS fill:#0068B5,color:#fff
AMT provides three redirection features that allow remote operators to interact with a device as if physically present. These all use the Intel AMT Redirection Protocol over dedicated ports, proxied through MPS via WebSocket.
| Feature | Full Name | Protocol | AMT Port | Purpose |
|---|---|---|---|---|
| KVM | Keyboard, Video, Mouse | RFB 3.8 (VNC) | 16994 | Remote desktop — view screen, control keyboard and mouse |
| SOL | Serial Over LAN | Serial terminal | 16994 | Remote serial console — BIOS setup, OS install, recovery |
| IDER | IDE Redirection | USB-R (storage redirection) | 16994 | Mount ISO/floppy images to boot from remotely |
All three features connect to AMT port 16994 (the redirection port). The Intel AMT Redirection Protocol handles session setup, authentication, and multiplexing between the three services.
Reference: RFB Protocol 3.8 (RFC 6143)
The browser does not connect directly to the AMT device. Instead, MPS acts as a relay — the browser opens a WebSocket to MPS, and MPS bridges it to the device's CIRA channel:
sequenceDiagram
participant Browser as Browser<br/>(ui-toolkit)
participant MPS as MPS<br/>(WebSocket relay)
participant AMT as AMT Device<br/>(port 16994)
Browser->>MPS: WebSocket UPGRADE<br/>/relay/webrelay.ashx?host={uuid}&port=16994&mode=kvm
MPS->>MPS: Verify JWT token
MPS->>MPS: Look up device in connected devices map
MPS->>AMT: Open CIRA channel to port 16994
Note over Browser,AMT: AMT Redirection Protocol Handshake
Browser->>MPS: StartRedirectionSession (0x10)<br/>+ protocol type (SOL/KVM/IDER)
MPS->>AMT: Forward bytes
AMT->>MPS: StartRedirectionSessionReply (0x11)
MPS->>Browser: Forward bytes
Note over Browser,AMT: Digest Authentication (handled by MPS interceptor)
AMT->>MPS: AuthenticateSession (challenge)
MPS->>MPS: RedirectInterceptor injects<br/>device credentials from Vault
MPS->>AMT: AuthenticateSession (response)
AMT->>MPS: AuthenticateSessionReply (success)
MPS->>Browser: Forward success
Note over Browser,AMT: Protocol-specific data flows directly
Browser->>AMT: RFB / SOL / IDER data (relayed through MPS)
AMT->>Browser: Screen updates / serial output / disk reads (relayed through MPS)
Key detail: The browser never handles AMT credentials. MPS's RedirectInterceptor intercepts the authentication challenge and responds with the device password from Vault, then passes the success back to the browser. After authentication, MPS enters "direct relay mode" — it just forwards bytes in both directions.
KVM uses the RFB (Remote Framebuffer) protocol version 3.8 — the same protocol used by VNC. After the AMT redirection handshake and authentication, the connection transitions into standard RFB:
RFB Handshake:
- AMT sends
RFB 003.008\n(server version) - Client responds
RFB 003.008\n(client version) - Security negotiation (type "None" — already authenticated via redirection)
- Server init — sends framebuffer dimensions, pixel format, desktop name
Data flow after handshake:
- Server → Client: Framebuffer updates (Raw or ZRLE encoding)
- Client → Server: Key events, pointer (mouse) events, framebuffer update requests
Encoding support:
| Encoding | ID | Description |
|---|---|---|
| Raw | 0 | Uncompressed pixel data (simple, higher bandwidth) |
| ZRLE | 16 | Zlib-compressed Run-Length Encoding (lower bandwidth) |
| Desktop Size | -223 | Pseudo-encoding for screen resize notification |
SOL provides access to the device's serial port over the network. After the AMT redirection handshake, raw serial data flows in both directions:
- AMT → Browser: Serial output bytes (ASCII, translated to Unicode for display)
- Browser → AMT: Keyboard input bytes
The terminal is rendered using xterm.js in the browser. The TerminalDataProcessor handles character encoding translation (extended ASCII → Unicode) before passing data to xterm.
Use cases:
- BIOS/UEFI configuration before OS boots
- OS installation (text-mode installers)
- System recovery when OS is unresponsive
- Headless server management
IDER allows mounting local ISO or floppy disk images to the remote device as virtual USB storage. The device sees these as physically attached drives and can boot from them.
Protocol flow after handshake:
- Client sends
OPEN_SESSIONwith timeout and heartbeat parameters - AMT responds with firmware version, buffer sizes, protocol info
- Client sends
DISABLE_ENABLE_FEATURESto register virtual floppy and/or CD-ROM - AMT issues
COMMAND_WRITTENrequests (SCSI-like commands: READ, MODE_SENSE, etc.) - Client reads sectors from the local file and sends
DATA_FROM_HOSTresponses
Command types handled:
| Command | Purpose |
|---|---|
OPEN_SESSION / CLOSE
|
Session lifecycle |
KEEPALIVE_PING / PONG
|
Connection heartbeat |
RESET_OCCURRED |
Device reset notification |
COMMAND_WRITTEN |
SCSI read/write/inquiry from AMT |
DATA_FROM_HOST |
Sector data sent to AMT |
HEARTBEAT |
Periodic heartbeat |
Use cases:
- Remote OS installation from ISO
- Boot into diagnostic/recovery tools
- Firmware update from bootable media
The implementation is split across three packages:
graph TB
subgraph Core["ui-toolkit (core library)"]
Redirector["AMTRedirector<br/>WebSocket connection,<br/>AMT redirection protocol,<br/>digest auth handshake"]
KvmRedir["AMTKvmDataRedirector<br/>extends AMTRedirector<br/>for KVM data routing"]
Desktop["AMTDesktop<br/>Canvas rendering,<br/>RFB framebuffer updates,<br/>mouse/keyboard encoding"]
RFB["RFBStateProcessors/<br/>Handshake, SecurityOptions,<br/>ServerInit, Encoding"]
Terminal["AmtTerminal<br/>Serial data handling,<br/>ASCII-to-Unicode mapping"]
TermProc["TerminalDataProcessor<br/>Processes serial bytes<br/>for xterm.js display"]
IDER["AMTIDER<br/>IDE redirection protocol,<br/>sector read/write handling"]
IDERProc["IDERDataProcessor<br/>SCSI command interpretation,<br/>file I/O coordination"]
end
subgraph React["ui-toolkit-react"]
RKVM["KVM component<br/>(canvas + mouse/keyboard)"]
RSOL["Sol component<br/>(xterm.js terminal)"]
RIDER["IDER component<br/>(headless, file mount)"]
end
subgraph Angular["ui-toolkit-angular"]
AKVM["KVMComponent<br/>(canvas + mouse/keyboard)"]
ASOL["SolComponent<br/>(xterm.js terminal)"]
AIDER["IderComponent<br/>(headless, file mount)"]
end
RKVM --> KvmRedir
RKVM --> Desktop
RSOL --> Redirector
RSOL --> Terminal
RSOL --> TermProc
RIDER --> Redirector
RIDER --> IDER
AKVM --> KvmRedir
AKVM --> Desktop
ASOL --> Redirector
ASOL --> Terminal
ASOL --> TermProc
AIDER --> Redirector
AIDER --> IDER
KvmRedir --> Redirector
Desktop --> RFB
IDER --> IDERProc
style Core fill:#E3F2FD,color:#000
style React fill:#E8F5E9,color:#000
style Angular fill:#FFF3E0,color:#000
Package roles:
| Package | Role |
|---|---|
ui-toolkit |
Core protocol implementations — framework-agnostic TypeScript classes that handle WebSocket connections, AMT redirection protocol, RFB rendering, serial processing, and IDER disk I/O |
ui-toolkit-react |
React components (KVM, Sol, IDER) that wrap the core classes with React lifecycle, state management, and JSX rendering |
ui-toolkit-angular |
Angular components (KVMComponent, SolComponent, IderComponent) that wrap the core classes with Angular lifecycle hooks, signals, and templates |
The browser connects to MPS using this WebSocket URL pattern:
wss://{mps-server}/relay/webrelay.ashx?p=2&host={device-uuid}&port=16994&tls=0&tls1only=0&mode={kvm|sol|ider}
| Parameter | Value | Purpose |
|---|---|---|
p |
2 |
Indicates redirection session (vs. other relay types) |
host |
Device UUID | Identifies which connected device to relay to |
port |
16994 |
AMT redirection port |
tls |
0 or 1
|
Whether to use TLS on the CIRA channel to AMT |
tls1only |
0 or 1
|
Restrict to TLS 1.0 only |
mode |
kvm, sol, or ider
|
Which redirection service (used for connection tracking) |
The JWT auth token is passed as the WebSocket subprotocol during the upgrade handshake.
| Data Type | Storage | Path / Table | Why |
|---|---|---|---|
| AMT admin password | Vault | devices/{uuid}/AMT_PASSWORD |
Secret - never stored in DB |
| AMT MEBx password | Vault | devices/{uuid}/MEBX_PASSWORD |
Secret - ACM only |
| MPS device password | Vault | devices/{uuid}/MPS_PASSWORD |
Secret - used for CIRA auth |
| TLS issued certificate | Vault | devices/{uuid}/TLS_ISSUED_CERTIFICATE |
Sensitive key material |
| Provisioning cert (ACM) | Vault |
certs/{domainName}/CERT + CERT_PASSWORD
|
PFX with private key |
| MPS root CA keys | Vault |
MPSCerts/root_key, root_ca
|
Root signing key |
| Profile passwords | Vault | profiles/{profileName}/AMT_PASSWORD |
Template secret |
| CIRA config passwords | Vault | CIRAConfigs/{configName}/MPS_PASSWORD |
Template secret |
| Device inventory | PostgreSQL (mpsdb) |
devices table |
Non-secret metadata: GUID, hostname, status, mpsInstance, tags, tenantId, lastSeen, deviceInfo |
| AMT Profiles | PostgreSQL (rpsdb) |
profiles table |
Non-secret config: activation mode, features, TLS mode, CIRA config reference |
| CIRA Configurations | PostgreSQL (rpsdb) |
ciraconfigs table |
Non-secret config: MPS address, port, auth method, root cert |
| Domains | PostgreSQL (rpsdb) |
domains table |
Domain suffix, cert storage format, expiration (cert itself in Vault) |
| Wireless configs | PostgreSQL (rpsdb) |
wirelessconfigs table |
SSID, auth method, encryption |
| 802.1x configs | PostgreSQL (rpsdb) |
ieee8021xconfigs table |
EAP type, CA cert references |
Secrets (passwords, private keys, certificates with keys) go to Vault. Everything else goes to PostgreSQL.
This separation ensures:
- Secrets are never exposed in database dumps or backups
- Vault provides access auditing, rotation, and encryption at rest
- PostgreSQL handles relational queries (device filtering, profile lookups, joins)
- In production, Vault should use proper authentication (AppRole, Kubernetes auth) instead of dev tokens
DMT is designed as a toolkit for ISVs to integrate into their existing platforms — not as a standalone production system. The reference
docker-compose.yml, sample configurations, and Sample Web UI are provided to demonstrate how the components work together and to accelerate development. ISVs are expected to leverage their existing infrastructure (container orchestration, databases, secret stores, API gateways, identity providers) and deploy DMT services into their existing clusters. You are the expert on your production environment — the guidance below identifies integration points, not prescriptions.
The docker-compose reference deployment includes supporting services (PostgreSQL, Vault, Kong) for convenience. In production, replace these with your existing enterprise equivalents:
| Reference Component | Production Replacement | Configuration |
|---|---|---|
| PostgreSQL | Your existing cloud-hosted database service (Azure SQL, AWS RDS, Cloud SQL, etc.) | Configure MPS_DB_* and RPS_DB_* environment variables to point to your database. MPS and RPS use standard PostgreSQL-compatible connections. |
| Vault | Your existing key vault service (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault Enterprise, etc.) | Configure the SECRETS_PATH environment variable and implement the ISecretManagerService interface for your provider. |
| Kong | Your existing API gateway (Azure API Management, AWS API Gateway, Nginx, Envoy, etc.) | Route /mps/ and /rps/ prefixes to the respective services. Apply JWT validation and rate limiting at your gateway layer. |
| Docker Compose | Your existing container orchestration (Kubernetes, ECS, AKS, EKS, GKE, Nomad, etc.) | Deploy MPS, RPS, and MPS-Router as containers/pods in your cluster. See Kubernetes deployment guide. The kubernetes/charts/ directory provides Helm chart references. |
DMT's reference deployment uses Kong JWT for API authentication. In production, integrate with your existing identity provider:
- API Authentication: Configure your API gateway or middleware to validate tokens from your IdP (Active Directory, Okta, Auth0, Keycloak, etc.) on all MPS and RPS API routes
- Authorization/RBAC: Implement role-based access control at your middleware or gateway layer — DMT APIs accept authorized requests and do not enforce roles internally
If deploying in a multi-tenant environment:
-
Custom middleware — Add a middleware layer (or modify the existing one) that extracts the
tenantIdfrom your authenticated user context and injects it into every request to MPS and RPS -
Tenant isolation — MPS and RPS use
tenantIdto scope all database queries and Vault paths, ensuring tenants cannot access each other's devices or configurations - Build custom image — Add your modified middleware file to the MPS/RPS Docker images at build time
RPC-Go is designed to be embedded into your existing device management agent:
-
As a shared library (DLL/.so) — Build RPC-Go as a C-shared library (
go build -buildmode=c-shared -o rpc.dll ./cmd/rpcon Windows, orlibrpc.soon Linux) and integrate it into agents written in any language via FFI. See the RPC-Go shared library build instructions and the .NET integration sample for a working example. -
Agent distribution — Bundle the
rpcbinary (or shared library) with your agent installer and invoke it during device onboarding workflows
Authentication model: The RPC-Go to RPS WebSocket connection itself does not carry API key or mutual TLS credentials. ISVs are expected to authenticate the device through their own agent before initiating the RPC-Go activation flow. The ISV agent establishes trust and authorization first, then connects RPC-Go to RPS over the already-authenticated session.
note: The RPS
/activate,/deactivate, and/maintenanceWebSocket paths are reachable without authentication in the reference deployment. ISVs must lock down these endpoints at the API gateway or network layer — restrict access so that only your trusted agent (running on managed devices) can reach RPS over WebSocket. Without this, any client with network access to RPS could initiate activation or deactivation flows.
The Sample Web UI is a reference implementation and demo — not intended for direct production use. For production, embed the DMT ui-toolkit components into your existing management console:
| Component | Framework | What It Provides |
|---|---|---|
| ui-toolkit-react | React | KVM, SOL, and IDER viewer components |
| ui-toolkit-angular | Angular | KVM, SOL, and IDER viewer components |
These are production-grade, tested components that handle the MPS WebSocket connections, rendering, and input forwarding. Embed them in your console alongside your existing device management UI, authentication, and RBAC layers.
graph TB
subgraph YourApp["Your Production Console"]
Auth["Your Auth & RBAC Layer"]
BizLogic["Your Business Logic &<br/>Workflow Orchestration"]
UIToolkit["DMT ui-toolkit<br/>(KVM/SOL/IDER components)<br/>Angular or React"]
APIs["Your API Gateway / Middleware"]
end
Auth --> BizLogic
BizLogic --> UIToolkit
UIToolkit --> APIs
APIs --> MPS["MPS"]
APIs --> RPS["RPS"]
style YourApp fill:#f0f5fa,color:#000
style UIToolkit fill:#0068B5,color:#fff
style APIs fill:#008080,color:#fff
Deploy DMT services as pods/containers in your existing cluster rather than standing up a separate environment:
graph TB
subgraph Cluster["Your Existing Kubernetes Cluster"]
subgraph DMTNamespace["dmt namespace"]
MPS["MPS Pod"]
RPS["RPS Pod"]
Router["MPS-Router Pod<br/>(if scaled)"]
end
subgraph ExistingInfra["Your Existing Infrastructure"]
GW["API Gateway"]
DB["Database Service"]
KV["Key Vault"]
IdP["Identity Provider"]
end
end
GW --> MPS
GW --> RPS
MPS --> DB
RPS --> DB
MPS --> KV
RPS --> KV
GW --> IdP
style DMTNamespace fill:#E3F2FD,color:#000
style ExistingInfra fill:#F5F5F5,color:#000
| Integration Point | Action |
|---|---|
| Container orchestration | Deploy MPS, RPS, MPS-Router in your existing cluster |
| Database | Point MPS/RPS at your managed database service |
| Secrets | Configure MPS/RPS to use your key vault |
| API Gateway | Route DMT API paths through your existing gateway |
| Authentication | Validate tokens from your IdP on DMT API routes |
| Multi-tenancy | Inject tenantId from authenticated context into requests |
| RPC-Go | Integrate into your device agent (subprocess or library) |
| UI | Embed ui-toolkit-react or ui-toolkit-angular in your console |
| Layer | Mechanism | Details |
|---|---|---|
| API Clients → Kong | JWT (Bearer token) | Signed with shared jwt_secret, expiration enforced |
| Kong → MPS/RPS | Internal network | No additional auth (trusted Docker network) |
| AMT Device → MPS | TLS + APF USERAUTH | Device authenticates with username + password (verified against Vault) |
| RPC → RPS | Not authenticated | WebSocket connection with no API key or mutual TLS |
| MPS → AMT | HTTP Digest Auth | Over CIRA channel, credentials from Vault |
| Services → Vault | Vault Token | Dev token for development, AppRole/Kubernetes auth for production |
| Services → PostgreSQL | Username/Password | Via connection string |
The system uses four certificates for different purposes:
flowchart TB
subgraph Vault["Vault (MPSCerts)"]
VRoot["C3: MPS Root CA + key"]
VLeaf["C3: MPS Server TLS Certificate"]
end
subgraph RPSDomain["RPS Domain Configuration"]
ProvPFX["C2: Provisioning PFX + private key"]
end
subgraph AMTDevice["AMT Firmware"]
AMTTrust["C3: Trusted MPS Root CA"]
AMTE2E["C4: AMT Device TLS Certificate"]
AMTProvTrust["C2: Trusted provisioning CA hash"]
end
User["User/Admin"] -.->|"uploads C2"| ProvPFX
User -.->|"uploads C3"| VRoot
MPS -->|"loads C3"| VLeaf
RPS -.->|"reads C2"| ProvPFX
RPS -.->|"checks C2 trust"| AMTProvTrust
RPS -.->|"reads C3"| VRoot
RPS -.->|"installs C3"| AMTTrust
RPS -->|"issues C4"| AMTE2E
MPS -->|"presents C3"| AMTTrust
MPS -->|"validates C4"| AMTE2E
| Aspect | Details |
|---|---|
| Purpose | Presented to clients on :443 (browsers, RPC-Go) |
| Certificate Source | Self-signed in the reference deployment (why -n is needed) |
| Production Certificate Source | ISV replaces it with a CA-signed certificate through Kong configuration |
| Aspect | Details |
|---|---|
| Purpose | Required only for ACM activation |
| Certificate Source | Purchased from a supported CA (Comodo, DigiCert, Entrust, GoDaddy) |
| Requirement | CN must match DHCP Option 15 DNS suffix |
| Storage Location | Uploaded to RPS as part of Domain configuration (PFX format) |
| Usage | RPS injects cert chain into AMT via AddNextCertInChain, signs activation with private key |
| Aspect | Details |
|---|---|
| Purpose | Presented by MPS to AMT devices on :4433 |
| Certificate Source | User creates the MPS Root CA and MPS Server TLS Certificate, then uploads both to Vault at MPSCerts
|
| Requirement | Required when AMT devices use CIRA to connect to MPS on port 4433 |
| Storage Location | Vault MPSCerts: root_key, mps_tls_config.cert, mps_tls_config.key, web_tls_config.ca
|
| Runtime Behavior | MPS reads the certificate material on startup. If the user has not created and uploaded the MPS Root CA and MPS Server TLS Certificate to Vault, MPS generates a self-signed fallback set. |
| Trust Establishment | During activation, RPS adds the MPS Root CA to AMT with AddTrustedRootCertificate
|
| Usage | MPS presents this certificate during the AMT-to-MPS CIRA TLS handshake |
| Aspect | Details |
|---|---|
| Purpose | Enables E2E TLS between MPS and the AMT device for management communication on port 16993 |
| Certificate Source | RPS creates it during the TLS provisioning phase from an AMT-generated key pair and certificate signing request |
| Requirement | Required only when the profile and AMT platform enable E2E TLS between MPS and the AMT device |
| Signing Authority | MPS Root CA private key from Vault |
| Provisioning Flow | RPS creates an AMT Device TLS Certificate (CN=AMT-{hostname}), signs it with the MPS Root CA, adds it to AMT with AddCertificate, then creates a TLSCredentialContext
|
| Usage | AMT presents this certificate to MPS during E2E TLS management connections on port 16993 |
| Service | Port | Protocol | Direction | Purpose |
|---|---|---|---|---|
| Kong | 443 | HTTPS | Inbound | API gateway, TLS termination |
| MPS CIRA | 4433 | TLS+APF | Inbound (devices) | Persistent device connections |
| MPS Web | 3000 | HTTP/WS | Internal | REST API + WebSocket relay |
| MPS Router | 8003 | HTTP | Internal | Device-affinity routing |
| RPS REST | 8081 | HTTP | Internal | Profile management API |
| RPS WebSocket | 8080 | WS | Inbound (RPC) | Activation/deactivation |
| PostgreSQL | 5432 | TCP | Internal | Shared database |
| Vault | 8200 | HTTP | Internal | Secrets management |
| Web UI | 80 | HTTP | Internal (via Kong) | Management console |
| Port | Protocol | Service | Used By |
|---|---|---|---|
| 16992 | HTTP | WSMAN (non-TLS) | Management commands (AMT < 19) |
| 16993 | HTTPS | WSMAN (TLS) | Management commands (TLS enforced, AMT 19+) |
| 16994 | TCP | KVM | Remote desktop (RFB/VNC) |
| 16995 | TCP | SOL | Serial Over LAN |
| 16996 | TCP | IDER | IDE Redirection (boot media) |
| Term | Definition |
|---|---|
| AMT | Intel Active Management Technology — hardware-based remote management built into Intel vPro platforms |
| CIRA | Client-Initiated Remote Access — AMT feature where the device establishes an outbound connection to a management server |
| APF | AMT Port Forwarding Protocol — multiplexing protocol inside CIRA TLS tunnel (SSH-like channels) |
| WSMAN | WS-Management — SOAP/XML-based management protocol used by AMT |
| MEI | Management Engine Interface — OS driver interface to Intel Management Engine |
| HECI | Host Embedded Controller Interface — hardware interface to ME (accessed via MEI driver) |
| PTHI | Platform/Topology Host Interface — binary command protocol for AMT host operations |
| LMS | Local Manageability Service — OS service that provides TCP socket access to AMT firmware |
| LME | Local Manageability Engine — direct MEI access using APF protocol (fallback when LMS unavailable) |
| CCM | Client Control Mode — activation mode that doesn't require provisioning certificates (limited features) |
| ACM | Admin Control Mode — full-featured activation requiring provisioning certificates |
| KVM | Keyboard Video Mouse — remote desktop access to AMT-managed device |
| SOL | Serial Over LAN — remote serial console access |
| IDER | IDE Redirection — remote boot media mounting |
| RPC | Remote Provisioning Client — agent installed on managed devices |
| RPS | Remote Provisioning Server — cloud service for device activation |
| MPS | Management Presence Server — cloud service maintaining device connections |
| MEBx | Management Engine BIOS Extension — BIOS-level AMT configuration interface |
| LSA | Local System Account — AMT-provided credentials for local WSMAN access |
| ODCA | On-Die Certificate Authority — factory-installed certificate authority in AMT firmware, used for initial TLS verification of genuine Intel hardware |
| E2E TLS | End-to-End TLS — RPS performs TLS handshake directly with AMT through RPC-Go as a byte relay |
| Resource | Link |
|---|---|
| DMT Documentation | https://device-management-toolkit.github.io/docs/2.36/ |
| MPS REST API | https://device-management-toolkit.github.io/docs/2.36/APIs/indexMPS/ |
| RPS REST API | https://device-management-toolkit.github.io/docs/2.36/APIs/indexRPS/ |
| Kubernetes Deployment Guide | https://device-management-toolkit.github.io/docs/2.36/Tutorials/Scaling/Kubernetes/deployingk8s/ |
| RFB Protocol 3.8 (RFC 6143) | https://datatracker.ietf.org/doc/html/rfc6143 |
| Intel AMT Port Forwarding Protocol | https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/HTMLDocuments/MPSDocuments/Intel%20AMT%20Port%20Forwarding%20Protocol%20Reference%20Manual.pdf |