Glossary

    Least Privilege

    Identity & Access

    Least Privilege is the foundational security principle that every identity (user, role, service) should have only the minimum permissions required to perform its intended function. Nothing more.

    In AWS, this means writing IAM policies that specify exact actions on exact resources instead of using wildcards. A Lambda function that reads from one S3 bucket should have s3:GetObject on that specific bucket ARN, not s3:* on *.

    Why It Matters

    • Blast radius reduction: if credentials are compromised, the attacker can only do what that identity was allowed to do
    • Compliance requirement: CIS, SOC 2, PCI DSS, and HIPAA all require least-privilege access
    • Audit clarity: narrow policies make it clear who can do what

    AWS Tools for Least Privilege

    • IAM Access Analyzer: generates policies based on actual usage from CloudTrail logs
    • IAM Access Advisor: shows which services an identity has accessed and when
    • Permission boundaries: set maximum permissions regardless of what policies are attached
    • SCPs: enforce guardrails at the organization level

    How It Goes Wrong in Practice

    The most common failure I see is the "temporary" wildcard that becomes permanent. A team is under deadline pressure, an application fails with an AccessDenied error, and someone attaches AdministratorAccess or writes "Action": "s3:*", "Resource": "*" to unblock the release. The intent is to tighten it later. Nobody ever does, because the application works and the policy is invisible until an audit or an incident.

    The damage shows up when that identity is compromised. A classic chain: an EC2 instance runs a web application with a server-side request forgery (SSRF) flaw, the attacker uses it to query the instance metadata service and steal the instance role credentials, and because the role carries a wildcard policy instead of the three actions the application actually needs, the attacker can now enumerate and exfiltrate every S3 bucket in the account. The vulnerability was in the application, but the blast radius was defined entirely by the IAM policy. With a least-privilege role, the same SSRF would have exposed read access to one bucket.

    The other recurring failure is granting broad iam:* permissions to humans or CI/CD pipelines. Any identity that can create policies, attach policies, or pass roles can usually escalate itself to administrator, so a sloppy IAM grant silently converts every other narrow policy in the account into a formality.

    Checking Actual Usage From the CLI

    IAM can tell you which services an identity was actually allowed to use versus which ones it really touched. Generating that report is a two-step, asynchronous process:

    aws iam generate-service-last-accessed-details --arn arn:aws:iam::123456789012:role/my-app-role

    This returns a JobId. Retrieve the report with:

    aws iam get-service-last-accessed-details --job-id <job-id>

    The output lists every service the role's policies allow and the last time each was actually accessed. Services that were never accessed in the tracking period are prime candidates for removal from the policy. You can pass --granularity ACTION_LEVEL on the generate call to get last-accessed data per action for supported services, which is even more useful for trimming policies. For net-new policies, use IAM Access Analyzer policy generation, which builds a policy from the CloudTrail activity of the role over a period you choose.

    A Realistic Way to Get There

    Perfect least privilege on day one is not realistic, and chasing it can paralyze delivery. What works in practice:

    • Start new workloads with a narrow policy and add actions when a real AccessDenied appears, rather than starting broad and hoping to trim later
    • Scope Resource to specific ARNs even when you cannot yet narrow the action list
    • Review high-risk actions first: anything in iam:, sts:AssumeRole, kms:Decrypt, and data-read actions on sensitive stores
    • Put permission boundaries or SCP guardrails around the identities that create other identities, so one mistake cannot escalate
    • Schedule a recurring review using Access Advisor data instead of treating policies as write-once

    Frequently Asked Questions

    Is least privilege the same thing as zero trust?

    No. Least privilege is about the size of the permission set an identity holds. Zero trust is a broader architecture principle that says no request should be trusted based on network location alone and every request must be authenticated and authorized. Least privilege is one ingredient of a zero trust design, not a synonym.

    Does least privilege apply to AWS managed policies?

    AWS managed policies like ReadOnlyAccess or PowerUserAccess are convenient but deliberately broad, because they have to serve every customer. They are acceptable for exploration in sandbox accounts. For production workloads, write customer managed policies scoped to the exact resources the workload uses.

    How do I find over-permissive identities I already have?

    Combine three sources: IAM Access Advisor (services granted but never used), IAM Access Analyzer unused access findings (unused roles, unused permissions, and unused access keys), and CloudTrail analysis for the actions actually called. Start with identities that hold administrative or IAM permissions, since those carry the escalation risk.

    Related AWS Services

    Toc Consulting: AWS Security & Cloud Architecture

    Securing your AWS estate?

    Our team helps engineering teams secure and architect AWS the right way: assessment in week one, a prioritized action plan in week two.