Cloud logging and trails
The control-plane audit trail is the one record of who did what in your cloud — and the first thing an attacker deletes. If they can edit it, you have a log, not evidence. Tamper-resistance is what turns one into the other.
The breach call comes in at 02:00. Someone spun up a fleet of GPU instances in a region you don’t use, billed to a service-account key. Your first instinct is right: pull the control-plane audit trail and reconstruct exactly which identity made which API call, from which IP, in what order. You open the trail — and the relevant hours are gone. Not corrupted, not gaps from an outage. Deleted. The same key that launched the miners had cloudtrail:StopLogging and cloudtrail:DeleteTrail, and the very first thing it did, before touching compute, was turn off the camera. You no longer have an incident timeline. You have a guess.
By the end of this lesson you’ll know why the audit trail is the source of truth for everything that happens in your cloud, and the specific controls that keep an attacker who reaches it from rewriting history.
What the audit trail actually records
There are two log planes in any cloud, and people constantly confuse them. Data-plane logs record traffic through your services: HTTP requests to a load balancer, reads on an object, queries to a database. Control-plane logs — AWS CloudTrail, GCP Cloud Audit Logs, Azure Activity Log — record management actions against the cloud API itself: who called CreateUser, who attached a policy, who changed a security group, who rotated a key, who deleted a bucket. When you are reconstructing a breach, the control-plane trail is the one that matters, because every privilege escalation and every act of persistence is, underneath, a sequence of authenticated API calls.
A single CloudTrail event is a structured record with the fields an investigator actually needs: eventTime, eventName (the API called), userIdentity (the IAM principal, including assumed-role session and the originating account), sourceIPAddress, userAgent, the request parameters, and the response. Read those five fields across a few thousand events and you can answer the only question that matters at 02:00: which identity did this, when, from where, and what did it touch. This is why the trail is called the source of truth — it is the one place where the cloud itself, not your application, attests to what happened.
The catch is default coverage. Out of the box, a trail typically logs management events but not data events — an attacker reading every object out of an S3 bucket generates zero control-plane records unless you explicitly enabled data-event logging, which is off by default partly because it is voluminous and billed per event. The senior reflex: know precisely what your trail does and does not capture before the incident, because “we assumed S3 GetObject was logged” is a discovery you do not want to make while exfiltration is in progress.
Why the trail is the attacker’s first target
Think like the adversary for one paragraph. You have compromised a credential. Your goals are escalate, persist, and act — mine crypto, exfiltrate data, ransom the account. Every one of those leaves API-call evidence in the trail. So the highest-leverage move you can make, before anything noisy, is to blind the defender: stop the trail, delete it, or stop it from delivering to its destination. This is not theoretical — “defense evasion via impairing logging” is a named, catalogued technique in the MITRE ATT&CK cloud matrix precisely because it is the standard opening move. A trail an attacker can switch off is a smoke detector with an accessible off switch: it protects you exactly until the moment you need it.
Tamper-resistance: turning a log into evidence
The difference between a log and evidence is whether the person being recorded could have altered it. Four controls, layered, get you there.
Deliver to immutable, append-only storage. The trail should write to object storage with an object-lock / retention policy in compliance mode, so that even an account administrator cannot delete or overwrite an object before its retention period expires. Append-only is the property that defeats “edit history” — you can add records, never rewrite them.
Put the sink in a separate account. This is the single highest-value architectural move. A compromised principal in the workload account should not have IAM permissions over the log archive at all. Centralize trails from every account into one dedicated, locked-down logging account whose only job is to receive and retain. Now blinding the trail requires compromising a second, far smaller, far more tightly controlled account — you have raised the cost of evasion by an order of magnitude.
Verify integrity cryptographically. Enable log-file integrity validation (CloudTrail signs each delivered file and emits a hash-chained digest). At investigation time you can prove a file was not modified after delivery — turning “we think this is complete” into “we can demonstrate this is complete,” which is what makes the trail hold up in a forensic or legal context.
Alert on the act of tampering itself. The API calls that disable logging — StopLogging, DeleteTrail, PutEventSelectors narrowing scope, deleting a log sink — are themselves logged events. Wire a real-time alert on them. The attacker’s first move becomes their loudest. This is also the answer to NIST SP 800-137’s continuous-monitoring premise: a control you set once and never watch has unknown status; security state has to be observed on an ongoing basis, and “is logging still on?” is the most basic thing to observe.
| Control | Attack it blocks | What it costs you |
|---|---|---|
| Append-only / object-lock sink | Deleting or overwriting past records | Retention storage spend; no early purge |
| Separate logging account | Workload-account compromise reaching logs | Cross-account setup + org governance |
| Log-file integrity validation | Silent post-delivery edits | A verification step at investigation time |
| Alert on StopLogging / DeleteTrail | Quietly switching the camera off | Alert pipeline; tuning out false positives |
| Multi-region + data-event logging | Acting in an unmonitored region / data plane | Per-event billing; higher log volume |
▸Why this works
Why not just keep logs forever and skip the object-lock complexity? Because “kept” and “immutable” are different properties. A standard bucket the workload account can write to can also be emptied by anyone with delete permission on it — and the credential that owns the workload often has, or can grant itself, exactly that. Retention without immutability protects you from accidental deletion and disk failure; it does nothing against a motivated insider or an attacker with admin. Object-lock in compliance mode is the part that says even root can’t shorten this — which is the whole point when the threat model includes a compromised administrator.
Reading the trail well, not just keeping it
Tamper-resistance keeps the record honest; it does not make it useful on its own. A trail you never query is just expensive storage. Two senior habits close the gap. First, centralize and normalize: ship every account’s trail into one queryable store so an investigator runs a single query across the whole org, not twelve. Second, baseline the normal so the abnormal stands out: a new IAM user created at 03:00, a console login from a country you don’t operate in, a sudden burst of RunInstances in an unused region — these are signal only if you know what boring looks like. This is exactly the loop NIST SP 800-137 calls continuous monitoring: collect, assess against a known baseline, respond, repeat — security status is a thing you keep measuring, not a box you checked at launch.
Your control-plane trail currently delivers to an S3 bucket in the same workload account, with versioning on. An attacker who compromises an admin role in that account wants to erase the last 6 hours of activity. Which change actually stops them?
An attacker compromises a credential and immediately calls `StopLogging` on the trail before doing anything else. Why is this the standard opening move?
What does log-file integrity validation (signed, hash-chained digests) buy you that retention alone does not?
Order the steps to make a control-plane trail genuinely tamper-resistant, from the broadest architectural move to the finest detection:
- 1 Deliver the trail to a separate, locked-down logging account
- 2 Apply object-lock / compliance-mode retention so records are append-only
- 3 Enable log-file integrity validation (signed, hash-chained)
- 4 Alert in real time on StopLogging / DeleteTrail / sink deletion
- 01Why is the control-plane audit trail the source of truth in a cloud breach investigation, and what gap exists in its default coverage?
- 02What four layered controls turn an audit trail from a log an attacker can edit into evidence, and what is the single highest-value one?
The control-plane audit trail — CloudTrail and its peers — is the source of truth in any cloud breach: it records every management API call with the identity, time, source IP, and parameters an investigator needs, which is exactly why disabling it is the attacker’s standard opening move (a catalogued MITRE ATT&CK defense-evasion technique). A trail an attacker can stop or delete is a smoke detector with an off switch. Four layered controls turn it into evidence: deliver to immutable, append-only storage; isolate the sink in a separate locked-down logging account so a compromised workload account can’t reach it; enable cryptographic integrity validation so post-delivery edits are provable; and alert in real time on StopLogging / DeleteTrail so the blinding move announces itself. Watch the default-coverage gap — data events like S3 reads are off by default. And remember the NIST SP 800-137 loop: keeping the trail isn’t enough; you have to keep watching it, because a control you never observe has unknown status. Next time you stand up a cloud account, your first question is: if the credential I just issued were compromised, could it erase its own tracks?
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.
Apply this
Put this lesson to work on a real build.