Enforce MFA for All Users Accessing Cloud Services (AWS)

This runbook helps with a key task for SOC2 compliance, requiring Multi-Factor Authentication (MFA) for all cloud service users in AWS. This step strengthens security and access control, meeting SOC2's requirements for safeguarding data and maintaining robust account security in cloud environments.

  1. 1

    This lists all IAM users in an AWS account, providing key details like usernames, user IDs, and creation dates. Essential for managing permissions and auditing access, this function supports security and compliance protocols by offering a clear view of user entities and their access levels. It's instrumental in enforcing security policies and the principle of least privilege in AWS resource access management.

    import boto3 import botocore.exceptions creds = _get_creds(cred_label)['creds'] access_key = creds['username'] secret_key = creds['password'] # Initialize the IAM client iam_client = boto3.client('iam',aws_access_key_id=access_key,aws_secret_access_key=secret_key) try: # Create a paginator for the list_users operation paginator = iam_client.get_paginator('list_users') # Use the paginator to paginate through the users table = context.newtable() table.title = "User list" table.num_cols = 3 table.num_rows = 1 table.has_header_row = True rownum = 0 table.setval(rownum, 0, "User name") table.setval(rownum, 1, "User ID") table.setval(rownum, 2, "Created on") for page in paginator.paginate(): users = page['Users'] table.num_rows += len(page['Users']) # Output user details if users: # print("List of IAM Users:") for user in users: rownum += 1 # print(f"Username: {user['UserName']}, User ID: {user['UserId']}, Created On: {user['CreateDate']}") table.setval(rownum, 0, user['UserName']) table.setval(rownum, 1, user['UserId']) table.setval(rownum, 2, user['CreateDate']) else: print("No IAM users found in this page.") # Handle specific exceptions except botocore.exceptions.NoCredentialsError: print("Credentials not available") except botocore.exceptions.PartialCredentialsError: print("Incomplete credentials provided") except botocore.exceptions.SSLError: print("SSL connection could not be established. Ensure your network allows SSL connections to AWS services") except botocore.exceptions.EndpointConnectionError: print("Unable to connect to the endpoint. Check your AWS configuration and network settings") except botocore.exceptions.ClientError as e: print(f"Unexpected error occurred accessing AWS: {e}") # Handle general exceptions except Exception as e: print(f"An unhandled error occurred: {str(e)}")
    copied
    1
  2. 2

    This task aims at enhancing SOC2 compliance by identifying AWS IAM users without Multi-Factor Authentication (MFA). This process helps enforce strict access control measures, crucial for SOC2 guidelines, by pinpointing and addressing accounts lacking essential security features.

    import boto3 from botocore.exceptions import ClientError, BotoCoreError creds = _get_creds(cred_label)['creds'] access_key = creds['username'] secret_key = creds['password'] def check_mfa_enabled_for_users(iam_client): """ Checks if MFA is enabled for all IAM users with console access. :param iam_client: An IAM client from boto3 :return: Tuple containing counts of compliant, non-compliant, and not-applicable users """ compliant_count = 0 non_compliant_count = 0 not_applicable_count = 0 try: # Paginator to handle the case if there are more users than what a single call can return paginator = iam_client.get_paginator('list_users') table = context.newtable() table.title = "MFA compliance summary" table.num_cols = 3 table.num_rows = 1 table.has_header_row = True rownum = 0 table.setval(rownum,0, "User") table.setval(rownum,1, "Compliant") table.setval(rownum,2, "Console Access") for page in paginator.paginate(): table.num_rows += len(page['Users']) for user in page['Users']: rownum += 1 username = user['UserName'] table.setval(rownum,0, username) # Check if the user has console access by looking for login profile try: iam_client.get_login_profile(UserName=username) console_access = True table.setval(rownum,2, "YES") except iam_client.exceptions.NoSuchEntityException: console_access = False table.setval(rownum,2, "NO") not_applicable_count += 1 # User without console access # Check if the user has MFA enabled if console_access: mfa_devices = iam_client.list_mfa_devices(UserName=username)['MFADevices'] mfa_enabled = len(mfa_devices) > 0 # Update compliance status if not mfa_enabled: #print(f"User: {username} is NON-COMPLIANT - Console Access: Yes, MFA Enabled: No") non_compliant_count += 1 table.setval(rownum,1, "NO") else: #print(f"User: {username} is COMPLIANT - Console Access: Yes, MFA Enabled: Yes") compliant_count += 1 table.setval(rownum,1, "YES") except ClientError as e: print(f"AWS client error occurred: {e}") except BotoCoreError as e: print(f"Boto core error occurred: {e}") except Exception as e: print(f"An unexpected error occurred: {e}") return compliant_count, non_compliant_count, not_applicable_count # Create a boto3 client for IAM iam_client = boto3.client('iam',aws_access_key_id=access_key,aws_secret_access_key=secret_key) # Check if MFA is enabled for all IAM users with console access compliant, non_compliant, not_applicable = check_mfa_enabled_for_users(iam_client) # Print compliance summary print("\nCompliance Summary:") print(f"Total Compliant Users (MFA Enabled): {compliant}") print(f"Total Non-Compliant Users (MFA Disabled): {non_compliant}") print(f"Total Users for Whom MFA Check is Not Applicable (No Console Access): {not_applicable}") # Print final verdict if non_compliant == 0: print("\nFinal Verdict: COMPLIANT - All users with console access have MFA enabled.") else: print("\nFinal Verdict: NON-COMPLIANT - There are users with console access who do not have MFA enabled.")
    copied
    2