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에 넣어준다.
자세한 방법은 https://sarc.io/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") }