init
This commit is contained in:
+96
-30
@@ -1,17 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
"""All-in-one: generate seeds, rebuild secondary packs + core/daily, print DGA domains."""
|
||||
"""All-in-one: patch secondary packs + core/daily (DGA seeds or fixed domain lists)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import secrets
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
TOOLS = Path(__file__).resolve().parent
|
||||
LAB_ROOT = TOOLS.parent
|
||||
SOURCE_ROOT = LAB_ROOT / "source"
|
||||
CAMPAIGN_HASH = "34f5121f572d6742703eb84ec2f866a6"
|
||||
|
||||
|
||||
def gen_seed() -> str:
|
||||
@@ -24,20 +27,53 @@ def run(cmd: list[str]) -> None:
|
||||
subprocess.run(cmd, cwd=str(LAB_ROOT), check=True)
|
||||
|
||||
|
||||
def _ignore_junk(_dir: str, names: list[str]) -> set[str]:
|
||||
skip = {"_bak", "__pycache__", ".DS_Store"}
|
||||
return {n for n in names if n in skip or n.endswith(".pyc")}
|
||||
|
||||
|
||||
def ensure_working_tree(root: Path) -> None:
|
||||
"""If web/sync missing under root, copy from source/ (same as new_project --skip-patch)."""
|
||||
camp = root / "web" / CAMPAIGN_HASH
|
||||
sync = root / "sync"
|
||||
if camp.is_dir() and sync.is_dir():
|
||||
return
|
||||
src_web = SOURCE_ROOT / "web"
|
||||
src_sync = SOURCE_ROOT / "sync"
|
||||
if not (src_web / CAMPAIGN_HASH).is_dir() or not src_sync.is_dir():
|
||||
raise SystemExit(
|
||||
f"missing working tree and source template.\n"
|
||||
f"expected: {src_web / CAMPAIGN_HASH} and {src_sync}"
|
||||
)
|
||||
print("=== bootstrap working tree from source/ ===")
|
||||
for src, dst in ((src_web, root / "web"), (src_sync, root / "sync")):
|
||||
if dst.exists():
|
||||
shutil.rmtree(dst)
|
||||
shutil.copytree(src, dst, symlinks=False, ignore=_ignore_junk)
|
||||
print(f"copied {src.relative_to(LAB_ROOT)} -> {dst}")
|
||||
print()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Generate Deployment/Reporting seeds, run patch_secondary_packs → "
|
||||
"patch_core → compute_dga_domains, print final domains."
|
||||
"Patch type0x01 + core/daily. Use either DGA seeds (default random) "
|
||||
"or fixed --deployment-domains / --reporting-domains."
|
||||
)
|
||||
)
|
||||
parser.add_argument("--deployment-seed", help="optional; default: random 32 hex")
|
||||
parser.add_argument("--reporting-seed", help="optional; default: random 32 hex")
|
||||
parser.add_argument(
|
||||
"--deployment-seed",
|
||||
help="optional; default: random 32 hex chars",
|
||||
"--deployment-domains",
|
||||
action="append",
|
||||
default=[],
|
||||
help="fixed Deployment hosts (comma-separated or repeatable)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reporting-seed",
|
||||
help="optional; default: random 32 hex chars",
|
||||
"--reporting-domains",
|
||||
action="append",
|
||||
default=[],
|
||||
help="fixed Reporting hosts (comma-separated or repeatable)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--root",
|
||||
@@ -47,24 +83,29 @@ def main() -> int:
|
||||
parser.add_argument(
|
||||
"--apply",
|
||||
action="store_true",
|
||||
help="pass --apply to patch_secondary_packs and patch_core (write into --root)",
|
||||
help="write into --root web/ + sync/",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--count",
|
||||
type=int,
|
||||
default=5,
|
||||
help="DGA candidates to print per pool (default 5)",
|
||||
help="DGA candidates to print when not using fixed domains (default 5)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.apply and not args.root:
|
||||
raise SystemExit("--apply requires --root <project-dir>")
|
||||
if bool(args.deployment_domains) != bool(args.reporting_domains):
|
||||
raise SystemExit("provide both --deployment-domains and --reporting-domains, or neither")
|
||||
|
||||
if args.apply and args.root:
|
||||
ensure_working_tree(args.root.resolve())
|
||||
|
||||
fixed_mode = bool(args.deployment_domains)
|
||||
dep = args.deployment_seed or gen_seed()
|
||||
rep = args.reporting_seed or gen_seed()
|
||||
if dep == rep:
|
||||
# avoid accidental identical pools
|
||||
while rep == dep:
|
||||
rep = gen_seed()
|
||||
|
||||
@@ -76,6 +117,7 @@ def main() -> int:
|
||||
{
|
||||
"deployment_seed": dep,
|
||||
"reporting_seed": rep,
|
||||
"mode": "fixed_domains" if fixed_mode else "dga",
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
@@ -83,6 +125,7 @@ def main() -> int:
|
||||
)
|
||||
|
||||
print("=== seeds ===")
|
||||
print(f"mode: {'fixed_domains' if fixed_mode else 'dga'}")
|
||||
print(f"deployment: {dep}")
|
||||
print(f"reporting: {rep}")
|
||||
print(f"saved: {seeds_path}")
|
||||
@@ -93,6 +136,12 @@ def main() -> int:
|
||||
py = sys.executable
|
||||
apply = ["--apply"] if args.apply else []
|
||||
root = ["--root", str(args.root.resolve())] if args.root else []
|
||||
domain_args: list[str] = []
|
||||
if fixed_mode:
|
||||
for item in args.deployment_domains:
|
||||
domain_args += ["--deployment-domains", item]
|
||||
for item in args.reporting_domains:
|
||||
domain_args += ["--reporting-domains", item]
|
||||
|
||||
print("=== 1/3 patch_secondary_packs ===")
|
||||
run(
|
||||
@@ -103,6 +152,7 @@ def main() -> int:
|
||||
dep,
|
||||
"--reporting-seed",
|
||||
rep,
|
||||
*domain_args,
|
||||
*root,
|
||||
*apply,
|
||||
]
|
||||
@@ -118,33 +168,49 @@ def main() -> int:
|
||||
dep,
|
||||
"--reporting-seed",
|
||||
rep,
|
||||
*domain_args,
|
||||
*root,
|
||||
*apply,
|
||||
]
|
||||
)
|
||||
print()
|
||||
|
||||
print("=== 3/3 compute_dga_domains ===")
|
||||
result = subprocess.run(
|
||||
[
|
||||
py,
|
||||
str(TOOLS / "compute_dga_domains.py"),
|
||||
"--deployment-seed",
|
||||
dep,
|
||||
"--reporting-seed",
|
||||
rep,
|
||||
"-n",
|
||||
str(args.count),
|
||||
"--json",
|
||||
],
|
||||
cwd=str(LAB_ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
domains = json.loads(result.stdout)
|
||||
domains_path = out_root / "domains.json"
|
||||
domains_path.write_text(json.dumps(domains, indent=2) + "\n")
|
||||
if fixed_mode:
|
||||
# Prefer MANIFEST from patch_core output
|
||||
manifest_path = out_root / "sync" / "MANIFEST.json"
|
||||
if not manifest_path.is_file():
|
||||
manifest_path = LAB_ROOT / "out" / "sync" / "MANIFEST.json"
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
domains = {
|
||||
"mode": "fixed_domains",
|
||||
"deployment": {"seed": dep, "domains": manifest["deployment_domains"]},
|
||||
"reporting": {"seed": rep, "domains": manifest["reporting_domains"]},
|
||||
}
|
||||
domains_path.write_text(json.dumps(domains, indent=2) + "\n")
|
||||
print("=== 3/3 fixed domains ===")
|
||||
else:
|
||||
print("=== 3/3 compute_dga_domains ===")
|
||||
result = subprocess.run(
|
||||
[
|
||||
py,
|
||||
str(TOOLS / "compute_dga_domains.py"),
|
||||
"--deployment-seed",
|
||||
dep,
|
||||
"--reporting-seed",
|
||||
rep,
|
||||
"-n",
|
||||
str(args.count),
|
||||
"--json",
|
||||
],
|
||||
cwd=str(LAB_ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
domains = json.loads(result.stdout)
|
||||
domains["mode"] = "dga"
|
||||
domains_path.write_text(json.dumps(domains, indent=2) + "\n")
|
||||
|
||||
print()
|
||||
print("=== final domains ===")
|
||||
|
||||
Reference in New Issue
Block a user