Every cloud security assessment produces the same finding: too many roles, too many permissions, no review since creation. And every remediation plan that proposes reviewing them all fails, because a 900-role review is a project nobody finishes.
The approach that works is not comprehensive. It removes specific classes of permission in an order determined by how cloud compromises actually unfold.
Order of operations#
1. Eliminate long-lived credentials
Before touching a single permission boundary, remove static access keys.
The reason this comes first is that permission scoping is a mitigation, while credential elimination removes an entire attack path. A leaked key with modest permissions is still an unauthenticated foothold; no key means no foothold from that vector.
The targets, in order of how often they appear:
- Access keys in CI systems. Replace with OIDC federation. GitHub Actions, GitLab CI, CircleCI and Azure DevOps all support this against all three major clouds.
- Keys on developer machines. Replace with short-lived credentials from your identity provider via SSO.
- Keys in application configuration. Replace with workload identity — instance roles, IRSA on EKS, workload identity federation on GCP, managed identity on Azure.
- Keys in scripts and scheduled jobs. These are the ones nobody remembers. Find them by auditing which keys have been used in the last ninety days and where from.
# AWS: every access key, its age and last use
aws iam list-users --query 'Users[*].UserName' --output text \
| tr '\t' '\n' \
| while read -r user; do
aws iam list-access-keys --user-name "$user" \
--query "AccessKeyMetadata[*].[UserName,AccessKeyId,CreateDate,Status]" \
--output text
doneThen set an organisation-level guardrail that prevents new IAM users being created at all, so the problem does not regrow.
2. Remove wildcard administrative policies
The second pass targets identities with Action: "*" on Resource: "*", or their equivalents in Azure and GCP.
You will find more than you expect, and most will be attached to things nobody uses. Typical distribution in a five-year-old estate:
- A handful of genuine break-glass administrator identities. Keep, but move behind hardware MFA and session recording.
- Service roles created during a proof of concept in year one. Delete.
- Roles created by a departed engineer to unblock a deployment. Scope down, using CloudTrail or the equivalent to determine what they actually call.
- Third-party integration roles granted admin because the vendor's documentation asked for it. Scope down to the documented minimum, and if the vendor cannot tell you what they need, treat that as a vendor risk finding.
3. Separate production from everything else
If production and non-production share an account, subscription or project boundary, permission scoping inside that boundary is doing work that a boundary would do better.
The move to separate accounts is disruptive but bounded, and it converts a permanent, expensive control problem into a one-time migration. Afterwards, the blast radius of a compromised non-production identity is a non-production account.
Pair this with service control policies (or Azure Policy / GCP organisation policies) that make dangerous actions structurally impossible rather than merely discouraged:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyCloudTrailTampering",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail",
"cloudtrail:UpdateTrail"
],
"Resource": "*"
},
{
"Sid": "DenyDisablingGuardDuty",
"Effect": "Deny",
"Action": ["guardduty:DeleteDetector", "guardduty:DisassociateFromMasterAccount"],
"Resource": "*"
},
{
"Sid": "DenyRootUserActions",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": { "StringLike": { "aws:PrincipalArn": "arn:aws:iam::*:root" } }
}
]
}These three statements alone remove the most common post-compromise actions: disable logging, disable detection, operate as root.
4. Then, and only then, scope the long tail
By this point the acute exposure is gone and the remaining work is genuinely incremental. It is also now automatable: permission-recommendation tooling produces useful output once the obvious over-grants are removed, because the signal is no longer drowned in noise.
Set a quarterly cadence, target the roles with the widest gap between granted and used, and accept that you will never reach a state where every permission is minimal. Least privilege is a direction, not a destination.
The mistake that undoes all of it#
Guardrails that block a legitimate pattern without providing an alternative get exceptions granted, then exceptions become the norm, then the guardrail is removed.
Every restriction needs a paved road. If you deny public S3 buckets, provide a documented, one-command pattern for publishing static assets through a CDN. If you deny long-lived keys, provide a working OIDC template for the CI system your teams actually use.
The teams that succeed at this treat platform engineering and security as the same programme. The ones that fail hand a policy document to a team that then has to work out how to comply with it.
What good looks like, measurably#
Four metrics that tell you whether this is working:
Cloud identity health metrics
- 1Number of IAM users with active access keys — target zero, measured weekly.
- 2Number of identities with wildcard administrative permissions — target under five, all break-glass, all with session recording.
- 3Median gap between permissions granted and permissions used across service roles — track the trend, not the absolute.
- 4Percentage of accounts covered by preventive organisation-level guardrails — target 100%, including sandbox accounts.
One tier-one manufacturing client reduced over-privileged roles by 81% and reached zero long-lived keys in pipelines within a quarter, without a single reviewed-role spreadsheet.
Human identities and workload identities are different problems#
Treating them as one programme is why cloud identity work stalls. They have different lifecycles, different failure modes and different owners.
Workload identities — service roles, instance profiles, service accounts — are created by engineers, live in code, and are best governed in the pipeline. They should carry no long-lived credentials at all, and their permissions can be derived mechanically from access history. This half is tractable and largely automatable.
Human identities are governed through the identity provider, not the cloud console. The target state is that no person holds a standing cloud role: access is assumed just-in-time through SSO, for a bounded session, with the elevation recorded. Permanent human access to production is the single finding we raise most often, and the fix is organisational as much as technical — someone has to give up the console bookmark they have used for four years.
Sequence workloads first. They are the larger population, the work is mechanical, and the win is visible — which buys the political capital for the human-access conversation.
Azure and Google Cloud, where the shape differs#
The principles transfer; the mechanics do not.
Azure. Role assignments inherit through the management group, subscription, resource group and resource hierarchy, so scope is where over-permission accumulates rather than in the role definition. Look for Owner and Contributor assigned at subscription or management-group scope — that is the equivalent of a wildcard policy. Privileged Identity Management provides the just-in-time elevation described above; Azure Policy plus management-group structure gives you the preventive guardrails.
Google Cloud. IAM binds at organisation, folder, project and resource level, and the trap is
primitive roles — Owner, Editor, Viewer — which are extremely broad and still widely assigned. The
roles/editor binding at project level is the finding to hunt. Organisation policy constraints supply
the preventive layer, and Workload Identity Federation removes service account keys, which are GCP's
equivalent of long-lived access keys and the most common leaked credential in the ecosystem.
Common to all three. Service accounts and roles with permission to modify logging or disable detection should be denied at the organisation level rather than merely reviewed. That single control survives most post-compromise playbooks.
The cadence that keeps it from regrowing#
Permission creep is not a project you finish; it is a rate you manage. Three recurring activities hold the line, and they are cheap once the acute exposure is gone.
Weekly, automated. Alert on the creation of any IAM user, any access key, any wildcard policy attachment, and any change to organisation-level guardrails. These should be rare enough that each one warrants a look, and if they are not rare yet, that itself is the finding.
Quarterly, half a day. Pull the permissions-granted versus permissions-used gap for every service role and scope down the worst ten. Ten is deliberate — a target that fits in an afternoon gets done, and a target of "all of them" gets deferred forever.
Annually, with the business. Re-examine the account and subscription structure against how the organisation is now shaped. Team boundaries move, products are retired, acquisitions land. A landing zone designed for the org chart of three years ago is a landing zone accumulating exceptions.
The trap to avoid is measuring the wrong thing. Counting policies reviewed rewards activity; tracking the granted-versus-used gap rewards outcome. One tier-one client held their gap flat for six quarters while tripling their cloud footprint — which is a better result than a one-off reduction that quietly regrew.
Our Cloud & Platform Security practice does this work, and the provider-specific ordered checks are published in our Cloud Security Baseline Checklist.
Cyber Security & Cloud
Our security practice covers architecture, cloud, detection engineering and operational technology. Every member has operated production infrastructure before advising on it, which shapes what we recommend and what we refuse to.
- CISSP
- GCIA
- OSCP
- AWS Security Specialty
Where do you actually stand?
Score your Digital Trust posture in fifteen minutes
Free, no sales call required. Privacy, security, governance, risk and AI readiness scored against sector benchmarks, with a prioritised gap list.

