Skip to content

Instantly share code, notes, and snippets.

@andymotta
Created October 30, 2017 23:41
Show Gist options
  • Save andymotta/35ddd594ff8757573d1eda409e7cc615 to your computer and use it in GitHub Desktop.
Save andymotta/35ddd594ff8757573d1eda409e7cc615 to your computer and use it in GitHub Desktop.
Report AWS IAM access keys that require rotation within 45 days to SNS topic (Compliance)
import boto3
from botocore.exceptions import ClientError
import datetime
from datetime import date
import os
from ConfigParser import SafeConfigParser
access_file = os.path.join(os.environ['HOME'], '.aws', 'credentials')
access_list = SafeConfigParser()
access_list.read(access_file)
global DEFAULT_WARNING_THRESHOLD_IN_DAYS
DEFAULT_WARNING_THRESHOLD_IN_DAYS = 45
global DEFAULT_ROTATION_THRESHOLD_IN_DAYS
DEFAULT_ROTATION_THRESHOLD_IN_DAYS = 90
def main():
sns = boto3.client('sns')
access = generate_access_list() # Use sts_assume instead
offending = []
for p in access:
#will loop through every boto profile on control machine
try:
if p == 'default':
print "Skipping 'default' access profile"
continue
os.environ["AWS_PROFILE"] = p
# Create a custom session to switch profiles later
session = boto3.session.Session()
global iam
iam = session.client('iam')
keys = iam_access_keys_due_for_rotation()
offending.append(p.upper())
if keys:
offending.extend(keys)
else:
offending.append('No keys due for rotation in this account')
except:
raise
print "Skipping " + p
continue
msg = '\n\n'.join(offending)
response = sns.publish(
#fill in your sns topic arn here
TopicArn='arn:aws:sns:us-west-2:000000000000:iam-access-keys-requiring-rotation',
Message=msg,
Subject='IAM Access Keys Requiring Rotation'
)
def generate_access_list():
lst = []
for profile in access_list.sections():
lst.append(profile)
return lst
def iam_access_keys_due_for_rotation():
text = []
try:
for user in iam.list_users()['Users']:
now = date(datetime.date.today().year, datetime.date.today().month, datetime.date.today().day)
for access_key in iam.list_access_keys(UserName = user['UserName'])['AccessKeyMetadata']:
if access_key['Status'] == 'Active':
# response = iam.get_access_key_last_used(AccessKeyId = access_key['AccessKeyId'])
# if 'LastUsedDate' in response['AccessKeyLastUsed']:
access_key_create_date = access_key['CreateDate']
access_key_create_date = date(access_key_create_date.year, access_key_create_date.month, access_key_create_date.day)
age = (now - access_key_create_date).days
if age >= DEFAULT_WARNING_THRESHOLD_IN_DAYS:
user_name = user['UserName']
when = DEFAULT_ROTATION_THRESHOLD_IN_DAYS - age
if when > 0:
text.append('User {0} access key {1} created {2} is {3} days old and will require rotation in {4} days'.format(user_name.upper(), access_key['AccessKeyId'], access_key_create_date, age, when))
else:
text.append('User {0} access key {1} created {2} is {3} days old and immediately requires rotation'.format(user_name.upper(), access_key['AccessKeyId'], access_key_create_date, age))
return text
except ClientError as e:
if e.response['Error']['Code'] == 'InvalidClientTokenId':
return "Not authorized to perform iam maintainence"
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment