How to Configure AWS IAM Roles, Policies and Permissions
Master AWS IAM roles, policies, and permissions with hands-on CLI examples.
AWS Identity and Access Management (IAM) is the cornerstone of security in the AWS cloud. This guide walks you through creating IAM roles, attaching policies, and managing permissions using the AWS CLI. You'll learn how to define trust policies, apply least-privilege permissions, and test access with real commands. Whether you're preparing for the AWS Solutions Architect Associate or Security Specialty exam, these hands-on steps will solidify your understanding of IAM fundamentals and best practices.
Create an IAM Role with a Trust Policy
First, create a trust policy JSON file that defines which entities can assume the role. For example, allow an EC2 instance to assume the role by specifying the service principal 'ec2.amazonaws.com'. Save the policy as 'trust-policy.json' and use the AWS CLI command 'aws iam create-role' to create the role named 'EC2-S3-ReadOnly-Role'.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}Always restrict the trust policy to specific AWS accounts or services to avoid unauthorized access.
Never use a wildcard principal (*) in a trust policy unless absolutely necessary.
Attach a Managed Policy to the Role
Attach an AWS managed policy to grant permissions. For read-only S3 access, use the 'AmazonS3ReadOnlyAccess' policy. Run 'aws iam attach-role-policy --role-name EC2-S3-ReadOnly-Role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess'. Verify the attachment with 'aws iam list-attached-role-policies'.
aws iam attach-role-policy --role-name EC2-S3-ReadOnly-Role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam list-attached-role-policies --role-name EC2-S3-ReadOnly-RoleUse AWS managed policies for common use cases to reduce maintenance overhead.
Managed policies can be updated by AWS; review changes in the 'Changes' tab of the policy.
Create a Custom Inline Policy for Fine-Grained Permissions
For granular control, create an inline policy that allows listing only a specific S3 bucket. Write a JSON policy document with 's3:ListBucket' on 'arn:aws:s3:::my-secure-bucket' and attach it to the role using 'aws iam put-role-policy'. This ensures the role can only list objects in that bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-secure-bucket"
}
]
}Use condition keys like 'aws:SourceIp' to further restrict access based on IP address.
Inline policies are harder to audit; prefer managed policies for reusable permissions.
Launch an EC2 Instance with the IAM Role
Associate the IAM role with an EC2 instance at launch. Use the AWS CLI: 'aws ec2 run-instances --image-id ami-0abcdef1234567890 --instance-type t2.micro --iam-instance-profile Name=EC2-S3-ReadOnly-Role'. The instance will automatically inherit the role's permissions. Verify by SSHing into the instance and running 'aws s3 ls'.
aws ec2 run-instances --image-id ami-0abcdef1234567890 --instance-type t2.micro --iam-instance-profile Name=EC2-S3-ReadOnly-Role
aws s3 lsUse '--iam-instance-profile Arn' if you have the ARN instead of the name.
Ensure the AMI ID and subnet are valid for your region to avoid launch failures.
Test Permissions with the AWS CLI on the Instance
SSH into the EC2 instance and test the permissions. Run 'aws s3 ls s3://my-secure-bucket' to list objects. Then try to upload a file with 'aws s3 cp test.txt s3://my-secure-bucket/' — this should fail with an 'AccessDenied' error because the role only has read-only access. This validates least-privilege.
aws s3 ls s3://my-secure-bucket
aws s3 cp test.txt s3://my-secure-bucket/Use 'aws sts get-caller-identity' to confirm the role ARN being used.
Always clean up test resources to avoid ongoing costs.
Create a Cross-Account IAM Role
For cross-account access, modify the trust policy to allow a user from another AWS account to assume the role. Set the principal to the account ID: 'arn:aws:iam::123456789012:root'. Then attach a policy granting 's3:GetObject' on a specific bucket. The external user can assume the role using 'aws sts assume-role'.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole"
}
]
}Use external IDs for additional security when allowing third-party access.
Cross-account roles should be monitored with AWS CloudTrail for suspicious activity.
Review IAM Best Practices with the IAM Access Analyzer
Enable IAM Access Analyzer to identify resources shared with external entities. Run 'aws accessanalyzer create-analyzer --analyzer-name my-iam-analyzer --type ACCOUNT'. Then list findings with 'aws accessanalyzer list-findings --analyzer-arn <arn>'. This helps identify overly permissive policies and potential security risks.
aws accessanalyzer create-analyzer --analyzer-name my-iam-analyzer --type ACCOUNT
aws accessanalyzer list-findings --analyzer-arn arn:aws:access-analyzer:us-east-1:123456789012:analyzer/my-iam-analyzerReview findings regularly and archive false positives to reduce noise.
Access Analyzer has a cost; review pricing before enabling on large accounts.
Key tips
Always apply the principle of least privilege: grant only the permissions required for the task.
Use IAM roles instead of long-term access keys for EC2 instances and Lambda functions.
Enable IAM Access Analyzer to automatically detect overly permissive policies.
Use condition keys like 'aws:SourceIp' or 'aws:RequestedRegion' to add context-based restrictions.
Rotate IAM user access keys every 90 days and use AWS Secrets Manager for automated rotation.
Audit IAM policies with the IAM Policy Simulator before applying them to production.
Frequently asked questions
What is the difference between an IAM role and an IAM user?
An IAM user is a permanent identity with long-term credentials (password, access keys) used by a person or service. An IAM role is a temporary identity that can be assumed by trusted entities like AWS services, users, or external accounts. Roles use temporary security credentials via AWS STS, making them more secure for cross-account and service-to-service access.
How do I grant an EC2 instance access to an S3 bucket?
Create an IAM role with a trust policy that allows 'ec2.amazonaws.com' to assume it. Attach a policy granting the desired S3 permissions (e.g., 'AmazonS3ReadOnlyAccess'). Then launch the EC2 instance with the IAM role using the '--iam-instance-profile' parameter. The instance will automatically inherit the role's permissions.
Can I attach multiple policies to a single IAM role?
Yes, you can attach up to 20 managed policies and multiple inline policies to a single IAM role. The effective permissions are the union of all attached policies. Use managed policies for reusable permissions and inline policies for role-specific, fine-grained access. AWS evaluates all policies together when authorizing a request.
What is the AWS IAM Policy Simulator and how do I use it?
The IAM Policy Simulator is a tool that lets you test the effects of policies before applying them. You can select a user, group, or role, specify actions and resources, and see whether access is allowed or denied. It helps validate least-privilege and troubleshoot permission issues. Access it via the AWS Management Console under IAM > Policy Simulator.
How do I set up cross-account IAM access securely?
Create an IAM role in the target account with a trust policy that specifies the source account's root user or a specific IAM user as the principal. Attach a permissions policy granting only the necessary actions. The external user assumes the role using 'aws sts assume-role'. Use an external ID for third-party access and monitor with CloudTrail.
Practice with real exam questions
Apply what you just learned with exam-style practice questions.