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

PracticeDescriptionImplementation Method
Principle of Least PrivilegeGrant only the minimum permissions needed to complete workUse specific policies instead of administrator permissions
Role-Based AccessAuthorize through roles rather than users directlyCreate functional roles and have users assume them
Regular Permission ReviewsRegularly check and clean up unnecessary permissionsSet up automated review processes
Separation of DutiesCritical operations require multi-person collaborationUse MFA and approval workflows
Access LoggingRecord all access activitiesEnable 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