wulf-pulse/migrations/089_appgate_tables.sql

151 lines
6.4 KiB
MySQL
Raw Normal View History

-- AppGate SDP integration — Postgres schema.
--
-- Mirrors the slices of Appgate SDP Controller REST API v22.5 that Pulse
-- surfaces for the manager-on-the-go view:
--
-- • Active sessions (current snapshot) -> appgate_active_sessions
-- • On-boarded devices (slowly changing list) -> appgate_devices
-- • Controllers / Gateways -> appgate_appliances
-- • Per-user license consumption -> appgate_license_users
-- • Daily license capacity rollup -> appgate_license_snapshots
-- • Daily login totals (history series) -> appgate_user_logins_daily
-- Current active sessions — replaced each sync (no history beyond appliances log).
CREATE TABLE IF NOT EXISTS appgate_active_sessions (
distinguished_name TEXT PRIMARY KEY,
device_id UUID,
username TEXT,
provider_name TEXT,
hostname TEXT,
os_family TEXT,
os_name TEXT,
os_parent TEXT,
client_version TEXT,
client_type TEXT,
client_support TEXT,
geo_ip_latitude DOUBLE PRECISION,
geo_ip_longitude DOUBLE PRECISION,
gateways JSONB,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_appgate_sessions_username ON appgate_active_sessions(username);
CREATE INDEX IF NOT EXISTS idx_appgate_sessions_provider ON appgate_active_sessions(provider_name);
-- On-boarded devices — persistent inventory. Uses the same soft-delete
-- pattern as qbo_invoices: a full sync tombstones any row not returned.
CREATE TABLE IF NOT EXISTS appgate_devices (
distinguished_name TEXT PRIMARY KEY,
device_id UUID,
username TEXT,
provider_name TEXT,
device_type TEXT,
hostname TEXT,
on_boarded_at TIMESTAMPTZ,
last_seen_at TIMESTAMPTZ,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
is_deleted BOOLEAN NOT NULL DEFAULT false,
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_appgate_devices_username ON appgate_devices(username);
CREATE INDEX IF NOT EXISTS idx_appgate_devices_is_deleted ON appgate_devices(is_deleted);
CREATE INDEX IF NOT EXISTS idx_appgate_devices_last_seen ON appgate_devices(last_seen_at);
-- Appliances (controllers, gateways, log servers, etc.).
CREATE TABLE IF NOT EXISTS appgate_appliances (
id UUID PRIMARY KEY,
name TEXT NOT NULL,
hostname TEXT,
notes TEXT,
version INTEGER,
site TEXT,
site_name TEXT,
activated BOOLEAN,
pending_certificate_renewal BOOLEAN,
tags JSONB,
roles JSONB, -- {controller, gateway, logServer, ...} subset flags
raw JSONB, -- full payload — versioned schema changes
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
is_deleted BOOLEAN NOT NULL DEFAULT false,
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_appgate_appliances_is_deleted ON appgate_appliances(is_deleted);
CREATE INDEX IF NOT EXISTS idx_appgate_appliances_site ON appgate_appliances(site);
-- Per-user license consumption — current snapshot, replaced each sync.
CREATE TABLE IF NOT EXISTS appgate_license_users (
user_distinguished_name TEXT PRIMARY KEY,
username TEXT,
provider_name TEXT,
license_type TEXT,
profile_name TEXT,
created_at TIMESTAMPTZ,
last_seen_at TIMESTAMPTZ,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_appgate_license_users_username ON appgate_license_users(username);
-- Daily license capacity rollup — one row per day, history retained.
CREATE TABLE IF NOT EXISTS appgate_license_snapshots (
snapshot_date DATE PRIMARY KEY,
max_users INTEGER,
max_portal_users INTEGER,
max_service_users INTEGER,
used_users INTEGER,
expiration TIMESTAMPTZ,
license_type INTEGER,
license_version INTEGER,
risk_engine_enabled BOOLEAN,
app_discovery_enabled BOOLEAN,
captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Daily login totals — derived from the rolling 24h /stats/user-logins endpoint.
-- Sync replaces yesterday/today rows; older days never change.
CREATE TABLE IF NOT EXISTS appgate_user_logins_daily (
login_date DATE PRIMARY KEY,
total_logins INTEGER NOT NULL DEFAULT 0,
captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Sync history.
CREATE TABLE IF NOT EXISTS appgate_sync_history (
id SERIAL PRIMARY KEY,
sync_id TEXT NOT NULL,
sync_type TEXT NOT NULL,
triggered_by TEXT NOT NULL,
started_at TIMESTAMPTZ NOT NULL,
completed_at TIMESTAMPTZ,
status TEXT NOT NULL,
sessions_synced INTEGER NOT NULL DEFAULT 0,
devices_synced INTEGER NOT NULL DEFAULT 0,
devices_tombstoned INTEGER NOT NULL DEFAULT 0,
appliances_synced INTEGER NOT NULL DEFAULT 0,
appliances_tombstoned INTEGER NOT NULL DEFAULT 0,
license_users_synced INTEGER NOT NULL DEFAULT 0,
last_error TEXT
);
CREATE INDEX IF NOT EXISTS idx_appgate_sync_history_started ON appgate_sync_history(started_at DESC);
-- Scheduler entries — disabled by default until credentials configured.
-- sync_schedules has no unique constraint on name, so guard with NOT EXISTS.
INSERT INTO sync_schedules (id, name, description, cron_expression, sync_type, is_enabled)
SELECT 'appgate-sessions',
'AppGate Sessions',
'Active session snapshot every 5 minutes during business hours.',
'*/5 11-23 * * 1-5', 'appgate-sessions', false
WHERE NOT EXISTS (SELECT 1 FROM sync_schedules WHERE name = 'AppGate Sessions');
INSERT INTO sync_schedules (id, name, description, cron_expression, sync_type, is_enabled)
SELECT 'appgate-daily',
'AppGate Daily',
'Full AppGate sync — devices, appliances, license, login totals.',
'15 6 * * *', 'appgate-daily', false
WHERE NOT EXISTS (SELECT 1 FROM sync_schedules WHERE name = 'AppGate Daily');