Deep dive · extends M02 and M04

Preventive vs Detective

A governance requirement is not inherently preventive or detective. That is an implementation choice, and it has consequences you inherit for years. This page takes one requirement, writes it both ways, and is honest about what each version cannot do.

SCP — refuse the call Config rule — notice after Honest limits Interception explorer

One requirement, two implementations

Somebody at AnyCompany writes a sentence: no S3 bucket in this organisation may be publicly readable. That sentence is the governance requirement. It says nothing about how it will be enforced — and the two available answers behave so differently that choosing between them is the actual design work.

Preventive — refuse the request

Write it as a service control policy. When someone calls the API that would make a bucket public, the call is evaluated against the policy and denied. Not attempted-then-reverted: denied. The bucket is never public, not even briefly.

Because the decision happens in the authorisation path, there is no interval during which the estate is wrong. The state you are trying to avoid never exists.

EvaluatesThe request — who is calling, what operation, with what parameters and context
AnswerAllowed, or denied
TimingBefore anything changes
StatesEnforced Not enabled
Detective — notice afterwards

Write it as an AWS Config rule. The bucket gets created, Config records what it looks like, and the rule evaluates that recorded state against your condition. If it fails, you get a finding.

The bucket was public for an interval. In exchange, you can evaluate things a policy decision cannot see — the resulting configuration of a resource, rather than the shape of the call that produced it.

EvaluatesThe resource's state — what it actually looks like now
AnswerCompliant, or non-compliant
TimingAfter the change lands
StatesClear In violation Not enabled
The distinction that generates every other difference. A preventive control inspects a request. A detective control inspects a resource. Everything else on this page — the exposure window, the cost model, the Region coverage, what each one is blind to — falls out of that one asymmetry. If you remember nothing else, remember which noun each mechanism operates on.

Why you cannot always pick preventive

The obvious reaction is that preventing is strictly better than detecting, so use preventive controls for everything and skip the rest of this page. It does not work, for a reason worth understanding precisely.

Some properties you care about are not expressible as a condition on an API call. "This bucket has versioning enabled" is a property of the bucket's configuration — it can be reached by several different call sequences, changed later by a different operation, or simply never set because the default applied. A policy that inspects one request has no view of the accumulated state a resource ends up in.

Worse, a preventive control cannot help with anything that already exists. Attach one today and it governs tomorrow's calls. The four hundred buckets already in the estate are entirely outside its reach — those need something that looks at what is there, which is precisely what a detective control does.

Expressible as a request condition

"Nobody may delete an object without MFA." The condition key is present on the request. A policy can decide.

Only visible in resulting state

"Every bucket has versioning on." Not a property of any single call. Only a rule reading the resource can tell you.

Already in the estate

Four hundred existing buckets. A preventive control is blind to all of them; it only sees future requests.

Where you have seen these already. M02 introduced both control types and showed the two policy documents. M04 built out the detective side into a full operating model with Config, Systems Manager, GuardDuty and Security Hub. This page sits between them and takes the comparison further than either module has time for.

Where each one intercepts

One API call — s3:PutBucketAcl making a bucket publicly readable — traced from the request to the corrected state. Switch the two controls on and off and watch where the story stops. All four combinations tell you something.

Detective only. The request will succeed, the bucket will become public, and the rule will catch it afterwards. Press play to watch how long it stays wrong.
Request path — preventive territory Resource path — detective territory bucket is public from here… …until here 1 Request made s3:PutBucketAcl 2 Authorisation evaluated identity policy + SCP ceiling 3 API accepts bucket is now public 4 Config records & evaluates configuration item → rule 5 Finding raised non-compliant · someone told 6 Remediation runs state corrected
Outcome
Exposure window
Stopped at stage
Anyone notified?

All four combinations, stated plainly

PreventiveDetectiveWhat actually happens
On On The mature answer. The direct path is refused outright, so there is no exposure window on that route. Detective still earns its place: it catches resources that were already non-compliant before the policy was attached, changes arriving through paths the policy does not cover, and anything created in the management account — which an SCP does not restrict.
Off On The request succeeds and the bucket is genuinely public for a measurable interval. You find out, and if remediation is wired up it gets corrected. Whether that is acceptable depends entirely on what was exposed during the window — and the window is not something you control precisely.
On Off Better than it looks for new activity, and worse than it looks overall. Tomorrow's calls are refused. But existing non-compliant buckets stay non-compliant indefinitely, and you have no way to know they are there, because nothing is evaluating resource state.
Off Off Nothing stops it and nothing notices. Worth running in the widget once, because this is the actual state of most requirements that exist only as a sentence in a policy document.
About the exposure window. The widget shows it as a fixed interval so it is visible. In reality it is variable and not under your direct control — it depends on when Config records the configuration item, when the rule is triggered, and how quickly remediation runs. That variability is itself the argument: if a requirement genuinely cannot tolerate the resource being wrong at all, detective controls alone will never satisfy it, no matter how fast you make them.

The two artefacts

Both mechanisms are documents you can read, review and put in version control. Worth reading them next to each other, because the difference in shape tells you more than any comparison table.

Preventive — a service control policy

The example from the Control Tower catalogue: refuse S3 delete operations that arrive without multi-factor authentication.

SCP · deny S3 delete without MFA
{ "Version": "2012-10-17", "Statement": [ { "Sid": "GRRESTRICTS3DELETEWITHOUTMFA", "Effect": "Deny", "Action": [ "s3:DeleteObject", "s3:DeleteBucket" ], "Resource": [ "*" ], "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": [ "false" ] } } } ] }

Reading it element by element

VersionWhich grammar to evaluate the document under. A version of the language, not of your policy. Leave it at the current date string.
EffectDeny. And this is the element people misread most: an SCP is a ceiling on what identity policies in the account can grant. An SCP with Effect: Allow still grants nobody anything — it only widens what the ceiling permits. Permission always comes from an identity or resource policy.
ActionSpecific API operations, not services. Naming operations keeps the control narrow enough that people can still do their jobs — the difference between "no deleting without MFA" and "no S3".
ResourceEverything, via the wildcard. Correct here: an exception list of "buckets it is fine to delete carelessly" is not a list anyone wants to own.
ConditionThe clause that turns a blanket ban into a control. BoolIfExists on aws:MultiFactorAuthPresent being false means the deny only bites when the request demonstrably arrived without a second factor. Present MFA and the identical call proceeds. Note what is being inspected: a property of the request context. Nothing here can see what the bucket looks like.
Detective — an AWS Config rule

The same catalogue, the detective half: every S3 bucket should have versioning enabled. Delivered as CloudFormation, because that is how you get it into every account consistently.

CloudFormation · Config rule checking bucket versioning
AWSTemplateFormatVersion: 2010-09-09 Description: Configure AWS Config rules to check whether versioning is turned on for your S3 buckets. Parameters: ConfigRuleName: Type: 'String' Description: 'Name for the Config rule' Resources: CheckForS3VersioningEnabled: Type: AWS::Config::ConfigRule Properties: ConfigRuleName: !Sub ${ConfigRuleName} Description: Checks whether versioning is turned on for your S3 buckets. Source: Owner: AWS SourceIdentifier: S3_BUCKET_VERSIONING_ENABLED Scope: ComplianceResourceTypes: - AWS::S3::Bucket

Reading it element by element

ParametersOne input, ConfigRuleName. Parameterising the name is what lets one template deploy across many OUs and environments without editing it — which matters, because you will deploy this via StackSets to every account.
TypeAWS::Config::ConfigRule. The control is a Config rule resource. Nothing bespoke, nothing hidden — which is why you can review it like any other infrastructure.
Source · OwnerAWS means this is a managed rule: AWS writes and maintains the evaluation logic. Set Owner to a custom value instead and you supply your own Lambda function — more power, and now you own the correctness of the check.
Source · SourceIdentifierWhich managed rule. Exhaust this catalogue before writing Lambda; there are several hundred and the one you need usually exists.
ScopeNarrows evaluation to S3 buckets. Scope is the cost and noise dial — evaluate the resource types the rule can actually say something about, not everything in the account. Note what is being inspected: the recorded state of a resource. Nothing here can see who made the call, or refuse it.
Look at the shape of the two documents. The SCP is built from Action and Condition — verbs and request context. The Config rule is built from SourceIdentifier and Scope — a check and a set of resource types. Neither vocabulary can express the other's job. That is not an API inconsistency; it is the two mechanisms telling you honestly what they operate on.
One SCP can back several controls. Some mandatory Control Tower controls are implemented by a single policy performing multiple denials rather than one policy each. So you will see the same SCP text quoted under more than one control in the reference. Not a documentation bug.

Further reading

What each one cannot do

This is the tab the slides do not have room for, and the one worth arguing about. Both mechanisms are genuinely useful and both have limits that will surprise you in production. Knowing them in advance is the difference between a control that holds and an exception process that quietly eats it.

Five things a preventive control will not do for you
1

It never grants anything

An SCP defines the maximum available permissions in an account. It does not give anyone access. If an identity policy does not permit the action, an Allow in an SCP changes nothing.

Consequence: "we attached the SCP, so the team has access now" is always wrong. Debugging a denial means checking both layers, and the SCP is the one people forget is even in the path.

2

It does not restrict the management account

Service control policies do not apply to the organisation's management account, regardless of where in the tree you attach them.

Consequence: the account with the most reach is the one your strongest preventive control cannot cover. Run no workloads there, keep the number of people who can reach it very small, and use detective controls plus CloudTrail to watch it — because that is all you have.

3

It cannot see resulting resource state

The evaluation has the request, the principal and the condition context. It does not have the configuration the resource will end up in, and it cannot reason about accumulated state across several calls.

Consequence: anything phrased as "every resource of this type must have property X" is not expressible preventively. That whole class of requirement belongs to the detective side.

4

It is blind to everything that already exists

Attaching a policy governs future calls. It performs no scan and takes no action against resources that are already there.

Consequence: a preventive control on a mature estate stops the bleeding and tells you nothing about the wound. You still need a detective sweep to find out how much pre-existing non-compliance you inherited.

5

Written too broadly, it gets exception-requested into uselessness

This is an organisational failure mode rather than a technical one, and it is the most common way preventive controls die. A deny that blocks legitimate work generates exception requests. Enough exceptions and the policy has holes shaped like every team that complained loudest.

Consequence: narrow beats broad. A control that denies exactly the thing you mean, with a documented and genuinely usable path for the rare legitimate case, survives. One that denies a whole service does not.

Five things a detective control will not do for you
1

There is always a window

Between the change landing and the rule evaluating, the resource is non-compliant and nothing is stopping anyone using it. The interval depends on when the configuration item is recorded and when evaluation is triggered.

Consequence: for a requirement where any exposure at all is unacceptable, detective controls cannot be the answer on their own — no matter how much you tune them.

2

It stops nothing

A detective control produces a verdict. The resource stays exactly as it was unless something else acts. Remediation is a separate thing you have to build and own.

Consequence: a Config dashboard full of red is not a control, it is a report. The control is the loop, and the loop is only closed when a finding reliably causes a change.

3

It costs money per item and per evaluation

Recording configuration items and running rule evaluations both have a unit cost. Recording everything in every Region and evaluating every rule against every resource type adds up faster than teams expect.

Consequence: Scope is not a tidiness setting, it is a budget setting. Scope each rule to the resource types it can actually say something about.

4

Its coverage is Region-bound

Detective controls only apply in the Regions where the service operates and where you have enabled recording. Preventive controls, by contrast, are evaluated in the authorisation path everywhere.

Consequence: an unmonitored Region is not a low-risk Region — it is the one place an attacker gets no findings raised against them. Pair Region-restriction preventive controls with your detective coverage so the two agree on the footprint.

5

A finding with no owner is not a control

Also organisational, also the most common cause of death. Findings arriving in a shared mailbox that six people are members of and nobody owns have no state, no ageing and no accountability.

Consequence: route findings into the queue your team already works from, with an owner and an ageing report. "We have Security Hub enabled" and "somebody acts on Security Hub findings" are entirely different claims.

And two things neither of them does
1

Neither validates business intent

Both mechanisms check conformance to a rule you wrote. Neither has an opinion on whether the rule was the right rule, or whether a perfectly compliant architecture is nonetheless a bad idea for what you are building.

Consequence: a fully green compliance dashboard is a statement about your rules, not about your security. If the rules are wrong, the dashboard is confidently wrong with them.

2

Neither substitutes for threat modelling the application

Both operate on cloud resource configuration. Neither looks at your authorisation logic, your dependency tree, your input handling, or what a trusted insider could do while remaining entirely within policy.

Consequence: governance at scale is the floor. It removes a large category of avoidable misconfiguration so your security effort can go to the problems that are actually specific to your product.

Choosing between them

A workable decision framework. Run a requirement through these questions in order and the answer usually falls out — and for most requirements the answer is "both, doing different jobs".

Four questions, in this order

1. Request or state? Can the requirement be expressed as a condition on an API call, or does it describe a property a resource ends up having? If it is state, preventive is off the table for the check itself — skip to detective and stop agonising.
2. Is any exposure acceptable? If the resource being wrong for even a short interval is genuinely unacceptable — a regulatory absolute, an irreversible action, a public data path — you need preventive. Detective cannot close that gap by getting faster.
3. Does legitimate work need this action? If some teams genuinely and correctly need the operation, a broad deny will generate exceptions until it is meaningless. Either narrow the control until it only catches the case you mean, or accept detective plus a fast response.
4. What already exists? On any estate that is not brand new, you need detective regardless — it is the only way to find out how much pre-existing non-compliance you have inherited. This question is why "both" is so often the answer.
Reach for preventive when
  • The rule is a bright line. No exceptions are contemplated, and anyone asking for one is escalating rather than negotiating.
  • The action is irreversible. Deleting the log archive, disabling the audit trail, terminating a database without a snapshot. Detecting these after the fact has limited value.
  • It is a regulatory absolute. "Data does not leave these Regions" is not a thing you want to discover retrospectively.
  • The blast radius is other people. Anything that could expose customer data publicly, or grant standing access broadly.
  • The condition is genuinely in the request. MFA presence, source Region, principal, requested resource ARN — all available at authorisation time.
Reach for detective when
  • The property is state-based. Versioning, encryption-at-rest settings, tag presence, retention configuration. Not expressible as a request condition.
  • You must permit the action but want to know. Opening a security group is sometimes correct; you want a record and a conversation, not a refusal.
  • You are rolling out a new standard. Start detective in report-only to size the problem before you break anyone's deployment.
  • You need evidence. An auditor wants a history of configuration and compliance over time. Only the detective side produces that.
  • You inherited an estate. Existing resources are invisible to preventive controls, full stop.

Guidance tiers — and the assumption that catches people

Guidance is advice about where to attach a control, and it is independent of whether the control prevents or detects. A control can be preventive and elective, or detective and mandatory. The consequential column is the last one.

TierWhat it meansEnabled by default?
Mandatory Always enforced. The rules Control Tower treats as non-negotiable for a governed environment — protecting the integrity of the log archive, for instance. Yes — on automatically, and OUs created through Control Tower get them without being asked.
Strongly recommended Established practice for well-architected multi-account environments. Sensible almost everywhere, but AWS will not assume your circumstances. No — you turn these on deliberately.
Elective Lets you track or lock down actions enterprises commonly restrict. Genuinely situational — plenty of organisations legitimately want the opposite. No — opt in per OU.
The single most common misreading in this whole course. Strongly recommended controls are not on by default. Only mandatory controls are. The name suggests otherwise, and teams routinely believe they have a level of governance they have not actually enabled. If you check one thing after this course, check which non-mandatory controls are active in your OUs — and be prepared for the answer to be "fewer than we thought".
An analogy that survives scrutiny. Preventive controls are the bumpers in a bowling lane: the ball physically cannot reach the gutter, so there is nothing to correct afterwards. Detective controls are the scoreboard: it faithfully records that you knocked over two pins and does nothing whatsoever to improve your next throw. You want both, because only one of them prevents the outcome and only one of them can tell you how you are actually doing.

Rolling one out without breaking things

Knowing which mechanism to use is the easy half. Attaching a preventive control to a live organisation on a Tuesday afternoon is how you find out which deployment pipelines depended on the thing you just denied. This is the sequence that avoids that.

Step 1

Detective first, and only detective

Deploy the Config rule with no remediation attached, scoped to the resource types that matter, and let it run. You are not governing yet — you are measuring. The output is the number nobody has: how many resources violate this requirement today, and which accounts they live in.

Step 2

Read the violations before you fix them

The list will contain surprises, and some of them will be legitimate. A bucket that is public because it serves a static website is not the same finding as a bucket that is public because someone was debugging. Sort them into "must fix", "needs an exception with an owner", and "the rule is wrong". If the third pile is large, go back and narrow the rule — you have learned something before breaking anything.

Step 3

Remediate the backlog, deliberately

Clear the existing violations before you attach anything preventive. Do this with a documented change rather than an unattended automation on first run — a bulk automated fix against resources you have not inventoried is its own incident. Once the backlog is at or near zero, you know the estate is in the state the control assumes.

Step 4

Attach preventive, low in the tree first

Now add the SCP — to one non-production OU. Watch for a full deployment cycle. What breaks here breaks cheaply. Only when a sandbox or development OU has lived with it without incident do you move it up toward the root.

Step 5

Keep the detective control running forever

The temptation is to retire it now that the preventive control is in place. Do not. It is what catches resources arriving through paths the policy does not cover, anything created in the management account (which the SCP cannot restrict), drift from a Region you have not preventively fenced, and the day someone detaches the policy without telling you.

Step 6

Fold it into the baseline

Last step, most often skipped. Add the requirement to the account baseline and to the Service Catalog product template, so accounts and resources created from now on start compliant instead of being corrected into compliance. This is what stops the same violation reappearing every month forever — and it is the subject of the governance lifecycle deep dive.

Why this order and not the reverse. Attaching preventive first feels decisive and produces an outage. You block calls that legitimate pipelines were making, you have no inventory of what was already wrong, and your first signal is a broken deployment rather than a report. Detective is cheap, reversible and informative; preventive is none of those. Learn with the cheap one, then commit.

What to take away

Where to go from here

Deep dive

Governance Lifecycle

Step 6 above is where most organisations stop, and it is the step that determines whether you are fixing the same violation forever. This page follows one requirement all the way round the implement, provision, operate loop and shows what closing it is worth.

Close the loop Baseline
M04

Detective Controls

The full operating model on the detective side: AWS Config as the configuration recorder and rule engine, Systems Manager for grouped action and remediation, GuardDuty for threat detection, Security Hub for aggregation and prioritisation.

AWS Config Systems Manager
Deep dive · interactive

Landing Zone Builder

Step 4 said "attach it low in the tree first". Which presumes you have a tree worth attaching to. Build one here and see what the OU layout does to where controls can usefully sit.

Click-to-build OU design

Further reading