From b9242d101425170a0037ab3126b3969913fea4ab Mon Sep 17 00:00:00 2001 From: Gregor Lyttek <107279662+GLyttek@users.noreply.github.com> Date: Tue, 3 Jun 2025 23:44:22 +0200 Subject: [PATCH] Add compliance baseline scanner example --- README.md | 6 +++ compliance/README.md | 12 +++++ compliance/baseline/os_baseline.json | 12 +++++ compliance/scan.py | 72 ++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 compliance/README.md create mode 100644 compliance/baseline/os_baseline.json create mode 100755 compliance/scan.py diff --git a/README.md b/README.md index 48f235a..4ae8dc6 100644 --- a/README.md +++ b/README.md @@ -12,5 +12,11 @@ All scripts are located in the `scripts/` directory. expert opinions using the Groq API. - **testing_local_model.py** – Evaluate local models with Ollama and save the outputs. +- **compliance/scan.py** – Prototype baseline scanner that checks file hashes + against a JSON-defined configuration. See [scripts/README.md](scripts/README.md) for more details on each script. + +The `compliance` directory contains a **prototype** baseline scanner. This +repository does not implement a production-ready compliance monitoring +platform. diff --git a/compliance/README.md b/compliance/README.md new file mode 100644 index 0000000..fc8410a --- /dev/null +++ b/compliance/README.md @@ -0,0 +1,12 @@ +# Compliance Scanner (Prototype) + +This directory contains a simple proof-of-concept script for checking +system configuration files against a baseline hash list. + +The baseline file `baseline/os_baseline.json` defines the expected SHA256 +hash of important files such as `/etc/ssh/sshd_config`. Run `scan.py` to +calculate current hashes, compare them to the baseline, and log the +results in `compliance_logs/`. + +This is **not** a full-featured compliance monitoring platform, but a +minimal example to demonstrate how baseline validation might work. diff --git a/compliance/baseline/os_baseline.json b/compliance/baseline/os_baseline.json new file mode 100644 index 0000000..aefe31a --- /dev/null +++ b/compliance/baseline/os_baseline.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "path": "/etc/ssh/sshd_config", + "sha256": "expectedhash1" + }, + { + "path": "/etc/passwd", + "sha256": "expectedhash2" + } + ] +} diff --git a/compliance/scan.py b/compliance/scan.py new file mode 100755 index 0000000..c70bdbc --- /dev/null +++ b/compliance/scan.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Simplified compliance baseline scanner. + +This script compares system configuration file hashes against a baseline +configuration defined in JSON. It outputs a compliance score and logs +detailed results to `compliance_logs/`. +""" + +import hashlib +import json +import os +from datetime import datetime + +BASELINE_FILE = os.path.join(os.path.dirname(__file__), "baseline", "os_baseline.json") +LOG_DIR = os.path.join(os.path.dirname(__file__), "compliance_logs") + + +def sha256_file(path: str) -> str: + """Return SHA256 hex digest of file contents.""" + h = hashlib.sha256() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(8192), b""): + h.update(chunk) + return h.hexdigest() + + +def load_baseline(path: str) -> dict: + with open(path, "r") as f: + return json.load(f) + + +def check_compliance() -> dict: + baseline = load_baseline(BASELINE_FILE) + results = [] + for entry in baseline.get("files", []): + file_path = entry["path"] + expected_hash = entry.get("sha256") + if not os.path.exists(file_path): + results.append({"path": file_path, "status": "missing"}) + continue + actual_hash = sha256_file(file_path) + status = "match" if actual_hash == expected_hash else "mismatch" + results.append({ + "path": file_path, + "status": status, + "expected": expected_hash, + "actual": actual_hash, + }) + matched = sum(1 for r in results if r["status"] == "match") + total = len(results) + score = (matched / total) * 100 if total else 0 + return {"score": score, "results": results} + + +def log_results(data: dict) -> None: + os.makedirs(LOG_DIR, exist_ok=True) + timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") + log_file = os.path.join(LOG_DIR, f"scan_{timestamp}.json") + with open(log_file, "w") as f: + json.dump(data, f, indent=2) + + +def main(): + report = check_compliance() + print(f"Compliance score: {report['score']:.2f}%") + for r in report["results"]: + print(f"{r['path']}: {r['status']}") + log_results(report) + + +if __name__ == "__main__": + main()