audit-labs/audit-tools

A collection of scripts, queries, and other goodies you can use in an audit. audit automation compliance evidence scripts

Commit d4bbf635ef

d4bbf635ef2ad99c0a48aaf32d99b3fcd7d8bd1d

parent: 31f6eb371d

Unsigned

cmc <hello@cleberg.net> · 2026-07-29 04:21 UTC

style: make repo ruff-clean

Resolve ruff check errors across the repo so the lint CI passes:

- Apply ruff autofixes: sort imports (I001), modernize type hints (UP006/
  UP035/UP045), drop a redundant int() cast (RUF046).
- Mark the two shebang scripts executable (EXE001).
- Add ruff.toml ignoring three rules that flag intentional patterns: BLE001
  (collectors deliberately catch broadly so one failing check never aborts a
  run), DTZ011 (local date used for date-stamped output folders), and S112
  (skip unavailable resources during collection). This also lets the inline
  BLE001 noqa comments be removed.

No behavior changes. ruff check and ruff format --check both pass; all tests pass.

Layout: unified · split

applications/aws/aws_password_policy/evaluate_policy.py +8 −8
@@ -21,7 +21,7 @@ import json
2121import sys
2222from datetime import datetime, timezone
2323from pathlib import Path
24from typing import Any, Dict, List, Optional
24from typing import Any
2525
2626# ----------------------------------------------------------------------
2727# Mapping of the 10 password‑policy fields we care about
@@ -49,7 +49,7 @@ def utc_now() -> datetime:
4949 return datetime.datetime.now(timezone.utc)
5050
5151
52def prompt_expected(field_type: str, description: str) -> Optional[Any]:
52def prompt_expected(field_type: str, description: str) -> Any | None:
5353 """
5454 Ask the auditor for the expected value.
5555 Returns:
@@ -78,7 +78,7 @@ def prompt_expected(field_type: str, description: str) -> Optional[Any]:
7878 return raw
7979
8080
81def evaluate(expect: Optional[Any], actual: Any, field_type: str) -> str:
81def evaluate(expect: Any | None, actual: Any, field_type: str) -> str:
8282 """Return PASS / FAIL / N/A."""
8383 if expect is None:
8484 return "N/A"
@@ -89,7 +89,7 @@ def evaluate(expect: Optional[Any], actual: Any, field_type: str) -> str:
8989 return "FAIL"
9090
9191
92def load_json(path: Path) -> Dict[str, Any]:
92def load_json(path: Path) -> dict[str, Any]:
9393 """Read the JSON file generated by the Bash script."""
9494 try:
9595 with path.open("r", encoding="utf-8") as fh:
@@ -100,8 +100,8 @@ def load_json(path: Path) -> Dict[str, Any]:
100100
101101def write_csv(
102102 out_path: Path,
103 metadata: Dict[str, Any],
104 rows: List[List[Any]],
103 metadata: dict[str, Any],
104 rows: list[list[Any]],
105105) -> None:
106106 """Write the CSV report, including a metadata header block."""
107107 with out_path.open("w", newline="", encoding="utf-8") as csvfile:
@@ -136,7 +136,7 @@ def main() -> None:
136136 # --------------------------------------------------------------
137137 # 1. Prompt the auditor for expectations
138138 # --------------------------------------------------------------
139 expectations: Dict[str, Optional[Any]] = {}
139 expectations: dict[str, Any | None] = {}
140140 print("\n=== Expected / Minimum Values (press <Enter> for N/A) ===\n")
141141 for _, key, friendly, typ in POLICY_FIELDS:
142142 expectations[key] = prompt_expected(typ, friendly)
@@ -144,7 +144,7 @@ def main() -> None:
144144 # --------------------------------------------------------------
145145 # 2. Build the CSV rows (including PASS/FAIL)
146146 # --------------------------------------------------------------
147 csv_rows: List[List[Any]] = []
147 csv_rows: list[list[Any]] = []
148148 for rule_no, key, friendly, typ in POLICY_FIELDS:
149149 expected = expectations[key]
150150 actual = policy.get(key, "(missing)")
applications/github/audit.py +1 −1
@@ -34,7 +34,7 @@ import sys
3434from datetime import date
3535
3636import config
37from collectors import members, branch_protections, commits, audit_log
37from collectors import audit_log, branch_protections, commits, members
3838from reporters import csv_reporter
3939
4040
applications/github/collectors/audit_log.py +1 −1
@@ -5,9 +5,9 @@ Requires GitHub Enterprise Cloud. Skips gracefully with a warning if not
55available.
66"""
77
8from datetime import date, datetime, timezone, timedelta
98import json
109import sys
10from datetime import date, datetime, timedelta, timezone
1111
1212import requests
1313
project_management/dash/app.py +1 −1
@@ -3,9 +3,9 @@ Extensible dashboard for project status.
33"""
44
55# Import packages
6from dash import Dash, html, dcc
76import pandas as pd
87import plotly.express as px
8from dash import Dash, dcc, html
99
1010# Incorporate data
1111df = pd.read_excel("project_data.xlsx")
ruff.toml added +14
@@ -0,0 +1,14 @@
1# Ruff configuration for audit-tools.
2#
3# A few lint rules are disabled because they flag patterns this project uses
4# deliberately:
5#
6# BLE001 - The audit collectors and their CLI wrappers intentionally catch
7# broad exceptions so that one failing check never aborts a whole
8# audit run. The error is reported and collection continues.
9# DTZ011 - date.today() is used to build human-facing, date-stamped output
10# folder names, where the local date is the intended value.
11# S112 - try/except/continue is used to skip resources that are unavailable
12# during collection (e.g. a repo without the requested branch).
13[lint]
14ignore = ["BLE001", "DTZ011", "S112"]
sampling/audit_sample.py +1 −3
@@ -1,15 +1,13 @@
11#!/usr/bin/env python3
22"""Command-line entrypoint for the audit sampling tool."""
33
4from pathlib import Path
54import sys
6
5from pathlib import Path
76
87if __package__ is None or __package__ == "":
98 sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
109
1110from sampling.sampling_tool.cli import main
1211
13
1412if __name__ == "__main__":
1513 raise SystemExit(main())
sampling/sampling_tool/cli.py +1 −1
@@ -2,11 +2,11 @@
22
33from __future__ import annotations
44
5import sys
56from argparse import ArgumentParser, Namespace
67from datetime import datetime, timezone
78from pathlib import Path
89from types import SimpleNamespace
9import sys
1010
1111import pandas as pd
1212
sampling/sampling_tool/io.py +1 −2
@@ -2,12 +2,11 @@
22
33from __future__ import annotations
44
5from pathlib import Path
65import hashlib
6from pathlib import Path
77
88import pandas as pd
99
10
1110SUPPORTED_EXCEL_SUFFIXES = {".xlsx", ".xls", ".xlsm"}
1211
1312
sampling/sampling_tool/manifest.py +1 −1
@@ -2,8 +2,8 @@
22
33from __future__ import annotations
44
5from pathlib import Path
65import json
6from pathlib import Path
77
88from . import __version__
99
sampling/sampling_tool/validation.py +1 −1
@@ -69,7 +69,7 @@ def validate_and_prepare(population: pd.DataFrame, options) -> ValidationResult:
6969 keep=False
7070 )
7171 duplicate_rows = working.loc[nonblank_ids].loc[duplicate_mask].copy()
72 duplicate_id_count = int(len(duplicate_rows))
72 duplicate_id_count = len(duplicate_rows)
7373 if duplicate_id_count:
7474 if options.dedupe_id == "fail":
7575 raise AuditSamplingError(
sampling/stratified_sample.py +2 −1
@@ -1,7 +1,8 @@
11# Import packages
2import pandas as pd
32import math
43
4import pandas as pd
5
56# Load data
67df = pd.read_csv("FILENAME_GOES_HERE.csv")
78
tui/app.py +1 −1
@@ -226,7 +226,7 @@ class RunScreen(Screen):
226226 keys,
227227 lambda ev: self.app.call_from_thread(self._handle_event, ev),
228228 )
229 except Exception as e: # noqa: BLE001 - report unexpected failures in the UI
229 except Exception as e:
230230 self.app.call_from_thread(self._log, f"[red]Run failed:[/] {e}")
231231 finally:
232232 self.app.call_from_thread(self._finish)
tui/github_runner.py +2 −2
@@ -147,7 +147,7 @@ def run_audit(
147147 on_event(ProgressEvent("fetch", "Repo collaborators (shared cache)"))
148148 try:
149149 repo_collabs = members.fetch_repo_collaborators(org, cfg)
150 except Exception as e: # noqa: BLE001 - surface, keep going
150 except Exception as e:
151151 on_event(
152152 ProgressEvent(
153153 "error", "Repo collaborators (shared cache)", message=str(e)
@@ -165,7 +165,7 @@ def run_audit(
165165 rows = c.fn(org, cfg, branch)
166166 else:
167167 rows = c.fn(org, cfg)
168 except Exception as e: # noqa: BLE001 - one bad check shouldn't kill the run
168 except Exception as e:
169169 on_event(ProgressEvent("error", c.label, message=str(e)))
170170 sections.append((c.label, 0))
171171 continue
tui/gitlab_runner.py +2 −2
@@ -136,7 +136,7 @@ def run_audit(
136136 on_event(ProgressEvent("fetch", "Projects (shared cache)"))
137137 try:
138138 project_cache = projects.fetch_projects(group, cfg)
139 except Exception as e: # noqa: BLE001 - surface, keep going
139 except Exception as e:
140140 on_event(ProgressEvent("error", "Projects (shared cache)", message=str(e)))
141141 project_cache = []
142142
@@ -148,7 +148,7 @@ def run_audit(
148148 rows = c.fn(group, cfg, project_cache or [])
149149 else:
150150 rows = c.fn(group, cfg)
151 except Exception as e: # noqa: BLE001 - one bad check shouldn't kill the run
151 except Exception as e:
152152 on_event(ProgressEvent("error", c.label, message=str(e)))
153153 sections.append((c.label, 0))
154154 continue