# AWS Account Audit — Sample

**This is an illustrative example.** The estate, findings and figures are invented to show the
shape of an audit that produces a sequence of work. Copy the structure; audit your own
accounts.

The audit is ordered by **blast radius**: what a single compromised credential or a single
mistake could reach. Findings that widen blast radius come first, regardless of how they score
in any framework.

---

## AWS estate audit — August 2026

| | |
|---|---|
| Accounts | 7 |
| Regions in use | 2 (plus resources found in 3 others) |
| Method | Organisation configuration review, identity audit, network review, external scan |
| Verdict | Structure is sound. **Guardrails are largely absent, so the structure is not enforced.** |

## 1. Account structure

| Account | Purpose | Assessment |
|---|---|---|
| Management | Billing, organisation | ⚠️ **Runs 3 workloads.** Should run none. |
| Security | Log archive, findings | ✅ Correct, and logs are genuinely centralised |
| Shared services | DNS, images, CI | ✅ Correct |
| Production A | Customer application | ✅ Correct |
| Production B | Reporting platform | ✅ Correct |
| Development | All non-production | ⚠️ Shared by 4 teams; one team's mistake affects the others |
| Sandbox | Experiments | ⚠️ No budget alert, no expiry on resources |

**The management account running workloads is the structural finding.** It is the account that
sets every guardrail and controls the organisation; a compromise there is a compromise of
everything. It should be reachable by very few people and should host nothing worth attacking.

The three workloads found there are a monitoring stack, a scheduled report and an internal
tool — none of which needed to be there, all of which were placed there because it was the
account that existed first.

## 2. Guardrails — the gap

| Guardrail | Status |
|---|---|
| Service control policies | ❌ **None.** Nothing is prevented at the organisation level. |
| Central identity with per-account roles | ⚠️ Partial — 3 accounts still have local users |
| Organisation-wide audit trail | ✅ Enabled, delivered to the security account |
| Configuration recording | ⚠️ 2 accounts only |
| Budget alerts | ⚠️ 4 of 7 accounts |
| Region restriction | ❌ None — resources found in 3 unused regions |

**No service control policies is the finding that carries the others.** Without them,
every guarantee about the estate depends on nobody making a mistake, including administrators,
including in accounts created next year. Four policies would take an afternoon:

- Deny leaving the organisation
- Deny disabling or altering the audit trail
- Deny use of regions the business does not operate in
- Deny deletion of log archive storage

None of them affect day-to-day work. All of them hold when everything else fails.

The resources found in three unused regions are the practical case: nobody chose to run
anything there, nothing prevented it, and they were found by an audit rather than by a
control.

## 3. Identity, ranked by reachability

| | Finding | Reach |
|---|---|---|
| I1 | 11 long-lived access keys, oldest 3 years | Whatever the key can do, from anywhere, until rotated |
| I2 | 2 keys with administrator permissions | Full account, no MFA, no expiry |
| I3 | 6 roles with wildcard permissions | Broad, and no audit of what they actually use |
| I4 | Local users in 3 accounts | Outside central identity, missed by joiners-and-leavers |
| I5 | Root account has MFA but no alert on use | Root use is invisible until someone looks |

**I2 is the one to fix today.** A long-lived administrator key with no MFA is the credential
that appears in nearly every public breach write-up, because it needs no exploit — only
exposure. Both were found in configuration files on developer machines during interviews.

I3 deserves a note on method. The wildcard roles were compared against 90 days of actual use:
the six roles collectively used 34 distinct permissions out of thousands granted. Replacing
wildcards with what is actually used is mechanical work with the access analyser, and it is
the difference between a compromised role being an incident and being a catastrophe.

## 4. Network

| | Finding | Note |
|---|---|---|
| N1 | Security group open to the world on port 22 | 3 instances, one in Production A |
| N2 | Storage bucket with public read | Contains marketing assets — intentional, but unmarked |
| N3 | No VPC endpoints | All service traffic via NAT gateway |
| N4 | Development VPC peered to Production A | Peered in 2024 for a migration that finished |
| N5 | Default VPCs remain in unused regions | Nothing running, but nothing preventing it |

**N4 undoes the account separation.** Development is shared by four teams and is peered into
production; the strongest boundary in the estate has a door in it, left from work that ended
two years ago.

N3 is a cost finding as well as a routing one — NAT gateway charges are hourly *and* per GB,
and endpoints remove both for traffic that never needed to leave.

## 5. What is already right

- **The security account is correct**, and logs are delivered there rather than kept beside
  the workloads that produce them. An intruder in a workload account cannot edit the evidence.
- **Production A and B are separate accounts**, not separate VPCs in one account.
- **Encryption at rest is on by default** for storage and databases.
- **Infrastructure is described in code** for the two production accounts.
- **The root account has MFA** on every account. The alerting gap in I5 is real, but the
  fundamental control is in place.

## 6. Sequence

| When | Action |
|---|---|
| Today | Delete the 2 administrator access keys · close the 3 open SSH rules |
| This week | Four service control policies · alert on root account use · remove the development-to-production peering |
| Weeks 2–3 | Rotate or eliminate the remaining 9 keys · move the 3 workloads out of the management account · budget alerts on all 7 accounts |
| This month | Local users into central identity · VPC endpoints · configuration recording everywhere |
| This quarter | Replace wildcard permissions with measured usage · separate development per team · delete default VPCs in unused regions |

**Deliberately not recommended:** a third-party cloud security platform. Every finding in this
audit came from the organisation's own configuration and logs. A platform would have presented
the same findings on a nicer page, and it would not have fixed the absence of service control
policies — which is the finding that makes all the others recur.

---

## Notes on using this format

**Order by blast radius.** An open SSH port on a development instance and an administrator key
with no expiry are both "high" in most frameworks. One of them reaches everything.

**Compare granted permissions to used permissions.** It converts "we should apply least
privilege" from a principle into a list, and the list is usually much shorter than anyone
expects.

**Separate structural findings from configuration findings.** Closing an SSH port is a task.
A management account that runs workloads, and a peering connection that joins development to
production, are decisions — and they will be recreated by the next migration unless something
prevents it.
