audit-labs/audit-tools
A collection of scripts, queries, and other goodies you can use in an audit.
clone: git clone https://gitbay.org/audit-labs/audit-tools.git
fbf7718daa9030664bc62118541eb47000973d04
verified · cmc
author: Christian Cleberg <hello@cleberg.net> · 2026-07-29T04:21:42Z
applications/aws/aws_password_policy/evaluate_policy.py | 16 ++++++++-------- applications/github/audit.py | 2 +- applications/github/collectors/audit_log.py | 2 +- project_management/dash/app.py | 2 +- ruff.toml | 14 ++++++++++++++ sampling/audit_sample.py | 4 +--- sampling/sampling_tool/cli.py | 2 +- sampling/sampling_tool/io.py | 3 +-- sampling/sampling_tool/manifest.py | 2 +- sampling/sampling_tool/validation.py | 2 +- sampling/stratified_sample.py | 3 ++- tui/app.py | 2 +- tui/github_runner.py | 4 ++-- tui/gitlab_runner.py | 4 ++-- 14 files changed, 37 insertions(+), 25 deletions(-) old mode 100644 new mode 100755 @@ -21,7 +21,7 @@ import json import sys from datetime import datetime, timezone from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Any # ---------------------------------------------------------------------- # Mapping of the 10 password‑policy fields we care about @@ -49,7 +49,7 @@ def utc_now() -> datetime: return datetime.datetime.now(timezone.utc) -def prompt_expected(field_type: str, description: str) -> Optional[Any]: +def prompt_expected(field_type: str, description: str) -> Any | None: """ Ask the auditor for the expected value. Returns: @@ -78,7 +78,7 @@ def prompt_expected(field_type: str, description: str) -> Optional[Any]: return raw -def evaluate(expect: Optional[Any], actual: Any, field_type: str) -> str: +def evaluate(expect: Any | None, actual: Any, field_type: str) -> str: """Return PASS / FAIL / N/A.""" if expect is None: return "N/A" @@ -89,7 +89,7 @@ def evaluate(expect: Optional[Any], actual: Any, field_type: str) -> str: return "FAIL" -def load_json(path: Path) -> Dict[str, Any]: +def load_json(path: Path) -> dict[str, Any]: """Read the JSON file generated by the Bash script.""" try: with path.open("r", encoding="utf-8") as fh: @@ -100,8 +100,8 @@ def load_json(path: Path) -> Dict[str, Any]: def write_csv( out_path: Path, - metadata: Dict[str, Any], - rows: List[List[Any]], + metadata: dict[str, Any], + rows: list[list[Any]], ) -> None: """Write the CSV report, including a metadata header block.""" with out_path.open("w", newline="", encoding="utf-8") as csvfile: @@ -136,7 +136,7 @@ def main() -> None: # -------------------------------------------------------------- # 1. Prompt the auditor for expectations # -------------------------------------------------------------- - expectations: Dict[str, Optional[Any]] = {} + expectations: dict[str, Any | None] = {} print("\n=== Expected / Minimum Values (press <Enter> for N/A) ===\n") for _, key, friendly, typ in POLICY_FIELDS: expectations[key] = prompt_expected(typ, friendly) @@ -144,7 +144,7 @@ def main() -> None: # -------------------------------------------------------------- # 2. Build the CSV rows (including PASS/FAIL) # -------------------------------------------------------------- - csv_rows: List[List[Any]] = [] + csv_rows: list[list[Any]] = [] for rule_no, key, friendly, typ in POLICY_FIELDS: expected = expectations[key] actual = policy.get(key, "(missing)") @@ -34,7 +34,7 @@ import sys from datetime import date import config -from collectors import members, branch_protections, commits, audit_log +from collectors import audit_log, branch_protections, commits, members from reporters import csv_reporter @@ -5,9 +5,9 @@ Requires GitHub Enterprise Cloud. Skips gracefully with a warning if not available. """ -from datetime import date, datetime, timezone, timedelta import json import sys +from datetime import date, datetime, timedelta, timezone import requests @@ -3,9 +3,9 @@ Extensible dashboard for project status. """ # Import packages -from dash import Dash, html, dcc import pandas as pd import plotly.express as px +from dash import Dash, dcc, html # Incorporate data df = pd.read_excel("project_data.xlsx") new file mode 100644 @@ -0,0 +1,14 @@ +# Ruff configuration for audit-tools. +# +# A few lint rules are disabled because they flag patterns this project uses +# deliberately: +# +# BLE001 - The audit collectors and their CLI wrappers intentionally catch +# broad exceptions so that one failing check never aborts a whole +# audit run. The error is reported and collection continues. +# DTZ011 - date.today() is used to build human-facing, date-stamped output +# folder names, where the local date is the intended value. +# S112 - try/except/continue is used to skip resources that are unavailable +# during collection (e.g. a repo without the requested branch). +[lint] +ignore = ["BLE001", "DTZ011", "S112"] old mode 100644 new mode 100755 @@ -1,15 +1,13 @@ #!/usr/bin/env python3 """Command-line entrypoint for the audit sampling tool.""" -from pathlib import Path import sys - +from pathlib import Path if __package__ is None or __package__ == "": sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from sampling.sampling_tool.cli import main - if __name__ == "__main__": raise SystemExit(main()) @@ -2,11 +2,11 @@ from __future__ import annotations +import sys from argparse import ArgumentParser, Namespace from datetime import datetime, timezone from pathlib import Path from types import SimpleNamespace -import sys import pandas as pd @@ -2,12 +2,11 @@ from __future__ import annotations -from pathlib import Path import hashlib +from pathlib import Path import pandas as pd - SUPPORTED_EXCEL_SUFFIXES = {".xlsx", ".xls", ".xlsm"} @@ -2,8 +2,8 @@ from __future__ import annotations -from pathlib import Path import json +from pathlib import Path from . import __version__ @@ -69,7 +69,7 @@ def validate_and_prepare(population: pd.DataFrame, options) -> ValidationResult: keep=False ) duplicate_rows = working.loc[nonblank_ids].loc[duplicate_mask].copy() - duplicate_id_count = int(len(duplicate_rows)) + duplicate_id_count = len(duplicate_rows) if duplicate_id_count: if options.dedupe_id == "fail": raise AuditSamplingError( @@ -1,7 +1,8 @@ # Import packages -import pandas as pd import math +import pandas as pd + # Load data df = pd.read_csv("FILENAME_GOES_HERE.csv") @@ -226,7 +226,7 @@ class RunScreen(Screen): keys, lambda ev: self.app.call_from_thread(self._handle_event, ev), ) - except Exception as e: # noqa: BLE001 - report unexpected failures in the UI + except Exception as e: self.app.call_from_thread(self._log, f"[red]Run failed:[/] {e}") finally: self.app.call_from_thread(self._finish) @@ -147,7 +147,7 @@ def run_audit( on_event(ProgressEvent("fetch", "Repo collaborators (shared cache)")) try: repo_collabs = members.fetch_repo_collaborators(org, cfg) - except Exception as e: # noqa: BLE001 - surface, keep going + except Exception as e: on_event( ProgressEvent( "error", "Repo collaborators (shared cache)", message=str(e) @@ -165,7 +165,7 @@ def run_audit( rows = c.fn(org, cfg, branch) else: rows = c.fn(org, cfg) - except Exception as e: # noqa: BLE001 - one bad check shouldn't kill the run + except Exception as e: on_event(ProgressEvent("error", c.label, message=str(e))) sections.append((c.label, 0)) continue @@ -136,7 +136,7 @@ def run_audit( on_event(ProgressEvent("fetch", "Projects (shared cache)")) try: project_cache = projects.fetch_projects(group, cfg) - except Exception as e: # noqa: BLE001 - surface, keep going + except Exception as e: on_event(ProgressEvent("error", "Projects (shared cache)", message=str(e))) project_cache = [] @@ -148,7 +148,7 @@ def run_audit( rows = c.fn(group, cfg, project_cache or []) else: rows = c.fn(group, cfg) - except Exception as e: # noqa: BLE001 - one bad check shouldn't kill the run + except Exception as e: on_event(ProgressEvent("error", c.label, message=str(e))) sections.append((c.label, 0)) continue