122 lines
6.2 KiB
MySQL
122 lines
6.2 KiB
MySQL
|
|
-- Migration 058: Create Duo Security tables
|
||
|
|
-- Stores data from both Accounts API (child accounts) and Admin API (users, phones, auth logs, groups, integrations)
|
||
|
|
|
||
|
|
-- ── duo_accounts ─────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_accounts (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
account_id VARCHAR(20) NOT NULL UNIQUE,
|
||
|
|
name VARCHAR(255),
|
||
|
|
api_hostname VARCHAR(255),
|
||
|
|
autotask_company_id BIGINT REFERENCES companies(id) ON DELETE SET NULL,
|
||
|
|
user_count INTEGER DEFAULT 0,
|
||
|
|
integration_count INTEGER DEFAULT 0,
|
||
|
|
edition VARCHAR(50),
|
||
|
|
is_parent BOOLEAN DEFAULT false,
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE,
|
||
|
|
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_accounts_company ON duo_accounts(autotask_company_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_accounts_is_parent ON duo_accounts(is_parent);
|
||
|
|
|
||
|
|
-- ── duo_users ────────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_users (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
user_id VARCHAR(30) NOT NULL UNIQUE,
|
||
|
|
duo_account_id VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
|
||
|
|
username VARCHAR(255),
|
||
|
|
email VARCHAR(255),
|
||
|
|
realname VARCHAR(255),
|
||
|
|
status VARCHAR(50),
|
||
|
|
is_enrolled BOOLEAN DEFAULT false,
|
||
|
|
last_login TIMESTAMP WITHOUT TIME ZONE,
|
||
|
|
last_directory_sync TIMESTAMP WITHOUT TIME ZONE,
|
||
|
|
created TIMESTAMP WITHOUT TIME ZONE,
|
||
|
|
notes TEXT,
|
||
|
|
phones_count INTEGER DEFAULT 0,
|
||
|
|
groups JSONB,
|
||
|
|
aliases JSONB,
|
||
|
|
enable_auto_prompt BOOLEAN DEFAULT true,
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_users_account ON duo_users(duo_account_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_users_status ON duo_users(status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_users_email ON duo_users(email);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_users_enrolled ON duo_users(is_enrolled);
|
||
|
|
|
||
|
|
-- ── duo_phones ───────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_phones (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
phone_id VARCHAR(30) NOT NULL UNIQUE,
|
||
|
|
duo_account_id VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
|
||
|
|
name VARCHAR(255),
|
||
|
|
number VARCHAR(50),
|
||
|
|
type VARCHAR(50),
|
||
|
|
platform VARCHAR(50),
|
||
|
|
model VARCHAR(255),
|
||
|
|
os_version VARCHAR(50),
|
||
|
|
app_version VARCHAR(50),
|
||
|
|
activated BOOLEAN DEFAULT false,
|
||
|
|
last_seen TIMESTAMP WITHOUT TIME ZONE,
|
||
|
|
capabilities JSONB,
|
||
|
|
users JSONB,
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_phones_account ON duo_phones(duo_account_id);
|
||
|
|
|
||
|
|
-- ── duo_auth_logs ────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_auth_logs (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
txid VARCHAR(50) NOT NULL UNIQUE,
|
||
|
|
duo_account_id VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
|
||
|
|
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||
|
|
user_name VARCHAR(255),
|
||
|
|
user_id VARCHAR(30),
|
||
|
|
factor VARCHAR(50),
|
||
|
|
result VARCHAR(50),
|
||
|
|
reason VARCHAR(255),
|
||
|
|
application_name VARCHAR(255),
|
||
|
|
application_key VARCHAR(50),
|
||
|
|
access_device_ip INET,
|
||
|
|
access_device_location JSONB,
|
||
|
|
auth_device_ip INET,
|
||
|
|
auth_device_name VARCHAR(255),
|
||
|
|
event_type VARCHAR(50),
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_account ON duo_auth_logs(duo_account_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_timestamp ON duo_auth_logs(timestamp DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_result ON duo_auth_logs(result);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_user ON duo_auth_logs(user_name);
|
||
|
|
|
||
|
|
-- ── duo_groups ───────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_groups (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
group_id VARCHAR(30) NOT NULL UNIQUE,
|
||
|
|
duo_account_id VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
|
||
|
|
name VARCHAR(255),
|
||
|
|
description TEXT,
|
||
|
|
member_count INTEGER DEFAULT 0,
|
||
|
|
status VARCHAR(50),
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_groups_account ON duo_groups(duo_account_id);
|
||
|
|
|
||
|
|
-- ── duo_integrations ─────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS duo_integrations (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
integration_key VARCHAR(50) NOT NULL UNIQUE,
|
||
|
|
duo_account_id VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
|
||
|
|
name VARCHAR(255),
|
||
|
|
type VARCHAR(100),
|
||
|
|
enabled BOOLEAN DEFAULT true,
|
||
|
|
notes TEXT,
|
||
|
|
synced_at TIMESTAMP WITHOUT TIME ZONE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_duo_integrations_account ON duo_integrations(duo_account_id);
|