windows installer fixes
This commit is contained in:
+22
-209
@@ -53,6 +53,21 @@ try:
|
||||
except ImportError:
|
||||
import server_enrollment as enrollment
|
||||
|
||||
try:
|
||||
from src.log_collector import (
|
||||
get_machine_identifier,
|
||||
WindowsLogCollector,
|
||||
LinuxLogCollector,
|
||||
get_log_collector
|
||||
)
|
||||
except ImportError:
|
||||
from log_collector import (
|
||||
get_machine_identifier,
|
||||
WindowsLogCollector,
|
||||
LinuxLogCollector,
|
||||
get_log_collector
|
||||
)
|
||||
|
||||
CONFIG_FILE_NAME = "server_config.json"
|
||||
DEFAULT_DB_FILE = "logar_state.db"
|
||||
EVALUATION_WINDOW_HOURS = 12
|
||||
@@ -915,224 +930,22 @@ def process_ingested_logs(payload: Dict[str, Any], db_path: str, window_hours: i
|
||||
}
|
||||
|
||||
|
||||
# --- Integrated Local Hub Host Log Collector ---
|
||||
|
||||
def get_machine_identifier() -> str:
|
||||
"""Returns the hostname / FQDN of the local server hub host."""
|
||||
fqdn = socket.getfqdn()
|
||||
if fqdn and "." in fqdn and not fqdn.startswith("localhost"):
|
||||
return fqdn
|
||||
|
||||
hostname = socket.gethostname()
|
||||
user_dns_domain = os.environ.get("USERDNSDOMAIN")
|
||||
if user_dns_domain and user_dns_domain.lower() != hostname.lower():
|
||||
return f"{hostname}.{user_dns_domain.lower()}"
|
||||
|
||||
try:
|
||||
host_ip = socket.gethostbyname(hostname)
|
||||
canonical_name = socket.gethostbyaddr(host_ip)[0]
|
||||
if canonical_name and "." in canonical_name and not canonical_name.startswith("localhost"):
|
||||
return canonical_name
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return hostname
|
||||
|
||||
|
||||
def get_local_windows_logs(hours: int = 24, state: Optional[dict] = None) -> list:
|
||||
"""Collects local Windows Application and System event logs."""
|
||||
if win32evtlog is None:
|
||||
return []
|
||||
|
||||
logs = []
|
||||
cutoff_time = datetime.now() - timedelta(hours=hours)
|
||||
machine_id = get_machine_identifier()
|
||||
|
||||
last_record_number = 0
|
||||
sent_record_ids = set()
|
||||
if state:
|
||||
last_record_number = int(state.get("last_record_number", 0))
|
||||
sent_record_ids = set(state.get("sent_record_ids", []))
|
||||
|
||||
sev_map = {
|
||||
1: "ERROR",
|
||||
2: "WARNING",
|
||||
4: "INFO"
|
||||
}
|
||||
|
||||
newest_record_number = 0
|
||||
collected_record_ids = []
|
||||
|
||||
for log_type in ["Application", "System"]:
|
||||
flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ
|
||||
try:
|
||||
hand = win32evtlog.OpenEventLog("localhost", log_type)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
while True:
|
||||
try:
|
||||
events = win32evtlog.ReadEventLog(hand, flags, 0)
|
||||
except Exception:
|
||||
break
|
||||
if not events:
|
||||
break
|
||||
|
||||
for event in events:
|
||||
rec_num = int(event.RecordNumber)
|
||||
if newest_record_number == 0:
|
||||
newest_record_number = rec_num
|
||||
|
||||
if event.TimeGenerated < cutoff_time:
|
||||
break
|
||||
|
||||
if last_record_number > 0 and newest_record_number >= last_record_number:
|
||||
if rec_num <= last_record_number:
|
||||
break
|
||||
|
||||
rec_id = f"{log_type}:{rec_num}:{event.TimeGenerated.isoformat()}"
|
||||
if rec_id in sent_record_ids:
|
||||
continue
|
||||
|
||||
if event.EventType in sev_map:
|
||||
msg = " ".join(event.StringInserts) if event.StringInserts else "Event Log Entry"
|
||||
logs.append({
|
||||
"server": machine_id,
|
||||
"os_type": "windows",
|
||||
"signature": f"{log_type}/{event.SourceName or 'Windows-Event'}",
|
||||
"severity": sev_map[event.EventType],
|
||||
"message": msg[:2048]
|
||||
})
|
||||
collected_record_ids.append(rec_id)
|
||||
|
||||
if events[-1].TimeGenerated < cutoff_time:
|
||||
break
|
||||
if last_record_number > 0 and newest_record_number >= last_record_number and events[-1].RecordNumber <= last_record_number:
|
||||
break
|
||||
|
||||
try:
|
||||
win32evtlog.CloseEventLog(hand)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if state is not None:
|
||||
target_rec = max(newest_record_number, last_record_number)
|
||||
state["last_record_number"] = target_rec
|
||||
state["sent_record_ids"] = (list(sent_record_ids) + collected_record_ids)[-1000:]
|
||||
state["last_run_timestamp"] = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
return logs
|
||||
collector = WindowsLogCollector(state=state, channels=["Application", "System"])
|
||||
return collector.collect_logs(hours=hours)
|
||||
|
||||
|
||||
def get_local_linux_logs(hours: int = 24, state: Optional[dict] = None) -> list:
|
||||
"""Collects local Linux journalctl events."""
|
||||
last_cursor = None
|
||||
last_timestamp_us = 0.0
|
||||
sent_cursors = set()
|
||||
if state:
|
||||
last_cursor = state.get("last_cursor")
|
||||
try:
|
||||
last_timestamp_us = float(state.get("last_timestamp_us", 0))
|
||||
except (ValueError, TypeError):
|
||||
last_timestamp_us = 0.0
|
||||
sent_cursors = set(state.get("sent_cursors", []))
|
||||
|
||||
cmd = ["journalctl", "--since", f"{hours} hours ago", "-p", "info", "--output=json"]
|
||||
result = None
|
||||
|
||||
if last_cursor:
|
||||
cmd_with_cursor = ["journalctl", "--since", f"{hours} hours ago", "--after-cursor", str(last_cursor), "-p", "info", "--output=json"]
|
||||
try:
|
||||
res = subprocess.run(cmd_with_cursor, capture_output=True, text=True, check=False)
|
||||
if res.returncode == 0:
|
||||
result = res
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if result is None:
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
if not result or result.returncode != 0:
|
||||
return []
|
||||
|
||||
logs = []
|
||||
machine_id = get_machine_identifier()
|
||||
cutoff_epoch_us = (datetime.now(timezone.utc) - timedelta(hours=hours)).timestamp() * 1_000_000
|
||||
|
||||
newest_cursor = None
|
||||
newest_timestamp_us = last_timestamp_us
|
||||
collected_cursors = []
|
||||
|
||||
for line in result.stdout.splitlines():
|
||||
line_str = line.strip()
|
||||
if not line_str:
|
||||
continue
|
||||
try:
|
||||
entry = json.loads(line_str)
|
||||
entry_cursor = entry.get("__CURSOR")
|
||||
entry_ts_us_raw = entry.get("__REALTIME_TIMESTAMP")
|
||||
|
||||
entry_ts_us = 0.0
|
||||
if entry_ts_us_raw:
|
||||
try:
|
||||
entry_ts_us = float(entry_ts_us_raw)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if entry_ts_us and entry_ts_us < cutoff_epoch_us:
|
||||
continue
|
||||
|
||||
if entry_cursor and (entry_cursor in sent_cursors or entry_cursor == last_cursor):
|
||||
continue
|
||||
if last_timestamp_us > 0 and entry_ts_us > 0 and entry_ts_us < last_timestamp_us:
|
||||
continue
|
||||
|
||||
if entry_cursor:
|
||||
newest_cursor = entry_cursor
|
||||
collected_cursors.append(entry_cursor)
|
||||
if entry_ts_us > newest_timestamp_us:
|
||||
newest_timestamp_us = entry_ts_us
|
||||
|
||||
priority = int(entry.get("PRIORITY", "6"))
|
||||
if priority > 6:
|
||||
continue
|
||||
|
||||
if priority <= 3:
|
||||
sev = "ERROR"
|
||||
elif priority in (4, 5):
|
||||
sev = "WARNING"
|
||||
else:
|
||||
sev = "INFO"
|
||||
|
||||
logs.append({
|
||||
"server": machine_id,
|
||||
"os_type": "linux",
|
||||
"signature": entry.get("SYSLOG_IDENTIFIER", "unknown"),
|
||||
"severity": sev,
|
||||
"message": entry.get("MESSAGE", "")[:2048]
|
||||
})
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if state is not None:
|
||||
state["last_cursor"] = newest_cursor or last_cursor
|
||||
state["last_timestamp_us"] = max(newest_timestamp_us, last_timestamp_us)
|
||||
state["sent_cursors"] = (list(sent_cursors) + collected_cursors)[-1000:]
|
||||
state["last_run_timestamp"] = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
return logs
|
||||
"""Collects local Linux journalctl / syslog events."""
|
||||
collector = LinuxLogCollector(state=state)
|
||||
return collector.collect_logs(hours=hours)
|
||||
|
||||
|
||||
def get_local_system_logs(hours: int = 24, state: Optional[dict] = None) -> list:
|
||||
"""Platform-agnostic local host log collector."""
|
||||
if sys.platform == "win32":
|
||||
return get_local_windows_logs(hours=hours, state=state)
|
||||
elif sys.platform.startswith("linux"):
|
||||
return get_local_linux_logs(hours=hours, state=state)
|
||||
return []
|
||||
collector = get_log_collector(state=state)
|
||||
return collector.collect_logs(hours=hours)
|
||||
|
||||
|
||||
def run_local_log_collection_cycle(db_path: str, window_hours: int = 12, min_runs: int = 1, state: Optional[dict] = None) -> int:
|
||||
|
||||
Reference in New Issue
Block a user