Chapter 02: IAM User and Group Management
Haiyue
22min
Chapter 02: IAM User and Group Management
Learning Objectives
- Create and manage IAM users
- Set up user access credentials
- Create and manage user groups
- Implement hierarchical user permission management
- Configure Multi-Factor Authentication (MFA)
Key Concepts
IAM User Types and Uses
🔄 正在渲染 Mermaid 图表...
User Group Management Architecture
🔄 正在渲染 Mermaid 图表...
Example Code
Complete IAM User Management Example
import boto3
import json
import secrets
import string
from datetime import datetime
from botocore.exceptions import ClientError
class IAMUserManager:
"""
IAM User Manager - Provides complete user lifecycle management
"""
def __init__(self):
self.iam = boto3.client('iam')
def create_user_with_credentials(self, username, enable_console=True,
enable_programmatic=True, groups=None):
"""
Create a user and configure access credentials
Args:
username: Username
enable_console: Whether to enable console access
enable_programmatic: Whether to enable programmatic access
groups: List of user groups
"""
print(f"Creating user: {username}")
try:
# 1. Create user
user_response = self.iam.create_user(
UserName=username,
Tags=[
{'Key': 'CreatedBy', 'Value': 'IAMManager'},
{'Key': 'CreatedDate', 'Value': datetime.now().isoformat()},
{'Key': 'Environment', 'Value': 'Development'}
]
)
user_arn = user_response['User']['Arn']
print(f"✓ User created successfully: {user_arn}")
credentials = {}
# 2. Configure console access
if enable_console:
password = self._generate_password()
self.iam.create_login_profile(
UserName=username,
Password=password,
PasswordResetRequired=True
)
credentials['console_password'] = password
print("✓ Console access enabled")
# 3. Configure programmatic access
if enable_programmatic:
access_key_response = self.iam.create_access_key(UserName=username)
access_key = access_key_response['AccessKey']
credentials['access_key_id'] = access_key['AccessKeyId']
credentials['secret_access_key'] = access_key['SecretAccessKey']
print("✓ Programmatic access enabled")
# 4. Add to user groups
if groups:
for group_name in groups:
try:
self.iam.add_user_to_group(
GroupName=group_name,
UserName=username
)
print(f"✓ User added to group: {group_name}")
except ClientError as e:
if e.response['Error']['Code'] == 'NoSuchEntity':
print(f"⚠️ Group does not exist, will create group: {group_name}")
self.create_group(group_name)
self.iam.add_user_to_group(
GroupName=group_name,
UserName=username
)
print(f"✓ User added to newly created group: {group_name}")
else:
print(f"❌ Failed to add to group: {e}")
return credentials
except ClientError as e:
if e.response['Error']['Code'] == 'EntityAlreadyExists':
print(f"❌ User {username} already exists")
else:
print(f"❌ Failed to create user: {e}")
return None
def create_group(self, group_name, description="", policies=None):
"""
Create a user group and attach policies
Args:
group_name: Group name
description: Group description
policies: List of policy ARNs to attach
"""
print(f"Creating user group: {group_name}")
try:
# Create group
response = self.iam.create_group(
GroupName=group_name,
Path='/departments/'
)
group_arn = response['Group']['Arn']
print(f"✓ Group created successfully: {group_arn}")
# Attach policies
if policies:
for policy_arn in policies:
try:
self.iam.attach_group_policy(
GroupName=group_name,
PolicyArn=policy_arn
)
print(f"✓ Policy attached: {policy_arn}")
except ClientError as e:
print(f"❌ Failed to attach policy {policy_arn}: {e}")
return group_arn
except ClientError as e:
if e.response['Error']['Code'] == 'EntityAlreadyExists':
print(f"❌ Group {group_name} already exists")
else:
print(f"❌ Failed to create group: {e}")
return None
def setup_mfa_for_user(self, username, device_name="default"):
"""
Set up MFA device for a user
Args:
username: Username
device_name: MFA device name
"""
print(f"Setting up MFA for user {username}")
try:
# Create virtual MFA device
response = self.iam.create_virtual_mfa_device(
VirtualMFADeviceName=f"{username}-{device_name}",
Tags=[
{'Key': 'Owner', 'Value': username},
{'Key': 'CreatedDate', 'Value': datetime.now().isoformat()}
]
)
mfa_device = response['VirtualMFADevice']
serial_number = mfa_device['SerialNumber']
qr_code_png = mfa_device['QRCodePNG']
print(f"✓ MFA device created successfully")
print(f" Device serial number: {serial_number}")
print(f" QR code data length: {len(qr_code_png)} bytes")
# Note: In production, you need to display the QR code to the user for scanning
# Then obtain two consecutive TOTP codes to activate the device
print("📱 Please scan the QR code with your MFA app, then call enable_mfa_device method")
return {
'serial_number': serial_number,
'qr_code_png': qr_code_png
}
except ClientError as e:
print(f"❌ Failed to create MFA device: {e}")
return None
def enable_mfa_device(self, username, serial_number, auth_code1, auth_code2):
"""
Enable MFA device
Args:
username: Username
serial_number: MFA device serial number
auth_code1: First authentication code
auth_code2: Second authentication code
"""
try:
self.iam.enable_mfa_device(
UserName=username,
SerialNumber=serial_number,
AuthenticationCode1=auth_code1,
AuthenticationCode2=auth_code2
)
print(f"✓ MFA device enabled: {serial_number}")
return True
except ClientError as e:
print(f"❌ Failed to enable MFA device: {e}")
return False
def rotate_access_keys(self, username):
"""
Rotate user access keys
Args:
username: Username
"""
print(f"Rotating access keys for user {username}")
try:
# 1. Get existing access keys
current_keys = self.iam.list_access_keys(UserName=username)
if len(current_keys['AccessKeyMetadata']) >= 2:
print("❌ User already has 2 access keys, cannot create more")
return None
# 2. Create new access key
new_key_response = self.iam.create_access_key(UserName=username)
new_key = new_key_response['AccessKey']
print(f"✓ New access key created successfully: {new_key['AccessKeyId']}")
print(f"📋 New key information:")
print(f" Access Key ID: {new_key['AccessKeyId']}")
print(f" Secret Access Key: {new_key['SecretAccessKey']}")
# 3. Prompt user to update application configuration
print("⚠️ Please update application configuration to use the new access key")
print("⚠️ After confirming the new key works properly, call delete_old_access_key method to delete old key")
return new_key
except ClientError as e:
print(f"❌ Failed to rotate access keys: {e}")
return None
def delete_access_key(self, username, access_key_id):
"""
Delete specified access key
Args:
username: Username
access_key_id: Access key ID to delete
"""
try:
self.iam.delete_access_key(
UserName=username,
AccessKeyId=access_key_id
)
print(f"✓ Access key deleted: {access_key_id}")
return True
except ClientError as e:
print(f"❌ Failed to delete access key: {e}")
return False
def get_user_summary(self, username):
"""
Get detailed user information summary
Args:
username: Username
"""
print(f"Getting detailed information for user {username}")
try:
summary = {}
# Basic user information
user = self.iam.get_user(UserName=username)
summary['user'] = {
'username': user['User']['UserName'],
'arn': user['User']['Arn'],
'user_id': user['User']['UserId'],
'create_date': user['User']['CreateDate'].isoformat(),
'tags': user['User'].get('Tags', [])
}
# Login profile
try:
login_profile = self.iam.get_login_profile(UserName=username)
summary['console_access'] = {
'enabled': True,
'password_reset_required': login_profile['LoginProfile']['PasswordResetRequired'],
'create_date': login_profile['LoginProfile']['CreateDate'].isoformat()
}
except ClientError as e:
if e.response['Error']['Code'] == 'NoSuchEntity':
summary['console_access'] = {'enabled': False}
# Access keys
access_keys = self.iam.list_access_keys(UserName=username)
summary['access_keys'] = []
for key in access_keys['AccessKeyMetadata']:
summary['access_keys'].append({
'access_key_id': key['AccessKeyId'],
'status': key['Status'],
'create_date': key['CreateDate'].isoformat()
})
# User groups
groups = self.iam.get_groups_for_user(UserName=username)
summary['groups'] = [group['GroupName'] for group in groups['Groups']]
# Directly attached policies
attached_policies = self.iam.list_attached_user_policies(UserName=username)
summary['attached_policies'] = [
policy['PolicyName'] for policy in attached_policies['AttachedPolicies']
]
# Inline policies
inline_policies = self.iam.list_user_policies(UserName=username)
summary['inline_policies'] = inline_policies['PolicyNames']
# MFA devices
mfa_devices = self.iam.list_mfa_devices(UserName=username)
summary['mfa_devices'] = [
device['SerialNumber'] for device in mfa_devices['MFADevices']
]
return summary
except ClientError as e:
print(f"❌ Failed to get user information: {e}")
return None
def _generate_password(self, length=12):
"""
Generate secure password
Args:
length: Password length
"""
# Ensure password contains various character types
password_chars = (
string.ascii_lowercase +
string.ascii_uppercase +
string.digits +
"!@#$%^&*()"
)
password = ''.join(secrets.choice(password_chars) for _ in range(length))
# Ensure it contains at least one digit, uppercase letter, lowercase letter, and symbol
if (not any(c.islower() for c in password) or
not any(c.isupper() for c in password) or
not any(c.isdigit() for c in password) or
not any(c in "!@#$%^&*()" for c in password)):
return self._generate_password(length)
return password
# Usage example
def demo_user_management():
"""
User management demonstration
"""
manager = IAMUserManager()
# 1. Create development group
dev_policies = [
'arn:aws:iam::aws:policy/PowerUserAccess', # Development environment permissions
]
manager.create_group('developers', 'Development team', dev_policies)
# 2. Create user
credentials = manager.create_user_with_credentials(
username='john.developer',
enable_console=True,
enable_programmatic=True,
groups=['developers']
)
if credentials:
print("\n🔐 User Credentials:")
if 'console_password' in credentials:
print(f" Console Password: {credentials['console_password']}")
if 'access_key_id' in credentials:
print(f" Access Key ID: {credentials['access_key_id']}")
print(f" Secret Access Key: {credentials['secret_access_key'][:8]}...")
# 3. Set up MFA
mfa_info = manager.setup_mfa_for_user('john.developer')
# 4. Get user summary
summary = manager.get_user_summary('john.developer')
if summary:
print("\n📋 User Summary:")
print(json.dumps(summary, indent=2, default=str))
# Group management example
def setup_organizational_groups():
"""
Set up organizational user group structure
"""
manager = IAMUserManager()
# Define organizational structure and permissions
groups_config = {
'administrators': {
'description': 'System administrators with full access',
'policies': [
'arn:aws:iam::aws:policy/AdministratorAccess'
]
},
'developers': {
'description': 'Application developers',
'policies': [
'arn:aws:iam::aws:policy/PowerUserAccess'
]
},
'devops': {
'description': 'DevOps engineers',
'policies': [
'arn:aws:iam::aws:policy/job-function/SystemAdministrator'
]
},
'analysts': {
'description': 'Data analysts',
'policies': [
'arn:aws:iam::aws:policy/job-function/DataScientist'
]
},
'readonly': {
'description': 'Read-only access users',
'policies': [
'arn:aws:iam::aws:policy/ReadOnlyAccess'
]
}
}
# Create all groups
for group_name, config in groups_config.items():
manager.create_group(
group_name=group_name,
description=config['description'],
policies=config['policies']
)
print(f"✓ Group {group_name} setup complete")
print("\n🏢 Organizational structure setup complete!")
if __name__ == "__main__":
print("IAM User and Group Management Demo")
print("=" * 50)
# Run demonstration
setup_organizational_groups()
demo_user_management()
Password Policy Configuration
import boto3
from botocore.exceptions import ClientError
def configure_password_policy():
"""
Configure account password policy
"""
iam = boto3.client('iam')
# Define strong password policy
password_policy = {
'MinimumPasswordLength': 12,
'RequireSymbols': True,
'RequireNumbers': True,
'RequireUppercaseCharacters': True,
'RequireLowercaseCharacters': True,
'AllowUsersToChangePassword': True,
'MaxPasswordAge': 90, # Expires in 90 days
'PasswordReusePrevention': 5, # Cannot reuse last 5 passwords
'HardExpiry': False # Allow login after expiration but must change
}
try:
iam.update_account_password_policy(**password_policy)
print("✓ Account password policy updated")
print("Policy details:")
for key, value in password_policy.items():
print(f" - {key}: {value}")
except ClientError as e:
print(f"❌ Failed to set password policy: {e}")
def get_password_policy():
"""
Get current password policy
"""
iam = boto3.client('iam')
try:
response = iam.get_account_password_policy()
policy = response['PasswordPolicy']
print("Current password policy:")
for key, value in policy.items():
print(f" - {key}: {value}")
return policy
except ClientError as e:
if e.response['Error']['Code'] == 'NoSuchEntity':
print("⚠️ No custom password policy set, using AWS default policy")
else:
print(f"❌ Failed to get password policy: {e}")
return None
if __name__ == "__main__":
configure_password_policy()
get_password_policy()
User Lifecycle Management
User State Management Flow
🔄 正在渲染 Mermaid 图表...
Permission Management Best Practices
| Practice | Description | Implementation Method |
|---|---|---|
| Principle of Least Privilege | Grant only the minimum permissions needed to complete work | Use specific policies instead of administrator permissions |
| Role-Based Access | Authorize through roles rather than users directly | Create functional roles and have users assume them |
| Regular Permission Reviews | Regularly check and clean up unnecessary permissions | Set up automated review processes |
| Separation of Duties | Critical operations require multi-person collaboration | Use MFA and approval workflows |
| Access Logging | Record all access activities | Enable CloudTrail and CloudWatch |
MFA Configuration Recommendations
- Administrator Accounts: MFA must be enabled
- Privileged Users: MFA is recommended
- Programmatic Access: Use roles instead of long-term access keys
- Mobile Devices: Use hardware tokens or authentication apps
- Backup Devices: Configure multiple MFA devices in case of loss
Security Considerations
- Access Key Management: Rotate regularly, don’t hardcode in code
- Password Security: Use strong passwords, avoid reuse
- Permission Inheritance: Understand that group permissions are inherited by users
- Temporary Credentials: Prefer using roles and temporary credentials
- Monitor Anomalies: Set up alerts for abnormal access
Management Tips
- Use tags to manage users and groups for batch operations
- Establish naming conventions, such as username format: firstname.lastname
- Set up automated scripts to handle routine user management tasks
- Use IAM condition keys for more fine-grained permission control
- Regularly generate IAM credential reports for security audits