深入 Hadoop 18 - Hadoop 安全 Kerberos Token ProxyUser
上一篇讲了序列化与压缩。本篇讲 Hadoop 的安全机制——Kerberos 认证、Delegation Token、Proxy User。
Hadoop 安全常被介绍成"Kerberos 配置"。这个描述对应了最显眼的部分但漏了完整设计。准确的说法是:Hadoop 安全是一个分层模型——底层用 Kerberos 做初始强认证,中间层用 Delegation Token 减轻 KDC 压力,资源访问层用 Block Token / Container Token 做时间受限授权,最上层用 ACL 做细粒度权限控制。Proxy User 让超级用户代表真实用户访问 Hadoop,是 HiveServer2 / Oozie / Hue 这类网关服务的核心机制。
本篇只抓一个问题:Kerberos 在 Hadoop 里到底起什么作用、Delegation Token 怎么减少 KDC 压力、Proxy User 与 doAs 模型怎么让网关服务代用户访问。
为什么 Hadoop 需要 Kerberos
Hadoop 默认是 SIMPLE 认证——客户端声称自己是哪个用户,Hadoop 就当作用户名。这种"自报家门"在内部开发环境够用,但在多租户生产集群里完全不安全——任何用户都能伪造身份。
Kerberos 是 MIT 1980 年代设计的网络认证协议,用对称加密 + 可信第三方(KDC)保证身份不可伪造。Kerberos 的核心是票据(ticket)——客户端拿到某个服务的票据后,向服务证明自己身份,不需要每次都查 KDC。
Hadoop 在 Hadoop 1.x 时代(2010 年左右)才集成 Kerberos,原因是早期 Hadoop 假设集群部署在受信任的内部网络。随着 Hadoop 在企业级生产环境普及,多租户集群的安全需求让 SIMPLE 认证不可接受,Kerberos 成为生产部署的标配。
Hadoop 通过 RPC 层的 SASL 抽象接入 Kerberos。Secure Mode 要求所有相关服务使用一致的安全配置,并为每个服务实例配置 principal 与 keytab;这不是可以任意逐节点混开的普通滚动开关,切换认证模式需要按集群升级方案协调重启和验证。
Kerberos 的认证流程
Kerberos 认证的标准流程涉及三方:Client、KDC(Key Distribution Center)、Service。
1 | |
Hadoop 集群的 Kerberos 配置:
1 | |
每个 Hadoop 服务(NameNode、ResourceManager、NodeManager、DataNode)有自己的 principal(服务身份)和 keytab(密码文件,可以本地读取不需要人工输入)。_HOST 是占位符,运行时替换为实际 hostname。
用户侧 Kerberos 认证通过 kinit 命令:
1 | |
TGT 默认有效期 10 小时(KDC 配置),到期前可以 renew(最长 7 天)。renew 不需要重新输入密码。
Kerberos 认证的关键好处是身份不可伪造——Client 必须知道对应 principal 的密码才能拿到有效票据。密码不通过网络传输(只本地使用),KDC 是唯一可信第三方。
Delegation Token:减轻 KDC 压力
Kerberos 的缺陷是每次访问服务都需要 Service Ticket。如果每个 Hadoop RPC 都走 Kerberos,KDC 会成为瓶颈——NameNode 一个集群每秒几万次 RPC,每次都查 KDC 不现实。
Delegation Token 是 Hadoop 自己设计的 token 机制(不是 Kerberos 标准)。Client 第一次用 Kerberos 认证 NameNode 时,可以申请一个 Delegation Token。后续 Client 与 NameNode 的所有 RPC 都用这个 Token 而不是 Kerberos。
1 | |
Delegation Token 的关键设计:
Token 由 NameNode 用 HMAC(基于自己密钥的消息认证码)签发,Client 不需要每次都查 KDC——NameNode 自己能验证 Token 真伪。
Token 有生命周期(默认 24 小时,最长 7 天,dfs.namenode.delegation.token.max-lifetime)。Token 到期前可以 renew(默认 renew 间隔 24 小时)。
Token 可以在 Client 之间传递(例如作业提交时 Client 把 Token 拷贝给 ApplicationMaster,让 AM 代表自己访问 HDFS)。这是 MapReduce 长作业访问 HDFS 的核心机制——作业持续几小时甚至几天,不可能让 AM 每小时重新 Kerberos 认证。
ResourceManager 也有自己的 Delegation Token(RMDelegationToken),用于 AM 与 RM 的 RPC 认证。机制类似 NN 的 Delegation Token。
Block Token 与 Container Token:资源级授权
Hadoop 还有两类细粒度 token:
Block Token:HDFS 文件块的访问凭证。NameNode 在 Client 打开文件时签发该文件每个 block 的 Block Token。Client 直连 DataNode 读 block 时出示 Block Token,DataNode 验证后允许读。
1 | |
Block Token 解决的问题是 DataNode 不知道用户的 ACL——DataNode 只存 block 字节,不知道哪些用户能读。如果不验证,任何 Client 都可以伪造 block ID 直接读 DataNode 拿到数据。Block Token 让 NameNode 在签发 token 时一次性做 ACL 检查,DataNode 只需要验证 token 真伪。
Container Token:YARN Container 的启动凭证。ResourceManager 在分配 Container 给 AM 时签发 Container Token,AM 拿这个 Token 向对应 NodeManager 启动 Container。
1 | |
Container Token 让 NodeManager 只接受 RM 授权的 container 启动请求,AM 不能凭空在自己想要的节点启动任意 container。
ACL:操作级权限控制
Kerberos 解决"你是谁",ACL 解决"你能做什么"。Hadoop 的 ACL 在多个层面:
HDFS ACL:文件 / 目录的权限。每个文件有 owner、group、permission(类似 POSIX rwx)。Hadoop 2.x+ 扩展支持细粒度 ACL(user:alice:rwx、group:dev:r-x)。
1 | |
YARN ACL:队列的访问控制。Capacity Scheduler 配置每个队列的 submit-applications 和 administer-queue ACL。
1 | |
MapReduce ACL:作业的查看和修改权限。mapreduce.job.acl-view-job 和 mapreduce.job.acl-modify-job 配置作业的访问控制。
Service Level Authorization:服务级开关。hadoop.security.authorization=true 启用后,每个 Hadoop 服务可以配置允许访问的用户 / 主机列表。
ACL 是 Hadoop 多租户集群的核心控制机制。Kerberos 保证身份真实,ACL 决定身份能做什么。两层组合让 Hadoop 可以在企业级生产环境安全运行。
Proxy User:网关服务代用户访问
很多 Hadoop 生态服务是"网关"——用户不直接用 hadoop 命令访问集群,而是通过 HiveServer2、Oozie、Hue、Presto 等中间服务。这些服务代用户访问 Hadoop(HDFS / YARN)。
最简单的实现是网关服务用一个超级用户身份访问所有数据,但这破坏了 Hadoop 的审计——NameNode 日志只看到 “hive” 用户访问,不知道真实用户是谁。
Proxy User 机制解决这个问题。超级用户(例如 hive)可以"代表"另一个用户访问 Hadoop,Hadoop 在审计日志里同时记录超级用户和被代表的真实用户。
Proxy User 的 RPC 调用在 ConnectionHeader 里带两个信息:
1 | |
NameNode 收到这种 RPC 时:
- 验证 realUser(hive)的 Kerberos 票据。
- 检查 hive 是否允许 proxy 给 alice(
hadoop.proxyuser.hive.hosts,再配groups和/或users)。 - 如果允许,用 alice 身份做 ACL 检查、写审计日志。
Proxy User 配置:
1 | |
这种“主机 + 组和/或用户”限制收窄 hive 超级用户密钥泄露的影响范围:请求来源必须命中 hosts,目标用户还必须命中允许的 groups 或 users。
Proxy User 的常见场景:
HiveServer2:业务用户通过 JDBC 连 HiveServer2,HiveServer2 用 hive 身份认证后用 doAs=真实用户身份提交 MapReduce/Tez/Spark 作业。
Oozie:工作流引擎,工作流定义里指定 user,Oozie 用 oozie 身份提交作业但 doAs=工作流所有者。
Hue:Web UI,用户登录 Hue 后所有 Hadoop 操作通过 Hue 的 hue 身份 doAs=登录用户。
实验:观察 Hadoop 安全状态
实验状态:UNVERIFIED_RUNTIME。下面是验证步骤,本轮没有连接真实 Kerberos + Hadoop 集群执行。
如果集群启用了 Kerberos,hadoop fs -ls / 在 kinit 之前会失败:
1 | |
观察 NameNode 的审计日志(hdfs.audit.logger,默认 INFO 级别):
1 | |
每条审计日志记录:是否允许(allowed)、用户身份(ugi,含认证机制)、来源 IP、操作类型、目标文件、权限。
观察 Delegation Token:
1 | |
输出 token 的所有者、renewer、签发时间、过期时间。
Proxy User 的审计日志:
1 | |
这条日志同时记录了 effective user(alice)、real user(hive)和认证机制(PROXY 表示通过 proxy user 机制)。审计完整性比 SIMPLE 模式强得多。
模式提炼
Hadoop 安全体现的设计模式:
1 | |
这个模式不只是 Hadoop。Kafka 的安全栈(SASL + ACL + quotas)与 Hadoop 类似。Spark on YARN 复用 Hadoop 的 Kerberos + Token 机制。HBase 的安全直接用 Hadoop 的 UserGroupInformation,安全机制与 HDFS 完全一致。
云原生时代的对应是 Kubernetes RBAC + ServiceAccount + TokenRequest API。二者都使用有生命周期的 bearer token,但 Kubernetes 投影 token 由 kubelet 自动轮换,没有 Hadoop Delegation Token 那套服务端 renew/cancel 同构语义。
工程迁移表
| Hadoop 安全概念 | Kafka | HBase | Kubernetes | AWS IAM |
|---|---|---|---|---|
| Kerberos 认证 | SASL/GSSAPI | 复用 Hadoop UGI | x509 证书 | access key + secret |
| Delegation Token | SCRAM Token | HBase AuthToken | Service Account Token | STS Session Token |
| Block Token | - | - | - | S3 Pre-signed URL |
| Container Token | - | - | Service Account Token | ECS Task Role |
| Proxy User | - | - | impersonate-users | STS AssumeRole |
| ACL | topic ACL | table ACL | RBAC | IAM policy |
注意 Kubernetes 这一列。K8s 支持 x509 客户端证书等认证方式,也用短期 ServiceAccount Token 给 Pod 访问 API;投影 token 由 kubelet 轮换,不等同于 Hadoop Delegation Token 的 renew/cancel。K8s impersonation 与 Hadoop doAs 都表达代用户操作,但授权模型不同。
常见误解
误解一:“Kerberos 启用后所有 RPC 都查 KDC”。Kerberos 的 Service Ticket 有生命周期(默认 10 小时),Client 拿到后缓存复用,不每次查 KDC。Delegation Token 进一步减少 KDC 压力——长作业只需要一次 Kerberos,后续都用 Token。
误解二:“Proxy User 等于普通用户切换”。Proxy User 是受控的——超级用户只能从配置允许的主机代理命中的组和/或用户。普通用户不能借此任意切换身份;它是 HiveServer2、Oozie 等网关服务的特权。
误解三:“Kerberos 启用很复杂所以可以不开”。Hadoop 1.x 时代确实复杂(需要手工配置 keytab、principal、防火墙),但 Hadoop 2.x+ 之后配置标准化,配合自动化部署工具(Cloudera Manager、Ambari)一键启用。生产集群不开 Kerberos 等于完全无安全,必须开。
误解四:“Token 泄露无所谓,反正会过期”。Token 泄露在过期前仍然有效——攻击者拿到 token 可以冒充用户访问。生产环境通过加密传输(TLS)、keytab 文件严格权限(仅服务用户可读)降低泄露风险。
误解五:“SIMPLE 认证就是不开认证”。SIMPLE 认证仍然有认证机制——Client 通过 whoami 报告用户名,Hadoop 用这个用户名做 ACL 检查。攻击者可以伪造 whoami 输出(修改用户名环境变量),但需要在能跑 hadoop 命令的机器上。SIMPLE 不安全在多租户集群,但在单租户开发环境可以接受。
练习
-
在 Kerberos 启用的集群上跑
kinit alice@REALM获取 TGT,然后hadoop fs -ls /验证认证成功。kdestroy后再试hadoop fs -ls /,观察错误信息。 -
用
hdfs fetchdt /tmp/token.bin申请 Delegation Token,执行kdestroy删除 TGT,再运行HADOOP_TOKEN_FILE_LOCATION=/tmp/token.bin hadoop fs -ls /,观察 Token 是否仍能认证。hadoop.security.authentication只接受simple或kerberos,没有token这个配置值。 -
在
apache/hadoop源码里找到UserGroupInformation.java、KerberosInfo.java、SecretManager.java、DelegationTokenIdentifier.java(hadoop-common-project 模块),观察 Kerberos 认证和 Token 签发的核心实现。 -
思考题:如果让 Hadoop 用 OAuth 2.0 替代 Kerberos(像现代云原生系统),需要改造哪些组件?这种改造对 Hadoop 多租户隔离有什么影响?
系列导航
参考资料
- C. Neuman et al. The Kerberos Network Authentication Service (V5). RFC 4120.(Kerberos 协议规范)
- Apache Hadoop 官方文档:Security. https://hadoop.apache.org/docs/r3.4.1/hadoop-project-dist/hadoop-common/SecureMode.html
- Apache Hadoop 官方文档:Hadoop Token. https://hadoop.apache.org/docs/r3.4.1/hadoop-project-dist/hadoop-hdfs/HdfsPermissionsGuide.html#Authentication
- Apache Hadoop 源码:
UserGroupInformation.java、AuthenticationFilter.java、DelegationTokenSecretManager.java. https://github.com/apache/hadoop - Konstantin Shvachko. Hadoop Security Design.(Hadoop Summit 演讲,描述了 Hadoop 安全分层的动机)
- Ethan S. Hadoop Application Architectures. O’Reilly, 2015. Chapter 9 “Security” 详细描述了企业级 Hadoop 部署的安全配置实践。
