Grant least privilege through a group, then watch an explicit deny win

short · 25 min · Task statement 2.3

Task

Build the pattern AWS recommends: a customer managed policy that allows one action, attached to a group, with a user in the group. Then use the IAM policy simulator to prove what that user may and may not do, add an inline policy with an explicit deny, and see the deny override the group's allow. The user never gets a password or access keys, and you finish by confirming whether your own CloudShell session runs on a role's temporary credentials.

Steps

  1. Write a customer managed policy that allows listing your buckets and nothing else, and create it:
echo '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*"}]}' > list-buckets.json
aws iam create-policy --policy-name clf-lab09-list-buckets --policy-document file://list-buckets.json
  1. Create a group and attach the policy to it, so every member gets the same permission from one attachment:
aws iam create-group --group-name clf-lab09-readers
aws iam attach-group-policy --group-name clf-lab09-readers --policy-arn arn:aws:iam::111122223333:policy/clf-lab09-list-buckets
  1. Create a user with no credentials and put it in the group:
aws iam create-user --user-name clf-lab09-sam
aws iam add-user-to-group --user-name clf-lab09-sam --group-name clf-lab09-readers
  1. Ask the policy simulator what the user may do. It evaluates every policy that applies, including the group's, without the user making a single request:
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::111122223333:user/clf-lab09-sam --action-names s3:ListAllMyBuckets s3:DeleteBucket --query 'EvaluationResults[].[EvalActionName,EvalDecision]' --output text

Listing reads allowed. Deleting a bucket reads implicitDeny: nothing allows it, and everything starts denied. 5. Add an inline policy to the user that explicitly denies the very action the group allows:

echo '{"Version": "2012-10-17", "Statement": [{"Effect": "Deny", "Action": "s3:ListAllMyBuckets", "Resource": "*"}]}' > deny-list.json
aws iam put-user-policy --user-name clf-lab09-sam --policy-name clf-lab09-deny-list --policy-document file://deny-list.json

Run the simulator command from step 4 again. Listing now reads explicitDeny. An explicit deny in any applicable policy overrides an allow, wherever the allow came from. 6. Confirm that the user holds no long-term credentials:

aws iam list-access-keys --user-name clf-lab09-sam --query 'length(AccessKeyMetadata)'
aws iam get-login-profile --user-name clf-lab09-sam

The first prints 0. The second returns an error naming NoSuchEntity, because the user has no console password. 7. Look at your own identity:

aws sts get-caller-identity --query Arn --output text

If you signed in through IAM Identity Center, the ARN contains assumed-role and a role name starting AWSReservedSSO_: your session is a role created from a permission set, running on temporary credentials that expire on their own. If you are an IAM user, the ARN ends in user/ and your user name, which is why AWS recommends Identity Center for people.

Verify

aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::111122223333:user/clf-lab09-sam --action-names s3:ListAllMyBuckets --query 'EvaluationResults[0].EvalDecision' --output text

Expected output: explicitDeny.

aws iam list-attached-group-policies --group-name clf-lab09-readers --query 'AttachedPolicies[0].PolicyName' --output text

Expected output: clf-lab09-list-buckets.

Cost and clean-up

IAM is offered at no additional charge, so this lab is not expected to cost anything.

Created by this lab: the customer managed policy clf-lab09-list-buckets; the group clf-lab09-readers; the user clf-lab09-sam, with its inline policy clf-lab09-deny-list; the CloudShell files list-buckets.json and deny-list.json.

  1. Remove the user's inline policy, take the user out of the group, then delete the user:
aws iam delete-user-policy --user-name clf-lab09-sam --policy-name clf-lab09-deny-list
aws iam remove-user-from-group --user-name clf-lab09-sam --group-name clf-lab09-readers
aws iam delete-user --user-name clf-lab09-sam
  1. Detach the policy from the group and delete the group:
aws iam detach-group-policy --group-name clf-lab09-readers --policy-arn arn:aws:iam::111122223333:policy/clf-lab09-list-buckets
aws iam delete-group --group-name clf-lab09-readers
  1. Delete the customer managed policy, which is now attached to nothing:
aws iam delete-policy --policy-arn arn:aws:iam::111122223333:policy/clf-lab09-list-buckets
  1. Remove the working files from CloudShell:
rm list-buckets.json deny-list.json

Check it is gone

aws iam list-users --query "length(Users[?starts_with(UserName, 'clf-lab09')])"
aws iam list-groups --query "length(Groups[?starts_with(GroupName, 'clf-lab09')])"
aws iam list-policies --scope Local --query "length(Policies[?starts_with(PolicyName, 'clf-lab09')])"

Expected output: 0 from each of the three commands.

Notes

IAM deletes in a strict order: a user with an inline policy or a group membership cannot be deleted, a group with an attached policy cannot be deleted, and a policy still attached to something cannot be deleted. If a delete fails with DeleteConflict, the step before it was skipped. In a real organisation the person would get an IAM Identity Center user and a permission set rather than an IAM user; this lab uses an IAM user only because the simulator can test one without anyone signing in.

This is an independent study companion for the AWS Certified Cloud Practitioner (CLF-C02) exam and is not produced by or endorsed by Amazon Web Services. AWS, Amazon Web Services and AWS Certified Cloud Practitioner are trademarks of Amazon.com, Inc. or its affiliates.

This is an independent study companion for AWS Certified Cloud Practitioner CLF-C02 and is not produced by or endorsed by CompTIA.