You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 21:15:19