mirror of https://github.com/OISF/suricata
ci: check for enum integer keywords
And generic documentation about it Ticket: 8675pull/16404/head
parent
b47bde6cda
commit
49aefe7093
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Check that each Suricata keyword with the feature "enum uint" has an
|
||||
"enum_values" object in --list-keywords=json output.
|
||||
|
||||
Usage:
|
||||
python3 scripts/check-enum-uint-keywords.py [--suricata-bin PATH]
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
def resolve_suricata_bin(repo_root: Path, configured: Optional[str]) -> Path:
|
||||
if configured:
|
||||
return Path(configured)
|
||||
|
||||
in_path = shutil.which("suricata")
|
||||
if in_path:
|
||||
return Path(in_path)
|
||||
|
||||
candidates = [repo_root / "src" / "suricata", repo_root / "suricata"]
|
||||
for candidate in candidates:
|
||||
if candidate.exists():
|
||||
return candidate
|
||||
|
||||
raise SystemExit(
|
||||
"Unable to find Suricata binary. Use --suricata-bin to provide it."
|
||||
)
|
||||
|
||||
|
||||
def list_keywords_json(suricata_bin: Path) -> list[dict[str, Any]]:
|
||||
"""Return keyword objects from --list-keywords=json output."""
|
||||
proc = subprocess.run(
|
||||
[str(suricata_bin), "--list-keywords=json"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
payload = proc.stdout.strip()
|
||||
if not payload:
|
||||
payload = proc.stderr.strip()
|
||||
|
||||
if not payload:
|
||||
raise SystemExit("No output from suricata --list-keywords=json")
|
||||
|
||||
try:
|
||||
data = json.loads(payload)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise SystemExit(f"Failed to parse JSON output: {exc}") from exc
|
||||
|
||||
r = []
|
||||
for keyword in data:
|
||||
obj = data[keyword]
|
||||
obj["name"] = keyword
|
||||
r.append(obj)
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def has_enum_uint_feature(keyword_obj: dict[str, Any]) -> bool:
|
||||
feature_fields = []
|
||||
if "features" in keyword_obj:
|
||||
for feature in keyword_obj["features"]:
|
||||
if feature == "enum uint":
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def keyword_name(keyword_obj: dict[str, Any]) -> str:
|
||||
for key in ("name", "keyword"):
|
||||
value = keyword_obj.get(key)
|
||||
if isinstance(value, str) and value:
|
||||
return value
|
||||
return "<unknown>"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Check enum-uint keywords expose enum_values object in "
|
||||
"--list-keywords=json output."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"--suricata-bin",
|
||||
default=None,
|
||||
help="Path to Suricata binary (default: auto-detect)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
repo_root = Path(__file__).resolve().parents[1]
|
||||
suricata_bin = resolve_suricata_bin(repo_root, args.suricata_bin)
|
||||
keyword_objects = list_keywords_json(suricata_bin)
|
||||
|
||||
candidates = [obj for obj in keyword_objects if has_enum_uint_feature(obj)]
|
||||
|
||||
if not candidates:
|
||||
print('No keywords found with feature "enum uint".')
|
||||
return 0
|
||||
|
||||
failures: list[str] = []
|
||||
print(f"Checking {len(candidates)} keyword(s) with feature 'enum uint'...\n")
|
||||
|
||||
for obj in candidates:
|
||||
name = keyword_name(obj)
|
||||
enum_values = obj.get("enum_values")
|
||||
ok = isinstance(enum_values, dict)
|
||||
print(f" [{'OK' if ok else 'FAIL'}] {name}")
|
||||
if not ok:
|
||||
failures.append(name)
|
||||
|
||||
if failures:
|
||||
print(f"\n{len(failures)} keyword(s) missing enum_values object:\n")
|
||||
for name in failures:
|
||||
print(f" - {name}")
|
||||
return 1
|
||||
|
||||
print("\nAll checks passed.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Reference in New Issue