审计日志数据模型:字段、事件与JSON结构
说到KMS审计日志,很多新手第一反应就是——“不就是一堆JSON吗?”
嗯,这话对了一半。
JSON没错,但你如果不懂里面每个字段的真实含义,排查问题时你就会像无头苍蝇一样乱转。
我个人习惯把审计日志数据模型理解成“谁在什么时候对哪个密钥做了什么,结果如何”。
拆开来看,核心就那么几块。今天咱们就把这层窗户纸捅破。
核心字段结构:一条审计日志到底长什么样?
先看一条真实的KMS审计日志(JSON格式)。我简化了一些敏感信息,但核心字段都在:
{
"eventVersion": "1.08",
"userIdentity": {
"type": "IAMUser",
"arn": "arn:aws:kms:cn-north-1:123456789012:user/admin",
"accountId": "123456789012",
"userName": "admin"
},
"eventTime": "2024-03-15T08:30:00Z",
"eventSource": "kms.amazonaws.com",
"eventName": "Decrypt",
"awsRegion": "cn-north-1",
"sourceIPAddress": "203.0.113.42",
"userAgent": "console.amazonaws.com",
"requestParameters": {
"keyId": "arn:aws:kms:cn-north-1:123456789012:key/mrk-1234abcd5678efgh",
"encryptionAlgorithm": "SYMMETRIC_DEFAULT"
},
"responseElements": {
"keyId": "arn:aws:kms:cn-north-1:123456789012:key/mrk-1234abcd5678efgh",
"encryptionAlgorithm": "SYMMETRIC_DEFAULT"
},
"resources": [
{
"arn": "arn:aws:kms:cn-north-1:123456789012:key/mrk-1234abcd5678efgh",
"accountId": "123456789012",
"type": "AWS::KMS::Key"
}
],
"eventType": "AwsApiCall",
"recipientAccountId": "123456789012"
}
这里面每个字段都不是摆设。我挑几个容易踩坑的来说。
字段深度解析:这些坑我替你们趟过了
| 字段 | 说明 | 避坑要点 |
|---|---|---|
| eventVersion | 日志格式版本,目前主流是1.08 | 不同版本字段可能有增减,解析时不要硬编码 |
| userIdentity | 发起请求的身份信息,含类型、ARN、用户名 | 这里可能是IAM用户、角色、账户根用户,注意type字段 |
| eventName | 操作名称,如Decrypt、Encrypt、CreateKey | 大小写敏感,查询时注意精确匹配 |
| requestParameters | 请求参数,通常包含keyId和加密算法 | Decrypt请求里不一定有明文密钥,只有密文标识 |
| resources | 涉及的资源列表,一般是目标密钥的ARN | 有时会有多个资源,需要遍历处理 |
| eventType | 事件类型,常见AwsApiCall、AwsServiceEvent | 很多工具只过滤AwsApiCall,会漏掉服务内部调用 |
事件类型分类:四种事件,各有用途
KMS审计日志里的eventType字段,说白了就四种情况:
- AwsApiCall — 用户或角色通过API/SDK/控制台发起的操作。最常见,占95%以上。
- AwsServiceEvent — 其他AWS服务替用户调用的KMS操作。比如S3用KMS密钥加密对象时,日志里就是这种类型。
- AwsConsoleAction — 通过控制台操作时产生。跟AwsApiCall有点像,但会带上控制台的具体操作路径。
- AwsInternal — KMS内部维护操作。一般不需要分析,可以过滤掉。
我建议在做聚合分析时,把AwsServiceEvent单独拎出来看。为什么呢?因为这类操作往往跟你的业务密钥流出有关。我记得有一次,客户说“我们没人用KMS解密,但审计日志里有大量Decrypt”。一查,全是AwsServiceEvent,是数据库服务自动解密的。你想想看,如果混在一起统计,这水就浑了。
JSON格式实战:如何快速提取关键信息?
手动翻JSON太累了。我习惯写一个简单的解析流程:
// 伪代码,以Python为例
def parse_kms_log(log_json):
event = json.loads(log_json)
identity = event.get('userIdentity', {})
return {
'time': event.get('eventTime'),
'who': identity.get('userName', identity.get('type')),
'what': event.get('eventName'),
'which_key': event.get('requestParameters', {}).get('keyId'),
'source_ip': event.get('sourceIPAddress'),
'result': event.get('responseElements', {}).get('keyId', 'N/A')
}
为什么要注意responseElements?因为有些操作失败了,keyId可能为空。这时候你要去看errorCode字段。我补充一下:很多审计日志分析脚本只提取requestParameters,忽略了失败操作的响应信息,筛查异常时就会漏掉。
审计日志数据模型核心关系图
下面这张图整理了KMS审计日志的数据模型骨架:
你看,从左到右,从上到下,一条日志的信息流就是这样的。从主体发起操作,到操作作用于密钥资源,然后产生结果,最后带上时间、来源、账户信息。理解了这个流向,后续你再做自动化分析就轻松多了。
避坑实战清单
- 永远检查userIdentity.type:是用户操作还是服务代理操作?这两类行为的审计排查逻辑完全不同。
- 筛选时别只盯着eventName:建议同时看eventType和errorCode,很多隐蔽问题藏在错误日志里。
- responseElements里的keyId可能为空:如果成功,它返回操作的密钥ID;如果失败,可能只有errorMessage。
- 时间戳用UTC:多数环境下的KMS审计日志使用UTC时间,分析前务必跟本地时间做好换算。
SELECT eventName, count(*) as count FROM kms_logs WHERE eventType='AwsApiCall' GROUP BY eventName ORDER BY count DESC
明白了模型,下一件事就是去实际环境里跑几条日志看看。我建议你先从自己的账号拉一周的KMS审计日志,手动解析一条对照本文的字段结构。嗯,真的,遇到问题的时候你会感谢今日的自己。