#!/usr/bin/env python3 """Zabbix Low-Level Discovery for centrally checked SSL/TLS targets.""" from __future__ import annotations import argparse import json import sys from pathlib import Path try: from ssl_check import ConfigError, load_targets except ImportError as exc: # pragma: no cover - defensive for odd install paths print(f"Could not import ssl_check.py helpers: {exc}", file=sys.stderr) sys.exit(2) def build_lld(targets: list[dict[str, object]]) -> dict[str, list[dict[str, str]]]: """Convert normalized target dictionaries to Zabbix LLD JSON.""" data: list[dict[str, str]] = [] seen: set[tuple[str, int]] = set() for target in targets: host = str(target["host"]) port = int(target["port"]) key = (host.lower(), port) if key in seen: continue seen.add(key) data.append( { "{#SSL_NAME}": str(target["name"]), "{#SSL_HOST}": host, "{#SSL_PORT}": str(port), "{#SSL_OWNER}": str(target["owner"]), "{#SSL_PROFILE}": str(target["profile"]), } ) return {"data": data} def parse_args(argv: list[str] | None = None) -> argparse.Namespace: """Parse command-line arguments.""" parser = argparse.ArgumentParser(description="Discover SSL/TLS targets for Zabbix LLD.") parser.add_argument("--config", required=True, help="Path to ssl_targets.json") return parser.parse_args(argv) def main(argv: list[str] | None = None) -> int: """Load target config and print Zabbix LLD JSON.""" args = parse_args(argv) try: targets = load_targets(Path(args.config)) print(json.dumps(build_lld(targets), separators=(",", ":"), ensure_ascii=False)) return 0 except ConfigError as exc: print(f"Configuration error: {exc}", file=sys.stderr) return 1 except OSError as exc: print(f"Could not read config: {exc}", file=sys.stderr) return 1 except json.JSONDecodeError as exc: print(f"Invalid JSON in config: {exc}", file=sys.stderr) return 1 if __name__ == "__main__": sys.exit(main())