AWS Fundamentals: Accounts, IAM Users, Roles and Least Privilege
Cloud ComputingLesson 1 of 45 min read
What you'll learn
- Explain why the root user is protected and what to use instead
- Tell IAM users, roles and Identity Center sign-in apart
- Read and write a basic IAM policy with Action and Resource
- Apply least privilege and debug an AccessDenied error
On this page
Every call to AWS, whether from the console, the command line or your code, is answered by the same question: is this identity allowed to do this action on this resource? Nearly every confusing AWS error is that question being answered no, or being answered by something you did not expect. This lesson sets up the pieces behind that question, using a community photo club's image archive as the example, and ends with a safe way to give a small program access to exactly one bucket.
The account is the boundary, the root user is the skeleton key
An AWS account is the container for your resources and your bill. When you sign up, the email address you used becomes the root user, which can do anything in the account and cannot be restricted by ordinary policies. Treat it like the master key to a building: secure it, lock it away and do not use it for daily work.
- Turn on multi-factor authentication for the root user immediately.
- Do not create access keys for the root user.
- Sign in as root only for the small set of account-level tasks that require it, then sign out.
- Do everyday work as a less powerful identity, which the next sections set up.
Users, roles and the case for roles
Identity and Access Management (IAM) is the service that holds identities and permissions. Three kinds of identity matter to a beginner.
| Identity | Credentials | Best for |
|---|---|---|
| IAM user | Long-lived password and optional access keys | Legacy setups and a few special cases; keys that never expire are risky |
| IAM role | Temporary credentials issued on demand by the Security Token Service (STS) | Software running on AWS (Lambda, EC2) and anything assumed temporarily |
| Human sign-in via IAM Identity Center | Short-lived session after a browser login | People in a company or team; one login, many accounts |
The big idea is that roles hand out credentials that expire, so a leaked one stops working soon, and no secret is stored in your code. When you can, avoid creating access keys at all. For yourself, use IAM Identity Center with the CLI's SSO support (aws configure sso); for programs, attach a role.
aws sso login --profile photo-dev
aws sts get-caller-identity --profile photo-devOutput
{
"UserId": "AROAEXAMPLEEXAMPLE1:asha",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_Developer_0123456789abcdef/asha"
}The output above is illustrative with placeholder values: 123456789012 is a dummy account ID and the role name is made up. The command is the one to run whenever you are unsure which identity your terminal is using, which is the first step in debugging any permission error. When the session has expired you will see a message that the SSO session associated with the profile has expired; run aws sso login again.
Anatomy of a policy
A policy is a JSON document that lists statements. Each statement says whether to Allow or Deny, which Action names (such as s3:GetObject), and which Resource they apply to, identified by an Amazon Resource Name (ARN). The policy below lets a program list one bucket and read its objects, and nothing else. The bucket name is an example, and bucket names are globally unique, so yours will differ.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListTheBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-photo-club-archive"
},
{
"Sid": "ReadPhotos",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-photo-club-archive/*"
}
]
}Notice that two statements are needed. s3:ListBucket applies to the bucket itself, so its resource is the bucket ARN. s3:GetObject applies to the objects inside, so its resource ends in /*. Mixing these up is the most common reason an S3 policy that looks right still fails.
Giving a program a role
A role needs two documents. The trust policy says who may assume the role; here, the Lambda service. The permission policy says what the role can do once assumed. The commands below create a role for a thumbnail function, attach the inline permissions and add AWS's managed policy that lets Lambda write its logs. They were checked against the CLI's documented syntax but not run, since they need a real account.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}# trust.json holds the trust policy above; photo-read.json holds the permission policy
aws iam create-role \
--role-name photo-thumbnailer-role \
--assume-role-policy-document file://trust.json
aws iam put-role-policy \
--role-name photo-thumbnailer-role \
--policy-name read-photo-archive \
--policy-document file://photo-read.json
aws iam attach-role-policy \
--role-name photo-thumbnailer-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRoleHow AWS decides
- Everything is denied by default.
- An
Allowin an applicable policy permits the action. - An explicit
Denyanywhere beats everyAllow. - Other layers can also say no, such as a bucket policy, an organisation-level guardrail or a permissions boundary, so a missing permission is not always in the identity's own policy.
Least privilege means giving each identity only the actions and resources it needs for its job. Start narrow, run the program, and widen only when an AccessDenied message names a specific action. IAM Access Analyzer can also generate a policy from the activity recorded in CloudTrail, which gives you a data-based starting point.
Common mistakes
- Putting access keys in code or a public repository. Symptom: you may receive an AWS security notice, or unfamiliar resources appear in the account. Deactivate and rotate the key at once, then switch to roles.
- **Using
"Action": "*"on"Resource": "*"to make an error go away.** Symptom: it works, and the program can now delete anything. Read the denied action in the error and allow that. - Listing a bucket with only `GetObject` allowed. Symptom:
aws s3 ls s3://bucketreturnsAccessDeniedalthough downloading a known key works. - Reading IAM errors in the wrong place. Symptom:
User: arn:aws:iam::123456789012:user/asha-dev is not authorized to perform: ... because no identity-based policy allows the ... action(placeholder ARN). That wording says the identity policy is the gap; if it says an explicit deny, find the deny instead. - Confusing the role you are using with the one you think you are. Symptom: permissions differ between your laptop and a server. Run
aws sts get-caller-identityin both places.
How this shows up in projects and interviews
IAM is the topic where junior engineers are tested on judgement. Typical questions are the difference between a user and a role, why you should not use the root user, what an explicit deny does, and how you would give an application read-only access to one bucket. A good answer to the last one is the policy and role in this lesson. On the job, a large share of cloud incidents involve credentials or over-broad permissions, so showing you default to roles and narrow policies is a real signal. For the wider picture of what a cloud provider is, see Cloud Computing Fundamentals.
Try it yourself
Write a policy that lets a program put objects into the prefix uploads/ of a bucket called example-photo-club-archive but read nothing else. Then write a one-line explanation of what would happen if the program tried s3:DeleteObject. Finally, run aws sts get-caller-identity in your own setup and note whether you are a user or an assumed role.
Show a hint
Uploading uses the s3:PutObject action on a resource such as arn:aws:s3:::example-photo-club-archive/uploads/*. Anything not listed is denied by default.
Key takeaways
- Secure the root user with MFA and do everyday work as a less powerful identity.
- Roles issue temporary credentials, so prefer them over long-lived access keys.
- A policy has Effect, Action and Resource; S3 needs the bucket ARN for list and the /* form for objects.
- Access is denied by default and an explicit Deny always wins.
- Start narrow and widen from the named action in the error, not with wildcards.
Test yourself
A trick from this lesson's ride: Root is the master key: lock it in the safe, carry a day key instead. Four more tricks like it wait along the route, each followed by a question.
Frequently asked questions
What is the difference between an IAM user and an IAM role?
An IAM user is a permanent identity with a password or access keys that do not expire until you rotate them. A role has no long-term credentials; something assumes it and receives temporary ones from STS. Use roles for software running on AWS and for temporary access, and keep users to a minimum.
What is least privilege in AWS?
Least privilege means each identity gets only the actions on only the resources it needs, and nothing broader. In practice you start with a narrow policy, run the workload, and add exactly the permissions that AccessDenied errors reveal. It limits damage if a credential leaks or code misbehaves.
Why should I not use the AWS root user for daily work?
The root user has unrestricted access to the whole account and its permissions cannot be limited by normal IAM policies, so a compromise is catastrophic. Protect it with MFA, avoid creating access keys for it, and use an Identity Center or IAM identity with scoped permissions for everyday tasks.