Deactivate long-lasting AWS IAM Keys

This runbook refers to a security best practice where IAM access keys that have been active for an extended period of time are deactivated to prevent potential unauthorized use. This runbook involves monitoring the age of IAM access keys and automatically deactivating any that exceed a specified age threshold (e.g., 90 days). This proactive approach enhances security by reducing the likelihood of compromised keys being used for unauthorized or malicious activity over prolonged periods. Implementing this runbook typically involves using AWS SDK to interact with the IAM API, retrieving all user keys, evaluating their ages, and deactivating those that are deemed to be too old.

threshold_age=90 # Hardcoded for a single execution result for the whole runbook
copied
  1. 1

    This task identifies and isolates AWS IAM (Identity and Access Management) access keys that have surpassed a predefined age threshold. AWS IAM keys are utilized to securely control access to AWS services and resources. As a best practice for secure access management, it is recommended to regularly rotate IAM access keys and retire those that are no longer needed or have become outdated. By filtering out old access keys, administrators can ensure that access credentials are not overly permissive or unnecessarily prolonged, thereby enhancing the security posture. This task involves analyzing the creation date of each IAM access key, comparing it against the current date, and identifying keys that exceed the acceptable age limit, which are then either flagged for review to uphold stringent access control and minimize potential security risks.

    import boto3 from datetime import datetime 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) # Define the threshold age in days #threshold_age = 55 # List to store old access key data old_keys_data = [] try: # Initialize a flag for old keys detection old_keys_found = False # Check access keys for each user for user in users: username = user['UserName'] access_keys = iam_client.list_access_keys(UserName=username)['AccessKeyMetadata'] # Check age of each access key for key in access_keys: #print(key) # for debugging key_age = (datetime.now(datetime.utcnow().astimezone().tzinfo) - key['CreateDate']).days if key_age > int(threshold_age): print(f"User: {username}, Access Key: {key['AccessKeyId']}, Age: {key_age} days, Status: {key['Status']}") old_keys_found = True # Add old key data to list old_keys_data.append({ 'username': username, 'access_key_id': key['AccessKeyId'] }) # If no old keys are found, print a message if not old_keys_found: print("No access keys older than the defined threshold were found.") else: print("Old key data: ", old_keys_data) # Pass `old_keys_data` to downstream task here except boto3.exceptions.botocore.exceptions.PartialCredentialsError as pce: print(f"Credentials error: {str(pce)}") except boto3.exceptions.botocore.exceptions.BotoCoreError as bce: print(f"BotoCore Error: {str(bce)}") except boto3.exceptions.botocore.exceptions.ClientError as ce: print(f"Client Error: {str(ce)}") except Exception as e: print(f"An unexpected error occurred: {str(e)}") context.skip_sub_tasks=True
    copied
    1
    1. 1.1

      This task involves deactivating IAM (Identity and Access Management) access keys in AWS that have surpassed a specified age or are no longer in use, as a measure to enhance security. Regularly auditing and deactivating stale or outdated access keys restrict unauthorized or inadvertent access to AWS resources and services. This task deactivates access keys that are identified as old, thereby ensuring they cannot be used to authenticate API requests. This practice is pivotal in a robust IAM policy to assure that only active and necessary access keys are in circulation, thereby safeguarding the AWS environment against potential malicious activities or inadvertent misconfigurations by reducing the attack surface and adhering to the principle of least privilege.

      import boto3 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) ''' # Example input data old_keys_data = [ {'username': 'xyz_other_account', 'access_key_id': 'AJHBVFNONLHGBFHAS2CM'}, # ... received from parent task ] ''' try: # Check if old_keys_data is not empty if old_keys_data: # Loop through each key data in the input for key_data in old_keys_data: username = key_data['username'] access_key_id = key_data['access_key_id'] # Deactivate the access key #iam_client.update_access_key(UserName=username, AccessKeyId=access_key_id, Status='Inactive') print(f"Deactivated access key {access_key_id} for user {username}") else: print("No old keys provided for deactivation.") except boto3.exceptions.botocore.exceptions.PartialCredentialsError as pce: print(f"Credentials error: {str(pce)}") except boto3.exceptions.botocore.exceptions.BotoCoreError as bce: print(f"BotoCore Error: {str(bce)}") except boto3.exceptions.botocore.exceptions.ClientError as ce: print(f"Client Error: {str(ce)}") except Exception as e: print(f"An unexpected error occurred: {str(e)}") context.proceed=False
      copied
      1.1
    2. 1.2

      This task involves generating a new set of credentials – an access key ID and a secret access key – for an AWS Identity and Access Management (IAM) user. These credentials are vital for programmatic access to AWS services, enabling API calls to be authenticated and authorized. Within AWS, an IAM user can have a maximum of two active access keys, facilitating seamless key rotation. The procedure to create an access key includes the automatic creation of an access key ID and a secret key, which should be securely stored immediately upon creation, as AWS does not allow for the retrieval of the secret key at a later time. Implementing good practices, such as routinely rotating and responsibly managing access keys, is crucial to maintaining secure user access to AWS services.

      import boto3 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) if old_keys_data: # Iterate over old keys data and create new keys for the respective users for old_key in old_keys_data: try: new_key = iam_client.create_access_key(UserName=old_key['username']) print(f"New key created for {old_key['username']}:") print(new_key) except iam_client.exceptions.LimitExceededException as lee: print(f"Limit Error creating key for {old_key['username']}: {str(lee)}") except iam_client.exceptions.NoSuchEntityException as nee: print(f"No Such Entity Error for {old_key['username']}: {str(nee)}") except iam_client.exceptions.ServiceFailureException as sfe: print(f"Service Failure for {old_key['username']}: {str(sfe)}") except Exception as e: print(f"An unexpected error occurred while creating key for {old_key['username']}: {str(e)}") else: print("No old keys data was passed to this task") context.proceed=False
      copied
      1.2
    3. 1.3

      This task pertains to managing and refreshing AWS Identity and Access Management (IAM) user credentials to uphold security best practices. IAM access keys, which consist of an access key ID and a secret access key, are used to authenticate AWS API requests. However, if these keys are compromised or simply aged, updating them becomes crucial to safeguard the account. Updating might involve changing the status of the keys (activating or deactivating them), in this case we are deactivating them. The practice of regularly updating access keys is crucial in minimizing the risk associated with long-term key usage or potential unauthorized access.

      import boto3 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: # Check if old_keys_data is not empty if old_keys_data: # Loop through each key data in the input for key_data in old_keys_data: username = key_data['username'] access_key_id = key_data['access_key_id'] # Deactivate the access key iam_client.update_access_key(UserName=username, AccessKeyId=access_key_id, Status='Inactive') print(f"Deactivated access key {access_key_id} for user {username}") else: print("No old keys provided for deactivation.") except boto3.exceptions.botocore.exceptions.PartialCredentialsError as pce: print(f"Credentials error: {str(pce)}") except boto3.exceptions.botocore.exceptions.BotoCoreError as bce: print(f"BotoCore Error: {str(bce)}") except boto3.exceptions.botocore.exceptions.ClientError as ce: print(f"Client Error: {str(ce)}") except Exception as e: print(f"An unexpected error occurred: {str(e)}") context.proceed=False
      copied
      1.3
    4. 1.4

      This task refers to the removal of an AWS Identity and Access Management (IAM) user's access keys, ensuring they can no longer be used for authentication with AWS services and resources. IAM access keys comprise an access key ID and a secret access key, which are employed to sign programmatic requests that you make to AWS. Whether it is for security compliance, a response to a security incident, or part of a key rotation policy, deleting an IAM access key is a critical operation. After deletion, any applications or users utilizing the deleted access key will lose access to AWS resources, so it is crucial to update all instances where the key is used before deletion. Additionally, AWS recommends regular access key rotation as a best practice, which involves creating a new key, updating all applications to use the new key, and then safely deleting the old key to maintain secure and functional access control.

      import boto3 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) # Check if there is data to process if old_keys_data: # Iterate over old keys data and try to delete each key for old_key in old_keys_data: try: iam_client.delete_access_key( UserName=old_key['username'], AccessKeyId=old_key['access_key_id'] ) print(f"Deleted access key {old_key['access_key_id']} for user {old_key['username']}.") except iam_client.exceptions.NoSuchEntityException as nee: print(f"No Such Entity Error for {old_key['username']} with key {old_key['access_key_id']}: {str(nee)}") except iam_client.exceptions.LimitExceededException as lee: print(f"Limit Error for {old_key['username']} with key {old_key['access_key_id']}: {str(lee)}") except iam_client.exceptions.ServiceFailureException as sfe: print(f"Service Failure for {old_key['username']} with key {old_key['access_key_id']}: {str(sfe)}") except Exception as e: print(f"An unexpected error occurred while deleting key for {old_key['username']} with key {old_key['access_key_id']}: {str(e)}") else: print("No old keys data was passed to this task")
      copied
      1.4