Skip to main content

Security Architecture

SecureLink implements defense-in-depth across authentication, authorization, device identity, encrypted communication, and multi-tenant isolation. This page describes how these layers work together.

Authentication and Authorization

SecureLink separates authentication (verifying who you are) from authorization (determining what you can do):

  • Keycloak handles authentication — it manages user credentials, login flows, and issues identity tokens
  • VSN+ handles authorization — it issues session tokens containing the user's type, tenant, roles, and permissions

Login Flow

When a user signs in via the Web UI, the flow is entirely server-side — the user never sees a Keycloak login page:

Keycloak remains the credential store and enforces password policy and account lockout, but users interact only with the native SecureLink sign-in form. The /auth/exchange endpoint (which accepted a Keycloak JWT directly from the browser) is still present in the codebase for legacy integrations but is no longer the primary user-facing path.

The VSN+ session token contains the full authorization context:

FieldDescription
userType1 = SuperAdmin, 2 = Tenant Admin, 3 = VPN User
tenantIdThe tenant this user belongs to (null for SuperAdmin)
rolesRole names assigned to the user
permissionsFlattened list of permissions derived from roles
sessionIdReference to the server-side session record

This separation means Keycloak never needs to know about SecureLink's tenant model, roles, or permissions — it only verifies credentials.

Session Lifecycle

EventAction
LoginNative sign-in form submits to /auth/login; server performs KC password grant and issues VSN+ session token. Default expiry: 8 hours (configurable via VSN_SESSION_DURATION_HOURS). With "Keep me signed in for 30 days": 30 days
API callVSN+ token verified on every request; tenant context extracted for data filtering
RefreshSession token can be refreshed before expiry without re-entering credentials
LogoutSession is revoked server-side; token becomes invalid immediately
RevocationAdmin revokes a user's sessions — next API call returns 401, redirecting to /login

Session Revocation Enforcement

When a VSN+ session token is revoked (either by the user via "Revoke All Active" or by an admin):

  • The revoked token is definitively invalidated — it returns a 401 Unauthorized error
  • The auth middleware does not fall back to Keycloak validation for revoked VSN+ tokens
  • This ensures that session revocation is immediate and enforceable, even if the user's Keycloak session is still valid
  • The user must re-authenticate through the native login form at /login to obtain a new session

Keycloak Instance Separation

The platform uses two separate Keycloak instances with different purposes:

InstanceUsersPurpose
Production KeycloakTenant admins, VPN usersAuthentication for the SecureLink Web UI and API
Global VSA KeycloakMulti-orchestrator administratorsAuthentication for the Global VSA management plane

These instances have separate realms, client configurations, and user directories. They do not share state.

Certificate Provisioning

Every edge device establishes its identity through X.509 certificates provisioned during the bootstrap process. These certificates enable mutual TLS (mTLS) authentication on all subsequent MQTT communication.

Provisioning Flow

The SecureLink Installer CLI provisions devices using a one-time deployment token over HTTPS:

  1. The installer claims the deployment token via the orchestrator's provision API. The token claim is atomic (UPDATE ... SET status='claimed' WHERE status='active') to prevent double-use.
  2. The API generates a signed X.509 certificate with the device GUID as the Common Name. The private key is returned unencrypted over the HTTPS connection (secured by TLS + token authentication).
  3. The installer saves certificates with restricted file permissions (root-owned, 0600). The private key never traverses an unencrypted channel.
  4. The device establishes an mTLS connection to the MQTT broker using the provisioned certificates.

Deployment Token

Deployment tokens follow the format NLZ-XXXX-XXXX-XXXX-XXXX using an unambiguous character set (excludes I, O, 0, 1 to avoid confusion). Each token is:

  • Single-use — once claimed, it cannot be reused
  • Time-limited — tokens expire if not used within the configured window
  • Atomically claimed — database-level protection against race conditions

Certificate Storage on Edge

After provisioning, certificates are stored on the edge device:

FilePurpose
ca.crtCA certificate — validates the broker's identity
edge.crtDevice certificate — proves the edge's identity to the broker
edge.keyPrivate key — restricted file permissions (0600), never transmitted after provisioning

Mutual TLS (mTLS)

After bootstrap, all communication between edge devices and the MQTT broker uses mutual TLS:

  • The broker presents its certificate, which the edge validates against the CA
  • The edge presents its certificate, which the broker validates against the CA
  • Both sides must prove their identity before the connection is established

This means:

  • Unauthorized devices cannot connect to the MQTT broker
  • Messages cannot be intercepted or tampered with in transit
  • Each device's identity is cryptographically verified on every connection

MQTT Broker Trust Chain

The edge trust store (ca.crt) may contain two CA certificates:

CAPurpose
Tenant CASigns the edge's device certificate (client identity)
EMQX CASigns the MQTT broker's server certificate (server identity)

When the broker uses a separate self-signed CA (common in cloud deployments), the installer appends the broker CA to the edge's trust store automatically. The agent validates the broker's certificate against both CAs using TLS Server Name Indication (SNI) for hostname verification.

SSH Certificate Architecture

SecureLink uses SSH certificates (not plain keys) for both host identity and user authentication:

SSH CA

Each tenant has a dedicated Ed25519 SSH CA keypair stored on the API server. This CA signs both host certificates (for edge sshd identity) and user certificates (for admin access).

Host Certificates

During provisioning, the installer:

  1. Generates an Ed25519 host keypair on the edge
  2. Sends the public key to the API for signing
  3. Receives a signed host certificate with principals (GUID, IP address)
  4. Configures sshd with HostCertificate pointing to the signed cert

User Certificates

When an admin generates an SSH user certificate from the UI:

  1. The admin provides their SSH public key
  2. The API signs it with the tenant's SSH CA, valid for 24 hours
  3. The certificate includes principals edge and root
  4. The edge's sshd trusts the certificate via TrustedUserCAKeys (configured by the installer)

Bastion Architecture

The SSH bastion fetches authorized keys from the API on every connection attempt via AuthorizedKeysCommand. It also trusts all tenant SSH CAs via TrustedUserCAKeys, allowing admin user certificates for ProxyJump access. No static authorized_keys file is needed — the database is the sole source of truth.

Multi-Tenant Isolation

SecureLink enforces tenant isolation at multiple layers:

API Layer

Every API query is filtered by the authenticated user's tenant ID. A Tenant Admin can only see and modify resources belonging to their own tenant. SuperAdmins can access all tenants but must explicitly select a tenant context for most operations.

MQTT Layer

MTGE devices use per-tenant MQTT topics (VSR/{serial}/batch/{tenantId}), ensuring that configuration for one tenant is never delivered to another tenant's processing context on the device.

Data Plane Layer (MTGE)

On multi-tenant gateway edges, VRF (Virtual Routing and Forwarding) technology provides complete data plane isolation:

  • Each tenant gets a separate VRF with its own routing table
  • WireGuard tunnels, NAT rules, and ACLs are bound to the tenant's VRF
  • Traffic cannot cross VRF boundaries unless explicitly configured (e.g., internet breakout)

Database Layer

All tenant-scoped tables include a tenant_id column. Drizzle ORM queries always include a tenant filter when operating on behalf of a Tenant Admin.

WireGuard Key Security

WireGuard tunnels use X25519 key pairs. Keys are:

  • Generated using the Node.js native cryptography module
  • Encrypted at rest in the database using AES-256-GCM (key derived via PBKDF2 from a per-key salt)
  • Never logged — the API enforces that private keys are excluded from all logging output
  • Transmitted only inside batch configuration — delivered over the mTLS-encrypted MQTT channel

IKEv2 Certificate Security

IKEv2 App VPN uses a separate certificate chain for StrongSwan:

  • CA certificate and server certificate generated per-edge (or per-tenant for MTGEs)
  • Client certificates issued per VPN user, bundled as PKCS#12 with a one-time password
  • Certificate bundles encrypted in the database using AES-256-GCM with a static environment key (distinct from the PBKDF2 scheme used for WireGuard keys)
  • Certificate Revocation List (CRL) maintained and distributed via batch configuration

Further Reading