ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

CDH集群Sentry权限管理实战:从裸奔到精细化管控

CDH集群Sentry权限管理实战:从裸奔到精细化管控

1. 从一次数据泄露演练说起:为什么集群裸奔时代必须终结

几年前我参与过一个内部红蓝对抗演练,蓝队只用了不到二十分钟就从一个普通业务账号拿到了核心用户表的全量数据。复盘的时候发现,问题根本不在防火墙,也不在认证环节——那个业务账号确实是通过了Kerberos认证的合法用户,但它对Hive里几乎所有库都有读写权限。换句话说,门锁是好的,但每个进门的人都发了一把万能钥匙。

这件事之后,我们开始认真对待大数据平台里的权限治理。而在CDH这套体系里,Sentry就是那把用来把万能钥匙拆成一把把专用钥匙的核心工具。如果你正在管理一个CDH集群,或者正准备从"能跑就行"的阶段过渡到"谁都不能乱看数据"的阶段,那Sentry权限管理是你绕不过去的一关。

这篇文章面向的是已经对Hadoop生态有基本了解、正在或即将负责CDH集群安全加固的运维和开发人员。我会从Sentry到底解决什么问题讲起,把它的权限模型、配置流程、和Hive/HDFS的联动机制拆开揉碎,再结合我实际踩过的坑,给出可以直接照着做的操作步骤。不会只告诉你"点这个按钮",而是把每个配置项背后的逻辑讲清楚,这样遇到变体场景你也能自己判断。

2. Sentry到底在管什么:权限模型与核心概念拆解

2.1 没有Sentry的时候,权限是怎么失控的

在CDH集群里,Hive本身有一套基于SQL标准的授权机制,HDFS也有自己的POSIX权限体系。问题在于,这两套东西是割裂的。一个用户通过Hive查询表数据,Hive会检查自己的元数据权限;但同一份数据文件在HDFS上,如果用户直接用hadoop fs -cat命令去读,HDFS只认文件系统的权限位。这就导致一个很尴尬的局面:你在Hive里把表权限收得很紧,但底层文件可能对hive用户组可读,而任何能提交Hive作业的人都能以hive身份去读文件。

更麻烦的是,Hive的授权是基于SQL标准的GRANT/REVOKE,但它对"角色"的支持很弱,也没有统一的审计入口。当集群里有Hive、Impala、Solr、Kafka等多个组件时,每个组件各管各的权限,管理员根本没办法回答一个最基本的问题:用户A到底能访问哪些数据?

Sentry的出现就是为了解决这个"各自为政"的问题。它把权限从各个组件里抽出来,集中到一个统一的服务里管理,各个组件在執行操作前都去问Sentry:"这个用户能不能对这个对象做这个操作?"Sentry给出是或否,组件据此决定放行还是拒绝。

2.2 Sentry的权限模型:角色、权限、对象的三层结构

Sentry的权限模型可以用一句话概括:权限授予角色,角色授予用户或用户组,权限作用于具体对象。这三层结构是理解Sentry所有操作的基础。

先说什么叫"对象"。在Sentry的语境里,对象就是被保护的数据资源,比如Hive里的数据库、表、列,HDFS上的路径,Solr里的集合。每个对象都有一个唯一的标识,Sentry通过这个标识来定位它。

然后是"权限"。权限是对对象可以执行的操作,比如SELECT、INSERT、CREATE、DROP、ALTER、ALL。注意,Sentry的权限是分层的:数据库级别的权限会自动向下传递到该库下的所有表,表级别的权限会传递到该表的所有列。但反过来不行,你不能通过给一个表授权来获得整个库的权限。

最后是"角色"。角色是权限的集合,也是Sentry里最灵活的部分。你可以创建一个叫"analyst_readonly"的角色,把对某些表的SELECT权限授予它,然后把这个角色授予用户组"analysts"。这样,所有analysts组的用户就自动获得了这些表的读权限。当有新用户加入analysts组时,不需要单独给他授权,组继承自动生效。

这里有一个容易混淆的点:Sentry里的"用户组"是从哪里来的?在CDH里,Sentry默认从操作系统层面获取用户和组信息,也就是说,你在Linux上创建的用户和组,Sentry能直接识别。如果你接了LDAP或Active Directory,Sentry也可以通过Hue或Cloudera Manager的配置去同步这些外部目录里的用户组。这一点很关键,因为它决定了你是在操作系统层面管理用户,还是在外部目录里管理。

2.3 Sentry和HDFS权限的联动:为什么改了Sentry还要管HDFS

很多人以为配了Sentry就万事大吉了,结果发现用户还是能通过HDFS直接读到数据。这是因为Sentry管的是"通过Hive/Impala等组件访问"这条路径,而HDFS直接访问走的是另一条路径。

CDH里有一个叫"HDFS ACL同步"的机制,它的作用是:当你在Sentry里给某个角色授予了Hive表的权限时,Sentry会通知HDFS,把对应的底层文件或目录的ACL也更新成匹配的权限。这样,即使用户绕过Hive直接访问HDFS,HDFS的ACL也会拦住他。

但这个同步不是自动开启的,需要在Cloudera Manager里显式配置。而且同步有延迟,不是实时的。我在实际环境里遇到过这样的情况:刚在Hue里给用户授了权,用户立刻去查Hive能查到,但用hadoop fs命令去读底层文件却被拒绝,就是因为ACL还没同步过去。等几分钟再试就正常了。

所以正确的理解是:Sentry负责逻辑层面的权限判定,HDFS ACL负责物理层面的兜底。两者配合,才能做到"条条大路都设卡"。

3. 在CDH里把Sentry跑起来:配置流程与关键参数

3.1 前置条件检查:别急着点启用

在Cloudera Manager里启用Sentry之前,有几件事必须先确认,否则启用后会出现各种诡异问题。

第一,确认集群已经启用了Kerberos。Sentry强依赖Kerberos来做用户身份认证,没有Kerberos的环境里Sentry无法正常工作。如果你还没上Kerberos,建议先把这一步做完再考虑Sentry,否则后面会反复返工。

第二,确认Hive的元数据存储(Metastore)使用的是MySQL或PostgreSQL,而不是Derby。Derby只适合单用户测试,Sentry需要元数据存储支持并发访问和事务,Derby撑不住。

第三,确认所有节点的时钟同步正常。Kerberos对时间偏差很敏感,默认允许的最大偏差是5分钟。如果时钟不同步,Sentry的认证会间歇性失败,而且报错信息往往指向别的地方,很难排查。

第四,规划好Sentry的管理员用户和组。默认情况下,Sentry的管理员是hive用户和hadoop组。你可以额外指定其他用户或组作为Sentry管理员,但至少要保留一个可用的管理员入口,否则一旦配错就锁死自己了。

3.2 在Cloudera Manager里启用Sentry服务

确认前置条件后,在Cloudera Manager里操作。进入集群页面,点击"添加服务",选择Sentry,然后按照向导走。这里有几个配置项需要特别注意:

Sentry Server的数据库配置:Sentry自己也需要一个数据库来存储权限元数据。可以用MySQL或PostgreSQL,建议和Hive Metastore用同一个数据库实例但不同的库。数据库连接信息要填对,否则Sentry Server起不来。

Sentry的Group Mapping配置:这个决定了Sentry从哪里获取用户组信息。默认是"org.apache.sentry.provider.file.HadoopGroupResourceAuthorizationProvider",也就是从Hadoop的组映射机制获取。如果你的环境接了LDAP,需要改成对应的LDAP provider,并配置LDAP的连接信息。

Sentry与HDFS的ACL同步:在HDFS服务的配置里,找到"启用HDFS ACL"和"启用Sentry HDFS ACL同步"两个选项,都勾上。同时要确保HDFS的超级用户组(通常是hdfs或supergroup)配置正确,因为ACL同步需要超级用户权限。

配置完成后,重启相关服务。重启顺序有讲究:先重启Sentry Server,再重启Hive和Impala,最后重启HDFS。顺序错了可能导致服务间通信失败。

3.3 验证Sentry是否生效:一个简单的测试用例

服务起来之后,别急着配权限,先做个最小验证。用hive用户登录beeline,执行一条创建数据库的命令:

CREATE DATABASE sentry_test;

然后用一个普通用户(比如testuser)登录,尝试查询这个库:

SHOW TABLES IN sentry_test;

如果Sentry配置正确,testuser应该会收到权限拒绝的错误。如果testuser能正常查询,说明Sentry没有生效,需要检查Hive的配置里是否启用了Sentry授权。

在Hive的配置里,有一个关键参数叫"hive.security.authorization.enabled",必须设为true。还有一个"hive.security.authorization.manager",应该指向Sentry的实现类。这两个参数在Cloudera Manager里启用Sentry后会自动配置,但如果你之前手动改过Hive的配置文件,可能会被覆盖,需要确认一下。

4. 权限授予的实操:从角色创建到用户绑定

4.1 用Hue的图形界面做权限管理

对于日常的权限管理,Hue提供了一个比较直观的界面。用管理员账号登录Hue,进入"Security"页面,可以看到Sentry的权限管理入口。这里可以创建角色、给角色授权、把角色授予用户或组。

我个人的习惯是:先在Hue里把角色和权限的框架搭好,因为图形界面能看到全貌,不容易漏。比如我要给数据分析团队配权限,会先创建一个"analyst"角色,然后在Hue里浏览所有需要授权的数据库和表,逐个勾选SELECT权限。勾选的过程中能清楚地看到哪些表已经授权了、哪些还没授权。

但Hue的界面有一个局限:它只支持Hive和Solr的权限管理,不支持HDFS的路径权限。如果你需要给HDFS路径授权,还是得用命令行。

4.2 用命令行做精细化的权限控制

Sentry的命令行工具是sentry-shell,在Sentry Server所在的节点上可以找到。用beeline的方式连接Sentry:

sentry-shell -i /path/to/sentry-site.xml

连接成功后,就可以执行Sentry的SQL语句了。Sentry的SQL语法和标准SQL的GRANT/REVOKE很像,但有一些自己的扩展。

创建一个角色:

CREATE ROLE analyst_readonly;

给角色授予数据库的SELECT权限:

GRANT SELECT ON DATABASE sales TO ROLE analyst_readonly;

给角色授予表的SELECT权限:

GRANT SELECT ON TABLE sales.orders TO ROLE analyst_readonly;

给角色授予列的SELECT权限(列级权限):

GRANT SELECT(order_id, order_date, amount) ON TABLE sales.orders TO ROLE analyst_readonly;

把角色授予用户组:

GRANT ROLE analyst_readonly TO GROUP analysts;

把角色授予用户:

GRANT ROLE analyst_readonly TO USER testuser;

这里有一个实操中很容易踩的坑:Sentry的GRANT语句里,对象名的写法必须和Hive元数据里存储的完全一致。比如数据库名是大小写敏感的,如果你在Hive里创建的是"SALES",在Sentry里写"sales"就会报错说对象不存在。我建议在授权之前,先用SHOW DATABASES和SHOW TABLES确认一下准确的对象名。

4.3 权限的继承与优先级:搞懂这个才能避免"为什么他还能看"

Sentry的权限继承规则是:数据库权限自动继承到表,表权限自动继承到列。但有一个例外:如果你在表级别显式地REVOKE了某个权限,那么即使数据库级别有这个权限,表级别也会被拒绝。

举个例子:角色A有数据库sales的SELECT权限,那么角色A自动拥有sales下所有表的SELECT权限。但如果对sales.orders表执行了REVOKE SELECT ON TABLE sales.orders FROM ROLE A,那么角色A就不能查orders表了,但其他表还能查。

这个机制在实际中很有用。比如某个库里大部分表都可以给分析师看,但有一张包含敏感信息的表需要排除,就可以用这种方式做例外处理。

但要注意,Sentry的权限判定是"白名单"模式:默认拒绝所有,只有显式授予的才允许。所以如果你REVOKE了一个权限,又没有其他角色给这个用户授予同样的权限,那用户就彻底没权限了。在排查"为什么用户突然不能访问了"这类问题时,要检查是不是某个REVOKE操作影响了用户的权限。

5. 踩坑实录:那些让我加班到凌晨的Sentry问题

5.1 坑一:HDFS ACL同步不生效,用户绕过Hive直接读文件

这是我在生产环境遇到的第一个Sentry相关故障。现象是:在Sentry里给用户授了Hive表的SELECT权限,用户通过Hive查询正常,但用Spark直接读底层HDFS文件时被拒绝。检查HDFS ACL发现,底层文件的ACL根本没有更新。

排查过程是这样的:先确认Sentry Server的日志,看有没有ACL同步相关的报错。日志里显示"Sentry HDFS ACL sync failed: permission denied"。这说明Sentry尝试去更新HDFS ACL,但被HDFS拒绝了。

根因是:Sentry Server运行的用户(通常是sentry)没有权限去修改HDFS文件的ACL。HDFS的ACL修改需要文件所有者或超级用户权限。Sentry Server既不是文件所有者,也不是超级用户,所以被拒。

解决方案是在HDFS的配置里,把sentry用户加入超级用户组,或者配置HDFS的"超级用户组"包含sentry。具体操作是在Cloudera Manager的HDFS配置里,找到"Superuser Group"选项,把sentry加进去。改完后重启HDFS,ACL同步就正常了。

这个坑的教训是:Sentry和HDFS的集成不是"配了就行",还需要确保Sentry Server有足够的权限去操作HDFS。在启用ACL同步之前,先用sentry用户手动尝试修改一个测试文件的ACL,确认权限没问题再全面启用。

5.2 坑二:角色授予了但用户还是没权限,原来是组映射出了问题

有一次给一个新入职的同事配权限,把角色授予了他所在的用户组,但同事反馈说还是查不了数据。我检查了Sentry里的角色授予记录,确实有这条记录。又检查了同事的账号,确实在那个组里。

问题出在Sentry获取用户组信息的方式上。Sentry默认通过Hadoop的组映射机制获取用户组,而Hadoop的组映射是从操作系统层面读取的。但同事的账号是在LDAP里创建的,操作系统层面并没有这个用户,所以Hadoop的组映射拿不到他的组信息。

解决方案是配置Sentry使用LDAP作为组映射来源。在Sentry的配置里,把"Group Mapping"改为LDAP provider,并配置LDAP的URL、绑定DN、搜索基础等参数。改完后重启Sentry Server,同事的权限就生效了。

这个坑的教训是:Sentry的用户组来源必须和实际的用户管理体系统一。如果你的用户是在LDAP里管理的,那Sentry也必须从LDAP获取组信息,不能依赖操作系统的组映射。

5.3 坑三:权限变更后不生效,缓存惹的祸

Sentry为了提高性能,会在各个组件(Hive、Impala等)里缓存权限判定结果。默认缓存时间是几分钟。这意味着你在Sentry里改了权限,用户可能还要等几分钟才能看到变化。

这在测试环境里问题不大,但在生产环境里,如果紧急需要收回某个用户的权限,等几分钟可能就出事了。Sentry提供了一个刷新缓存的机制:在Sentry Server上执行一个刷新命令,或者通过Cloudera Manager的API触发刷新。

具体操作是:在Sentry的配置里,把"Privilege Cache TTL"调小,比如从默认的300秒改成60秒。但调太小会增加Sentry Server的负载,因为每次权限判定都要去查数据库。我一般建议设成120秒,在安全性和性能之间取个平衡。

如果确实需要立即生效,可以重启对应的组件服务(比如HiveServer2),重启后缓存会被清空。但重启服务影响面大,不建议频繁操作。

6. 把Sentry用好的几个进阶思路

6.1 角色设计要面向职责,而不是面向个人

我见过一些团队的做法是:每来一个新用户,就给他创建一个专属角色,把需要的权限都授给这个角色。这种做法在用户少的时候还行,用户一多就乱套了。角色数量爆炸,权限关系变成一团乱麻,根本维护不了。

正确的做法是面向职责设计角色。比如"数据分析师"角色、"数据工程师"角色、"报表开发"角色,每个角色对应一组固定的权限。新用户来了,看他属于哪个职责,就授予对应的角色。这样角色数量是可控的,权限关系也清晰。

如果某个用户有特殊的权限需求,不要给他创建新角色,而是看看能不能通过组合现有角色来满足。比如他需要分析师角色的权限加上某张表的额外写权限,那就授予分析师角色,再单独给他授予那张表的写权限。这样既满足了需求,又不会破坏角色体系的整洁。

6.2 用Sentry的审计日志做权限合规检查

Sentry会记录所有的权限判定请求,包括谁在什么时候尝试访问什么对象、结果是被允许还是被拒绝。这些日志默认存在Sentry Server的日志文件里,可以配置输出到单独的审计日志文件。

这些日志的价值在于:你可以定期分析被拒绝的访问请求,看看是不是有用户权限配置不足,或者是不是有人在尝试越权访问。前者说明权限配置需要调整,后者可能是安全事件的前兆。

我一般会写一个简单的脚本,每天定时扫描Sentry的审计日志,统计被拒绝次数最多的用户和对象,然后人工review一下。这个习惯帮我发现过好几次权限配置遗漏的问题。

6.3 权限变更要走流程,不能随手改

Sentry的权限管理入口很开放,管理员在Hue里点几下就能改权限。这种便利性是一把双刃剑:方便的同时也容易出问题。我经历过一次事故:一个管理员在调试问题时临时给一个用户授了敏感表的权限,调试完忘了收回,那个权限就一直留着了。

后来我们定了一个规矩:所有生产环境的权限变更必须走工单流程,由至少两个人review后才能执行。临时权限必须设置过期时间,到期自动收回。Sentry本身不支持权限过期,但我们通过定时脚本扫描临时角色并自动REVOKE来实现。

这个流程看起来麻烦,但比起数据泄露的风险,这点麻烦是值得的。

7. 关于Sentry和Ranger的选择,说点个人看法

CDH生态里除了Sentry,还有另一个权限管理方案叫Ranger。经常有人问我该选哪个。我的看法是:如果你用的是CDH,Sentry是原生集成的,配置和维护成本更低;如果你用的是HDP或者混合环境,Ranger的兼容性更好。两者在核心功能上差别不大,都是集中式权限管理,都支持Hive、HDFS、Solr等组件。

Sentry的一个优势是和Cloudera Manager的集成更紧密,很多配置可以在CM界面里完成,不需要手动改配置文件。Ranger的界面更友好一些,权限管理的粒度也更细,比如支持基于标签的权限控制。

但说实话,对于大多数中小规模的集群,Sentry已经够用了。与其纠结选哪个,不如先把Kerberos上了、把基本的权限体系搭起来。工具只是手段,真正的安全来自于规范的流程和持续的审计。

我在实际使用中的体会是:Sentry的配置本身不难,难的是权限体系的设计和维护。一个设计良好的角色体系,能让权限管理变成一件轻松的事;一个混乱的角色体系,会让每次权限变更都变成一场冒险。所以在动手配置之前,先花时间想清楚你的组织里有哪些职责、每个职责需要访问哪些数据,这比任何技术细节都重要。

RELATED READING

延伸阅读

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