Courses / Hands-on Cloud for Freshers

Session 2 of 8

Who can do what: identities and permissions

Overview

Unit 2 — Who Can Do What: Identities and Permissions

Course: Hands-on Cloud for Freshers

Prerequisites: You have an AWS account with an everyday administrator IAM user, hoc-admin, protected by MFA, as built in Unit 1, and you can sign in to the console as that user. You can open a terminal on your own computer and run a command in it. You can read a short JSON document: objects in braces, lists in square brackets, strings in double quotes.

What the reader can do after this unit:

  • Read an IAM policy statement and say, for a given request, whether AWS allows it, denies it explicitly, or denies it implicitly — and which statement decided.
  • Write a least-privilege identity-based policy for a named bucket, choosing the right ARN for a bucket-level action and for an object-level action, and prove it with the IAM policy simulator before attaching it to anything.
  • Install the AWS CLI version 2, sign it in with aws login so that it holds only short-lived credentials, and confirm which identity it is acting as with aws sts get-caller-identity.

Core question this unit answers: When AWS receives a request, how does it decide yes or no — and how do you write a policy that says yes to exactly what you need and nothing more?

Connections:

  • Builds on: Unit 1’s identities — the root user, the hoc-admin user and its group — and the denial message a user with no policies received at the end of Unit 1’s project.
  • Leads into: Unit 3, which creates the storage bucket this unit’s policy is written for, and uses the signed-in command line from this unit to upload files to it.

Your answers are scored

This unit is assessed. The quiz is marked against a key held separately from your materials. Questions 1–8 are multiple choice and are marked by comparing your letter with the key. Questions 9–11 ask you to write an answer in an exact format, and each one is marked by checks printed with the question — for the policy question, by running the AWS policy simulator against a printed list of requests that must be allowed and requests that must be denied.

  • You can check your constructed answers completely before you submit them. The requests the grader simulates are printed in the question, and the simulator is the same one you use in the project.
  • Style is not marked. A longer policy that produces the required decisions scores exactly what a shorter one does.

Notes

Hands-on Cloud for Freshers — Unit 2: Who Can Do What: Identities and Permissions

Before you start

You need the hoc-admin user from Unit 1, with its password and MFA device, and a computer where you can install software. Nothing in this unit creates a server, storage or database. IAM is documented as “offered at no additional charge”, and the policy simulator evaluates policies without sending a real request to any AWS service.

If you are starting here without Unit 1, you need an AWS account whose root user has an MFA device, and an everyday administrator user: an IAM user named hoc-admin with console access and MFA, in a group hoc-admins that has the AWS managed policy AdministratorAccess. You also need one Region to work in; the examples use ap-south-1. The project for this unit lists the console steps for all three under If you do not have Unit 1’s setup, and the AWS pages they come from are under Sources.

Every statement here about how AWS behaves is taken from the AWS documentation pages listed under Sources at the end, retrieved on 2026-10-02. Commands are shown for a Linux or macOS terminal; where Windows differs, the difference is noted.

Summary

Every action in AWS — clicking a button in the console, running a command, a program calling an API — arrives at AWS as a request, and AWS answers each request with yes or no. The answer comes from policies: JSON documents that list which actions are allowed or denied on which resources. Three rules decide the answer: everything is denied unless something allows it, an allow is needed to say yes, and an explicit deny anywhere beats every allow. This unit teaches you to read and write those policies, to name resources precisely with ARNs, and to prove what a policy does with the policy simulator before it touches anything real. It also sets up the AWS command line, signed in with short-lived credentials, so that from Unit 3 onward you can build from a terminal without ever creating a long-term access key.

Key concepts

Term Definition
Principal The identity making a request: the root user, an IAM user, or a role that someone or something has assumed
Request One attempt to do one action on one resource, such as “list the objects in bucket X”. AWS allows or denies each request separately
Policy A JSON document of statements that allow or deny actions on resources. AWS evaluates the policies that apply to a request to decide it
Identity-based policy A policy attached to a user, group or role. It says what that identity may do
Resource-based policy A policy attached to a resource, such as a bucket policy. It names which principals may act on that resource
Statement One rule inside a policy, with an Effect, an Action list and a Resource list
Effect Allow or Deny — what the statement does when it matches a request
Action The operation a statement covers, written service:Operation, for example s3:GetObject
ARN Amazon Resource Name: the unique, written-out name of a resource, such as arn:aws:s3:::my-bucket. Used in the Resource element
Implicit deny The default answer: a request that no statement allows is denied without any statement saying so
Explicit deny A Deny statement that matches the request. It overrides every allow
AWS managed policy A ready-made policy created and maintained by AWS, such as AdministratorAccess
Customer managed policy A policy you write and store in your own account, which you can attach to many identities
Role An identity with permissions but no password or access keys. Whoever assumes it receives temporary credentials
Trust policy The resource-based policy on a role that says which principals may assume it
Least privilege Granting only the actions a task needs, on only the resources it needs
AWS CLI The AWS Command Line Interface: the aws command, which sends the same requests the console sends
Profile A named set of CLI settings — Region, how to get credentials — stored in your CLI configuration

Explanations

The failure, before the explanation

A learner wants a teammate to be able to read the files in one bucket, hoc-site-ar-4821, and nothing else. They write this policy, which looks right:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": "arn:aws:s3:::hoc-site-ar-4821/*"
    }
  ]
}

The teammate can download a file if they know its exact name. But when they ask for the list of files in the bucket, they get an access-denied error. Nothing in the policy says “deny”, and s3:ListBucket is written right there.

Run the same two requests through the IAM policy simulator and it shows the difference:

Action Resource the request is about Simulator decision
s3:GetObject arn:aws:s3:::hoc-site-ar-4821/index.html allowed
s3:ListBucket arn:aws:s3:::hoc-site-ar-4821 implicitDeny

Listing is something you do to the bucket. Reading is something you do to an object inside it. The policy only names the objects — /* means “everything inside” — so the listing request is about a resource that no statement covers. It is not refused by a rule; it is refused because no rule says yes. The rest of this unit explains why, and how to write it correctly.

How AWS decides: three rules

Start with entry to a college fest. The gate starts from “nobody gets in”. Your name on the guest list gets you in. But if your name is also on the banned list, the guest list does not matter. And a name that appears on neither list is simply turned away, even though nobody wrote “turn this person away”.

AWS decides every request the same way. Its policy evaluation documentation summarises the logic in three lines:

“By default, all requests are implicitly denied with the exception of the AWS account root user, which has full access. Requests must be explicitly allowed by a policy or set of policies … An explicit deny overrides an explicit allow.”

So, for an IAM user or role:

  1. Start at no. Every request begins denied.
  2. Look for a deny. If any applicable policy has a Deny statement matching the request, the answer is no — final, whatever else says yes.
  3. Look for an allow. If no deny matched, the request needs at least one statement that allows it. Without one, it stays at the starting no: an implicit deny.

Back to the fest: “nobody gets in” is the implicit deny, the guest list is an allow, and the banned list is an explicit deny.

A second way to see it: think of the three outcomes as three different error messages for three different fixes. An explicit deny means someone deliberately blocked this; adding another allow will not help, and you must find and change the deny. An implicit deny means nobody granted it; the fix is to add a correctly-written allow. Allowed means the policies are not your problem. The policy simulator reports exactly these three words, which is why you run it before guessing.

This explains the denial your hoc-practice user saw at the end of Unit 1: it had no policies at all, so every request it sent stopped at rule 1.

The anatomy of a policy

Think of a policy as a printed permission slip with three blanks filled in: allowed or not, to do what, to which thing. Here is a real one, filled in to let someone read the files in one bucket:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOneBucket",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::hoc-site-ar-4821/*"
    }
  ]
}
  • Version is the version of the policy language, not of your policy. AWS says to always include it and set it to 2012-10-17; with the older 2008-10-17, features such as policy variables like ${aws:username} are not recognised and are treated as plain text.
  • Statement is a list of rules. A policy can hold several.
  • Sid is an optional label so that you can tell statements apart.
  • Effect, Action, Resource are the heart of each rule: allow or deny, which operations, on which named resources. Action and Resource can each be a single string or a list.
  • Principal does not appear in an identity-based policy, because the identity it is attached to is the principal. It appears in resource-based policies, such as a role’s trust policy, to say who the rule is about.

The order of elements inside a statement does not matter, and some pairs cannot appear together in one statement — for example Action and NotAction.

A second way to read any policy is aloud, as one sentence per statement: “Allow s3:GetObject on every object in hoc-site-ar-4821.” If you cannot say a statement as a sentence, you do not yet know what it does.

Naming resources: ARNs

A postal address works because it narrows down step by step — country, state, city, street, house — until exactly one door matches. An ARN does the same for a resource in AWS: it is the full written name that a policy uses to point at exactly one thing, or at a pattern of things. AWS documents the general shape as:

arn:partition:service:region:account-id:resource

Some resources leave fields empty. Compare:

Resource ARN Why it looks like that
An IAM user arn:aws:iam::111122223333:user/hoc-admin IAM is global, so the Region field is empty
An S3 bucket arn:aws:s3:::hoc-site-ar-4821 A general purpose bucket name is unique across all accounts and Regions within a partition, so Region and account are empty
Every object in that bucket arn:aws:s3:::hoc-site-ar-4821/* The /* after the bucket name means every object key inside it
Objects under one prefix arn:aws:s3:::hoc-site-ar-4821/private/* Only keys that begin with private/

A second way to picture it: the ARN is the address on the envelope, and a policy statement only delivers to the addresses written on it. A letter to “the house” does not reach “everyone inside the house”, and the reverse is also true.

Now the failure from the start of the unit makes sense. AWS’s own S3 example policy for one bucket puts s3:ListBucket on arn:aws:s3:::amzn-s3-demo-bucket1 and s3:GetObject on arn:aws:s3:::amzn-s3-demo-bucket1/*. Bucket-level actions take the bucket ARN; object-level actions take an object ARN. The corrected policy has two statements:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListTheBucket",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::hoc-site-ar-4821"
    },
    {
      "Sid": "ReadItsObjects",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::hoc-site-ar-4821/*"
    }
  ]
}

One warning about shortcuts. AWS documents that an incomplete ARN in an identity-based policy is completed with wildcards, so arn:aws:sqs is treated as arn:aws:sqs:*:*:* — every queue in every Region and account. A short ARN is not a narrow one.

Explicit deny in practice

Imagine you lend a friend your hostel room key so they can use anything in the room — except they must never throw away the files in one drawer. You do not list every allowed object; you give the broad permission and add one firm exception. Explicit deny is how you write that exception. Suppose a policy allows every S3 action on every object in the bucket but must protect one folder:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::hoc-site-ar-4821/*"
    },
    {
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "arn:aws:s3:::hoc-site-ar-4821/private/*"
    }
  ]
}
Request Decision Which rule decided
s3:DeleteObject on …/notes.txt allowed The first statement allows it; no deny matches
s3:DeleteObject on …/private/keep.txt explicitDeny The second statement matches; it overrides the allow
s3:GetObject on …/private/keep.txt allowed The deny is only for deleting
s3:ListBucket on arn:aws:s3:::hoc-site-ar-4821 implicitDeny The allow names objects, not the bucket

The last row is the opening failure again, hiding inside a policy that looks generous.

A second way to think about it: an explicit deny is a fence, and allows are gates. You can open as many gates as you like, but none of them lets anyone through the fence.

Identity-based and resource-based policies together

A library card says what a member may borrow anywhere; a sign on one shelf can also say “open to all visitors”. Either one can let you take a book from that shelf, and a “not for loan” label on the book beats both. AWS has the same two places for permissions.

Some resources carry their own policy — an S3 bucket policy is the common example. AWS documents that when a user or role in the same account requests such a resource, “the resulting permissions are the union” of the identity-based and resource-based policies: an allow in either is enough, and “an explicit deny in either of these policies overrides the allow”. Put as a rule of thumb: when checking a same-account request, look in two places for a yes and in two places for a no. Unit 3 uses a bucket policy to make a website readable by the public, and this rule is how you reason about it.

Roles: permissions without a password

At a hotel desk you are handed a key card programmed for certain doors. It is not anyone’s personal key: whoever is handed it can open those doors until the card expires, and the desk decides who may be handed one. A role is that key card. It is an identity with permission policies, like a user, but AWS describes the key difference: “a role does not have standard long-term credentials such as a password or access keys associated with it. Instead, when you assume a role, it provides you with temporary security credentials.” A role has two policies doing two jobs:

  • its permissions policy says what the role may do;
  • its trust policy says who may assume it — for example, the Lambda service or the EC2 service.

A second picture: a company car. No employee owns it; the transport desk decides who may sign it out, and the car can only be driven where its permit allows. In later units your server and your function will each be handed a hoc- role this way, so that no access key is ever stored on them — which is what AWS recommends: “Require workloads to use temporary credentials with IAM roles to access AWS.”

Start broad, then narrow

A new intern is often given a visitor pass to the whole office on day one, and a badge for just their team’s floor once everyone knows what they actually need. Permissions grow up the same way. AWS’s best practices say to grant “only the permissions required to perform a task”, and describe a path to get there: start with AWS managed policies, which “might not grant least-privilege permissions for your specific use cases because they are available for use by all AWS customers”, and move to customer managed policies written for your case. Your hoc-admin user is the broad start. The policy you write in this unit’s project is the narrow end: one bucket, read only. Another way to see it: every action a policy allows is something that a mistake, or a stolen credential, can also do.

The command line, signed in without keys

Picture a learner who pastes an access key into a script and pushes the script to a public code repository. Anyone who reads the file can now send requests as that user, and AWS describes access keys as “long-term credentials”: the key keeps working until it is deactivated or deleted. That is the risk the rest of this section avoids.

The AWS CLI sends the same requests as the console. To use it you need credentials. AWS now documents aws login, which uses your existing console sign-in instead of an access key:

  • It needs AWS CLI version 2.32.0 or later.
  • It works for the root user, an IAM user or a federated identity. An IAM identity needs the SignInLocalDevelopmentAccess managed policy or equivalent permissions; hoc-admin already has them, because AdministratorAccess allows every action.
  • aws login opens your browser, you choose the console identity to use, and the CLI receives temporary credentials. It asks for a Region the first time; give it the Region you chose in Unit 1 (or, if you are starting here, the one Region you picked).
  • The CLI refreshes the credentials automatically every 15 minutes, for up to 12 hours at most; after that you run aws login again. aws logout deletes the cached credentials.
  • The result is stored as a profile in your CLI configuration with a login_session line naming your identity’s ARN, and the temporary credentials are cached under ~/.aws/login/cache.

A second way to compare the two: an access key is a house key you cut once and must remember to take back; aws login is a guest pass that stops working on its own.

To check which identity the CLI is using, run:

aws sts get-caller-identity

It prints your account ID, a user ID and your ARN, and AWS notes it needs no permissions at all — which makes it the first command to run whenever something is denied: before asking “what am I allowed to do?”, ask “who am I?”.

Proving a policy before it touches anything: the policy simulator

Pilots practise an engine failure in a flight simulator, not in the air. The answer is the same as it would be in a real cockpit, but nothing can crash. The IAM policy simulator evaluates policies against requests “without sending a real request to any AWS service”. In Custom mode you paste a policy you are still drafting; nothing is saved to your account. From the CLI, aws iam simulate-custom-policy does the same thing:

aws iam simulate-custom-policy \
  --policy-input-list file://hoc-read-policy.json \
  --action-names s3:ListBucket \
  --resource-arns arn:aws:s3:::hoc-site-ar-4821

The answer for each action and resource is one of allowed, explicitDeny or implicitDeny — the three outcomes from the start of this unit. A second way to use it: as a test suite for a policy. Write down the requests that must be allowed and the ones that must be denied, then run all of them every time you change the policy. file:// tells the CLI to read the value from a file relative to your current directory. AWS also warns that simulator results “can differ from your live AWS environment” in some advanced setups, so the simulator is your first check, not your only one.

Flashcards

Say the answer aloud before revealing it. Speaking it is what exposes the gaps that reading past a written answer hides.

What is the starting answer to every request from an IAM user?

No. Requests are implicitly denied until a policy allows them; only the root user starts with full access.

A request matches one Allow and one Deny statement. What happens?

It is denied. An explicit deny overrides any number of allows.

What is the difference between `implicitDeny` and `explicitDeny`?

Implicit: nothing allowed it, so you fix it by adding a correct allow. Explicit: a Deny statement matched, so another allow will not help — you must change the deny.

Why does `s3:ListBucket` on `arn:aws:s3:::bucket/*` not let you list the bucket?

Listing is a request about the bucket, whose ARN is arn:aws:s3:::bucket. The /* form names only the objects inside it, so the request matches no statement.

Why are the Region and account fields empty in an S3 bucket ARN?

A general purpose bucket name is unique across all accounts and Regions within a partition, so the name alone identifies the bucket.

What `Version` should every new policy use, and what breaks without it?

2012-10-17. With the older version, policy variables such as ${aws:username} are treated as plain text.

Why is there no `Principal` in an identity-based policy?

The identity the policy is attached to is the principal. Principal is used in resource-based policies, such as trust policies.

How is a role different from a user?

A role has no password or long-term access keys; whoever assumes it gets temporary credentials. A trust policy says who may assume it.

What does `aws login` need, and what does it give you?

CLI version 2.32.0 or later and a console identity with sign-in permissions. It gives the CLI temporary credentials that refresh automatically, so no access key is ever created.

Which command tells you which identity the CLI is acting as?

aws sts get-caller-identity. AWS notes it needs no permissions.

Does the policy simulator create or change anything?

No. It evaluates the policy without sending a real request, and a custom policy is not saved to your account.

Is `arn:aws:sqs` in an identity-based policy a narrow resource?

No. AWS completes an incomplete ARN with wildcards, so it means every queue in every Region and account.

Model answer

The question: “A teammate’s script gets an access-denied error when it lists a bucket, but their policy ‘allows S3 read’. Talk me through how you find the cause and fix it.”

A good answer covers five beats, in this order: who, what exactly, which kind of no, smallest fix, prove both sides. Missing one is a failure state: each beat removes one place the fault could be hiding, and a fix proposed before them is a guess. Spoken, it sounds like this:

“First, who: I run aws sts get-caller-identity with the script’s own profile, because if the script is running as a different user or role, everything after this answers the wrong question. Second, what exactly: I write the failing request as an action and a resource ARN — s3:ListBucket on arn:aws:s3:::the-bucket — rather than ‘reading the bucket’. Third, which kind of no: I put the policy and that request into the policy simulator. If it says explicitDeny, I go looking for the Deny statement; if it says implicitDeny, nothing matches, so I compare each statement’s Resource with the request’s ARN — and here the policy names only the-bucket/*, the objects, not the bucket. Fourth, the smallest fix: I move s3:ListBucket into its own statement on the bucket ARN and leave s3:GetObject on the objects, without widening anything to s3:*. Fifth, I prove both sides: I re-run the simulator for the request that must now be allowed and for one that must still be denied, such as s3:DeleteObject, because a fix tested only on the failing case can quietly open something else.”

Beat five is the one most answers drop.

Why this matters

  • “It works on my laptop but not on the server.” The two can be different principals — your user locally, a role on the server. Beat one finds out in a single command.
  • A bucket accidentally made writable to everyone. A policy written with s3:* and * to “just make it work” grants far more than reading. Least privilege is what stops a convenience becoming an incident.
  • A leaked access key in a public code repository. Long-term keys keep working until they are deactivated or deleted. Temporary credentials from aws login and roles expire on their own, which is why AWS recommends them.
  • Explaining a permission to a teammate. “What wins, allow or deny?” and “why can’t this user list the bucket?” are questions you can now answer from the three rules and an ARN, and prove with the simulator rather than argue about.

After this unit

The project for this unit is Sign In, Then Prove a Policy (project.md). You will install the AWS CLI and sign it in with aws login, write a read-only policy for the bucket you will create in Unit 3, prove it with the simulator against requests that must be allowed and must be denied, store it in your account as a customer managed policy, and then delete it and sign out.

Unit 3 creates that bucket for real, uploads a small website to it from the command line you set up here, and uses a bucket policy — a resource-based policy — to let the public read it.

Sources

All retrieved 2026-10-02.

Project

Hands-on Project — Sign In, Then Prove a Policy

Objective

Set up the AWS command line so that it holds only short-lived credentials, then write a read-only policy for the bucket you will create in Unit 3, prove with the policy simulator that it allows exactly what it should and denies everything else in a test list, store it in your account, and delete it again. You finish holding a working, signed-in command line and a tested policy file — and an account with nothing new left in it.

What this project needs: your hoc-admin user from Unit 1, a computer on which you can install the AWS CLI, and a text editor. The project creates no server, storage or database: IAM is documented as “offered at no additional charge”, and the policy simulator evaluates a policy “without sending a real request to any AWS service” (see Sources).

If you do not have Unit 1’s setup. You need two things from it, and possibly an account first:

  • No AWS account yet? Create one from https://aws.amazon.com (Create account) following AWS’s sign-up steps, choosing the Free account plan when asked to choose your account plan. Then sign in as the root user, open your account name → Security credentials, and under Multi-Factor Authentication (MFA) choose Assign MFA device (see Sources).
  • An everyday administrator user. Sign in as the root user, open IAM → Users → Create user, name it hoc-admin, tick Provide user access to the AWS Management Console, choose I want to create an IAM user and a custom password. On Set permissions, create a group hoc-admins with the AWS managed policy AdministratorAccess and add the user to it. Sign in as hoc-admin at https://<your-12-digit-account-id>.signin.aws.amazon.com/console and assign it an MFA device under Security credentials.
  • One Region. Pick one Region code — the examples use ap-south-1 — and use it for every unit.

Your evidence file. Keep one plain-text file, unit2-evidence.txt, with one key: value line for each output below. The rule for each value is printed beside it, so you can check your own file.

Choose your bucket name now, because Unit 3 creates it with this exact name: hoc-site-<your-initials>-<random-digits>, all lowercase — for example hoc-site-ar-4821. The examples below use hoc-site-ar-4821; replace it with yours everywhere.


Task 1 — Install the CLI and sign it in without a key

Scope: one installed CLI, one signed-in profile, one identity check. Do not create an access key at any point.

  1. Install the AWS CLI version 2 with one of the methods in the AWS install guide (Installing or updating to the latest version of the AWS CLI, see Sources). The guide’s installer packages are:

    • Linux x86 (64-bit): curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip", then unzip awscliv2.zip, then sudo ./aws/install
    • macOS: download and run https://awscli.amazonaws.com/AWSCLIV2.pkg
    • Windows: download and run https://awscli.amazonaws.com/AWSCLIV2.msi

    The same guide also documents an install script, which it calls the recommended method on all three systems: curl -fsSL https://awscli.amazonaws.com/v2/install.sh | bash on Linux and macOS, and irm https://awscli.amazonaws.com/v2/install.ps1 | iex in PowerShell on Windows. Use either route.

  2. Check the version: aws --version. aws login needs 2.32.0 or later. If yours is older, update it by following the update instructions in the same install guide.

  3. Make sure you are signed in to the console as hoc-admin in your browser, then run:

    aws login

    When asked for a Region, enter the Region you chose in Unit 1 or in the setup path above (for example ap-south-1). Your browser opens; choose hoc-admin and return to the terminal.

  4. Run aws sts get-caller-identity and read the Arn it prints. It should name the user you chose in step 3; if it names anything else, stop and work out why before continuing.

  5. Open your CLI configuration file — ~/.aws/config on Linux and macOS, %USERPROFILE%\.aws\config on Windows — and find the login_session line. Confirm that there is no ~/.aws/credentials file containing an access key for this account.

Time budget: 30 minutes

Output: add these lines to unit2-evidence.txt:

Line Rule for the value
cli-version: <value> the version number from aws --version, such as 2.32.4; three numbers, the first 2
caller-arn: <value> the Arn value copied from aws sts get-caller-identity
login-session-line: <value> the whole line from your config file that begins login_session
credentials-file-has-key: <value> yes or no: whether a credentials file for this account contains an access key

Task 2 — Write the policy and prove it in the simulator

Scope: one policy file, eight simulated requests. Stop when you have recorded all eight.

  1. In an empty folder, create hoc-read-policy.json with a policy whose intent is: its holder may list your bucket and read its objects, and do nothing else. Include "Version": "2012-10-17". Use the notes’ section on ARNs to decide which resource each action needs.

  2. From that folder, simulate each request below. One example:

    aws iam simulate-custom-policy \
      --policy-input-list file://hoc-read-policy.json \
      --action-names s3:ListBucket \
      --resource-arns arn:aws:s3:::hoc-site-ar-4821

    On Windows Command Prompt, put the command on one line instead of using \.

  3. Record the EvalDecision the simulator prints for each request:

    # Action Resource
    1 s3:ListBucket arn:aws:s3:::hoc-site-ar-4821
    2 s3:GetObject arn:aws:s3:::hoc-site-ar-4821/index.html
    3 s3:GetObject arn:aws:s3:::hoc-site-ar-4821/css/site.css
    4 s3:PutObject arn:aws:s3:::hoc-site-ar-4821/index.html
    5 s3:DeleteObject arn:aws:s3:::hoc-site-ar-4821/index.html
    6 s3:DeleteBucket arn:aws:s3:::hoc-site-ar-4821
    7 s3:GetObject arn:aws:s3:::some-other-bucket/index.html
    8 s3:ListBucket arn:aws:s3:::some-other-bucket

    Compare each decision with the policy’s intent from step 1. If any request your intent allows is not allowed, or any request outside it is allowed, fix the policy and run all eight again.

  4. Break it on purpose. Change the resource of the statement that holds s3:ListBucket to the /* object form, save, and re-run request 1. Write down the decision you get. Then put the resource back and re-run request 1 once more.

Time budget: 45 minutes

Output: keep hoc-read-policy.json, and add these lines to unit2-evidence.txt:

Line Rule for the value
decisions: <value> eight values in request order, separated by commas, each one of allowed, explicitDeny, implicitDeny, copied from EvalDecision
broken-request-1: <value> one of the same three words, copied from the run in step 4
policy-version: <value> the value of Version in your file

Task 3 — Store it, look at it, delete it (the habit)

Scope: one customer managed policy, created and deleted. It is never attached to anyone.

  1. Create the policy in your account, tagged for this course:

    aws iam create-policy \
      --policy-name hoc-read-site-bucket \
      --policy-document file://hoc-read-policy.json \
      --description "Read-only access to the hands-on-cloud site bucket" \
      --tags Key=project,Value=hands-on-cloud

    Copy the Arn from the output.

  2. In the console, open IAM → Policies, filter to Customer managed, and open hoc-read-site-bucket. Read its JSON, its Tags tab and its list of attached entities.

  3. Delete it. The delete-policy reference says a customer managed policy must first be detached from every identity and have only its default version; this one was never attached and has one version, so you can delete it directly:

    aws iam delete-policy --policy-arn <the Arn you copied>

    The command prints nothing when it succeeds.

  4. Sign the CLI out: aws logout. Then run aws sts get-caller-identity once more and record the first line of what it prints.

Teardown checklist

Tick each line only after you have looked:

  • IAM → Policies → Customer managed does not list hoc-read-site-bucket.
  • IAM → Users lists hoc-admin, and no user was created in this project.
  • No access key exists for hoc-admin (IAM → Users → hoc-admin → Security credentials → Access keys is empty).
  • aws logout has been run, and you recorded what aws sts get-caller-identity printed after it.
  • hoc-read-policy.json is saved somewhere you can find it in Unit 3.

Time budget: 15 minutes

Output: add these lines to unit2-evidence.txt:

Line Rule for the value
policy-arn: <value> the Arn from create-policy; it contains your 12-digit account ID and ends :policy/hoc-read-site-bucket
policy-tag: <value> the tag shown on the policy’s Tags tab, written key=value
policy-listed-after-delete: <value> yes or no: whether Customer managed policies list hoc-read-site-bucket after step 3
after-logout-first-line: <value> the first line aws sts get-caller-identity printed after aws logout, copied verbatim
teardown-checklist: <value> the number of checklist lines above you ticked, out of 5

What this feeds

Unit 3 opens with aws login and aws sts get-caller-identity, then creates the bucket whose name you chose above. hoc-read-policy.json is the identity-based half of that bucket’s access story; Unit 3 adds the resource-based half — a bucket policy — so that the public can read your website, and uses the evaluation rules from this unit to explain why both halves together give the result they do.


Sources

Every AWS behaviour this project relies on comes from these pages, all fetched 2026-10-02:

Quiz

Online marking is not open yet. Work through the questions and check the written ones against the criteria printed with each question. The answer key is kept back for now.

Quiz — Unit 2: Who Can Do What: Identities and Permissions

Instructions: Ten questions in two parts, and both parts are scored.

  • Questions 1–8 are multiple choice. Pick one option per question. They are marked by comparing your letter against the key.
  • Questions 9–10 ask you to write an answer in an exact format. Question 9 prints the requests your policy is tested with, so you can run them yourself before you submit; question 10 states the format of its answer.

Work closed-book on questions 1–8 and 10. On question 9 you may run the policy simulator as often as you like; checking your own policy against the printed requests is part of the exercise. The answer key, which holds the marking rules, is held separately.


1. A request from an IAM user matches no statement in any policy that applies to it. What does AWS decide?

a) Allowed, because none of the applicable policies contains a statement that denies it b) Denied by an explicit deny, because AWS adds a hidden Deny statement for unmatched requests c) Denied by an implicit deny, because every request starts denied until a policy allows it d) Allowed for read-only actions, because only write actions need a matching Allow statement


2. One policy on a user allows s3:* on arn:aws:s3:::hoc-quiz-bucket/*. A policy on the user’s group denies s3:DeleteObject on the same resource. The user tries to delete hoc-quiz-bucket/a.txt. What happens?

a) It is denied, because an explicit deny overrides any allow from any policy b) It is allowed, because a policy on the user outranks a policy on its group c) It is allowed, because the broader s3:* statement is evaluated before a narrow one d) It is denied only if the group policy was attached after the user’s own policy


3. You want a user to be able to list the objects in the bucket hoc-site-ar-4821. Which value must the Resource of the s3:ListBucket statement match?

a) arn:aws:s3:::hoc-site-ar-4821/* b) arn:aws:s3:ap-south-1::hoc-site-ar-4821 c) arn:aws:s3:::*/hoc-site-ar-4821 d) arn:aws:s3:::hoc-site-ar-4821


4. Why does AWS say every new policy should include "Version": "2012-10-17"?

a) A policy that leaves out the element is rejected when you try to attach it to an identity b) Under the older version, policy variables like ${aws:username} are read as plain text c) The value records the date you wrote the policy, and AWS evaluates newer policies first d) Explicit deny exists only in that version, so older policies can never block a request


5. Which element would you expect to find in a role’s trust policy but not in an identity-based policy attached to a user?

a) Principal, which names who the statement is about b) Effect, which says whether the statement allows or denies c) Action, which lists the operations the statement covers d) Version, which names the policy language the document uses


6. You have just run aws login, and the next command fails with an access-denied error. What is the most useful command to run first?

a) aws configure, to paste in an access key that replaces the temporary credentials b) aws logout --all, to clear every cached sign-in before you try the command again c) aws sts get-caller-identity, to see which identity the CLI is acting as d) aws iam create-policy, to grant the missing permission to whoever is signed in


7. In Custom mode, what does the IAM policy simulator do with the policy you paste into it?

a) It attaches the policy to your user for a moment and sends each test request to the service b) It evaluates it against your chosen requests without sending them, and saves nothing c) It saves the policy as a customer managed policy so that you can attach it after the test d) It sends each request to the service in a dry-run mode that rolls back any change it makes


8. A program you will run on an EC2 server needs to read objects from one bucket. Which approach matches AWS’s recommendation for credentials?

a) Create an access key for hoc-admin and copy it into a file on the server’s disk b) Run aws login on the server as the root user so the program receives short-lived credentials c) Create an IAM user for the server and store that user’s console password in a settings file d) Give the server a role that allows the read, so it receives temporary credentials


Part 2 — Constructed response


9. Write an identity-based policy, as a single JSON document, that lets its holder list the bucket hoc-quiz-bucket and read any object in it — and nothing else in the table below.

Your policy is tested by passing it to aws iam simulate-custom-policy once for each row below. Rows in the left column should come back allowed; rows in the right column should not.

Should be allowed Should not be allowed
s3:ListBucket on arn:aws:s3:::hoc-quiz-bucket s3:PutObject on arn:aws:s3:::hoc-quiz-bucket/index.html
s3:GetObject on arn:aws:s3:::hoc-quiz-bucket/index.html s3:DeleteObject on arn:aws:s3:::hoc-quiz-bucket/index.html
s3:GetObject on arn:aws:s3:::hoc-quiz-bucket/css/site.css s3:GetObject on arn:aws:s3:::other-bucket/index.html
s3:ListBucket on arn:aws:s3:::other-bucket
s3:DeleteBucket on arn:aws:s3:::hoc-quiz-bucket

The document must also be valid JSON and carry "Version": "2012-10-17".


10. Here is a policy attached to a user, and four requests the user makes. For each request, in order, write the simulator’s decision as exactly one of allowed, explicitDeny or implicitDeny, separated by commas — for example allowed,allowed,allowed,allowed (that example is the format, not the answer).

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::hoc-quiz-bucket/*" },
    { "Effect": "Deny", "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::hoc-quiz-bucket/private/*" },
    { "Effect": "Allow", "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::hoc-quiz-bucket" }
  ]
}
  1. s3:PutObject on arn:aws:s3:::hoc-quiz-bucket/private/a.txt
  2. s3:GetObject on arn:aws:s3:::hoc-quiz-bucket/private/a.txt
  3. s3:DeleteObject on arn:aws:s3:::hoc-quiz-bucket/a.txt
  4. s3:ListBucket on arn:aws:s3:::hoc-quiz-bucket

Sources

All retrieved 2026-10-02:

TechEazy Consulting training material — not affiliated with or endorsed by Amazon Web Services (AWS).