MDM (device compliance)

Compliance policies, lock/retire, and OIDC device assertions.

MDM (device compliance)

lindir’s MDM layer provides compliance policies, custom discovery scripts, retire and lock remote actions, and OIDC Conditional Access via device assertions — a calm way to know a host’s posture before it opens an application.

What you get

Capability Behavior
Allowed distro/version Policy allowedDistros[{family,minVersion,maxVersion}]
Disk encryption requireEncryption — dm-crypt/LUKS on root (mapper/dm-)
Local password mins Compare /etc/security/pwquality.conf (and PAM hints) to policy mins
Custom scripts Admin POSIX scripts → JSON stdout; customAssert on policy
Lock Queue loginctl lock-sessions on next sync
Retire Clear enrollment secret, mark host retired, agent clears local secret + energy drop-ins
Conditional Access OIDC clients with requireCompliantDevice need a short-lived device assertion

Remote actions today: lock sessions and retire enrollment. Compliance can gate OIDC clients that require a compliant device.

Flow

  1. Admin creates a compliance policy and assigns host and/or label.
  2. Optional: create a custom script; set rules.customScriptId + customAssert.
  3. Host lindir-client sync collects signals, runs scripts, POST /v1/client/mdm/compliance-report.
  4. Server evaluates → mdm_host_compliance (compliant / noncompliant / unknown).
  5. For SSO apps that require a device: run lindir-client mdm-broker (listens on 127.0.0.1:1290); OIDC login page fetches /assertion.

Admin API (Bearer)

  • GET|POST /v1/mdm/policies, PUT|DELETE /v1/mdm/policies/{id}
  • GET /v1/mdm/policies/{id}/targets
  • POST /v1/mdm/assign / unassign — { policyId, hostIds[], labelIds[] }
  • GET|POST /v1/mdm/scripts, DELETE /v1/mdm/scripts/{id}
  • GET /v1/mdm/compliance, GET /v1/mdm/compliance/{hostId}
  • GET /v1/mdm/actions
  • POST /v1/mdm/lock / retire — { hostId }

Client API (Host auth)

  • GET /v1/client/mdm/scripts
  • POST /v1/client/mdm/compliance-report — signals JSON
  • GET /v1/client/mdm/actions / POST …/actions/{id}/result
  • POST /v1/client/mdm/assertion → { assertion, expiresIn }

CLI

lindir-admin mdm policy create --name laptop-baseline
lindir-admin mdm policies
# assign via API / Admin UI Compliance → Policies
lindir-admin mdm compliance
lindir-admin mdm lock --host-id HOST_UUID
lindir-admin mdm retire --host-id HOST_UUID

On the host:

sudo lindir-client sync
sudo lindir-client mdm-broker   # for OIDC apps that require compliant device

Admin UI

Compliance → Policies, Scripts, Devices. Platform → OIDC → Require compliant device.

Security notes

  • Retire clears the enrollment secret and rejects Host auth (host_unauthorized on sync). Re-enroll the same hostname to reactivate (new secret); use --skip-vpn if the device is already on the mesh.
  • Device assertions are HS256 JWTs (~5 min) signed with a server secret derived from bootstrap token — protect bootstrap credentials.
  • Localhost broker binds 127.0.0.1 only and sends Access-Control-Allow-Origin: * for the OIDC page origin; do not expose that port remotely.
  • Custom compliance scripts run as root during sync — same trust model as fleet scripts (OWASP Controls).

See also Fleet, Client, Admin Web UI.