第2章 数据资产盘点:如何发现企业内的结构化/非结构化数据源、元数据收集方法
2.1 盘点前的灵魂拷问
在做DSPM扫描之前,你得先搞清楚一个问题:你的数据到底散落在哪儿?
我见过不少团队,一上来就拿着扫描工具到处扫,结果扫出一堆临时文件、缓存日志,真正的敏感数据反而没抓到。说白了,没做资产盘点就直接扫描,就像蒙着眼进迷宫。
所以我习惯把资产盘点分成三个层次:数据源发现 → 元数据采集 → 资产目录建立。这章我们就聊前两步——怎么把藏在各个角落的数据源挖出来,再把它们的“身份证”(元数据)收集上来。
核心观点:资产盘点不是为了扫而扫,而是为了给后续的分类分级打地基。地基不稳,后面全白干。
2.2 结构化数据源:数据库与数据仓库
先从最熟悉的开始说。结构化数据,说白了就是关系型数据库里的表——MySQL、PostgreSQL、Oracle、SQL Server这类。它们的特点是schema明确,字段类型固定,元数据好拿。
发现方法:我记得第一次帮客户做盘点,他们自己都不知道内部有38套数据库实例。后来我写了个轻量脚本,直接连CMDB或者用nmap扫常见端口(3306、5432、1521等),再配合云厂商的RDS列表API,基本能覆盖90%。
小技巧:别光依赖人工运维清单。翻翻公司的内部Wiki、OnCall文档、甚至Git仓库里的docker-compose.yml,往往能发现被遗忘的开发库或测试库。
元数据采集清单:对每个数据库实例,至少得收这些:
- 数据库名称、版本、字符集
- 所有库、所有表、所有字段名与数据类型
- 主键、外键、索引、视图、存储过程
- 表行数(近似值)与存储大小
- 最近DDL/DML时间戳
为什么收这些?因为后面的数据分类分级,很大程度上依赖字段级别的元数据。比如字段名叫“id_card”,那大概率是身份证号,得重点关注。
2.3 非结构化数据源:文件系统与云存储
非结构化数据才是真正的老大难。一个企业里,结构化数据可能只占20%,剩下80%是文件——Word、PDF、Excel、图片、日志、源代码……它们散落在文件服务器、NAS、S3桶、SharePoint、Confluence等各个角落。
我之前遇到过一个客户,光S3桶就开了200多个,有些桶权限配得特别松,连外包商都能读。我们写了个Python脚本,用boto3遍历所有桶的列表和对象元数据,才把数据源摸清楚。
非结构化数据源的分类:
| 类型 | 常见载体 | 文件格式举例 |
|---|---|---|
| 办公文档 | 文件服务器、SharePoint、Google Drive | .docx, .pdf, .xlsx, .pptx |
| 多媒体文件 | NAS、OSS、S3 | .jpg, .mp4, .wav |
| 日志与导出 | ELK、Splunk、HDFS | .log, .csv, .json |
| 源代码与配置 | GitLab、GitHub、内部仓库 | .py, .java, .yaml, .conf |
| 备份与归档 | Tape、冷存储、Glacier | .tar, .gz, .bak |
元数据怎么收?对于文件系统,核心元数据包括:
- 文件路径、文件名、扩展名
- 创建时间、最后修改时间、最后访问时间
- 文件大小、权限(owner、group、ACL)
- 文件类型(通过magic bytes识别,不只看后缀)
- 是否加密、是否压缩
注意坑:我曾经踩过一个雷——只靠文件后缀判断类型,结果有人把敏感数据表重命名为.jpg藏在图片文件夹里。后来改用file命令读取魔数,才真正识别出来。所以,永远不要轻信后缀名。
2.4 半结构化数据源:NoSQL与日志流
半结构化数据介于两者之间——有结构但schema灵活。典型代表:MongoDB、Elasticsearch、Redis、Kafka Topic里的JSON消息。
嗯,这里要特别提一下NoSQL数据库。它们的元数据不像关系型那么规整。MongoDB你得通过listDatabases、getCollectionInfos接口拿集合名和文档样例;Elasticsearch得调_cat/indices和_mapping。收的时候注意别把整个文档全拉下来,那样数据量太大,只取字段路径和类型就行了。
# MongoDB元数据采集示例(Python)
from pymongo import MongoClient
client = MongoClient("mongodb://admin:password@localhost:27017")
dbs = client.list_database_names()
for db_name in dbs:
db = client[db_name]
colls = db.list_collection_names()
for coll_name in colls:
sample = db[coll_name].find_one() # 取一条样本
if sample:
fields = list(sample.keys())
print(f"{db_name}.{coll_name}: {fields}")
2.5 元数据收集的三种模式
在实际干活的时候,元数据收集不能靠人工一个一个点,得讲方法。我一般用三种模式:
- 直连扫描:直接连数据库、文件系统、云API。实时性强,适合新环境首次全量盘点。
- 日志采集:从审计日志、访问日志、查询日志中提取数据源信息。适合已经跑起来的业务,不影响生产。
- 代理部署:在目标服务器上装轻量Agent,定期上报元数据。适合大规模、跨机房的环境。
每种模式各有优劣,我画了张表对比:
| 模式 | 实时性 | 侵入性 | 覆盖范围 | 适用场景 |
|---|---|---|---|---|
| 直连扫描 | 高 | 中(需授权) | 广 | 首次盘点、小规模环境 |
| 日志采集 | 中 | 低 | 中 | 生产环境、持续监控 |
| 代理部署 | 高 | 高 | 广 | 大规模、多数据中心 |
我的经验:别上来就上代理。先直连扫一轮摸清家底,再决定是否持续用日志或代理。否则代理人多了,运维那边的告警会把你淹死。
2.6 常见避坑与最佳实践
干这行几年,踩过的坑我可以列一个list:
- 权限不足扫不全——我曾经因为只用了只读账号,漏掉了好几个关键数据库。后来我要求在盘点阶段向安全团队申请一个“准管理员”角色,扫描完立刻回收。
- 忽略影子IT——员工自己搭的MySQL、内部用的SaaS(如飞书、钉钉文档)、部门级的NAS,这些都不在IT资产管理范围内。我建议在盘点邮件里加一句“如果团队有自己的存储,请通报”,配合问卷调查。
- 元数据过度采集——有些人恨不得把每行数据都拉回来。其实没必要,收集字段级元数据就够了,内容级的扫描放到后续的数据分类分级环节去做。
- 不记录时间戳——元数据会变,如果你不记录采集时间,后面根本没法做增量更新。我每个条目都会加一个
collect_ts字段。