ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

数据仓库安全实战:从权限控制到加密审计的完整防护指南

数据仓库安全实战:从权限控制到加密审计的完整防护指南 1. 大数据时代数据仓库的攻击面到底发生了什么变化先说一个我印象特别深的场景。去年有个夜里线上告警群突然炸了——某个分析岗位的账号在凌晨三点连续拉取了几百张表的全量数据其中相当一部分是包含手机号和身份证号的用户维度表。平台侧第一时间做了账号禁用但还是花了几个小时才定位到这批数据到底被导去了哪里。事后复盘发现问题不在数据库本身而是在于我们根本说不清“这个账号在正常工作时间之外哪些表是允许触达的”。这件事给我的触动很大数据仓库的安全已经远远不是“装个防火墙、设个管理员密码”那个时代的问题了。1.1 数据流转路径拉长从采集、入湖、建模到服务的每一环都是风险点传统数仓时代数据基本是“业务库 — ETL — 数仓 — 报表”这么一条简单链路安全防护只需要守住几个关键节点就差不多了。但今天的数据平台通常同时存在离线数仓、实时数仓、数据湖、湖仓一体架构数据要在不同组件之间来回流动业务系统数据通过 Flink、Canal、DataX 等工具实时或批量写入消息队列或数据湖数仓内部完成 ODS、DWD、DWS、ADS 多层建模中间还有大量的临时表、中间表下游通过 JDBC/ODBC、BI 报表、API 服务、机器学习训练任务等几十种方式消费数据。每多一个环节就多一份被截获、被篡改、被越权读取的风险。很多团队的安全策略还停留在“对数据库本身做权限控制”结果黑客或内部人员根本不需要直接攻击数仓——攻破一个没有做认证的下游 BI 服务或者拿到一个权限过大的数据同步账号就能拿到几乎等价的访问能力。我之前处理过一起案例某个业务部门为了做临时分析私下申请了一个高权限账号然后这哥们的连接串明文写在 Jupyter Notebook 里Notebook 又被同步到了团队共享盘。等于说凡是能打开这个共享盘的人都能直连数仓核心库。这种场景在绝大多数公司里并不罕见——数据链路越长人的因素就越复杂安全防护越不能只盯着数仓那台服务器。1.2 数据量爆炸带来的三种“隐形泄露”数据量变大之后很多安全问题会被“淹没”在海量请求里。我总结了三种我们实际遇到过的隐形泄露第一种低频但大范围的批量导出。单次查询返回几百万行数据如果监控只看请求频率这种操作很难触发告警。但它对企业的杀伤力一点不亚于高频拖库——几张大表拼起来核心用户信息就全没了。第二种看似合法的组合权限。某个岗位单独看只能读 A 表另一个岗位只能读 B 表但两个权限落在同一个人身上再加上 C 表和 D 表的访问权这个账号就能把 ABCD 四张表 JOIN 起来还原出完整的用户画像。数据仓库的分级分类如果只做到表级别这种组合型越权基本防不住。第三种测试环境和灾备环境的“裸奔”。这是最容易被忽略的。生产环境做了各种权限管控和加密但开发测试环境经常直接同步生产数据权限放开到所有研发都能访问甚至连数据库账号口令都是统一的。很多数仓泄露事件攻击者真正突破的并不是生产环境而是某个安全等级很低的测试环境然后通过同步链路反向摸进核心库。这三种情况有一个共同点它们都不需要攻击者有多高深的技术只需要对业务和数据分布足够了解。所以大数据时代的数据仓库安全本质上是在跟“内部人员 账号滥用 链路绕过”作斗争而不仅仅是跟外部黑客作斗争。1.3 业务增速和安全建设的节奏错位数据仓库的安全建设普遍存在一个尴尬的现实业务永远跑得比安全快。数据接入需求从一个月几十张表变成一天几十张表建模团队、算法团队、分析团队都在抢数仓的资源安全管控如果走严格的审批流程业务就会抱怨“影响了迭代效率”。于是很多团队选择先放后管权限开通得很快回收却很慢时间一长整个数仓的权限分布就成了“僵尸账号 长期不用的高权限”的重灾区。这一点我必须说得直接一点数仓安全不是一次性上线一个系统就完事的它本质上是一个持续运营的过程。哪怕你权限模型设计得再好半年不清理账号、不复查权限系统的安全水位照样会快速下降。这也是为什么后面几章我会反复强调运营和审计——光有控制手段是不够的还得有持续发现问题的能力。2. 权限模型决定“谁能看到什么”之前先想清楚这三件事权限控制是数据仓库安全的地基。地基建歪了后面做再多的加密、审计、脱敏都是事倍功半。我的习惯是在设计权限模型之前先逼着业务方回答三个问题谁在用数仓他们用来做什么哪些数据是他们绝对不应该看到的这三个问题想清楚了再去选技术方案基本不会跑偏。2.1 RBAC、ABAC、数据分级到底怎么组合落地现在主流数仓产品无论是 Hive、Spark SQL、Doris、ClickHouse 还是云上的数仓服务基本都支持 RBAC基于角色的访问控制。但实际落地的时候只靠 RBAC 远远不够。我们的实践是“RBAC 数据分级 少量 ABAC”三层组合第一层按角色定权限。把用户归入角色角色再绑定库、表、行、列的权限。例如“数据分析师”只能读 DWD 和 DWS 层“算法工程师”可以读 DWD 层但不能读包含实名信息的字段“数仓开发”可以写 DWD/DWS 层但不能改 ODS 层。这个层次解决的是“岗位职责”问题。第二层按数据分级做附加约束。我们把数据分成 L1公开、L2内部、L3敏感、L4高敏感四个等级并约定L3 及以上数据默认不能直接授权给个人账号必须走特殊审批流程所有对 L4 数据的访问请求必须同时满足“在职、特定角色、临时授权、强制执行脱敏”四个条件。第三层用 ABAC 做动态限制。例如限定访问时间工作日 9:00-21:00 之外访问 L3 以上数据需要二次审批、限定客户端 IP只有办公网 IP 段可以直连数仓、限定数据量单次查询返回超过一定行数需要额外授权。这种基于属性的动态策略能有效拦截那种凌晨三点拖全表的操作。说白了权限模型的设计原则就一句话在尽量不影响正常工作的前提下把所有不必要的触达路径全部封死。不要试图让所有用户都方便地访问一切数据——安全系统的职责本来就是制造“有意义的摩擦”。2.2 两权分离与管理员权限的收敛管理数仓管理员权限是个非常微妙的东西。通常一个超级管理员账号能看所有数据、改所有配置、kill 所有任务如果不加约束地让两三个人长期持有风险极大。我们做过一次权限自查结果发现拥有数仓 DDL 权限的账号有十几个其中四个是已经离职员工的账号还有一个是某外包同学的账号——人已经换了两轮账号却没回收。这种场景我相信在很多公司都存在只是没人愿意主动去查。后来我们强制落地了“两权分离”负责系统运维的 DBA 账号只管集群节点、任务调度、资源队列不授予表级别数据查询权限负责数据建模的开发账号只拥有对应项目空间的表管理权限不授予集群级管理员权限跨层级的“超级管理员”只保留一个并托管在密码管理平台中每次操作都有录屏和审批记录日常登录必须通过跳板机。这个做法短期看会增加一些沟通成本——以前一个管理员账号搞定的事现在要走流程、分账号。但长期来看它避免了“一个人能同时改权限、看数据、抹日志”这种最危险的权力集中情况。2.3 数据脱敏不该是“上线后补救”而应该是前置能力权限管得再好也防不住“合法访问但非必要读取”的问题。比如数据分析师确实需要知道用户的年龄段分布但他真的需要看到手机号明文吗大部分场景其实是不需要的。这就是数据脱敏存在的意义。但我要提醒一个常见误区很多人把脱敏当成一个“事后处理程序”等数据已经落入业务方手里才去做打码这是典型的亡羊补牢。正确做法是把脱敏能力嵌入到数仓的访问引擎层让用户在查询发起的那一刻就被动态脱敏。以我们用的方案为例在 SQL 引擎前面加了一层统一 SQL 网关网关会解析用户的 SQL识别出涉及敏感字段的查询再根据用户角色和授权范围决定是否对返回结果做脱敏处理。比如角色是“运营分析”查询用户表时手机号自动显示为 138****1234角色是“客服质检”在特定时间段和特定工单范围内可以看完整手机号角色是“数仓开发”正常情况下根本不能在查询结果里 SELECT 手机号字段。这种动态脱敏的难点不在脱敏本身而在于敏感字段的自动发现和分类打标。我们一开始是纯手工人肉维护敏感字段清单后来表越来越多就开发了元数据扫描任务定期扫描表注释、字段注释、样本数据特征自动识别疑似敏感字段并提交确认。这个过程跑顺之后脱敏才能做到“有新表接入也能自动覆盖”而不是永远落后于业务建表速度。3. 数据加密链路从静态加密到动态防护的完整闭环权限模型解决的是“谁能看到”的问题加密解决的是“数据即使被拿到也看不懂”的问题。两者缺一不可。尤其在数据文件可能被直接拷贝、备份介质可能丢失、底层磁盘可能被回收再利用的场景下加密是最后一道物理防线。3.1 静态加密的选择TDE、文件级加密、列级加密怎么权衡数仓静态加密说来说去无非三种方案透明数据加密TDE是应用最广的。它工作在存储层数据库文件写入磁盘时自动加密读取时自动解密对上层应用完全无感。优点是性能影响小运维简单适合对整个库或表空间做整体加密。缺点是粒度比较粗一旦有人通过操作系统层面直接复制数据文件虽然文件是密文无法直接还原但如果备份数据和秘钥放在一起防护就等于零。文件级加密适合对象存储上的数据湖/湖仓架构。比如数据以 Parquet/ORC 格式落在 HDFS 或 S3 上时我们可以在数据写入文件之前做一次加密再落盘读取时先解密再加载。这个方案的灵活性更高可以按文件目录配置不同秘钥但也意味着需要自己管理加解密逻辑和秘钥生命周期稍有不慎很容易把性能搞坏。列级加密则是把最敏感的那几个字段单独加密。比如身份证号、银行卡号在写入时就用应用层秘钥加密成密文查询时必须通过解密函数才能还原。这种方案安全性最高但会牺牲查询性能和灵活性——一旦某个列被加密很多原本可以做的过滤、JOIN、聚合操作就做不了了除非引入可搜索加密之类的高级技术但成本太高生产环境很少用。我们的实际推荐是分层次核心高敏感表用列级加密 整库 TDE 双保险普通业务表做整库 TDE数据湖文件用文件级加密。这样既控制了成本又保证最敏感的数据拥有最完整的保护链条。3.2 传输链路上的加密与双向认证别忽略 JDBC/Spark 连接串说了半天存储加密我再问一句你数仓对外提供服务的连接通道是加密的吗很多团队只做了存储层加密结果应用连数仓用的还是明文协议数据在网络上裸奔。尤其是跨机房、跨云的数据同步和 JDBC 查询这类流量如果不做 TLS 加密抓包就能直接看到 SQL 语句和返回结果。这块我踩过坑曾经有一个实时数仓任务从业务库同步数据到数仓用的同步组件配置里没有启用 SSL因为当时觉得“内网环境没有风险”。后来安全扫描发现公司办公网到数仓机房的链路中间居然有一个网络回溯系统大量 SQL 明文被抓包留存。虽然那次没有造成实质泄露但那种“自己完全不设防”的感觉特别不好。正确的做法是所有 JDBC/ODBC 连接串强制启用 SSL/TLS数仓服务和客户端之间做双向认证mTLS客户端也需要持有合法证书内部组件之间的通信例如 HDFS DataNode 之间、Spark Executor 与 Driver 之间也尽量开启加密通道。第一次做全链路加密的时候性能确实会下降一些尤其是小文件多、并发高的场景CPU 开销会增加。但相比于数据在网络上裸奔的风险这个代价是值得的。3.3 秘钥管理与轮换机制权限和加密都绕不开的一环加密的安全性最薄弱的环节永远是秘钥管理本身。如果秘钥硬编码在配置文件里或者和数据库备份放在同一个目录那么加密就形同虚设。我们的做法是引入独立的密钥管理系统KMS数仓的 TDE 主密钥、列级加密密钥、传输层证书私钥全部存放在 KMS 中由 KMS 负责密钥的生成、存储、轮换和不透明使用。应用或数据库只拿到解密后的数据但永远接触不到原始主密钥。这里分享一个轮换的经验主密钥轮换不要做得太频繁但备份密钥的轮换一定要跟上。因为 TDE 主密钥轮换一次意味着整库的数据都要用新秘钥重新加密成本和风险都很高大多数时候只需要轮换加密秘钥DEK或备份加密证书即可。如果某个季度做了大规模的主密钥轮换务必要先做一次全量备份验证——我就见过有人轮换秘钥之后发现某些历史备份解不开原因就是轮换时没有同步更新备份的解密配置。3.4 实测的加密性能开销别被网上参数带偏关于加密的性能影响网上的说法褒贬不一我贴一组我们自己的实测数据供参考场景未加密TDE 加密性能影响TPC-DS 100GB 查询集基准平均增加约 8%-12%可接受高并发点查100QPS基准平均增加约 15%-20%可接受大批量数据写入基准平均增加约 10%-15%可接受全表扫描大表基准增加约 20%需要关注注意我这里用的是硬件加速AES-NI 指令集开启后的结果。有些老机器、虚拟化环境没开硬件加速性能影响会成倍放大。所以上加密之前先确认 CPU 支持 AES-NI并且确认内核和数据库版本默认打开了这个特性。4. 审计日志和行为画像让安全从“控制”升级为“感知”权限和加密做得再好也只是把门锁好了。可万一有人拿着合法的钥匙进来做非法的事呢这时候就得靠审计和行为感知能力来兜底。这也是我在实际工作中认为最难做、最容易被忽视的一部分——因为权限控制是一次性配置审计日志却需要常年累月地采集、分析、响应。4.1 审计日志的覆盖范围不是只记查询更不是只记“失败的登录”刚开始做审计的时候我们只关注数据库的登录日志和失败操作后来发现这远远不够。一次完整的数据访问事件其实包含了很多环节谁在什么时间通过哪个客户端连接到了数仓执行了什么 SQL 语句涉及哪些表返回了多少行数据扫描了多少分区是否执行了导出/下载操作导出了多少条记录是否新建了用户、变更了权限、修改了表结构是否访问了敏感字段手机号、身份证号、地址等有没有触发脱敏策略。这些信息分散在不同的日志来源里——数仓引擎日志、网关日志、BI 工具日志、任务调度日志、对象存储访问日志。我们当时做了两件事一是把最终用户认证收敛到统一 LDAP/SSO确保能追踪到真实自然人二是搭建了全链路的审计日志采集管道把引擎层、网关层、应用层的日志汇聚到同一个检索平台至少保证任何一次跨层级的敏感数据访问都能串出一条完整链路。这块我还想特别强调一下审计日志的留存本身也是安全的一部分。如果日志可以很容易地被修改或删除那么整个审计体系就没有意义。我们后来做了审计日志的防篡改设计把关键日志实时同步到独立的、权限隔离的存储中只有少数安全操作员能读连 DBA 都不能改。审计系统本身的账号也需要单独做双因子认证避免出现“管理员把自己的痕迹抹掉再跑路”的极端情况。4.2 从审计日志到行为基线UEBA 在数仓场景的落地姿势日志有了但光有日志不代表能发现安全问题。一个用户每天查几十次表有一天他突然在凌晨批量拉取大表——这种异常靠人肉翻日志几乎不可能发现必须借助行为分析。我们落地了一套简化版的 UEBA用户实体行为分析方案核心思路很朴素对每个用户、每个角色建立行为基线常用登录时段、常用客户端、常见表访问集合、单次查询返回行数分布对每一次新访问行为做偏离度打分时间偏离、地点偏离、表集合偏离、数据量偏离、查询模式偏离偏离度超过阈值时自动生成风险事件并推送到安全运营平台。比如某个数据开发同学平时只查询 DWD 层最近 30 天的分区某天突然直接查询 ODS 层全量历史分区并且返回了几十万行——系统会立刻把这个行为标记为高风险。即便他是正常业务需求也应该由审批人确认一下而不是让这种操作悄无声息地发生。做行为基线有一个关键点要按用户分组建基线不能全局一刀切。因为数据分析师和数据开发的行为模式完全不同全局基线只会导致两种情况——要么阈值太松放过了真正的异常要么阈值太紧把正常操作反复误报。我们的做法是先按角色分组建基线等数据足够多了再细化到个人级基线。4.3 告警分级与处置流程怎样做到“不吵不闹但关键时刻不缺席”行为分析如果产生了告警却不处置那就只是自我安慰。但告警的频率如果太高安全运营同学迟早会麻木。我们的做法是分三级处置低风险例如非工作时段登录、访问了平常很少访问的非敏感表记录存档每周汇总一次中风险例如批量导出超过阈值、访问了较高敏感级别的数据推送即时消息要求数据归属方 24 小时内确认是否业务需要高风险例如凌晨批量拖取高敏感数据、权限变更后立即异常访问、管理员账号异常操作立即阻断会话、冻结账号并拉通安全、业务、法务三方线上响应。我们在实践中经常发现中风险事件里面有相当比例其实是合理的业务需求——比如业务部门做“六一八”大促复盘需要一次性拉取大范围订单数据。这时候不用直接阻断但必须把审批流程补上。这个过程也是在培养业务方的“数据安全肌肉记忆”不是不能访问敏感数据而是每一次访问都要有理有据、可追溯。5. 安全防护的最后一公里集群边界、容灾同步与应急演练很多团队做到权限、加密、审计这三步之后就觉得安全建设大功告成但其实还有三件容易被忽略的事集群边界控制、容灾同步链路的安全复核以及真正的应急响应演练。前两件管的是“数据从数仓出去的路上还安不安全”后一件管的是“真出了事整个团队能不能在最短时间内止住血”。5.1 集群网络边界控制千万别把“所有端口对全网开放”当成常态我接手过一个数仓集群当时所有组件端口HDFS NameNode、HiveServer2、Spark ThriftServer 等都对办公网 IP 段开放连管理界面也是任何人都能访问。问原因答案是“为了方便业务自助分析”。这种场景下就算数据库权限做得再细、加密做得再全如果攻击者能从办公网摸到 HDFS 的 Web 管理端口一样可以把整个文件系统列表给拖走。正确的做法是分层隔离面向内部用户的 SQL 访问只允许通过统一的 SQL 网关代理进入不直接暴露引擎端口管理类端口例如 NameNode UI、ResourceManager UI、监控页面限制在运维跳板机 IP 段内其他来源一律拒绝集群内部节点之间保留必要的互通端口但对集群外部只开放经过代理的服务端口如果数仓在云上安全组规则要做到最小化授权并且定期检查是否存在“全 0.0.0.0/0 放行”的宽松规则。做边界控制的时候会收到不少开发同学的抱怨——“为什么我这里连不上 Spark ThriftServer 了以前明明可以。”遇到这种情况我们一般会帮助对方走审批、配正确的网段访问路径而不是直接放开防火墙。安全性的提升需要代价但大多数代价可以通过合理的流程设计来补偿。5.2 容灾同步链路的加密与权限复核数仓的容灾通常涉及主集群到备集群之间的数据同步。我们会定期把核心数据从生产集群同步到灾备机房以保证灾难发生时能快速恢复数据。但这套同步链路上有一个非常容易被忽略的安全盲区同步任务使用的账号往往是权限很大的复制账号一旦这个账号泄露攻击者就可以通过同步通道持续抽走数据。我建议把容灾同步链路当成一个独立的“高敏感资源”来管同步任务必须使用专门的同步账号不与其他用途合用同步链路必须加密不允许走明文传输同步账号的口令和证书要定期轮换且轮换时要同时检查灾备端的配置文件是否同步更新灾备集群本身也要遵循和主集群一致的权限、审计、加密标准不能因为是灾备就降低安全水位。很多公司会说“灾备环境只是冷备不对外服务安全问题影响不大”但我不这么看。容灾机房的数据完整性和生产是等价的灾备环境一旦被打穿同样会造成大规模数据泄露。更麻烦的是灾备环境往往安全监控最薄弱攻击者在这里滞留几个月都不容易被发现。5.3 应急响应的实际演练一个模拟数据泄露事件的处置流程最后讲讲应急演练。很多团队有应急响应预案但只是写了一份文档放在 wiki 上从来没真正演练过。等到数据泄露真的发生了才发现责任人不清晰、通讯录对不上、操作手册过期——整个响应过程乱成一锅粥。我们后来每半年做一次数据泄露模拟演练最典型的场景是“监测到异常账号在非工作时间导出高敏感数据疑似泄露请完成事件确认、止损、溯源、报告”。整个演练流程大体是这样的确认阶段目标 15 分钟内安全值班人员确认告警真实性评估涉及的数据范围与敏感等级决定是否触发紧急响应止损阶段目标 30 分钟内冻结账号、阻断连接、暂停相关任务、关闭相关服务入口。这里有一个关键决策点——要不要立刻 kill 正在执行的查询如果误判了正常业务任务会影响线上数据分析。我们的经验是对高敏感数据访问宁可错杀也必须先停后续再做事后再恢复溯源阶段目标 2 小时内从审计平台拉取该账号近期所有操作记录结合跳板机日志、应用系统日志还原事件链条定位泄露路径和受影响数据范围报告阶段目标 4 小时内输出事件复盘报告包含发生了什么、影响范围、根因、改进措施并同步给管理层和业务方。演练最大的价值不是测试某个人而是暴露流程和系统中的漏洞。比如第一次演练我们才发现审计日志平台虽然采集了 SQL 执行日志但业务部门在 BI 工具上下载数据的行为并没有被完整记录到审计系统——也就是说我们能看到“这个账号查了哪些表”却看不到“这个账号最终下载了多少行数据”。后来专门补了 BI 层的日志埋点才把这个盲区堵上。我个人在做完几次演练之后最大的体会是安全体系不是静态的配置堆叠而是一个需要持续对抗、持续演练、持续改进的动态系统。每一次演练、每一次真实事件复盘都会带出几个“原来这里也有问题”的盲区。安全建设做不到一劳永逸但能做到一步一步逼近更稳的状态。对一个大数据团队来说数据仓库的安全防护体系越扎实业务在数据创新上才越敢往前跑——因为你知道无论数据走到哪一层背后都有兜底的力量。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进