Skip to main content

audit-report

License: GPL v3 Python

Turns an audit-tools evidence package into a control-mapped, auditor-ready report — Markdown, self-contained HTML, or JSON — driven by declarative rulesets.

audit-tools collects raw CSVs (IAM users, branch protections, security groups…). audit-report reads that package, applies pass/fail rules, maps each result to SOC 2, ISO 27001, and NIST SP 800-53 controls, and produces a report you can hand to an auditor or gate a pipeline on.

Like gh-attest, this tool produces evidence, not a compliance verdict. A failing row means a setting is in a state that does not support a control; the final judgment belongs to the organization and its auditor.

Install

pip install audit-report

To hack on it from a clone instead, see Development.

Usage

Point it at a package directory produced by audit-tools:

# Markdown report to stdout (platform + ruleset auto-detected from the dir name)
audit-report ./output/aws_audit_default_2026-07-29

# All three formats into ./report/
audit-report ./output/github_audit_acme_2026-07-29 --format md,html,json --out report/

# Gate CI: exit non-zero if any high-severity check fails
audit-report ./output/aws_audit_prod_2026-07-29 --fail-on high --out report/

Diff mode — compare two packages

Pass --baseline to report how a package drifted from an earlier one. Both are evaluated with the same ruleset; the report classifies each rule as regressed, fixed, drifted (an ongoing failure whose evidence rows changed), changed, or unchanged — and shows exactly which evidence rows appeared or disappeared.

# How did prod change between two audit runs?
audit-report ./output/aws_audit_prod_2026-07-29 \
  --baseline ./output/aws_audit_prod_2026-06-29 \
  --format md,html --out drift/

# Fail CI if this change regressed any high-severity control
audit-report ./output/aws_audit_prod_2026-07-29 \
  --baseline ./output/aws_audit_prod_2026-06-29 --fail-on high

In diff mode --fail-on gates on regressions at or above the given severity, and output files are named diff.* instead of report.*.

Trend mode — track controls over time

Pass --trend and point at a folder of dated packages (for example audit-tools' output/). Every package in the series is evaluated with the same ruleset and laid out as a timeline — one row per rule, one column per date — so you can watch a control drift in and out of compliance.

# Heatmap of every control across all retained prod packages
audit-report ./output --trend --format html,json --out trend/

# Disambiguate when the folder holds more than one series
audit-report ./output --trend --subject prod --out trend/

The series must share one platform and subject (use --subject to pick one) and contain at least two packages. In trend mode --fail-on reflects the latest package, so it can double as a snapshot gate. Output files are named trend.*.

You can also run it without installing:

python -m audit_report ./output/aws_audit_default_2026-07-29

Options

Flag Description
--baseline PATH Diff mode: report how PACKAGE drifted from this earlier package.
--trend Trend mode: treat PACKAGE as a folder of dated packages and chart each rule over time.
--subject NAME In trend mode, pick one subject when the folder holds several series.
--ruleset PATH Use a specific ruleset instead of the bundled one for the detected platform.
--format md,html,json One or more output formats (default: md).
--out DIR Write report.<ext> files into DIR. Without it, the first format prints to stdout.
--fail-on low|medium|high|none Exit non-zero when a failing finding — or, in diff mode, a regression — meets this severity (default: none).

What a report contains

  • Summary — failing / passing / not-applicable counts.
  • Control coverage matrix — every cited control, its framework, and a worst-wins status rolled up from the rules that reference it. One failing rule marks the control as not fully evidenced.
  • Findings — failures first, then by severity, each with the reason, why it matters, remediation, and the exact evidence rows that failed.

Bundled rulesets

Platform Package prefix Checks include
AWS aws_audit_* Console-user MFA, access-key rotation, root MFA & keys, password policy, open SSH, public S3, CloudTrail logging
GitHub github_audit_* Org 2FA, base permission, secret-scanning push protection, default-branch protection, required reviews
GitLab gitlab_audit_* Force-push on protected branches, code-owner approval, approval-rule strength, public projects, instance password policy, audit logging

Writing your own rules

A ruleset is a YAML file: a platform and a list of rules. Each rule names a CSV table, a check, the controls it maps to, and human-readable text. Point at one with --ruleset.

platform: aws
rules:
  - id: aws.iam.console-mfa
    title: Console users have MFA enabled
    table: iam_users            # <table>.csv inside the package
    severity: high              # high | medium | low
    controls: [SOC2:CC6.1, ISO:A.5.17, NIST:IA-2]
    rationale: A console user without a second factor is one stolen password from access.
    remediation: Enforce MFA for all console users, or remove their console password.
    check:
      type: fail_rows_where     # every matching row is a failure
      when:
        all:
          - {column: console_password, op: is_true}
          - {column: mfa_enabled, op: is_false}

Check types

Type Meaning
fail_rows_where Each row matching when is a failing finding.
fail_if_any_rows The presence of any row (optionally filtered by when) is a failure.
require_any_row Passes only if at least one row satisfies when.
assert_row Checks each condition in require against the first row of a single-row config table.

Condition language — a condition is a leaf {column, op, value}, or one of {all: [...]}, {any: [...]}, {not: ...}. Operators: equals, not_equals, is_true, is_false, in, not_in, gt, gte, lt, lte, empty, not_empty. Control codes referenced by a rule must exist in audit_report/catalog.py.

Continuous integration

Run it on a schedule or in a pipeline to keep evidence current and gate on regressions. See docs/ci.md and the ready-to-copy examples:

The --fail-on exit code (1 = a finding/regression met the threshold, 2 = usage error) lets a workflow separate "the audit found a problem" from "the job is misconfigured".

Stability

audit-report is stable as of v1.0.0 and follows semantic versioning. The JSON report schema — findings carrying their controls and pass / fail / not_applicable status — is a committed contract that control-coverage consumes directly; it will not break without a major-version bump.

Development

pip install -e ".[dev]"
pytest        # run from the project root
ruff check .

License

GPL-3.0-or-later. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

audit_report-1.0.0.tar.gz (47.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

audit_report-1.0.0-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file audit_report-1.0.0.tar.gz.

File metadata

  • Download URL: audit_report-1.0.0.tar.gz
  • Upload date:
  • Size: 47.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for audit_report-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d832cc41bb56ca008a9b98550564c01a0f4b49371bff47a7d35312a5794700bd
MD5 ef41b1bfc8db71e1a5502475eaa2fbda
BLAKE2b-256 366af7769538db24ed2a4e8cfbcb25e0f8ac69b84ecc4ed4ea03c3cb7c861c1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for audit_report-1.0.0.tar.gz:

Publisher: release.yml on audit-labs/audit-report

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file audit_report-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: audit_report-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 47.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for audit_report-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c26087591b7997e021ee44e9c84bff6a071e27b3ae4cbaf0de08dd7bec11cd19
MD5 bd4579999094fa834c38522904d75219
BLAKE2b-256 13a4c43ba78b68e22290710e1640837bb1ee150c58bcc8490434426419872520

See more details on using hashes here.

Provenance

The following attestation bundles were made for audit_report-1.0.0-py3-none-any.whl:

Publisher: release.yml on audit-labs/audit-report

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page