diff --git a/server/db/pg/schema/schema.ts b/server/db/pg/schema/schema.ts index 4fae35f9..1ba1d16e 100644 --- a/server/db/pg/schema/schema.ts +++ b/server/db/pg/schema/schema.ts @@ -726,6 +726,99 @@ export const clientPostureSnapshots = pgTable("clientPostureSnapshots", { onDelete: "cascade" }), + collectedAt: integer("collectedAt").notNull() +}); + +export const olms = pgTable("olms", { + olmId: varchar("id").primaryKey(), + secretHash: varchar("secretHash").notNull(), + dateCreated: varchar("dateCreated").notNull(), + version: text("version"), + agent: text("agent"), + name: varchar("name"), + clientId: integer("clientId").references(() => clients.clientId, { + // we will switch this depending on the current org it wants to connect to + onDelete: "set null" + }), + userId: text("userId").references(() => users.userId, { + // optionally tied to a user and in this case delete when the user deletes + onDelete: "cascade" + }), + archived: boolean("archived").notNull().default(false) +}); + +export const currentFingerprint = pgTable("currentFingerprint", { + fingerprintId: serial("id").primaryKey(), + + olmId: text("olmId") + .references(() => olms.olmId, { onDelete: "cascade" }) + .notNull(), + + firstSeen: integer("firstSeen").notNull(), + lastSeen: integer("lastSeen").notNull(), + lastCollectedAt: integer("lastCollectedAt").notNull(), + + username: text("username"), + hostname: text("hostname"), + platform: text("platform"), + osVersion: text("osVersion"), + kernelVersion: text("kernelVersion"), + arch: text("arch"), + deviceModel: text("deviceModel"), + serialNumber: text("serialNumber"), + platformFingerprint: varchar("platformFingerprint"), + + // Platform-agnostic checks + + biometricsEnabled: boolean("biometricsEnabled").notNull().default(false), + diskEncrypted: boolean("diskEncrypted").notNull().default(false), + firewallEnabled: boolean("firewallEnabled").notNull().default(false), + autoUpdatesEnabled: boolean("autoUpdatesEnabled").notNull().default(false), + tpmAvailable: boolean("tpmAvailable").notNull().default(false), + + // Windows-specific posture check information + + windowsDefenderEnabled: boolean("windowsDefenderEnabled") + .notNull() + .default(false), + + // macOS-specific posture check information + + macosSipEnabled: boolean("macosSipEnabled").notNull().default(false), + macosGatekeeperEnabled: boolean("macosGatekeeperEnabled") + .notNull() + .default(false), + macosFirewallStealthMode: boolean("macosFirewallStealthMode") + .notNull() + .default(false), + + // Linux-specific posture check information + + linuxAppArmorEnabled: boolean("linuxAppArmorEnabled") + .notNull() + .default(false), + linuxSELinuxEnabled: boolean("linuxSELinuxEnabled").notNull().default(false) +}); + +export const fingerprintSnapshots = pgTable("fingerprintSnapshots", { + snapshotId: serial("id").primaryKey(), + + fingerprintId: integer("fingerprintId") + .references(() => currentFingerprint.fingerprintId, { + onDelete: "cascade" + }) + .notNull(), + + username: text("username"), + hostname: text("hostname"), + platform: text("platform"), + osVersion: text("osVersion"), + kernelVersion: text("kernelVersion"), + arch: text("arch"), + deviceModel: text("deviceModel"), + serialNumber: text("serialNumber"), + platformFingerprint: varchar("platformFingerprint"), + // Platform-agnostic checks biometricsEnabled: boolean("biometricsEnabled").notNull().default(false), @@ -759,67 +852,6 @@ export const clientPostureSnapshots = pgTable("clientPostureSnapshots", { .notNull() .default(false), - collectedAt: integer("collectedAt").notNull() -}); - -export const olms = pgTable("olms", { - olmId: varchar("id").primaryKey(), - secretHash: varchar("secretHash").notNull(), - dateCreated: varchar("dateCreated").notNull(), - version: text("version"), - agent: text("agent"), - name: varchar("name"), - clientId: integer("clientId").references(() => clients.clientId, { - // we will switch this depending on the current org it wants to connect to - onDelete: "set null" - }), - userId: text("userId").references(() => users.userId, { - // optionally tied to a user and in this case delete when the user deletes - onDelete: "cascade" - }), - archived: boolean("archived").notNull().default(false) -}); - -export const currentFingerprint = pgTable("currentFingerprint", { - fingerprintId: serial("id").primaryKey(), - - olmId: text("olmId") - .references(() => olms.olmId, { onDelete: "cascade" }) - .notNull(), - - firstSeen: integer("firstSeen").notNull(), - lastSeen: integer("lastSeen").notNull(), - - username: text("username"), - hostname: text("hostname"), - platform: text("platform"), - osVersion: text("osVersion"), - kernelVersion: text("kernelVersion"), - arch: text("arch"), - deviceModel: text("deviceModel"), - serialNumber: text("serialNumber"), - platformFingerprint: varchar("platformFingerprint") -}); - -export const fingerprintSnapshots = pgTable("fingerprintSnapshots", { - snapshotId: serial("id").primaryKey(), - - fingerprintId: integer("fingerprintId") - .references(() => currentFingerprint.fingerprintId, { - onDelete: "cascade" - }) - .notNull(), - - username: text("username"), - hostname: text("hostname"), - platform: text("platform"), - osVersion: text("osVersion"), - kernelVersion: text("kernelVersion"), - arch: text("arch"), - deviceModel: text("deviceModel"), - serialNumber: text("serialNumber"), - platformFingerprint: varchar("platformFingerprint"), - hash: text("hash").notNull(), collectedAt: integer("collectedAt").notNull() }); diff --git a/server/db/sqlite/schema/schema.ts b/server/db/sqlite/schema/schema.ts index eedbfb69..8b44e995 100644 --- a/server/db/sqlite/schema/schema.ts +++ b/server/db/sqlite/schema/schema.ts @@ -416,12 +416,117 @@ export const clientSiteResourcesAssociationsCache = sqliteTable( } ); -export const clientPostureSnapshots = sqliteTable("clientPostureSnapshots", { - snapshotId: integer("snapshotId").primaryKey({ autoIncrement: true }), - +export const olms = sqliteTable("olms", { + olmId: text("id").primaryKey(), + secretHash: text("secretHash").notNull(), + dateCreated: text("dateCreated").notNull(), + version: text("version"), + agent: text("agent"), + name: text("name"), clientId: integer("clientId").references(() => clients.clientId, { + // we will switch this depending on the current org it wants to connect to + onDelete: "set null" + }), + userId: text("userId").references(() => users.userId, { + // optionally tied to a user and in this case delete when the user deletes onDelete: "cascade" }), + archived: integer("archived", { mode: "boolean" }).notNull().default(false) +}); + +export const currentFingerprint = sqliteTable("currentFingerprint", { + fingerprintId: integer("id").primaryKey({ autoIncrement: true }), + + olmId: text("olmId") + .references(() => olms.olmId, { onDelete: "cascade" }) + .notNull(), + + firstSeen: integer("firstSeen").notNull(), + lastSeen: integer("lastSeen").notNull(), + lastCollectedAt: integer("lastCollectedAt").notNull(), + + username: text("username"), + hostname: text("hostname"), + platform: text("platform"), + osVersion: text("osVersion"), + kernelVersion: text("kernelVersion"), + arch: text("arch"), + deviceModel: text("deviceModel"), + serialNumber: text("serialNumber"), + platformFingerprint: text("platformFingerprint"), + + // Platform-agnostic checks + + biometricsEnabled: integer("biometricsEnabled", { mode: "boolean" }) + .notNull() + .default(false), + diskEncrypted: integer("diskEncrypted", { mode: "boolean" }) + .notNull() + .default(false), + firewallEnabled: integer("firewallEnabled", { mode: "boolean" }) + .notNull() + .default(false), + autoUpdatesEnabled: integer("autoUpdatesEnabled", { mode: "boolean" }) + .notNull() + .default(false), + tpmAvailable: integer("tpmAvailable", { mode: "boolean" }) + .notNull() + .default(false), + + // Windows-specific posture check information + + windowsDefenderEnabled: integer("windowsDefenderEnabled", { + mode: "boolean" + }) + .notNull() + .default(false), + + // macOS-specific posture check information + + macosSipEnabled: integer("macosSipEnabled", { mode: "boolean" }) + .notNull() + .default(false), + macosGatekeeperEnabled: integer("macosGatekeeperEnabled", { + mode: "boolean" + }) + .notNull() + .default(false), + macosFirewallStealthMode: integer("macosFirewallStealthMode", { + mode: "boolean" + }) + .notNull() + .default(false), + + // Linux-specific posture check information + + linuxAppArmorEnabled: integer("linuxAppArmorEnabled", { mode: "boolean" }) + .notNull() + .default(false), + linuxSELinuxEnabled: integer("linuxSELinuxEnabled", { + mode: "boolean" + }) + .notNull() + .default(false) +}); + +export const fingerprintSnapshots = sqliteTable("fingerprintSnapshots", { + snapshotId: integer("id").primaryKey({ autoIncrement: true }), + + fingerprintId: integer("fingerprintId") + .references(() => currentFingerprint.fingerprintId, { + onDelete: "cascade" + }) + .notNull(), + + username: text("username"), + hostname: text("hostname"), + platform: text("platform"), + osVersion: text("osVersion"), + kernelVersion: text("kernelVersion"), + arch: text("arch"), + deviceModel: text("deviceModel"), + serialNumber: text("serialNumber"), + platformFingerprint: text("platformFingerprint"), // Platform-agnostic checks @@ -476,67 +581,6 @@ export const clientPostureSnapshots = sqliteTable("clientPostureSnapshots", { .notNull() .default(false), - collectedAt: integer("collectedAt").notNull() -}); - -export const olms = sqliteTable("olms", { - olmId: text("id").primaryKey(), - secretHash: text("secretHash").notNull(), - dateCreated: text("dateCreated").notNull(), - version: text("version"), - agent: text("agent"), - name: text("name"), - clientId: integer("clientId").references(() => clients.clientId, { - // we will switch this depending on the current org it wants to connect to - onDelete: "set null" - }), - userId: text("userId").references(() => users.userId, { - // optionally tied to a user and in this case delete when the user deletes - onDelete: "cascade" - }), - archived: integer("archived", { mode: "boolean" }).notNull().default(false) -}); - -export const currentFingerprint = sqliteTable("currentFingerprint", { - fingerprintId: integer("id").primaryKey({ autoIncrement: true }), - - olmId: text("olmId") - .references(() => olms.olmId, { onDelete: "cascade" }) - .notNull(), - - firstSeen: integer("firstSeen").notNull(), - lastSeen: integer("lastSeen").notNull(), - - username: text("username"), - hostname: text("hostname"), - platform: text("platform"), - osVersion: text("osVersion"), - kernelVersion: text("kernelVersion"), - arch: text("arch"), - deviceModel: text("deviceModel"), - serialNumber: text("serialNumber"), - platformFingerprint: text("platformFingerprint") -}); - -export const fingerprintSnapshots = sqliteTable("fingerprintSnapshots", { - snapshotId: integer("id").primaryKey({ autoIncrement: true }), - - fingerprintId: integer("fingerprintId") - .references(() => currentFingerprint.fingerprintId, { - onDelete: "cascade" - }) - .notNull(), - - username: text("username"), - hostname: text("hostname"), - platform: text("platform"), - osVersion: text("osVersion"), - kernelVersion: text("kernelVersion"), - arch: text("arch"), - deviceModel: text("deviceModel"), - serialNumber: text("serialNumber"), - platformFingerprint: text("platformFingerprint"), - hash: text("hash").notNull(), collectedAt: integer("collectedAt").notNull() }); diff --git a/server/routers/olm/fingerprintingUtils.ts b/server/routers/olm/fingerprintingUtils.ts index eba64601..1462ce86 100644 --- a/server/routers/olm/fingerprintingUtils.ts +++ b/server/routers/olm/fingerprintingUtils.ts @@ -3,17 +3,32 @@ import { encodeHexLowerCase } from "@oslojs/encoding"; import { currentFingerprint, db, fingerprintSnapshots, Olm } from "@server/db"; import { desc, eq } from "drizzle-orm"; -function fingerprintHash(fp: any): string { +function fingerprintSnapshotHash(fingerprint: any, postures: any): string { const canonical = { - username: fp.username ?? null, - hostname: fp.hostname ?? null, - platform: fp.platform ?? null, - osVersion: fp.osVersion ?? null, - kernelVersion: fp.kernelVersion ?? null, - arch: fp.arch ?? null, - deviceModel: fp.deviceModel ?? null, - serialNumber: fp.serialNumber ?? null, - platformFingerprint: fp.platformFingerprint ?? null + username: fingerprint.username ?? null, + hostname: fingerprint.hostname ?? null, + platform: fingerprint.platform ?? null, + osVersion: fingerprint.osVersion ?? null, + kernelVersion: fingerprint.kernelVersion ?? null, + arch: fingerprint.arch ?? null, + deviceModel: fingerprint.deviceModel ?? null, + serialNumber: fingerprint.serialNumber ?? null, + platformFingerprint: fingerprint.platformFingerprint ?? null, + + biometricsEnabled: postures.biometricsEnabled ?? false, + diskEncrypted: postures.diskEncrypted ?? false, + firewallEnabled: postures.firewallEnabled ?? false, + autoUpdatesEnabled: postures.autoUpdatesEnabled ?? false, + tpmAvailable: postures.tpmAvailable ?? false, + + windowsDefenderEnabled: postures.windowsDefenderEnabled ?? false, + + macosSipEnabled: postures.macosSipEnabled ?? false, + macosGatekeeperEnabled: postures.macosGatekeeperEnabled ?? false, + macosFirewallStealthMode: postures.macosFirewallStealthMode ?? false, + + linuxAppArmorEnabled: postures.linuxAppArmorEnabled ?? false, + linuxSELinuxEnabled: postures.linuxSELinuxEnabled ?? false }; return encodeHexLowerCase( @@ -21,14 +36,23 @@ function fingerprintHash(fp: any): string { ); } -export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { - if (!fingerprint || !olm.olmId || Object.keys(fingerprint).length < 1) { +export async function handleFingerprintInsertion( + olm: Olm, + fingerprint: any, + postures: any +) { + if ( + !olm?.olmId || + !fingerprint || + !postures || + Object.keys(fingerprint).length === 0 || + Object.keys(postures).length === 0 + ) { return; } - const hash = fingerprintHash(fingerprint); - const now = Math.floor(Date.now() / 1000); + const hash = fingerprintSnapshotHash(fingerprint, postures); const [current] = await db .select() @@ -43,7 +67,9 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { olmId: olm.olmId, firstSeen: now, lastSeen: now, + lastCollectedAt: now, + // fingerprint username: fingerprint.username, hostname: fingerprint.hostname, platform: fingerprint.platform, @@ -52,7 +78,22 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { arch: fingerprint.arch, deviceModel: fingerprint.deviceModel, serialNumber: fingerprint.serialNumber, - platformFingerprint: fingerprint.platformFingerprint + platformFingerprint: fingerprint.platformFingerprint, + + biometricsEnabled: postures.biometricsEnabled, + diskEncrypted: postures.diskEncrypted, + firewallEnabled: postures.firewallEnabled, + autoUpdatesEnabled: postures.autoUpdatesEnabled, + tpmAvailable: postures.tpmAvailable, + + windowsDefenderEnabled: postures.windowsDefenderEnabled, + + macosSipEnabled: postures.macosSipEnabled, + macosGatekeeperEnabled: postures.macosGatekeeperEnabled, + macosFirewallStealthMode: postures.macosFirewallStealthMode, + + linuxAppArmorEnabled: postures.linuxAppArmorEnabled, + linuxSELinuxEnabled: postures.linuxSELinuxEnabled }) .returning(); @@ -69,6 +110,21 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { serialNumber: fingerprint.serialNumber, platformFingerprint: fingerprint.platformFingerprint, + biometricsEnabled: postures.biometricsEnabled, + diskEncrypted: postures.diskEncrypted, + firewallEnabled: postures.firewallEnabled, + autoUpdatesEnabled: postures.autoUpdatesEnabled, + tpmAvailable: postures.tpmAvailable, + + windowsDefenderEnabled: postures.windowsDefenderEnabled, + + macosSipEnabled: postures.macosSipEnabled, + macosGatekeeperEnabled: postures.macosGatekeeperEnabled, + macosFirewallStealthMode: postures.macosFirewallStealthMode, + + linuxAppArmorEnabled: postures.linuxAppArmorEnabled, + linuxSELinuxEnabled: postures.linuxSELinuxEnabled, + hash, collectedAt: now }); @@ -76,7 +132,6 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { return; } - // Get most recent snapshot hash const [latestSnapshot] = await db .select({ hash: fingerprintSnapshots.hash }) .from(fingerprintSnapshots) @@ -87,7 +142,6 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { const changed = !latestSnapshot || latestSnapshot.hash !== hash; if (changed) { - // Insert snapshot if it has changed await db.insert(fingerprintSnapshots).values({ fingerprintId: current.fingerprintId, @@ -101,15 +155,30 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { serialNumber: fingerprint.serialNumber, platformFingerprint: fingerprint.platformFingerprint, + biometricsEnabled: postures.biometricsEnabled, + diskEncrypted: postures.diskEncrypted, + firewallEnabled: postures.firewallEnabled, + autoUpdatesEnabled: postures.autoUpdatesEnabled, + tpmAvailable: postures.tpmAvailable, + + windowsDefenderEnabled: postures.windowsDefenderEnabled, + + macosSipEnabled: postures.macosSipEnabled, + macosGatekeeperEnabled: postures.macosGatekeeperEnabled, + macosFirewallStealthMode: postures.macosFirewallStealthMode, + + linuxAppArmorEnabled: postures.linuxAppArmorEnabled, + linuxSELinuxEnabled: postures.linuxSELinuxEnabled, + hash, collectedAt: now }); - // Update current fingerprint fully await db .update(currentFingerprint) .set({ lastSeen: now, + lastCollectedAt: now, username: fingerprint.username, hostname: fingerprint.hostname, @@ -119,11 +188,25 @@ export async function handleFingerprintInsertion(olm: Olm, fingerprint: any) { arch: fingerprint.arch, deviceModel: fingerprint.deviceModel, serialNumber: fingerprint.serialNumber, - platformFingerprint: fingerprint.platformFingerprint + platformFingerprint: fingerprint.platformFingerprint, + + biometricsEnabled: postures.biometricsEnabled, + diskEncrypted: postures.diskEncrypted, + firewallEnabled: postures.firewallEnabled, + autoUpdatesEnabled: postures.autoUpdatesEnabled, + tpmAvailable: postures.tpmAvailable, + + windowsDefenderEnabled: postures.windowsDefenderEnabled, + + macosSipEnabled: postures.macosSipEnabled, + macosGatekeeperEnabled: postures.macosGatekeeperEnabled, + macosFirewallStealthMode: postures.macosFirewallStealthMode, + + linuxAppArmorEnabled: postures.linuxAppArmorEnabled, + linuxSELinuxEnabled: postures.linuxSELinuxEnabled }) .where(eq(currentFingerprint.fingerprintId, current.fingerprintId)); } else { - // No change, so only bump lastSeen await db .update(currentFingerprint) .set({ lastSeen: now }) diff --git a/server/routers/olm/handleOlmPingMessage.ts b/server/routers/olm/handleOlmPingMessage.ts index 6ebbceb9..b87f49d2 100644 --- a/server/routers/olm/handleOlmPingMessage.ts +++ b/server/routers/olm/handleOlmPingMessage.ts @@ -1,5 +1,5 @@ import { disconnectClient, getClientConfigVersion } from "#dynamic/routers/ws"; -import { clientPostureSnapshots, db, currentFingerprint } from "@server/db"; +import { db } from "@server/db"; import { MessageHandler } from "@server/routers/ws"; import { clients, olms, Olm } from "@server/db"; import { eq, lt, isNull, and, or } from "drizzle-orm"; @@ -215,36 +215,11 @@ export const handleOlmPingMessage: MessageHandler = async (context) => { .set({ archived: false }) .where(eq(olms.olmId, olm.olmId)); } - - await handleFingerprintInsertion(olm, fingerprint); } catch (error) { logger.error("Error handling ping message", { error }); } - const now = Math.floor(Date.now() / 1000); - - if (postures && olm.clientId) { - await db.insert(clientPostureSnapshots).values({ - clientId: olm.clientId, - - biometricsEnabled: postures?.biometricsEnabled, - diskEncrypted: postures?.diskEncrypted, - firewallEnabled: postures?.firewallEnabled, - autoUpdatesEnabled: postures?.autoUpdatesEnabled, - tpmAvailable: postures?.tpmAvailable, - - windowsDefenderEnabled: postures?.windowsDefenderEnabled, - - macosSipEnabled: postures?.macosSipEnabled, - macosGatekeeperEnabled: postures?.macosGatekeeperEnabled, - macosFirewallStealthMode: postures?.macosFirewallStealthMode, - - linuxAppArmorEnabled: postures?.linuxAppArmorEnabled, - linuxSELinuxEnabled: postures?.linuxSELinuxEnabled, - - collectedAt: now - }); - } + await handleFingerprintInsertion(olm, fingerprint, postures); return { message: { diff --git a/server/routers/olm/handleOlmRegisterMessage.ts b/server/routers/olm/handleOlmRegisterMessage.ts index 82d4cdb9..958c4568 100644 --- a/server/routers/olm/handleOlmRegisterMessage.ts +++ b/server/routers/olm/handleOlmRegisterMessage.ts @@ -1,9 +1,4 @@ -import { - clientPostureSnapshots, - db, - currentFingerprint, - orgs -} from "@server/db"; +import { db, orgs } from "@server/db"; import { MessageHandler } from "@server/routers/ws"; import { clients, @@ -20,6 +15,7 @@ import { encodeHexLowerCase } from "@oslojs/encoding"; import { sha256 } from "@oslojs/crypto/sha2"; import { buildSiteConfigurationForOlmClient } from "./buildConfiguration"; import { OlmErrorCodes, sendOlmError } from "./error"; +import { handleFingerprintInsertion } from "./fingerprintingUtils"; export const handleOlmRegisterMessage: MessageHandler = async (context) => { logger.info("Handling register olm message!"); @@ -50,85 +46,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => { return; } - if (fingerprint) { - const [existingFingerprint] = await db - .select() - .from(currentFingerprint) - .where(eq(currentFingerprint.olmId, olm.olmId)) - .limit(1); - - if (!existingFingerprint) { - await db.insert(currentFingerprint).values({ - olmId: olm.olmId, - firstSeen: now, - lastSeen: now, - - username: fingerprint.username, - hostname: fingerprint.hostname, - platform: fingerprint.platform, - osVersion: fingerprint.osVersion, - kernelVersion: fingerprint.kernelVersion, - arch: fingerprint.arch, - deviceModel: fingerprint.deviceModel, - serialNumber: fingerprint.serialNumber, - platformFingerprint: fingerprint.platformFingerprint - }); - } else { - const hasChanges = - existingFingerprint.username !== fingerprint.username || - existingFingerprint.hostname !== fingerprint.hostname || - existingFingerprint.platform !== fingerprint.platform || - existingFingerprint.osVersion !== fingerprint.osVersion || - existingFingerprint.kernelVersion !== - fingerprint.kernelVersion || - existingFingerprint.arch !== fingerprint.arch || - existingFingerprint.deviceModel !== fingerprint.deviceModel || - existingFingerprint.serialNumber !== fingerprint.serialNumber || - existingFingerprint.platformFingerprint !== - fingerprint.platformFingerprint; - - if (hasChanges) { - await db - .update(currentFingerprint) - .set({ - lastSeen: now, - username: fingerprint.username, - hostname: fingerprint.hostname, - platform: fingerprint.platform, - osVersion: fingerprint.osVersion, - kernelVersion: fingerprint.kernelVersion, - arch: fingerprint.arch, - deviceModel: fingerprint.deviceModel, - serialNumber: fingerprint.serialNumber, - platformFingerprint: fingerprint.platformFingerprint - }) - .where(eq(currentFingerprint.olmId, olm.olmId)); - } - } - } - - if (postures) { - await db.insert(clientPostureSnapshots).values({ - clientId: olm.clientId, - - biometricsEnabled: postures?.biometricsEnabled, - diskEncrypted: postures?.diskEncrypted, - firewallEnabled: postures?.firewallEnabled, - autoUpdatesEnabled: postures?.autoUpdatesEnabled, - tpmAvailable: postures?.tpmAvailable, - - windowsDefenderEnabled: postures?.windowsDefenderEnabled, - - macosSipEnabled: postures?.macosSipEnabled, - macosGatekeeperEnabled: postures?.macosGatekeeperEnabled, - macosFirewallStealthMode: postures?.macosFirewallStealthMode, - - linuxAppArmorEnabled: postures?.linuxAppArmorEnabled, - linuxSELinuxEnabled: postures?.linuxSELinuxEnabled, - - collectedAt: now - }); - } + await handleFingerprintInsertion(olm, fingerprint, postures); if ( (olmVersion && olm.version !== olmVersion) ||