Skip to main content

Enrollment Flow

Introduction

Enrollment is the one-time process where a sensor agent registers itself with the backend, exchanging a temporary install token for a durable sensor token. This document describes the complete enrollment lifecycle, from token generation in the frontend to persistent token storage on the sensor host.


Enrollment Lifecycle

OperatorOperator runs Install CommandAgentAgent sends Enrollment RequestBackendBackend validates Token & MetadataBackendBackend issues durable Sensor TokenAgentAgent persists Token to Disk

Enrollment Request Payload

The agent sends the following data to the backend during enrollment:

{
"installToken": "one-time-token-from-frontend",
"hostname": "sensor-ubuntu-host",
"osInfo": "Ubuntu 24.04 LTS",
"architecture": "x86_64",
"agentVersion": "2.0.0",
"sensorIp": "192.168.1.100",
"sensorPort": 22,
"sudoUser": "sensoradmin",
"interfaces": [
{
"name": "enp130s0f0",
"isManagement": true,
"isLoopback": false,
"isVirtual": false,
"isWireless": false,
"isUp": true,
"bytesSent": 1073741824,
"bytesRecv": 2147483648
},
{
"name": "enp130s0f1",
"isManagement": false,
"isLoopback": false,
"isVirtual": false,
"isWireless": false,
"isUp": true,
"bytesSent": 0,
"bytesRecv": 0
}
]
}

Field Details

FieldSourceDescription
installTokenINSTALL_TOKEN env varOne-time token generated by frontend
hostname/host-hostname or os.Hostname()Host machine hostname, not container hostname
osInfo/host-os-release PRETTY_NAMEHost OS name (e.g., "Ubuntu 24.04 LTS")
architectureruntime.GOARCHCPU architecture, mapped to x86_64 / arm64
agentVersionConstant 2.0.0Agent software version
sensorIpUDP dial to 8.8.8.8:80Primary outbound IP of the host
sensorPortSENSOR_PORT env var (default: 22)SSH port for Ansible access
sudoUserHardcoded sensoradminUser for privilege escalation
interfacesnet.Interfaces() + gopsutilAll network interfaces with classification

Enrollment Response

{
"success": true,
"data": {
"sensorId": "uuid",
"sensorToken": "durable-token-for-heartbeats",
"backendUrl": "http://10.10.10.70:5009",
"heartbeatIntervalSeconds": 30
}
}

The agent extracts sensorToken and heartbeatIntervalSeconds from the response.


Token Persistence

After successful enrollment, persistSensorToken() writes the durable token to the config file (default: /etc/ravenxcope/sensor-agent.env):

Before enrollment:

SENSOR_ID=sensor-1
INSTALL_TOKEN=install-token
BACKEND_URL=https://backend.local

After enrollment:

SENSOR_ID=sensor-1
# INSTALL_TOKEN consumed during enrollment
BACKEND_URL=https://backend.local
SENSOR_TOKEN=durable-token

Key behaviors:

  • Creates parent directories if they don't exist (os.MkdirAll).
  • If SENSOR_TOKEN= already exists, replaces the value in-place.
  • If INSTALL_TOKEN= exists, comments it out as consumed.
  • File permissions are set to 0600 (owner read/write only).
  • If persistence fails, the agent logs a warning but continues running.

Host Metadata Detection

The agent detects host metadata using multiple strategies to work correctly inside Docker containers:

Hostname

  1. Read from bind-mounted file at HOST_HOSTNAME_FILE env var (default: /host-hostname)
  2. Fall back to os.Hostname()
  3. Last resort: return "unknown"

OS Info

  1. Read PRETTY_NAME from HOST_OS_RELEASE_FILE env var (default: /host-os-release)
  2. Fall back to /etc/os-release inside the container
  3. Last resort: return runtime.GOOS (e.g., "linux")

Primary IP

Uses a UDP dial to 8.8.8.8:80 (no actual traffic sent) to determine the local IP address of the default route interface.

Architecture

Maps runtime.GOARCH to human-readable names:

  • amd64x86_64
  • arm64arm64

Failure Modes

ScenarioBehavior
INSTALL_TOKEN missing on first runAgent exits with fatal error
Backend unreachable during enrollmentAgent exits with fatal error
Backend returns non-200 statusAgent exits with fatal error
Token persistence failsWarning logged, agent continues with in-memory token
Agent restarts with persisted SENSOR_TOKENEnrollment is skipped entirely