Write a least-privilege IAM policy and use roles instead of long-lived keys.
Why it matters
In the cloud, identity is the new perimeter. Anyone holding valid credentials with broad permissions can delete servers, read data or run up a huge bill, from anywhere in the world. Leaked access keys in public Git repositories are found by automated scanners within minutes. Identity and Access Management (IAM) is how you decide exactly who can do what, and it is the most important security control you own under the shared responsibility model.
The core idea
Every request to a cloud API is checked: who is asking (the principal), what they want to do (the action), on which resource, and under what conditions. On AWS the building blocks are:
- Root user: the account owner. Use it only for a handful of account tasks; protect it with MFA and never create access keys for it.
- Users and groups: for people. Today most organisations sign people in through a central identity provider (AWS IAM Identity Center, Microsoft Entra ID, Google Workspace) instead of creating many IAM users.
- Roles: identities that people or services assume to get temporary credentials. An EC2 instance, a Lambda function or a CI pipeline should use a role, never a hard-coded access key.
- Policies: JSON documents that allow or deny actions.
Azure uses role assignments (RBAC) at a scope, and Google Cloud uses IAM roles bound to principals on a resource; the ideas are the same.
Reading a policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadReports",
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::acme-reports-2026/reports/*"
},
{
"Sid": "ListReportsPrefix",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::acme-reports-2026",
"Condition": { "StringLike": { "s3:prefix": "reports/*" } }
}
]
}
EffectisAlloworDeny.Actionnames API operations,service:Operation.Resourceis an ARN (Amazon Resource Name). Note that listing applies to the bucket ARN, while reading applies to object ARNs ending in/*.Conditionnarrows when the statement applies.
The evaluation rules: everything is denied by default; an explicit Allow grants access; an explicit Deny anywhere always wins.
Least privilege, worked through
A nightly job copies a CSV export into s3://acme-reports-2026/reports/. A beginner might attach the managed policy AmazonS3FullAccess. That lets the job delete every bucket in the account. Least privilege asks: what is the smallest set of actions on the smallest set of resources that still lets the job work?
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::acme-reports-2026/reports/*"
}]
}
That is the whole policy: the job can add files to one prefix in one bucket and nothing else. Attach it to a role that the job's compute (EC2, Lambda or a container task) assumes, so there are no keys to leak.
How to find the minimum: start from what the task needs, test, and add only what fails. AWS also offers IAM Access Analyzer, which can suggest policies based on recorded activity, and "last accessed" information that shows permissions nobody uses.
Good habits
- MFA on every human login, especially root and administrators.
- Humans sign in through single sign-on and get temporary credentials; services use roles.
- Grant permissions to groups or roles, not to individuals one by one.
- Review and remove unused users, keys and permissions regularly.
- Use wildcards (
*) sparingly and never as"Action": "*", "Resource": "*"outside a break-glass admin role.
Common mistakes
- Daily work as the root user.
- Long-lived access keys pasted into code, scripts or
.envfiles that get committed. *FullAccesspolicies attached "just to make it work".- Forgetting that
s3:ListBucketneeds the bucket ARN, not the object ARN, and then widening everything to*out of frustration.
Quick recap
- Every API call is checked against principal, action, resource and conditions; default deny, explicit deny wins.
- People use SSO and MFA; workloads use roles with temporary credentials.
- Least privilege means the smallest actions on the smallest resources; start small and add what is proven necessary.
Try it
In the Do tab you write a least-privilege policy for a real task and test it with the IAM policy simulator.