深入 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 的 Kerberos 集成不修改 Hadoop 核心代码——通过 RPC 层的 SASL 抽象插入。RPC Server 在 ConnectionHeader 协商时声明认证机制(SIMPLE / KERBEROS / TOKEN),客户端按服务端要求做认证。这让 Kerberos 启用可以滚动升级——不需要重启整个集群,逐节点启用即可。
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 时:
- 验证 effectiveUser(hive)的 Kerberos 票据。
- 检查 hive 是否允许 proxy 给 alice(
hadoop.proxyuser.hive.hosts+hadoop.proxyuser.hive.groups配置)。 - 如果允许,用 alice 身份做 ACL 检查、写审计日志。
Proxy User 配置:
1 | |
这种"主机 + 组"双重限制保证 hive 超级用户密钥泄露的影响范围——攻击者即使拿到 hive 密钥,也只能从特定主机 proxy 特定组的用户,不能任意伪造身份。
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 安全状态
如果集群启用了 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(hive)、real user(alice)、认证机制(PROXY 表示通过 proxy user 机制)。审计完整性比 SIMPLE 模式强得多。
模式提炼
Hadoop 安全体现的设计模式:
1 | |
这个模式不只是 Hadoop。Kafka 的安全栈(SASL + ACL + quotas)与 Hadoop 类似。Spark on YARN 复用 Hadoop 的 Kerberos + Token 机制。HBase 的安全直接用 Hadoop 的 UserGroupInformation,安全机制与 HDFS 完全一致。
云原生时代的对应是 Kubernetes RBAC + Service Account + TokenRequest API。K8s 的 Service Account Token 与 Hadoop Delegation Token 概念几乎相同——服务签发、有生命周期、可以 renew、客户端用 Token 而不是密钥认证。
工程迁移表
| 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 客户端证书替代 Kerberos——同样是基于公私钥的强认证,但证书管理比 Kerberos 简单(不需要 KDC)。K8s 的 ServiceAccount Token 与 Hadoop Delegation Token 概念几乎一致——服务签发、有 TTL、客户端不需要每次重新认证。K8s 的 impersonate-users 字段与 Hadoop Proxy User 的 doAs 机制完全对应——超级用户代表真实用户访问。
常见误解
误解一:“Kerberos 启用后所有 RPC 都查 KDC”。Kerberos 的 Service Ticket 有生命周期(默认 10 小时),Client 拿到后缓存复用,不每次查 KDC。Delegation Token 进一步减少 KDC 压力——长作业只需要一次 Kerberos,后续都用 Token。
误解二:“Proxy User 等于普通用户切换”。Proxy User 是受控的——超级用户只能 proxy 配置允许的组和主机。普通用户不能用 su / sudo 切换身份(Kerberos 防止)。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申请一个 Delegation Token,保存到本地文件。然后用kdestroy删除 TGT,再hadoop fs -D hadoop.security.authentication=token -ls /,观察 Token 是否仍然能认证(在 token 有效期内)。 -
在
apache/hadoop源码里找到UserGroupInformation.java、KerberosInfo.java、SecretManager.java、DelegationTokenIdentifier.java(hadoop-common-project 模块),观察 Kerberos 认证和 Token 签发的核心实现。 -
思考题:如果让 Hadoop 用 OAuth 2.0 替代 Kerberos(像现代云原生系统),需要改造哪些组件?这种改造对 Hadoop 多租户隔离有什么影响?
系列导航
| 序号 | 主题 | 状态 |
|---|---|---|
| 00-06 | HDFS 存储层 | 第一阶段(已完成) |
| 07-12 | YARN 资源管理层 | 第二阶段(已完成) |
| 13-15 | MapReduce 计算模型 | 第三阶段(已完成) |
| 16 | Hadoop RPC 协议栈 | |
| 17 | 序列化与压缩:Writable、Avro 与 Codec | 上一篇 |
| 18 | Hadoop 安全:Kerberos、Delegation Token、Proxy User | 本篇 |
| 19 | 监控与运维:Metrics V2、JMX、日志聚合 | 下一篇 |
| 20-22 | 演进、生态与对比 | 第五阶段,待开始 |
参考资料
- C. Neuman et al. The Kerberos Network Authentication Service (V5). RFC 4120.(Kerberos 协议规范)
- Apache Hadoop 官方文档:Security. https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/SecureMode.html
- Apache Hadoop 官方文档:Hadoop Token. https://hadoop.apache.org/docs/current/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 部署的安全配置实践。
