Overview
This project guides you through the basic understanding of IAM. In the project that you will execute using the AWS CLI, you will create users, you will assign them to groups. You will also create policies with different permissions to operate an S3 bucket. After attaching those policies to the groups you will experience allow and deny access to certain actions. That will give you an initial understanding on how permissions works in AWS.
What You Will Learn
- IAM users, groups and policies.
- AWS CLI commands.
- Scripting knowledge (Bash).
- Policy permissions. Allows and denies (explicit and implicit).
Prerequisites
- An AWS account.
- Basic knowledge of Python.
- How to configure AWS CLI profiles.
Steps
1. Create your S3 bucket.
This bucket will help us to check the permissions of our fictional IAM users.
BUCKET_NAME="iam-lab-$(aws sts get-caller-identity --query Account --output text)"
aws s3api create-bucket \
--bucket $BUCKET_NAME \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1
echo "============================================"
echo "Bucket ARN: arn:aws:s3:::$BUCKET_NAME"
echo "============================================"
- In the first command, we will call STS service to get the account id we are working on. The Account information is part of the
aws sts get-caller-indentitycall. We do this because the name of the bucket needs to be universally unique across all AWS accounts (including the ones from clients). Account Id is unique per account, so that will increase our chances that the bucket name is not taken. - Remember the format of any AWS CLI call:
aws [service] [command] [arguments] - Secondly, we create our bucket, using the name we composed before.
2. Create users
aws iam create-user --user-name frodo
aws iam create-user --user-name sam
# Verify both exist
aws iam list-users --query 'Users[*].UserName' --output table
echo "============================================"
echo "Users frodo and sam created!"
echo "============================================"
- Now create the users
frodoandsam. The minimal information we need to supply is the name. - We can verify if they are created.
3. Create policies
- We need to store on our project root, two policies that we will use to attach to our users.
- Policy file name:
dev-s3-policy.json - Note: remember to change
ACCOUNT_IDfor your account id.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::iam-lab-ACCOUNT_ID"
},
{
"Sid": "ReadWriteObjects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::iam-lab-ACCOUNT_ID/*"
}
]
}
- Policy file name:
audit-policy.json - Note: remember to change
ACCOUNT_IDfor your account id.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::iam-lab-ACCOUNT_ID"
},
{
"Sid": "ReadObjectsOnly",
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::iam-lab-ACCOUNT_ID/*"
}
]
}
- The difference between policies are in the list of actions that each policy can do. Importante to remember that when you create a user, that user has an implicity DENY for all the actions on AWS, so unless you attach the user a policy is not allow to do anything.
- The
dev-s3-policy.jsonpolicy is the typical permissions that you will attach to a developer that needs to list that bucket, but also read and write permissions to that bucket, so the developer can put and delete content. - The
audit-policy.jsonis a typical auditor/reader permissions which only allows to read, in this case, any object on this bucket.
aws iam create-policy \
--policy-name dev-s3-policy \
--policy-document file://dev-s3-policy.json \
--description "Developer read/write access to iam-lab bucket"
aws iam create-policy \
--policy-name audit-s3-policy \
--policy-document file://audit-policy.json \
--description "Auditor read-only access to iam-lab bucket"
4. Create groups and attach policies
# Create groups
aws iam create-group --group-name dev-group
aws iam create-group --group-name audit-group
echo "============================================"
echo "Groups created!"
echo "============================================"
# Attach policies to groups (replace ACCOUNT_ID)
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "============================================"
echo "Attach policies to the group!"
echo "============================================"
aws iam attach-group-policy \
--group-name dev-group \
--policy-arn arn:aws:iam::$ACCOUNT_ID:policy/dev-s3-policy
aws iam attach-group-policy \
--group-name audit-group \
--policy-arn arn:aws:iam::$ACCOUNT_ID:policy/audit-s3-policy\
- The policy ARN is the unique identifier of the policy and is deterministic, so we can compose when attaching to the groups. The policy already exists as resource on our account, based on the commands on the previous steps.
5. Adding users to the group and create access keys
echo "============================================"
echo "Adding users!"
echo "============================================"
aws iam add-user-to-group --user-name tom --group-name dev-group
aws iam add-user-to-group --user-name penny --group-name audit-group
echo "============================================"
echo "Confirming membership!"
echo "============================================"
# Confirm membership
aws iam get-group --group-name dev-group
aws iam get-group --group-name audit-group
echo "============================================"
echo "Creating access keys. After creation, configure the credentials!"
echo "============================================"
# Create access keys for both users
aws iam create-access-key --user-name tom
aws iam create-access-key --user-name penny
- To test the permissions we need use the credentials of each of our users on the AWS CLI to perform the respective actions. For that we need to create the access keys.
- After having access keys we need to configure the profiles for the AWS CLI with those credentials.
6. Perform actions for testing our setup
#!/bin/bash
BUCKET="your-bucket-name"
echo "=== Testing as tom (developer) ==="
# Should succeed
aws s3 cp /tmp/test.txt s3://$BUCKET/test.txt --profile tom && echo "PUT: OK"
aws s3 ls s3://$BUCKET --profile tom && echo "LIST: OK"
aws s3 cp s3://$BUCKET/test.txt /tmp/ --profile penny && echo "GET: OK"
echo ""
echo "=== Testing as penny (auditor) ==="
# LIST and GET should succeed
aws s3 ls s3://$BUCKET --profile penny && echo "LIST: OK"
aws s3 cp s3://$BUCKET/test.txt /tmp/ --profile penny && echo "GET: OK"
# PUT should fail with AccessDenied
aws s3 cp /tmp/test.txt s3://$BUCKET/penny.txt --profile penny \
&& echo "PUT: OK (unexpected!)" \
|| echo "PUT: DENIED (expected)"
- Using the
--profilewill make the CLI using the user respective credentials to authenticate in AWS. Once the user is authenticated, the STS service, will provide termporary credentials to access to AWS resources. After that, the CLI command will be executed, but before the policies attach to the user will be evaluated to determine if the user can or can not perform the desired operations. The evaluation process consist in gathering all the policies that apples. We will go depeer on this process in other projects, but for now, only important to know if during the evalution, the process finds a DENY (implicit or explicit), it has priority over any other statement, so the action will be denied. That’s the resource penny as auditor can not put objects on the bucket, because the audit policy does not have this action ALLOW, or what is the same, the policy implies a implicit DENY.
Clean Up
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Remove users from groups
aws iam remove-user-from-group --user-name alice --group-name dev-group
aws iam remove-user-from-group --user-name bob --group-name audit-group
# Delete access keys (list first to get the key ID)
alice_key=$(aws iam list-access-keys --user-name alice --query 'AccessKeyMetadata[0].AccessKeyId' --output text)
bob_key=$(aws iam list-access-keys --user-name bob --query 'AccessKeyMetadata[0].AccessKeyId' --output text)
aws iam delete-access-key --user-name alice --access-key-id $alice_key
aws iam delete-access-key --user-name bob --access-key-id $bob_key
# Detach policies from groups
aws iam detach-group-policy --group-name dev-group \
--policy-arn arn:aws:iam::$ACCOUNT_ID:policy/dev-s3-policy
aws iam detach-group-policy --group-name audit-group \
--policy-arn arn:aws:iam::ACCOUNT_ID:policy/audit-s3-policy
# Delete groups and users
aws iam delete-group --group-name dev-group
aws iam delete-group --group-name audit-group
aws iam delete-user --user-name tom
aws iam delete-user --user-name penny
# Delete the policies
aws iam delete-policy --policy-arn arn:aws:iam:$ACCOUNT_ID:policy/dev-s3-policy
aws iam delete-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/audit-s3-policy
# Delete the bucket
aws s3 rb s3://iam-lab-$ACCOUNT_ID --force