如何通过AWS API编程获取KMS密钥最后使用日期并导出至JSON/CSV?
AWS KMS密钥最后使用日期的编程获取方案
核心结论
KMS本身没有直接返回密钥最后使用时间的API,必须通过CloudTrail日志提取,但可以通过AWS API编程实现,同时解决部分操作资源名缺失的问题,最终导出为JSON/CSV格式。
解决CloudTrail事件资源名缺失的问题
针对Decrypt/Encrypt等操作,密钥信息不会出现在resources字段,而是存储在requestParameters.keyId中;对于CreateKey/DisableKey等管理操作,密钥ARN会出现在resources数组里。处理时需根据eventName判断提取字段,优先用ARN避免跨区域密钥ID重复。
编程实现步骤
方法1:使用CloudTrail lookupEvents API(适合中小体量日志)
用AWS SDK(以Python boto3为例)分页查询KMS相关事件,提取密钥标识并聚合最后使用时间:
import boto3 from collections import defaultdict import json import csv from datetime import datetime # 初始化客户端 cloudtrail = boto3.client('cloudtrail') kms = boto3.client('kms') # 存储密钥最后使用记录 key_last_used = defaultdict(lambda: {'last_used': None, 'key_arn': None}) # 分页查询CloudTrail事件 paginator = cloudtrail.get_paginator('lookup_events') page_iterator = paginator.paginate( EventSource='kms.amazonaws.com', StartTime=datetime(2023, 1, 1), # 按需调整起始时间 EndTime=datetime.now() ) for page in page_iterator: for event in page['Events']: event_name = event['EventName'] event_time = event['EventTime'] key_id = None # 按事件类型提取密钥标识 if event_name in ['Decrypt', 'Encrypt', 'GenerateDataKey', 'GenerateDataKeyWithoutPlaintext']: key_id = event.get('RequestParameters', {}).get('keyId') else: for res in event.get('Resources', []): if res['Type'] == 'AWS::KMS::Key': key_id = res['ARN'] break if not key_id: continue # 转换密钥ID为ARN(避免跨区域ID冲突) if not key_id.startswith('arn:aws:kms'): try: key_meta = kms.describe_key(KeyId=key_id)['KeyMetadata'] key_arn = key_meta['Arn'] except Exception as e: print(f"跳过无效密钥 {key_id}: {str(e)}") continue else: key_arn = key_id # 更新最后使用时间 if (key_last_used[key_arn]['last_used'] is None or event_time > key_last_used[key_arn]['last_used']): key_last_used[key_arn]['last_used'] = event_time key_last_used[key_arn]['key_arn'] = key_arn # 导出为JSON with open('kms_last_used.json', 'w') as f: output = [ { 'key_arn': item['key_arn'], 'last_used_time': item['last_used'].isoformat() } for item in key_last_used.values() if item['last_used'] ] json.dump(output, f, indent=2) # 导出为CSV with open('kms_last_used.csv', 'w', newline='') as f: writer = csv.writer(f) writer.writerow(['Key ARN', 'Last Used Time']) for item in key_last_used.values(): if item['last_used']: writer.writerow([item['key_arn'], item['last_used'].isoformat()])
方法2:使用CloudTrail Lake(适合大量日志)
通过CloudTrail Lake的SQL查询过滤KMS事件,效率更高。先创建事件数据存储,再执行查询:
示例SQL查询语句:
SELECT eventName, eventTime, CASE WHEN eventName IN ('Decrypt', 'Encrypt', 'GenerateDataKey') THEN requestParameters.keyId ELSE resources.ARN END AS key_identifier, awsRegion FROM <your-event-data-store-id> WHERE eventSource = 'kms.amazonaws.com' AND eventTime >= '2023-01-01T00:00:00Z'
通过start_query API执行查询,再用get_query_results获取结果,后续聚合逻辑和方法1一致,最后导出格式。
关键注意事项
- 权限:IAM角色需具备
cloudtrail:LookupEvents、kms:DescribeKey(ID转ARN时)、cloudtrail:GetQueryResults(CloudTrail Lake时)权限 - 日志周期:CloudTrail默认保留90天,如需更长历史需将日志归档到S3
- 未使用密钥:调用KMS
ListKeys获取所有密钥,对比CloudTrail结果即可识别从未使用的密钥
内容的提问来源于stack exchange,提问作者fullstaxx
相关产品推荐
相关产品推荐

