# ============================================================================== # == Purpose: Lambda function to query IAM to get ACCESS KEY AGE for any and all users. # == Assumption: 1. Destination S3 Bucket has ACL log-delivery-write set. # == 2. S3 target bucket on the choosen destination has to exist. Created with TF # == 3. CloudWatch will be used to schedule events # == 4. SNS will be used to send emails # == # == Release Date: 03.03.2020 # == Version: 1.0 # == Testing Env: DataArt AWS account. # == Reference: https://github.com/miztiik/serverless-iam-key-sentry # == Change 03.01.2020: # == # == Author: DataArt # ============================================================================== import boto3 import datetime import os import json from botocore.exceptions import ClientError # ============================================================================== # Variable Definitions REGION_NAME= "us-east-1" SNS_ARN = "" CONDITION_80_DAYS = 80 CONDITION_KEY_AGE_DAYS = 90 BUCKET_NAME = "im443-589295909756-logs" #============================ # Define login 1st of 2 functions def get_key_age(CONDITION_KEY_AGE_DAYS_value_goes_here): # ******************************************************************************************************************************** # Defining internal variables for this get_key_age function # from https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.client iamclient = boto3.client('iam', region_name=REGION_NAME) snsClient = boto3.client('sns', region_name=REGION_NAME) # from https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam.html?highlight=client.list_users#IAM.Client.list_users # Leaving it empty so that it can return all users in the AWS account userlist = iamclient.list_users() # Generate container with JSON module to create a dictionary with list to host user's old keys users_with_old_keys = {'Users':[]} # Getting current time differences by substracting delta (the difference between today and what will be passed to keyage def) time_diff_result = datetime.datetime.now() - datetime.timedelta( days = int(CONDITION_KEY_AGE_DAYS_value_goes_here)) # ******************************************************************************************************************************** # Now starting the real work... # Iterate through list of users and compare it with "get_key_age" function's result for user in userlist['Users']: # from https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam.html?highlight=client.list_users#IAM.Client.list_access_keys # Returning information about the IAM user and associated access key ID access_keys = iamclient.list_access_keys(UserName=user['UserName']) # From the access_keys var and for each key get response # From this response get AccessKeyMetadata index dict property for each_key in access_keys['AccessKeyMetadata']: # this is the content of each_key var: # {'UserName': 'agerasimenko', 'AccessKeyId': 'AKIAYxxxxxxxxxxxxxxxxxx', # 'Status': 'Active', 'CreateDate': datetime.datetime(2019, 12, 26, 9, 24, 33, tzinfo=tzlocal())} # Now... if the time difference is greater than those on each access key... if time_diff_result.date() > each_key['CreateDate'].date(): #--------------------------------------------------------------------------------- # If the time difference is greater than each access key... #if time_diff_result.date() > each_key['CreateDate'].date(): # get index of users_with_old_keys, append to it the username properties and substract the result of each_key (basically, a date) users_with_old_keys['Users'].append({'UserName': user['UserName'], 'Access Key Age in Days':(datetime.date.today() - each_key['CreateDate'].date()).days}) #else: if age > CONDITION_80_DAYS: send email else: try: snsClient.get_topic_attributes(TopicArn = SNS_ARN) # from https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html?highlight=sns#SNS.Client.publish # from https://docs.python.org/3/library/json.html to serialize object to JSON snsClient.publish(TopicArn = SNS_ARN, Message = json.dumps(users_with_old_keys)) except ClientError as this_error: pass return users_with_old_keys # This function is what AWS Lambda calls: handler, and will run first invoquing to def get_key_age(CONDITION_KEY_AGE_DAYS_value_goes_here): def lambda_handler(event, context): global CONDITION_KEY_AGE_DAYS # this will call "def get_key_age(CONDITION_KEY_AGE_DAYS_value_goes_here):" passing KEY_AGE variable set above return get_key_age(CONDITION_KEY_AGE_DAYS) # ==============================================================================