Business Challenge
The distinction is stated in one sentence and it is worth reading twice:
“Declarative policies are enforced in the service's control plane, which is an important distinction from authorization policies such as service control policies (SCPs) and resource control policies (RCPs). While authorization policies regulate access to APIs, declarative policies are applied directly at the service level to enforce durable intent.”
An SCP answers may this principal make this call? A declarative policy answers what is this service's setting? The first is a gate on the path; the second is the value at the destination. Three consequences follow, and none of them is obvious from the policy editor.
AWS's own comparison table has a row that is easy to scroll past. Against “Governs service-linked roles?”, service control policies answer No, resource control policies answer No, and declarative policies answer Yes.
That is a real gap closed. An SCP is evaluated against a principal, and a service-linked role acting on the service's own behalf is outside what it constrains — which is why an estate that believes an SCP covers everything has a category of activity it has never governed. A declarative policy does not care which principal acted, because it is not evaluating a principal. It is asserting what the configuration is.
FixIf a control genuinely must hold regardless of who or what acts — including AWS services operating in your account — an SCP is the wrong instrument and a declarative policy may be the right one. Check the supported list first; the mechanism only covers the attributes AWS has onboarded.
A deny-based SCP enumerates actions, so it is a statement about the API surface on the day it was written. Ship a new action and the policy silently stops being complete. Declarative policies do not have that failure mode by construction:
“Once attached, the configuration is always maintained when the service adds new features or APIs.”
AWS calls this “Set once and forget”, and extends it in the direction that usually costs estates the most: “The baseline configuration is also maintained when new accounts are added to an organization or when new principals and resources are created”, with “Accounts joining an organization will automatically inherit the declarative policy in the organization.”
That is the answer to the drift problem in #102, where a Regional, account-level setting has to be re-applied in every new account and every new Region to mean anything. The declarative version arrives with the account.
FixWhere a setting exists in both forms, prefer the declarative one even for a single account, because the property you are buying is not today's value — it is that tomorrow's accounts, Regions and features inherit it without anybody remembering.
“If a declarative policy is detached, the attribute state will roll back to its previous state before the declarative policy was attached.”
So a declarative policy is a position held, not a change applied. While it is attached the value is what you declared; remove it and the account returns to whatever it had before — which, for an account that was non-compliant when the policy landed, means returning to non-compliant.
That is the same shape as the block public access settings in #102, and it is worth noticing that AWS has now built the pattern twice: the control suppresses a state rather than overwriting it, and the suppressed state is still underneath. Detaching a declarative policy during an incident to unblock a team does not leave the estate at the declared baseline. It restores the configuration the policy was hiding.
The other half of the same coin, from the services that implement it: “When a declarative policy is in use, you can't modify the setting directly within an account.” While attached, the local switch is gone.
FixTreat detaching as a configuration change with a blast radius, not as turning off a guardrail. Before you detach, know what each account's prior state was — the account status report is the tool for that, and the time to read it is before you need it.
Architecture
Three organization policies, three places they act
| Service control policy | Resource control policy | Declarative policy | |
|---|---|---|---|
| What it governs | Principals | Resources | A service's configuration |
| How | “controlling the maximum available access permissions of principals at an API level” | The same, “for resources at an API level” | “enforcing the desired configuration of an AWS service without using API actions” |
| Governs service-linked roles? | No | No | Yes |
| Survives a new API | Only if the policy anticipated it | Only if the policy anticipated it | Yes — “always maintained when the service adds new features or APIs” |
The second row is the whole thing. An authorization policy produces a denial at the moment of a call; a declarative policy produces a value that is simply true of the service. That is why the third row can say yes: there is no principal to exempt.
What they can hold, which is the real constraint
Declarative policies are not a general configuration language. They cover the services AWS has onboarded and the attributes within them, and the current set is a good map of where this mechanism is going: EC2, Backup, Tag, chat applications, AI services opt-out, Security Hub, Amazon Bedrock, Amazon Inspector, upgrade rollout, Amazon S3, Shield Network Security Director and Amazon GuardDuty policies.
Three of those have appeared in this series in the past week, which is the clearest signal of how much this mechanism is now carrying. The Allowed Images setting AWS gives as its example policy is the control from Daily #67; the upgrade rollout policy is the middle path in Daily #66; and the S3 and EC2 policies are how the block public access settings in #102 stop being per-account chores.
Inheritance, and the report that tells you what is actually in force
“Declarative policies can be applied to an entire organization, organizational units (OUs), or accounts”, and what lands on an account is the combination: “The effective policy is the set of rules that are inherited from the organization root and OUs along with those directly attached to the account.”
Because the mechanism sets values rather than denying calls, the question what is in force here? has an answer you can read rather than compute: “The account status report allows you to review the current status of all attributes supported by declarative policies for the accounts in scope.” That is a materially better position than SCP evaluation, where the effective permission is the intersection of several documents and a simulation is the only honest way to know.
The failure message is configurable, and that matters more than it sounds
“You can also create customizable error messages, which can help administrators redirect end users to internal wiki pages or provide a descriptive message that can help end users understand why an action failed.”
Anyone who has watched an engineer lose an afternoon to an unexplained AccessDenied from an
SCP they cannot read will recognise what this is worth. A control that explains itself at the point of
failure is a control that generates fewer tickets and less resentment, and resentment is what gets
guardrails removed.
Why This Architecture Holds Up
Enforcing configuration rather than access is the right fix for feature drift
Every deny-list policy decays, because the list is finite and the API surface is not. Moving enforcement into the control plane makes the guarantee about the service's state rather than about an enumeration of calls, and a statement about state does not need updating when a new call appears. That is a genuinely different durability profile, not a convenience.
Rolling back on detach is defensible, and must be understood
The alternative would be for AWS to leave accounts permanently mutated by a policy you removed, which would make attaching one far more frightening than it is. Reverting is the conservative choice. It does mean a declarative policy is a thing you hold rather than a thing you did, and the only real mistake is modelling it as the latter.
Covering service-linked roles closes a gap most people do not know they have
The limits of SCPs around service-linked roles are documented but rarely front of mind, and an estate can run for years believing its guardrails are universal. A mechanism that sidesteps principal evaluation entirely is the clean answer, and putting the comparison in a table beside the authorization policies is the right place to tell people.
Key Architecture Decisions
| Decision | Choose this | Because |
|---|---|---|
| Which policy type | Declarative for a configuration baseline; SCP for who may act | One sets a value “without using API actions”; the other bounds permissions at an API level |
| A control that must hold against AWS services too | Declarative | It is the only one of the three that governs service-linked roles |
| A per-account, per-Region setting | Declarative, even for one account | New accounts inherit it automatically; the local switch disappears while it is attached |
| Emergency removal | Plan it before you need it | Detaching rolls the attribute back to its prior state, which may be the non-compliant one |
| Explaining a denial | Write the custom error message when you attach | It is the difference between a guardrail people route around and one they understand |
The audit worth running
Pull the account status report and read it as an inventory of what is actually in force. It covers all supported attributes for the accounts in scope, which makes it the one document that answers the question your SCPs cannot answer without simulation.
For every attached declarative policy, record what each account's prior state was. That is the state you return to on detach. Without it, removing a policy is an action whose outcome you cannot predict per account.
Then look at your deny-based SCPs and ask which of them are really configuration statements. A policy that denies every API that could turn a setting off is a deny list approximating a declarative policy, and it will be incomplete the next time the service ships something.
Closing Thought
The useful way to hold these three apart is by the question each one answers. An SCP answers whether a principal may call. An RCP answers whether a resource may be reached. A declarative policy answers what the setting is. Only the third is immune to somebody inventing a new way to ask.
The cost of that immunity is the rollback on detach. Because the mechanism asserts a value rather than changing one, the account's own value is still underneath, waiting. That is the same design as the block public access settings in #102, and seeing it twice in a week suggests it is becoming the house pattern for AWS guardrails: suppress, do not overwrite, and make removal safe by making it reversible.
Which is fine, as long as nobody reads compliant while the policy is attached as compliant.
Security & Identity — AWS Organizations tag policies: what a tag policy evaluates, what it does when a resource does not comply, and where the boundary sits between reporting and preventing.
Official AWS Reference
- Declarative policies in AWS Organizations — enforcement in the service's control plane versus authorization policies at the API level, the comparison table including the service-linked roles row, the maintenance of configuration across new features and new accounts, automatic inheritance, the rollback on detach, the effective policy, the account status report, customizable error messages, and the list of supported policy types
- Block public access for Amazon EBS snapshots — the statements that a declarative policy applies a setting across multiple Regions and accounts simultaneously and that an account cannot modify the setting directly while one is in use
- Understanding declarative policy inheritance — further reading on how root, OU and account attachments combine; no claims in this post are drawn from it
- EC2 declarative policies — further reading on the EC2 attributes available, including the Allowed Images setting; no claims in this post are drawn from it
Comments