AWS IAM: Architecting Identity, Access, and Authorization at Scale

AWS IAM policy design, role architecture, CLI operations, security best practices, and integration patterns

@geomenaWed Jun 25 2025#aws-roadmap#security#identity1,176 views

Every AWS environment, regardless of scale or complexity, depends on a single foundational service to govern who may access what, and under which conditions. AWS Identity and Access Management — commonly referred to as IAM — serves as the centralized authentication and authorization backbone for the entire AWS ecosystem. It is not optional, nor is it a service you configure once and forget. IAM demands deliberate architectural thinking from the very first resource you provision.

The core challenge IAM addresses is multifaceted: granular permission control across hundreds of AWS services, secure credential lifecycle management, comprehensive access auditing, and the elimination of hardcoded credentials from application code. The relevant question is never whether to use IAM, but rather how to design a permission structure that is both secure and scalable from day one.

IAM is a global service — it is not region-scoped. Users, roles, groups, and policies you create are available across all AWS regions within the account.

Key Concepts

ConceptDescription
PoliciesJSON documents that define specific permissions — which actions are permitted on which resources. They answer one question: "What can this identity do?"
Identity-based PoliciesPolicies attached to identities such as users, groups, or roles. Example: "This user may read from S3 and write to CloudWatch."
Resource-based PoliciesPolicies attached directly to resources like S3 buckets or Lambda functions. Example: "This S3 bucket permits access from a specific role."
UsersIdentities representing human operators. They carry permanent credentials — a password, access keys, or both — that persist until manually rotated.
GroupsLogical collections of users sharing identical permissions, dramatically simplifying administration at scale.
RolesIdentities designed for temporary assumption by AWS services, applications, or cross-account users. They issue temporary credentials that expire and renew automatically.
Trust PolicyA specialized policy defining which principals may assume a given role. This is the role's authorization gate — it answers: "Who is permitted to use these permissions?"
Instance ProfileA container that makes a role attachable to EC2 instances, serving as the technical bridge between IAM roles and the compute layer.
Managed PoliciesPre-built policies maintained by AWS. Examples include AmazonS3ReadOnlyAccess and AmazonSSMManagedInstanceCore.
Custom PoliciesPolicies you author for specific use cases, granting full control over exact permission boundaries.
Instance Metadata ServiceAn internal service at 169.254.169.254 that furnishes temporary credentials to EC2 instances, enabling SDKs like boto3 to obtain credentials without any manual configuration.
ARNAmazon Resource Name — the unique identifier for every AWS resource. Format: arn:aws:service:region:account:resource.

Essential AWS CLI Commands

Create a custom policy
aws iam create-policy \
  --policy-name MyCustomPolicy \
  --policy-document file://policy.json \
  --description "Policy description"
Create a user
aws iam create-user \
  --user-name developer-john
Create access keys for CLI and SDK usage
aws iam create-access-key --user-name developer-john
Create a password for console login
aws iam create-login-profile \
  --user-name developer-john \
  --password 'TempPassword123!' \
  --password-reset-required
Create a group
aws iam create-group --group-name backend-developers
Add a user to a group
aws iam add-user-to-group \
  --user-name developer-john \
  --group-name backend-developers
Step 1: Define the trust policy
cat > trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Service": "ec2.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}
EOF
Step 2: Create the role
aws iam create-role \
  --role-name EC2AccessRole \
  --assume-role-policy-document file://trust-policy.json \
  --description "Role for EC2 instances"
Create an instance profile
aws iam create-instance-profile \
  --instance-profile-name EC2AccessProfile
Associate the role to the instance profile
aws iam add-role-to-instance-profile \
  --instance-profile-name EC2AccessProfile \
  --role-name EC2AccessRole
Attach a policy to a user
aws iam attach-user-policy \
  --user-name developer-john \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy
Attach a policy to a group
aws iam attach-group-policy \
  --group-name backend-developers \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Attach a custom policy to a role
aws iam attach-role-policy \
  --role-name EC2AccessRole \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy
Attach an AWS managed policy to a role
aws iam attach-role-policy \
  --role-name EC2AccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
List users
aws iam list-users
List groups
aws iam list-groups
List roles
aws iam list-roles
List custom policies
aws iam list-policies --scope Local
List AWS managed policies
aws iam list-policies --scope AWS
View policies attached to a user
aws iam list-attached-user-policies --user-name developer-john
View policies attached to a group
aws iam list-attached-group-policies --group-name backend-developers
View policies attached to a role
aws iam list-attached-role-policies --role-name EC2AccessRole
View the content of a policy version
aws iam get-policy-version \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy \
  --version-id v1
View members of a group
aws iam get-group --group-name backend-developers
List instance profiles
aws iam list-instance-profiles
View credentials from inside an EC2 instance
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
Update a user password
aws iam update-login-profile \
  --user-name developer-john \
  --password 'NewPassword456!'
Rotate access keys -- create a new key
aws iam create-access-key --user-name developer-john
Rotate access keys -- delete the old key
aws iam delete-access-key \
  --user-name developer-john \
  --access-key-id AKIAIOSFODNN7EXAMPLE
Update the trust policy of a role
aws iam update-assume-role-policy \
  --role-name EC2AccessRole \
  --policy-document file://new-trust-policy.json
Detach a policy from a user
aws iam detach-user-policy \
  --user-name developer-john \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy
Detach a policy from a group
aws iam detach-group-policy \
  --group-name backend-developers \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Detach a policy from a role
aws iam detach-role-policy \
  --role-name EC2AccessRole \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy
Remove a user from a group
aws iam remove-user-from-group \
  --user-name developer-john \
  --group-name backend-developers
Delete access keys
aws iam delete-access-key \
  --user-name developer-john \
  --access-key-id AKIAIOSFODNN7EXAMPLE
Delete console access
aws iam delete-login-profile --user-name developer-john
Delete a user -- must have no policies or access keys
aws iam delete-user --user-name developer-john
Delete a group -- must be empty
aws iam delete-group --group-name backend-developers
Remove a role from an instance profile
aws iam remove-role-from-instance-profile \
  --instance-profile-name EC2AccessProfile \
  --role-name EC2AccessRole
Delete an instance profile
aws iam delete-instance-profile \
  --instance-profile-name EC2AccessProfile
Delete a role -- must have no attached policies
aws iam delete-role --role-name EC2AccessRole
Delete a custom policy
aws iam delete-policy \
  --policy-arn arn:aws:iam::123456789012:policy/MyCustomPolicy

Architecture and Flows

IAM Identity and Permission Architecture

EC2 Authentication Flow with IAM Role

IAM User vs IAM Role: Credential Lifecycle

Best Practices

Security

The principle of least privilege is non-negotiable. Every policy should grant the absolute minimum set of permissions required for the task at hand. Using "Action": "*" or "Resource": "*" in production is a critical security liability.

  • Never use the root user for day-to-day operations — create dedicated IAM users for all administrative tasks
  • Enable MFA on every privileged account without exception
  • Rotate access keys on a cadence no longer than 90 days
  • Prefer roles over hardcoded keys — for any application running within AWS, roles with temporary credentials are the only defensible approach
  • Write specific resource ARNs in policies rather than relying on wildcard resource declarations
  • Constrain trust policies to the narrowest possible set of principals
  • Audit permissions regularly using IAM Access Analyzer to identify unused or excessive grants
  • Never commit credentials to version control under any circumstances

Cost Optimization

  • IAM itself is entirely free — there is no charge for users, groups, roles, or policies
  • Delete unused resources — orphaned users, roles, and policies create unnecessary attack surface
  • Consolidate and reuse policies rather than creating duplicates for each identity

Performance and Reliability

  • SDK credential caching — AWS SDKs automatically cache temporary credentials from roles, minimizing metadata service calls
  • Maintain multiple admin users — never depend on a single administrative identity
  • Version custom policies through infrastructure-as-code tooling such as Terraform or CloudFormation
  • Implement Service Control Policies for multi-account organizations managed through AWS Organizations

Operational Excellence

  • Adopt strict naming conventions — descriptive names such as prod-api-ec2-role or dev-s3-access-policy make auditing straightforward
  • Tag all IAM resources with metadata like Environment, Team, and Project
  • Manage IAM through infrastructure as code — Terraform and CloudFormation provide version control, peer review, and repeatability
  • Enable CloudTrail to maintain a complete audit trail of every IAM action
  • Enforce environment separation — distinct roles and policies for development, staging, and production

Common Mistakes

Cost Considerations

IAM Pricing Summary

ResourceCost
IAM UsersFree — no limit
GroupsFree — no limit
RolesFree — no limit
PoliciesFree — limit of 10,000 custom policies per account
Instance ProfilesFree
AssumeRole operationsFree
CloudTrail logs for IAMOnly the S3 storage cost for the destination bucket
ServicePricing
CloudTrail$2 per 100,000 events after the first 5,000 free per month
IAM Access Analyzer$0.20 per 100 findings after the first 10,000 free

Optimization Strategies

  • Remove unused resources — orphaned roles, users, and policies should be deleted as part of regular hygiene
  • Consolidate policies — reuse shared policies across identities rather than duplicating definitions
  • Disable users rather than deleting when there is a reasonable expectation they may be needed again

IAM is permanently free and fully covered under the AWS Free Tier with no 12-month expiration. There is no limit on standard IAM usage, making it one of the few AWS services with zero direct cost regardless of scale.

Integration with Other Services

AWS ServiceIntegration MechanismTypical Use Case
EC2Instance Profiles allow EC2 to assume rolesGrant instances access to S3, RDS, and secrets without hardcoded keys
LambdaExecution Role defines function permissionsAllow Lambda to write logs, access DynamoDB, and invoke other functions
S3Bucket Policies and IAM policies operate in tandemControl who may read from or write to specific buckets
RDSIAM Database AuthenticationAuthenticate database connections without static passwords
Secrets ManagerIAM policies govern secret accessRegulate access to API keys, passwords, and certificates
CloudWatchIAM policies authorize log and metric writesEC2 and Lambda send logs using role-derived permissions
DynamoDBGranular table-level IAM policiesRestrict access to read-only, write-only, or specific item conditions
STSGenerates temporary credentials for role assumptionServes as the backend engine for the entire role-based credential system
Systems ManagerSession Manager uses IAM roles instead of SSH keysConnect to EC2 instances without opening SSH ports, authenticating through IAM
API GatewayIAM authorization mode for API endpointsRequire AWS Signature V4 signing on incoming requests
CloudFormationService Role defines stack-level permissionsAllow CloudFormation to create and manage resources on your behalf
OrganizationsService Control Policies at the organizational levelRestrict permissions across entire accounts or organizational units
IAM Identity CenterTemporary role assignment through single sign-onProvide unified login across multiple AWS accounts

Additional Resources

Official Documentation

Whitepapers

Tools

Tutorials and Workshops