Chapter 03: Deep Dive into IAM Roles
Deep dive into AWS IAM role mechanisms, including service roles, cross-account access, and federated identity advanced applications
Haiyue
22min
Chapter 03: Deep Dive into IAM Roles
Learning Objectives
- Understand IAM role concepts and use cases
- Create and configure service roles
- Set up cross-account role access
- Configure federated identity roles
- Master role switching and temporary credentials
Role System Architecture Diagram
🔄 正在渲染 Mermaid 图表...
3.1 IAM Role Fundamentals
3.1.1 Differences Between Roles and Users
tip Core Differences
| Feature | IAM User | IAM Role |
|---|---|---|
| Identity Type | Permanent | Temporary |
| Credentials | Long-term | Temporary |
| Use Case | Human Access | Service-to-Service |
| Permission Acquisition | Direct Attachment | Assume to Get |
| Security | Requires Key Management | Auto Rotation |
3.1.2 How Roles Work
🔄 正在渲染 Mermaid 图表...
3.1.3 Creating Basic IAM Roles
import boto3
import json
from datetime import datetime, timedelta
def create_basic_role(role_name, trusted_entity, description=""):
"""
Create basic IAM role
Args:
role_name: Role name
trusted_entity: Trusted entity (service or account)
description: Role description
"""
iam = boto3.client('iam')
# Basic trust policy templates
trust_policy_templates = {
'ec2': {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
'lambda': {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
'cross-account': {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": f"arn:aws:iam::{trusted_entity}:root"
},
"Action": "sts:AssumeRole"
}
]
}
}
try:
# Select trust policy
if trusted_entity in trust_policy_templates:
trust_policy = trust_policy_templates[trusted_entity]
elif trusted_entity.startswith('arn:aws:iam::'):
# Cross-account role
trust_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": trusted_entity
},
"Action": "sts:AssumeRole"
}
]
}
else:
# Custom service
trust_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": trusted_entity
},
"Action": "sts:AssumeRole"
}
]
}
# Create role
response = iam.create_role(
RoleName=role_name,
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description=description,
MaxSessionDuration=3600, # 1 hour
Tags=[
{
'Key': 'CreatedBy',
'Value': 'IAM-Automation'
},
{
'Key': 'CreatedDate',
'Value': datetime.now().strftime('%Y-%m-%d')
}
]
)
print(f"✅ Role {role_name} created successfully")
print(f" ARN: {response['Role']['Arn']}")
return response['Role']
except Exception as e:
print(f"❌ Failed to create role: {str(e)}")
return None
# Examples of creating different types of roles
ec2_role = create_basic_role("EC2-S3-Access-Role", "ec2", "Role for EC2 instances to access S3")
lambda_role = create_basic_role("Lambda-Execution-Role", "lambda", "Lambda function execution role")
3.2 Service Roles Explained
3.2.1 EC2 Instance Roles
def create_ec2_instance_role():
"""
Create EC2 instance role and instance profile
"""
iam = boto3.client('iam')
# 1. Create role
trust_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
try:
# Create role
role_response = iam.create_role(
RoleName='EC2-WebServer-Role',
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description='Role for EC2 web servers with S3 and CloudWatch access'
)
role_arn = role_response['Role']['Arn']
print(f"✅ EC2 role created successfully: {role_arn}")
# 2. Attach AWS managed policies
managed_policies = [
'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess',
'arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy'
]
for policy_arn in managed_policies:
iam.attach_role_policy(
RoleName='EC2-WebServer-Role',
PolicyArn=policy_arn
)
print(f"✅ Policy attached: {policy_arn}")
# 3. Create custom policy
custom_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::my-web-logs/*"
},
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "arn:aws:ssm:*:*:parameter/webserver/*"
}
]
}
policy_response = iam.create_policy(
PolicyName='EC2-WebServer-CustomPolicy',
PolicyDocument=json.dumps(custom_policy),
Description='Custom policy for web server specific permissions'
)
# Attach custom policy
iam.attach_role_policy(
RoleName='EC2-WebServer-Role',
PolicyArn=policy_response['Policy']['Arn']
)
# 4. Create instance profile
iam.create_instance_profile(
InstanceProfileName='EC2-WebServer-Profile'
)
# 5. Add role to instance profile
iam.add_role_to_instance_profile(
InstanceProfileName='EC2-WebServer-Profile',
RoleName='EC2-WebServer-Role'
)
print("✅ EC2 instance profile created")
# 6. Example of using role when launching EC2 instance
ec2_launch_example = """
# Specify instance profile when launching EC2 instance
import boto3
ec2 = boto3.client('ec2')
response = ec2.run_instances(
ImageId='ami-0abcdef1234567890',
MinCount=1,
MaxCount=1,
InstanceType='t3.micro',
IamInstanceProfile={
'Name': 'EC2-WebServer-Profile'
},
SecurityGroupIds=['sg-12345678'],
SubnetId='subnet-12345678'
)
"""
print("📝 EC2 instance launch example:")
print(ec2_launch_example)
return role_arn
except Exception as e:
print(f"❌ Failed to create EC2 role: {str(e)}")
return None
# Test permissions in EC2 role
def test_ec2_role_permissions():
"""
Sample code to test role permissions in EC2 instance
"""
test_code = """
# This code should run in EC2 instance
import boto3
# EC2 instance automatically uses attached IAM role
s3 = boto3.client('s3')
ssm = boto3.client('ssm')
try:
# Test S3 read permission
buckets = s3.list_buckets()
print(f"✅ S3 access successful, found {len(buckets['Buckets'])} buckets")
# Test SSM parameter access
parameters = ssm.get_parameters_by_path(
Path='/webserver/',
Recursive=True
)
print(f"✅ SSM parameter access successful, found {len(parameters['Parameters'])} parameters")
# Test uploading logs to S3
s3.put_object(
Bucket='my-web-logs',
Key=f'access-logs/{datetime.now().strftime("%Y/%m/%d")}/access.log',
Body='Sample log content'
)
print("✅ Log upload to S3 successful")
except Exception as e:
print(f"❌ Permission test failed: {str(e)}")
"""
print("📝 Permission test code in EC2 instance:")
print(test_code)
create_ec2_instance_role()
test_ec2_role_permissions()
3.2.2 Lambda Execution Roles
def create_lambda_execution_role(function_name, additional_permissions=None):
"""
Create Lambda function execution role
Args:
function_name: Lambda function name
additional_permissions: List of additional permissions
"""
iam = boto3.client('iam')
role_name = f"Lambda-{function_name}-ExecutionRole"
# Lambda basic trust policy
trust_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
try:
# 1. Create role
role_response = iam.create_role(
RoleName=role_name,
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description=f'Execution role for Lambda function {function_name}'
)
role_arn = role_response['Role']['Arn']
print(f"✅ Lambda execution role created successfully: {role_arn}")
# 2. Attach basic Lambda execution policy
iam.attach_role_policy(
RoleName=role_name,
PolicyArn='arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
)
# 3. Attach additional permissions as needed
if additional_permissions:
# Create custom policy
custom_policy = {
"Version": "2012-10-17",
"Statement": additional_permissions
}
policy_response = iam.create_policy(
PolicyName=f'Lambda-{function_name}-CustomPolicy',
PolicyDocument=json.dumps(custom_policy),
Description=f'Custom permissions for Lambda function {function_name}'
)
# Attach custom policy
iam.attach_role_policy(
RoleName=role_name,
PolicyArn=policy_response['Policy']['Arn']
)
print(f"✅ Custom policy attached")
return role_arn
except Exception as e:
print(f"❌ Failed to create Lambda role: {str(e)}")
return None
# Create Lambda roles for specific scenarios
def create_specialized_lambda_roles():
"""
Create Lambda roles for specific scenarios
"""
# 1. S3 processing Lambda role
s3_permissions = [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::my-lambda-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::my-lambda-bucket"
}
]
s3_role = create_lambda_execution_role("S3Processor", s3_permissions)
# 2. DynamoDB processing Lambda role
dynamodb_permissions = [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Query",
"dynamodb:Scan"
],
"Resource": "arn:aws:dynamodb:*:*:table/MyTable*"
}
]
dynamodb_role = create_lambda_execution_role("DynamoDBProcessor", dynamodb_permissions)
# 3. SNS/SQS processing Lambda role
messaging_permissions = [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:*:*:MyTopic"
},
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:SendMessage"
],
"Resource": "arn:aws:sqs:*:*:MyQueue"
}
]
messaging_role = create_lambda_execution_role("MessagingProcessor", messaging_permissions)
print("\n📋 Lambda roles creation summary:")
print(f" S3 processing role: {s3_role}")
print(f" DynamoDB processing role: {dynamodb_role}")
print(f" Messaging processing role: {messaging_role}")
create_specialized_lambda_roles()
3.3 Cross-Account Role Access
3.3.1 Setting Up Cross-Account Roles
def create_cross_account_role(trusted_account_id, role_name, external_id=None):
"""
Create cross-account access role
Args:
trusted_account_id: Trusted AWS account ID
role_name: Role name
external_id: External ID (optional, enhances security)
"""
iam = boto3.client('iam')
# Build trust policy
trust_statement = {
"Effect": "Allow",
"Principal": {
"AWS": f"arn:aws:iam::{trusted_account_id}:root"
},
"Action": "sts:AssumeRole"
}
# Add condition if external ID provided
if external_id:
trust_statement["Condition"] = {
"StringEquals": {
"sts:ExternalId": external_id
}
}
trust_policy = {
"Version": "2012-10-17",
"Statement": [trust_statement]
}
try:
# Create cross-account role
role_response = iam.create_role(
RoleName=role_name,
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description=f'Cross-account role for account {trusted_account_id}',
MaxSessionDuration=3600,
Tags=[
{
'Key': 'Type',
'Value': 'CrossAccount'
},
{
'Key': 'TrustedAccount',
'Value': trusted_account_id
}
]
)
role_arn = role_response['Role']['Arn']
print(f"✅ Cross-account role created successfully: {role_arn}")
# Attach example permission policy
cross_account_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::shared-data-bucket",
"arn:aws:s3:::shared-data-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeSecurityGroups"
],
"Resource": "*"
}
]
}
# Create and attach policy
policy_response = iam.create_policy(
PolicyName=f'{role_name}-Policy',
PolicyDocument=json.dumps(cross_account_policy),
Description=f'Policy for cross-account role {role_name}'
)
iam.attach_role_policy(
RoleName=role_name,
PolicyArn=policy_response['Policy']['Arn']
)
print(f"✅ Cross-account policy attached")
# Provide usage instructions
usage_info = f"""
📝 Cross-Account Role Usage Instructions:
1. Role ARN: {role_arn}
2. External ID: {external_id if external_id else 'None'}
3. Trusted Account: {trusted_account_id}
Use this role in trusted account:
import boto3
sts = boto3.client('sts')
# Assume role
response = sts.assume_role(
RoleArn='{role_arn}',
RoleSessionName='CrossAccountSession'{external_id_param}
)
# Use temporary credentials
credentials = response['Credentials']
s3 = boto3.client(
's3',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken']
)
"""
external_id_param = f",\n ExternalId='{external_id}'" if external_id else ""
print(usage_info.format(
role_arn=role_arn,
external_id_param=external_id_param
))
return role_arn
except Exception as e:
print(f"❌ Failed to create cross-account role: {str(e)}")
return None
def assume_cross_account_role(role_arn, session_name, external_id=None, duration=3600):
"""
Assume cross-account role
Args:
role_arn: Role ARN
session_name: Session name
external_id: External ID
duration: Session duration (seconds)
"""
sts = boto3.client('sts')
try:
# Build AssumeRole parameters
assume_role_params = {
'RoleArn': role_arn,
'RoleSessionName': session_name,
'DurationSeconds': duration
}
if external_id:
assume_role_params['ExternalId'] = external_id
# Assume role
response = sts.assume_role(**assume_role_params)
credentials = response['Credentials']
assumed_role_user = response['AssumedRoleUser']
print(f"✅ Successfully assumed role")
print(f" User ARN: {assumed_role_user['Arn']}")
print(f" Credentials expiration time: {credentials['Expiration']}")
# Create client using temporary credentials
temp_session = boto3.Session(
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken']
)
# Test permissions
s3_client = temp_session.client('s3')
try:
buckets = s3_client.list_buckets()
print(f"✅ S3 access test successful, can access {len(buckets['Buckets'])} buckets")
except Exception as e:
print(f"⚠️ S3 access test failed: {str(e)}")
return temp_session
except Exception as e:
print(f"❌ Failed to assume role: {str(e)}")
return None
# Example of creating cross-account role
cross_account_role = create_cross_account_role(
trusted_account_id="123456789012",
role_name="CrossAccount-DataAccess-Role",
external_id="unique-external-id-12345"
)
Summary
This chapter provided an in-depth introduction to various aspects of AWS IAM roles:
- Role Fundamentals: Understanding the differences between roles and users and how they work
- Service Roles: Creating and configuring EC2 instance roles and Lambda execution roles
- Cross-Account Access: Secure cross-account role setup and advanced condition configuration
- Federated Identity: Implementation of SAML 2.0 and OIDC federated identity
- Session Management: Using temporary credentials and session policies
- Security Best Practices: Role permission auditing and monitoring alerts
Through this chapter, you should be able to:
- Proficiently create and manage various types of IAM roles
- Implement secure cross-account access
- Configure federated identity integration
- Manage role sessions and temporary credentials
- Audit and monitor role usage
In the next chapter, we will learn the detailed syntax and advanced features of IAM policies.