Skip to content

Architecture and Security

Tyler Hatfield edited this page Nov 12, 2026 · 4 revisions

Architecture & Security Specification (v2.5.1)

Vitrine RMM is architected around zero-trust authentication, Enterprise OIDC PKCE SSO, cryptographic secret vaulting at rest, strict multi-tenant RBAC, strict Content-Security-Policy (CSP), and defense-in-depth SSRF/WebSocket validation.


1. Authentication, Enterprise OIDC (S256 PKCE) & Session Architecture

  • Zero-Default Bootstrap: Fresh installations contain no pre-seeded user accounts. The initial super_admin is created interactively on first boot (POST /api/auth/setup-initial-admin), after which bootstrap is permanently locked (HTTP 409).
  • Memory-Hard Password Hashing (scrypt) & Mutation Guards: User and guest portal passwords are salted with 16 CSPRNG bytes, hashed via crypto.scryptSync (N=16384, r=8, p=1), and verified via crypto.timingSafeEqual. User updates (PUT /api/users/:id) enforce a minimum 10-character password policy, block demoting the last active super_admin (HTTP 400), and immediately revoke active sessions upon password, role, or tenant reassignment.
  • OpenID Connect (OIDC) Authorization Code + S256 PKCE SSO:
    • Supports Authentik, Keycloak, Pocket ID, Authelia, Okta, and Microsoft Entra ID via standard .well-known/openid-configuration discovery (POST /api/auth/oidc/test).
    • GET /api/auth/oidc/login generates a cryptographic 32-byte code_verifier, S256 code_challenge, state, and nonce bound to a short-lived HttpOnly cookie (vitrine_oidc_tx).
    • GET /api/auth/oidc/callback validates state, exchanges the authorization code with code_verifier, verifies ID token nonce/issuer/expiry and /userinfo claims, enforces verified email status, and optionally provisions Just-In-Time (JIT) technician accounts when oidc_auto_provision is enabled.
  • Revocable Sessions & Live WebSocket Enforcement:
    • Sign-in issues a 256-bit random session token stored only as a SHA-256 digest in auth_sessions (HttpOnly; SameSite=Lax, plus Secure over HTTPS).
    • /ws/terminal and /ws/telemetry enforce strict Origin header validation (isAllowedCorsOrigin) on HTTP upgrade and re-verify isSessionTokenActive(tokenHash) on every inbound frame and outbound broadcast tick — terminating WebSocket streams immediately if a session is logged out or revoked.

2. Server-Enforced Multi-Tenant RBAC

Every /api/* request and /ws/* WebSocket upgrade passes through a global authentication and authorization hook:

Role Tenant Scope Capabilities
MSP Super Admin (super_admin) Global (All Clients) Full fleet control, user/RBAC management, system settings, OIDC SSO, code signing, MeshCentral federation, client permanent deletion/purge, Backup Recovery Key reveal, encrypted backups & restores, and system updates.
Technician (technician) Global or Assigned Clients Remote KVM/Ghost/AMT sessions, background tools, patch & script execution, LAPS, BitLocker & secret Custom Field reveal (all gated by per-user Step-Up MFA), hypervisor sync, policy edits, and standard endpoint offboarding.
Client Admin (client_admin) Strictly Bound tenant_id Read-only visibility strictly isolated to their assigned tenant_id (including tenant-scoped notifications). Sub-routes for /files, /files/download, /registry, /processes, /services, /tasks, /eventlogs, /laps, /bitlocker, /notes, and /chat return HTTP 403 Forbidden, and secret custom fields are completely stripped.

3. AES-256-GCM At-Rest Vault (vault/index.ts)

Sensitive secrets are never stored in plaintext in SQLite or leaked in API list responses:

  • Master Key Management: Uses VITRINE_MASTER_KEY (or LAPS_MASTER_SECRET alias) when provided via secret manager, or auto-generates <DATA_DIR>/.vault-key.json with 0600 file permissions. Cross-machine backup restores automatically reload the active vault key in memory (reloadVaultMasterKey()).
  • Authenticated Encryption (enc:v1:<iv>:<tag>:<ciphertext>): Encrypts LAPS passwords (current & historical), BitLocker/LUKS/FileVault recovery keys, secret-type Custom Field values, per-user TOTP secrets, OIDC client secrets, MeshCentral API tokens, hypervisor & specialty device credentials, SMTP passwords, ITFlow API keys, PSA webhook secrets, S3 offsite secret keys, backup passphrases, and per-device agent heartbeat tokens.
  • Vaulted secret Custom Attributes: Custom fields defined with field_type = 'secret' are encrypted at rest in custom_field_values, masked (••••••••••••) for technicians by default, preserved without corruption when masked placeholders are saved back, stripped completely from client_admin and Guest Portal responses, and revealed only via GET /api/devices/:id/custom-fields?reveal=true with an active Step-Up MFA session.

4. Per-User RFC 6238 Step-Up TOTP MFA, Anti-Replay & Recovery Codes

Accessing high-impact vault secrets (GET /api/devices/:id/bitlocker, GET /api/devices/:id/laps?reveal=true, GET /api/devices/:id/custom-fields?reveal=true, POST /api/backups/recovery-key, and POST /api/laps/break-glass-export) requires Step-Up MFA (POST /api/auth/verify-mfa):

  • Strict Per-User TOTP Secrets: Every administrator and technician maintains an isolated per-user users.totp_secret (no shared global fallback).
  • Time-Step Anti-Replay: Records last_totp_step per user so a 6-digit TOTP code cannot be replayed within the same 30-second window (HTTP 401).
  • Single-Use Recovery Codes: Users receive 8 high-entropy emergency recovery codes stored as SHA-256 digests (recovery_codes_json), atomically consumed on use.

5. Browser CSP & DNS-Rebinding SSRF Hardening

  • Strict Content-Security-Policy (CSP): Responses enforce default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self' with zero inline <script> execution required by the SPA.
  • DNS-Rebinding Outbound SSRF Guard (validateOutboundHostSafety): All outbound connections — specialty appliance probes, hypervisor APIs, OIDC discovery/token endpoints, S3 offsite backup uploads, ITFlow PSA sync, Cloud HSM signing webhooks, and MeshCentral federation — resolve target hostnames via dns.promises.lookup(..., { all: true }) and block loopback (127.0.0.0/8, ::1), link-local metadata (169.254.0.0/16, fe80::/10), CGNAT, multicast, and IPv4-mapped IPv6 bypasses (preserving explicit private LAN opt-in only where intended for local infrastructure).

Clone this wiki locally