Files
api/services/nginx/app/classes/security_schema_bootstrap.php
T

141 lines
6.3 KiB
PHP

<?php
namespace classes;
class security_schema_bootstrap
{
private static bool $initialized = false;
public static function ensureTables(): void
{
if (self::$initialized) {
return;
}
global $db;
$queries = [
"CREATE TABLE IF NOT EXISTS security_firewall_rules (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
action VARCHAR(16) NOT NULL,
target_type VARCHAR(32) NOT NULL,
target_value VARCHAR(255) NOT NULL,
route_pattern VARCHAR(255) NULL,
priority INT NOT NULL DEFAULT 100,
reason TEXT NULL,
enabled TINYINT(1) NOT NULL DEFAULT 1,
expires_at DATETIME NULL,
metadata_json LONGTEXT NULL,
created_by INT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL,
INDEX idx_security_firewall_rules_active (enabled, deleted_at, expires_at),
INDEX idx_security_firewall_rules_target (target_type, target_value),
INDEX idx_security_firewall_rules_priority (priority)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS security_policy_rules (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
rule_key VARCHAR(64) NOT NULL,
enabled TINYINT(1) NOT NULL DEFAULT 1,
threshold_count INT NOT NULL,
window_seconds INT NOT NULL,
mode VARCHAR(16) NOT NULL DEFAULT 'observe',
exempt_permission_nodes_json LONGTEXT NULL,
updated_by INT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_security_policy_rules_key (rule_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS security_policy_events (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
rule_key VARCHAR(64) NOT NULL,
subject_type VARCHAR(32) NOT NULL,
subject_key VARCHAR(191) NOT NULL,
route_path VARCHAR(255) NULL,
route_template VARCHAR(255) NULL,
method VARCHAR(16) NULL,
source_ip VARCHAR(64) NULL,
customer_number INT NULL,
user_id INT NULL,
subuser_id INT NULL,
metadata_json LONGTEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_security_policy_events_window (rule_key, subject_type, subject_key, created_at),
INDEX idx_security_policy_events_created (created_at),
INDEX idx_security_policy_events_customer (customer_number, created_at),
INDEX idx_security_policy_events_ip (source_ip, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS security_incidents (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
incident_key VARCHAR(191) NOT NULL,
type VARCHAR(64) NOT NULL,
severity VARCHAR(16) NOT NULL DEFAULT 'medium',
status VARCHAR(32) NOT NULL DEFAULT 'open',
title VARCHAR(255) NOT NULL,
source_ip VARCHAR(64) NULL,
customer_number INT NULL,
user_id INT NULL,
subuser_id INT NULL,
route_path VARCHAR(255) NULL,
route_template VARCHAR(255) NULL,
method VARCHAR(16) NULL,
related_rule_id BIGINT UNSIGNED NULL,
related_firewall_rule_id BIGINT UNSIGNED NULL,
occurrence_count INT NOT NULL DEFAULT 1,
metadata_json LONGTEXT NULL,
first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
resolved_by INT NULL,
resolved_at DATETIME NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_security_incidents_key (incident_key),
INDEX idx_security_incidents_status_seen (status, last_seen_at),
INDEX idx_security_incidents_type_seen (type, last_seen_at),
INDEX idx_security_incidents_customer_seen (customer_number, last_seen_at),
INDEX idx_security_incidents_ip_seen (source_ip, last_seen_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS security_incident_notes (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
incident_id BIGINT UNSIGNED NOT NULL,
note TEXT NOT NULL,
created_by INT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_security_incident_notes_incident (incident_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
];
foreach ($queries as $query) {
$db->query($query);
}
self::$initialized = true;
}
public static function tablesExist(): bool
{
global $db;
$database = $db->escape_string($db->getDatabase());
$result = $db->query(
"SELECT COUNT(*) AS count
FROM information_schema.tables
WHERE table_schema = '{$database}'
AND table_name IN (
'security_firewall_rules',
'security_policy_rules',
'security_policy_events',
'security_incidents',
'security_incident_notes'
)"
);
$row = $result ? $result->fetch_assoc() : ['count' => 0];
return (int)($row['count'] ?? 0) === 5;
}
}