Skip to content

Instantly share code, notes, and snippets.

@andrew-aiken
Last active January 28, 2022 18:03
Show Gist options
  • Save andrew-aiken/2332e04910ba069e1e6aff4331da32fe to your computer and use it in GitHub Desktop.
Save andrew-aiken/2332e04910ba069e1e6aff4331da32fe to your computer and use it in GitHub Desktop.
AWS User API Access Token Age Check

AWS User Access Token Check

Intended for python3.8

Variables needed for lambda

  • env
    • dev, test, stage, etc.
  • DISABLE_ENV
    • True / False
  • USER_GROUP_TARGET
    • Developers
  • EMAIL_ADDRESS_BODY
    • @example.com
  • SOURCE_ADDRESS
  • CC_EMAIL_ADDRESS
  • WARN_DAYS
    • 80
  • DISABLE_DAY
    • 90

Python Modules:

  • boto3
  • datetime

AWS IAM Policy Required

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": [
				"iam:DeleteAccessKey",
				"iam:ListGroupsForUser",
				"iam:ListGroupPolicies",
				"iam:GetAccessKeyLastUsed",
				"iam:UpdateAccessKey",
				"iam:ListAttachedGroupPolicies",
				"iam:GetUser",
				"iam:CreateAccessKey",
				"iam:ListAccessKeys"
			],
			"Resource": [
				"arn:aws:iam::0123456789:group/*",
				"arn:aws:iam::0123456789:user/*"
			]
		},
		{
			"Sid": "VisualEditor1",
			"Effect": "Allow",
			"Action": [
				"iam:ListUsers",
				"iam:ListGroups",
				"iam:GetAccountSummary"
			],
			"Resource": "*"
		}
	]
}
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": [
				"ec2:CreateNetworkInterface",
				"ec2:CreateNetworkInterfacePermission",
				"ec2:DeleteNetworkInterface",
				"ec2:DescribeNetworkInterfaces",
				"ses:SendEmail"
			],
			"Resource": "*"
		},
		{
			"Sid": "VisualEditor1",
			"Effect": "Allow",
			"Action": "logs:CreateLogGroup",
			"Resource": "arn:aws:logs:us-east-1:0123456789:*"
		},
		{
			"Sid": "VisualEditor2",
			"Effect": "Allow",
			"Action": [
				"logs:CreateLogStream",
				"logs:PutLogEvents"
			],
			"Resource": "arn:aws:logs:us-east-1:0123456789:log-group:/aws/lambda/AccessKeyUpdateReminder:*"
		}
	]
}
import os
import boto3
from datetime import date
# Email stuff
EMAIL_ADDRESS_BODY = os.environ.get('EMAIL_ADDRESS_BODY')
SOURCE_ADDRESS = os.environ.get('SOURCE_ADDRESS')
CC_EMAIL_ADDRESS = os.environ.get('CC_EMAIL_ADDRESS')
ENV = os.environ.get('env')
DISABLE_ENV = os.environ.get('DISABLE_ENV')
USER_GROUP_TARGET = os.environ.get('USER_GROUP_TARGET')
WARN_DAYS = int(os.environ.get('WARN_DAYS'))
DISABLE_DAY = int(os.environ.get('DISABLE_DAY'))
def findOldAccessKeys():
iam = boto3.client('iam')
currentdate = date.today()
for user in iam.list_users()['Users']:
userGroups = iam.list_groups_for_user(UserName=user['UserName'])
for groupName in userGroups['Groups']:
if USER_GROUP_TARGET in groupName['GroupName']:
res = iam.list_access_keys(UserName=user['UserName'])
for AccessKeys in res['AccessKeyMetadata']:
active_days = currentdate - AccessKeys['CreateDate'].date()
if (AccessKeys['Status'] == 'Active'):
if (active_days.days > DISABLE_DAY and DISABLE_ENV == "True"):
print(f"Username: {user['UserName']} ({active_days.days}) is over 100 days, disabling access key & sending email.")
sendDisableEmail(user['UserName'], ENV)
disableAccessKey(iam, AccessKeys['AccessKeyId'], user['UserName'])
elif (active_days.days >= WARN_DAYS):
print(f"Username: {user['UserName']} ({active_days.days}) is over {WARN_DAYS} days, sending reminder email.")
sendWarningEmail(user['UserName'], ENV)
def disableAccessKey(iam, keyID, username):
iam.update_access_key(
AccessKeyId = keyID,
Status = 'Inactive',
UserName = username
)
def sendDisableEmail(username, ENV):
ses = boto3.client('ses')
bodyEmail = f"""Hello {username},<br><br>
Your aws {ENV} CLI access key is outdated, and has been disabled.<br>
Please loging to aws and create a new access key.<br><br>
Guide to update your access key<br>
https://aws.amazon.com/blogs/security/how-to-find-update-access-keys-password-mfa-aws-management-console/
"""
ses.send_email(
Source = SOURCE_ADDRESS,
Destination = {
'ToAddresses': [
username + EMAIL_ADDRESS_BODY,
],
'CcAddresses': [
CC_EMAIL_ADDRESS,
]
},
Message = {
'Subject': {
'Data': 'Outdated AWS Access Key'
},
'Body': {
'Html': {
'Data': bodyEmail
}
}
}
)
def sendWarningEmail(username, ENV):
ses = boto3.client('ses')
bodyEmail = f"""Hello {username},<br><br>
Your {ENV} aws cli access key is getting old.<br>
Please replace your access key or delete/disable if it's currently unused.<br><br>
Guide to update your access key<br>
https://aws.amazon.com/blogs/security/how-to-find-update-access-keys-password-mfa-aws-management-console/
"""
ses.send_email(
Source = SOURCE_ADDRESS,
Destination = {
'ToAddresses': [
username + EMAIL_ADDRESS_BODY,
]
},
Message = {
'Subject': {
'Data': 'Outdated AWS Access Key'
},
'Body': {
'Html': {
'Data': bodyEmail
}
}
}
)
def lambda_handler(event, context):
findOldAccessKeys()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment