Audit your own estate and track the findings to closure

applied · 80 min · Objective 5.5

Task

Run an internal audit against your lab, gather the evidence the way an auditor would, produce findings in the form an audit committee would receive, and then do the part organisations skip: track them to closure and check whether any recur.

Steps

  1. Define the audit scope and criteria explicitly in /tmp/audit-scope.md: which systems, against which standard, for which period, and what is excluded. An audit with no stated scope produces findings nobody can act on.
  2. Gather evidence the way an auditor does. For one control with a large population (every local account, every sudo rule, every listening port), list the whole population with a command, choose the items to test at random with shuf -n, and record in /tmp/audit-scope.md the population size, the number tested and how they were chosen. The auditor chooses from the full population; the auditee never does.
  3. Perform the audit by testing rather than by recollection, and record every finding in /tmp/findings.csv as id,finding,criteria,evidence,risk,owner,due_date,status.
  4. Write the evidence for each as something reproducible, the command and its output, so the finding can be re-verified by somebody else. A record the system produced outranks a statement that a control exists.
  5. Save the first cycle's findings, one per line, as /tmp/audit-run1.txt. Remediate three of them, and record the change.
  6. Re-run the audit. Confirm the three now pass, and that the re-run produces the same result for everything you did not touch: an audit that gives different answers on consecutive runs is measuring something other than the estate.
  7. Now deliberately reintroduce one of the three, re-run, save that third cycle's findings in the same wording as /tmp/audit-run3.txt, and mark the finding as a REPEAT in /tmp/findings.csv. Record in /tmp/audit-report.md why a repeat finding is a governance failure rather than a technical one.

Verify

python3 - <<'PY'
import csv,re
rows=list(csv.DictReader(open('/tmp/findings.csv')))
assert len(rows)>=6, 'fewer than six findings'
for r in rows:
    assert r['evidence'].strip(), 'no evidence for '+r['id']
    assert r['owner'].strip(), 'no owner for '+r['id']
    assert re.match(r'\d{4}-\d{2}-\d{2}', r['due_date'].strip()), 'no due date for '+r['id']
closed=[r for r in rows if r['status'].strip().lower() in ('closed','remediated')]
assert len(closed)>=3, 'fewer than three findings closed'
rep=[r for r in rows if 'repeat' in r['status'].strip().lower()]
assert rep, 'no repeat finding recorded - reintroduce one and re-run'
print('%d findings, %d closed, %d repeat' % (len(rows),len(closed),len(rep)))
PY
diff <(sort /tmp/audit-run1.txt) <(sort /tmp/audit-run3.txt) | grep -c '^[<>]'
grep -ciE "population|random|shuf" /tmp/audit-scope.md
grep -ciE "governance|recur|control did not" /tmp/audit-report.md

Every finding needs evidence, an owner and a due date, and at least three must close: an audit whose findings are never closed is a report. The repeat finding is the deliberate part: it means the remediation did not hold and nobody noticed, which is what an audit committee most needs to see. The scope grep confirms the tested items were drawn from a stated population.

Notes

The reproducibility check matters more than it looks. An audit that returns different answers on consecutive runs against an unchanged estate is measuring the auditor's attention rather than the controls, and every finding it produces is arguable. The same goes for how items were chosen: a set picked by the team being audited tests only what that team was confident about.

This is an independent study companion for CompTIA Security+ SY0-801 and is not produced by or endorsed by CompTIA.