-- Schema für minimale Metadatenhaltung (SQLite-kompatibel) -- Profil: Minimal — externe .htpasswd, direkte ansible-playbook CLI, SSH-Keys nur abgelegt -- Hinweis: Keine sensitiven Secrets oder Passwörter werden in dieser DB gespeichert. -- Erweiterung: Automatisches Host-Onboarding (Strict Ops-First Policy) PRAGMA foreign_keys = ON; CREATE TABLE playbooks ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, filename TEXT NOT NULL UNIQUE, uploaded_by TEXT, uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE runs ( id TEXT PRIMARY KEY, playbook_id INTEGER NOT NULL, inventory TEXT, extra_vars_json TEXT, -- JSON-codierte Extra-Variablen tags_json TEXT, -- JSON-codierte Tags become INTEGER NOT NULL DEFAULT 0, status TEXT NOT NULL, -- queued|running|success|failed exit_code INTEGER, started_at DATETIME DEFAULT CURRENT_TIMESTAMP, finished_at DATETIME, stdout_path TEXT, -- Dateipfad zu stdout stderr_path TEXT, -- Dateipfad zu stderr FOREIGN KEY(playbook_id) REFERENCES playbooks(id) ON DELETE CASCADE ); -- Host-Onboarding: Hosts und Jobs CREATE TABLE hosts ( id INTEGER PRIMARY KEY AUTOINCREMENT, host_identifier TEXT NOT NULL UNIQUE, -- FQDN oder IP port INTEGER NOT NULL DEFAULT 22, fingerprint_sha256 TEXT, -- SHA256 des Host-Keys (nur Fingerprint) fingerprint_status TEXT NOT NULL DEFAULT 'pending', -- pending|verified|mismatch status TEXT NOT NULL DEFAULT 'pending', -- pending|awaiting_approval|onboarded|failed|cancelled description TEXT, requested_by TEXT, approved_by TEXT, approved_at DATETIME, onboarded_at DATETIME, last_error TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME ); CREATE TABLE onboard_jobs ( id TEXT PRIMARY KEY, -- UUID host_id INTEGER NOT NULL, requested_by TEXT NOT NULL, login_user TEXT NOT NULL, desired_user TEXT NOT NULL, options_json TEXT, -- JSON-codierte Optionen/Flags approval_required INTEGER NOT NULL DEFAULT 0, approved_by TEXT, approved_at DATETIME, status TEXT NOT NULL, -- created|queued|running|awaiting_approval|approved|onboarded|failed|cancelled retries INTEGER NOT NULL DEFAULT 0, max_retries INTEGER NOT NULL DEFAULT 3, started_at DATETIME, finished_at DATETIME, error_code TEXT, error_message TEXT, last_fingerprint_sha256 TEXT, -- Fingerprint zuletzt geprüft created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(host_id) REFERENCES hosts(id) ON DELETE CASCADE ); CREATE TABLE ssh_keys ( id INTEGER PRIMARY KEY AUTOINCREMENT, key_id TEXT NOT NULL UNIQUE, host_id INTEGER UNIQUE, -- Pro Host genau ein aktiver Key key_type TEXT NOT NULL, -- ed25519|rsa4096|external public_key TEXT, -- Öffentlicher Schlüssel (optional für extern verwaltete Keys) fingerprint_sha256 TEXT NOT NULL UNIQUE, managed_externally INTEGER NOT NULL DEFAULT 0, -- 0: App erzeugt/verwalten, 1: Ops verwaltet created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(host_id) REFERENCES hosts(id) ON DELETE CASCADE ); CREATE TABLE audit_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, run_id TEXT, onboard_job_id TEXT, host_id INTEGER, category TEXT NOT NULL, message TEXT NOT NULL, metadata_json TEXT, -- JSON-kodierte Zusatzinfos (z. B. Fingerprint-Hash) created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(run_id) REFERENCES runs(id) ON DELETE SET NULL, FOREIGN KEY(onboard_job_id) REFERENCES onboard_jobs(id) ON DELETE SET NULL, FOREIGN KEY(host_id) REFERENCES hosts(id) ON DELETE SET NULL ); CREATE INDEX idx_runs_playbook ON runs(playbook_id); CREATE INDEX idx_runs_status ON runs(status); CREATE INDEX idx_hosts_status ON hosts(status); CREATE INDEX idx_hosts_fingerprint_status ON hosts(fingerprint_status); CREATE INDEX idx_onboard_jobs_host ON onboard_jobs(host_id); CREATE INDEX idx_onboard_jobs_status ON onboard_jobs(status); CREATE INDEX idx_ssh_keys_fingerprint ON ssh_keys(fingerprint_sha256); CREATE INDEX idx_audit_logs_run ON audit_logs(run_id); CREATE INDEX idx_audit_logs_job ON audit_logs(onboard_job_id); CREATE INDEX idx_audit_logs_host ON audit_logs(host_id); -- Alle Betriebsaufgaben (Pflege .htpasswd, TLS, SSH-Key Berechtigungen) liegen außerhalb der Applikation. -- Onboarding-Policy: Privater Schlüssel und Passwörter werden nicht persistiert; nur Fingerprints und Metadaten.