1. 개요
사용자별 Active key age를 보고 싶다.
2. 코드
파일명.py
import boto3
from datetime import datetime, timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
def diff_dates(date1, date2):
return abs(date2 - date1).days
resource = boto3.resource('iam')
client = boto3.client("iam")
KEY = 'LastUsedDate'
print ("{:<30} {:<25} {:<25} {:<10} {:<10}".format('User','Key','LastUsed','AgeOfKey',"Critical"))
for user in resource.users.all():
Metadata = client.list_access_keys(UserName=user.user_name)
if Metadata['AccessKeyMetadata']:
for key in user.access_keys.all():
AccessId = key.access_key_id
Status = key.status
CreatedDate = key.create_date
numOfDays = diff_dates(utc_to_local(datetime.utcnow()), utc_to_local(CreatedDate))
LastUsed = client.get_access_key_last_used(AccessKeyId=AccessId)
if (Status == "Active"):
if KEY in LastUsed['AccessKeyLastUsed']:
accessKeyLastUsed = LastUsed['AccessKeyLastUsed'][KEY].strftime("%Y-%m-%d %H:%M:%S")
print("{:<30} {:<25} {:<25} {:<10} {:<10}".format(user.user_name, AccessId, accessKeyLastUsed, numOfDays, "O" if numOfDays>90 else ""))
else:
print("{:<30} {:<25} {:<25}".format(user.user_name, AccessId, "Active Key but never used"))
else:
print("{:<30} {:<25} {:<25}".format(user.user_name, AccessId, "Inactive Key"))
else:
print("{:<30} {:<25} {:<25}".format(user.user_name, AccessId, "No Key"))
3. Lambda 코드화
위 기본 Python 코드를 기반이며, 결과를 특정 S3 버킷에 저장하는 람다 코드이다.
3.1. 권한 부여
해당 Lambda 코드 role에 다음 policy를 부여한다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:GetAccessKeyLastUsed",
"iam:ListUsers",
"iam:ListAccessKeys"
],
"Resource": "*"
}
]
}
3.2. 추가 패키지 설치
prettytable import를 위해 패키지를 설치하고 Lambda에 넣어준다.
자세한 방법은 /index.php/aws/805-aws-lambda-zip-python 을 참고한다.
Lambda 상에서 lambda_function.py 와 같은 레벨로 각 패키지의 디렉토리들이 존재하면 된다.
3.3. 코드
lambda_function.py
import json
import boto3
import traceback
from prettytable import PrettyTable
from datetime import datetime, timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
def diff_dates(date1, date2):
return abs(date2 - date1).days
def upload_file_s3(bucket, file_name, file):
s3 = boto3.client('s3')
try:
s3.put_object(Bucket=bucket, Key=file_name, Body=str(file))
return True
except:
traceback.print_exc()
return False
def lambda_handler(event, context):
resource = boto3.resource('iam')
client = boto3.client("iam")
KEY = 'LastUsedDate'
t = PrettyTable(['User', 'Key', 'LastUsed', 'AgeOfKey', 'Critical'])
print ("{:<30} {:<25} {:<25} {:<10} {:<10}".format('User','Key','LastUsed','AgeOfKey',"Critical"))
for user in resource.users.all():
Metadata = client.list_access_keys(UserName=user.user_name)
if Metadata['AccessKeyMetadata']:
for key in user.access_keys.all():
AccessId = key.access_key_id
Status = key.status
CreatedDate = key.create_date
numOfDays = diff_dates(utc_to_local(datetime.utcnow()), utc_to_local(CreatedDate))
LastUsed = client.get_access_key_last_used(AccessKeyId=AccessId)
if (Status == "Active"):
if KEY in LastUsed['AccessKeyLastUsed']:
accessKeyLastUsed = LastUsed['AccessKeyLastUsed'][KEY].strftime("%Y-%m-%d %H:%M:%S")
t.add_row([user.user_name, AccessId, accessKeyLastUsed, numOfDays, "O" if numOfDays>90 else ""])
else:
t.add_row([user.user_name, AccessId, "Active Key but never used", "", ""])
else:
t.add_row([user.user_name, AccessId, "Inactive Key", "", ""])
else:
#print("{:<30} {:<25} {:<25}".format(user.user_name, AccessId, "No Key"))
t.add_row([user.user_name, AccessId, "No Key", "", ""])
bucket = '<S3 버킷 이름>'
file_name = "iam-user-access-key-" + datetime.now().strftime("%Y%m%d-%H%M%S")
result = upload_file_s3(bucket, file_name + '.txt', t)
if result:
return {
'statusCode': 200,
'body': json.dumps("Upload success")
}
else:
return {
'statusCode': 400,
'body': json.dumps("Upload fail")
}