Replaces MalwareBazaar with theZoo (https://github.com/ytisf/theZoo). theZoo is a public security-research repo with hundreds of malware samples organized by family, password-protected with the well-known 'infected'. No API key, no signup, nothing for an operator to do — which is what zero-touch tier-4 actually means. Changes: - tools/auto_fetch_samples.py: rewrite. Clones theZoo (shallow, ~500 MB) to /var/lib/cis490/theZoo on first run, then for each manifest family without a sha256 it locates a matching Binaries/<Name> dir, extracts the .zip with password 'infected', picks the largest non-text payload as the binary, sha256s it, stages at samples/store/<sha256>, and rewrites manifest.toml in place (atomic tempfile + os.replace, stat preserved). Mandatory exit semantic: non-zero if no real samples landed. - scripts/install-tier-3-4.sh: dropped the MB-key resolution chain (env var → local file → bootstrap.wg fetch). Now just runs auto_fetch_samples.py and dies if zero samples land. SKIP_TIER4 remains as the explicit override but is documented as defeating the project. - bootstrap/app.py + __main__.py + etc/cis490-bootstrap.service: removed the /v1/secret/<name> endpoint and the --secrets-root flag. Dead code now that no API key needs distributing. Live-rolled back on the Pi (404 verified post-restart, stale /etc/cis490/secrets dir removed). - scripts/set-malwarebazaar-key.sh: deleted. No MB key means no one-time operator step. - tests/test_bootstrap_secrets.py: deleted (route removed). - AGENTS.md: rewrote tier-4 section to reflect zero-operator model. 148/148 tests pass. Bootstrap service rolled back live.
65 lines
1.8 KiB
Python
65 lines
1.8 KiB
Python
"""``cis490-bootstrap`` launcher.
|
|
|
|
Runs as root (needs CA private key access). Listens on 127.0.0.1:8446
|
|
behind Caddy's ``bootstrap.wg`` site — Caddy terminates TLS, this
|
|
service speaks plain HTTP on loopback only.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import uvicorn
|
|
|
|
from bootstrap.app import make_app
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
p = argparse.ArgumentParser(prog="cis490-bootstrap")
|
|
p.add_argument("--listen-host", default="127.0.0.1")
|
|
p.add_argument("--listen-port", type=int, default=8446)
|
|
p.add_argument(
|
|
"--issuer-script",
|
|
type=Path,
|
|
default=Path("/home/max/.env/wg-pki/scripts/issue-cis490-client-cert.sh"),
|
|
help="Path to the wg-pki leaf-cert mint script.",
|
|
)
|
|
p.add_argument(
|
|
"--issued-root",
|
|
type=Path,
|
|
default=Path("/home/max/.env/wg-pki/issued"),
|
|
help="Where minted tarballs are cached.",
|
|
)
|
|
p.add_argument("--log-level", default="info")
|
|
args = p.parse_args(argv)
|
|
|
|
logging.basicConfig(
|
|
level=getattr(logging, args.log_level.upper(), logging.INFO),
|
|
format="%(asctime)s %(levelname)s %(name)s %(message)s",
|
|
)
|
|
log = logging.getLogger("cis490.bootstrap.main")
|
|
|
|
if not args.issuer_script.exists():
|
|
log.error("issuer script missing: %s", args.issuer_script)
|
|
return 2
|
|
|
|
app = make_app(
|
|
issuer_script=args.issuer_script,
|
|
issued_root=args.issued_root,
|
|
)
|
|
log.info("listening on %s:%d", args.listen_host, args.listen_port)
|
|
uvicorn.run(
|
|
app,
|
|
host=args.listen_host,
|
|
port=args.listen_port,
|
|
log_level=args.log_level,
|
|
access_log=True,
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|