前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >0578-5.15.1-Kerberos环境下Java应用程序认证超时异常分析

0578-5.15.1-Kerberos环境下Java应用程序认证超时异常分析

作者头像
Fayson
发布于 2019-04-28 10:03:18
发布于 2019-04-28 10:03:18
2.9K00
代码可运行
举报
文章被收录于专栏:Hadoop实操Hadoop实操
运行总次数:0
代码可运行

作者:谢敏灵/辉少

1

文档编写目的

在Kerberos环境中,我们的应用程序通过Java代码来提交任务需要先进行Kerberos凭证的初始化然后进行应用程序的提交,本文档主要讲述Java应用程序长时间运行作业Kerberos不自动重新认证问题

  • 测试环境

1.CM和CDH版本为5.15.1

2.操作系统版本为RedHat7.2

3.集群已启用Kerberos

2

问题描述

在使用JDK 8时,在Kerberos环境下应用程序在执行的过程中报以下错误:

Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

3

问题分析

在Kerberos环境下长时间运行的作业会出现认证失败问题,认证失败是由于Ticket过期导致。Ticket过期是由ticket_lifetime和renew_lifetime两个参数控制,具体分析如下:

先了解下krb5.conf里ticket_lifetime和renew_lifetime参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ticket_lifetime = 24h
renew_lifetime = 7d

注:这里其实还跟kdc.conf里的ticket_lifetime和renew_lifetime相关,本文不做讨论,假设你配置都是一致的。

每一个Kerberos的ticket,包括TGT,都有一个ticket_lifetime(默认:1天);Ticket可以被延续,但最多只能延续到renew_lifetime(默认:7天),超过7天后无法再延续,此时ticket失效,只能重新login。

如果你的应用程序需要运行很长时间或者需要持续不断地一直运行,就会有一个问题,即:

在应用程序启动时进行Kerberos认证登录后,是否还需要定时renew ticket或在ticket期满失效后使用keytab重新login?例如,是否需要在应用程序代码里,在每个UGI.doAS(...)前调用UGI.checkTGTAndReloginFromKeytab或者使用一个Timer周期性地调用UGI.checkTGTAndReloginFromKeytab?

关于这个问题,首先需要了解在Hadoop系统里是如何进行Kerberos认证的:

Hadoop Kerberos认证的主要使用场景是Hadoop RPC框架(使用SASL进行kerberos认证)。大部分Hadoop daemon进程在启动时会调用UGI(org.apache.hadoop.security.UserGroupInformation),UGI.loginUserFromKeytab做kerberos认证并获取ticket,并在后续每一次RPC调用时使用该ticket认证。比如,DataNode必须认证它对NameNode的RPC调用,NodeManager也必须认证它对ResourceManager的RPC调用。那么,这些daemon进程为什么能在启动后长时间持续运行而不会出现kerberos ticket错误呢(甚至已经超过了renew_lifetime)?这是因为Hadoop在RPC Client层实现了一种自动relogin机制。在Client.handleSaslConnectionFailure(org.apache.hadoop.ipc.Client)方法里有如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
      // try re-login
    if (UserGroupInformation.isLoginKeytabBased()) {
              UserGroupInformation.getLoginUser().reloginFromKeytab();
    } else if (UserGroupInformation.isLoginTicketBased()) {
        UserGroupInformation.getLoginUser().reloginFromTicketCache();
    }

上述代码说明在使用RPC连接时,如果因为ticket失效造成认证失败,会自动relogin。

基于以上认识,可以得出以下结论:

1.如果应用程序的使用模式是从keytab登录后执行典型的Hadoop RPC Java调用(如调用HDFS FileSystem API),那么是不需要在应用层增加renew ticket或relogin代码的,因为RPC Client层已经帮你实现了。

2.如果应用程序的使用模式是不使用Hadoop RPC,而是调用HDFS REST API或YARN REST API(使用SPNEGO进行kerberos认证),那么需要在应用程序里增加relogin代码。具体实现方式是:

Java方式:主Java程序使用keytab调用UGI.loginUserFromKeytab登录,然后在每个UGI.doAS前调用UGI.checkTGTAndReloginFromKeytab方法,或者另启动一个线程周期性调用该方法。

Shell方式:主程序使用kinit登录,然后启动另一个子进程周期性的调用kinit -R去renew ticket或者调用kinit -kt去relogin。

需要注意的是当使用JDK 8时,UGI的relogin存在一个bug,即HADOOP-10786。该bug是因为JDK 8的Krb5LoginModule有些小改动,这些改动会造成UGI的relogin代码认为之前的登录并不是基于keytab登录的。所以,UGI.reloginFromKeytab和UGI.checkTGTAndReloginFromKeytab方法实际上什么都没有做,并没有执行relogin。所以,此时应用程序仍然会报以下错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

4

解决办法

对于使用JDK 8应用程序不能正常reloginFromKeytab的 bug,workaround是:

1. 使用JDK 7而不是JDK 8,或者

2. 确保hadoop-common包含了HADOOP-10786补丁。

建议使用CDH5.13.0或者以上版本的包,这些包已经包括了该补丁。如果仍然在IDE开发环境出现了以上问题,可以检查一下IDE依赖的hadoop-common包的版本是否有问题。

参考文档:

https://issues.apache.org/jira/browse/HADOOP-10786

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hadoop实操 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Hadoop Delegation Tokens详解【译文】
本文是cloudera公司的一篇技术博客,原文地址: Hadoop Delegation Tokens Explained
topgunviper
2022/05/12
2.2K0
Hadoop Delegation Tokens详解【译文】
Hadoop Authentication
我被被派去做别的事情了,所以与Hadoop相关的工作就只能搁下。写篇总结,把最近遇到的和kerberos相关的东西列一下。 JAAS是Java 认证和授权服务(Java Authentication and Authorization Service)的缩写,是PAM框架的Java实现。 javax.sercurity.auth.Subject是一个不可继承的实体类,它表示单个实体的一组相关信息,与请求的来源相关。 javax.security.auth.Principal是一个接口,表示带有不同类型凭证的标识,基本上来说,Principal可以是任意对象。 JAAS的授权机制主要就是围绕着Subject和Principal。关于JAAS比较详细的参考是这里:http://docs.oracle.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html 几个比较重要的java属性: java.security.krb5.realm java.security.krb5.kdc java.security.krb5.conf hadoop的身份认证和授权都是建立在JAAS之上。 hadoop.security.authentication属性有2种值: simple: Security is disabled。 kerberos: Security is enabled。 org.apache.hadoop.security.UserGroupInformation有一个静态方法:getCurrentUser()。它会返回一个UserGroupInformation类的实例(以下简称UGI)。如果subject为空,或者这个subject中与org.apache.hadoop.security.User对应的Principal为空,那么说明尚未登录过,调用getLoginUser()创建UserGroupInformation的实例。 getLoginUser()的流程: 1.创建LoginContext: name:如果hadoop.security.authentication等于”kerberos”,那么是“hadoop-user-kerberos”或者“hadoop-keytab-kerberos”,否则是“hadoop-simple”。它的主要作用是作为appName传递给UserGroupInformation.HadoopConfiguration.getAppConfigurationEntry(String appName)方法。 subject: callbackHandler: 空 Configuration: UserGroupInformation.HadoopConfiguration的实例。 2.login.login(); 这个会调用HadoopLoginModule的login()和commit()方法。 HadoopLoginModule的login()方法是一个空函数,只打印了一行调试日志 LOG.debug("hadoop login"); commit()方法负责把Principal添加到Subject中。 此时一个首要问题是username是什么? 在使用了kerberos的情况下,从javax.security.auth.kerberos.KerberosPrincipal的实例获取username。 在未使用kerberos的情况下,优先读取HADOOP_USER_NAME这个系统环境变量,如果不为空,那么拿它作username。否则,读取HADOOP_USER_NAME这个java环境变量。否则,从com.sun.security.auth.NTUserPrincipal或者com.sun.security.auth.UnixPrincipal的实例获取username。 如果以上尝试都失败,那么抛出异常LoginException("Can’t find user name")。 最终拿username构造org.apache.hadoop.security.User的实例添加到Subject中。 测试登录: HADOOP_JAAS_DEBUG=true HADOOP_ROOT_LOGGER=DEBUG,console  bin/hadoop  org.apache.hadoop.security.UserGroupInformation 其中,UGI应该是这样的形式: UGI: host/xx.xx.xx.com@xx.xx.com (auth:KERBEROS)
星哥玩云
2022/07/01
4750
安全知识&kerberos初识
问题一 kinit alice beeline -u “jdbc:hive2://baogang2:10000/default;principal=hive/baogang2@TDH” 请问这个beeline连接到inceptor中之后,当前用户是谁?principal=hive/baogang2@TDH指的又是什么? 当前用户是baogang2 principal=hive/baogang2@TDH指的是在baogang2的权限下使用hive 问题二 尝试写一个访问
小爷毛毛_卓寿杰
2019/02/13
1K0
安全知识&kerberos初识
如何使用Java连接Kerberos的HBase
出于CDH集群安全考虑,在CDH集群中增加了Kerberos认证机制。因为HBase的存储系统是基于Hadoop的存储,所以通过HBase客户端访问HBase数据库时需要进行身份认证。在Linux下使用HBase客户端访问HBase数据时需要先kinit初始化Kerberos账号,认证完成后我们就可以直接使用HBase shell操作HBase了。通过Linux的Kinit命令可以方便的完成Kerberos的认证,那么在Java开发中如何完成Kerberos的登录认证呢?本篇文章主要讲述如何使用Java连接Kerberos环境的HBase。
Fayson
2018/03/29
5.9K0
如何使用Java连接Kerberos的HBase
基于Kerberos环境下,使用Java连接操作Hive
虽然可以使用 Hive 服务本身的 Principal 与 keytab 来连接 Hive ,但使用服务本身的 principal 不具有普遍性,所以还是建议使用自定义的 Principal 。
create17
2019/08/20
10.1K1
一文搞懂hadoop中的用户
又有一段时间没有更新了,最近忙着搬砖的同时,也填了一些坑,其中不少坑是有关联的,甚至其中有一个配置项接连引发了两三个问题,后续打算逐个总结输出,这里先进行一些铺垫~
陈猿解码
2023/02/28
1.4K0
一文搞懂hadoop中的用户
0579-5.15.1-Java 应用程序中修改Kerberos ticket_lifetime参数无效异常分析
在Kerberos环境中,我们的应用程序通过Java代码来提交任务需要先进行Kerberos凭证的初始化然后进行应用程序的提交,本文档主要讲述Java应用程序中读取krb5.conf 中配置ticket_lifetime 参数不生效的异常分析。
Fayson
2019/04/28
1.8K0
0579-5.15.1-Java 应用程序中修改Kerberos ticket_lifetime参数无效异常分析
[1067]CDH6.3.2之Kerberos安全认证
Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构,并且能够进行相互认证,即客户端和服务器端均可对对方进行身份认证。可以用于防止窃听、防止重放攻击、保护数据完整性等场合,是一种应用对称密钥体制进行密钥管理的系统。
周小董
2021/11/11
1.2K0
[1067]CDH6.3.2之Kerberos安全认证
使用Docker快速搭建Kerberos环境
Kerberos认证在大数据场景下用的比较多,特别是在Hadoop生态下,认证基本用的都是Kerberos认证。一般来讲Kerberos认证相对于其他方式的认证安全很多,同样的认证的时候性能应该差一点。
zeekling
2022/07/16
1.3K0
2.X版本又一个极端情况下的偶现严重问题
前段时间,在异常测试的环境里,发现yarn任务无法提交,经过逐步排查,最后发现在一个极端的场景下,存在JN不会重新向kerberos进行认证,导致整体均无法提供服务的情况。本文就来详细聊聊问题出现时的情况以及分析复现过程。
陈猿解码
2023/02/28
6250
2.X版本又一个极端情况下的偶现严重问题
Centos7.9安装kerberos
亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。
刘大猫
2025/01/15
1110
hive metastore配置kerberos认证
hive从3.0.0开始提供hive metastore单独服务作为像presto、flink、spark等组件的元数据中心。但是默认情况下hive metastore在启动之后是不需要进行认证就可以访问的。所以本文基于大数据组件中流行的kerberos认证方式,对hive metastore进行认证配置。
从大数据到人工智能
2022/01/18
1.2K0
hive metastore配置kerberos认证
如何使用Java代码访问Kerberos环境下的Kudu
前面Fayson介绍了《如何使用Java API访问CDH的Kudu》,文章是在非安全环境下实现,随着对集群安全要求的提高,在Kerberos环境下的使用API访问Kudu也会有一些变化,本篇文章Fayson主要介绍如何使用Java代码访问Kerberos环境下的Kudu。
Fayson
2018/11/16
3K0
如何使用HAProxy实现Kerberos环境下的Impala负载均衡
前面Fayson介绍过《如何使用HAProxy实现Impala的负载均衡》,在Kerberos环境HAProxy的配置与非Kerberos环境下是一样的,只是在Impala的配置上需要做一些修改,接下来本篇文件主要讲述如何在Kerberos环境下使用HAProxy实现Impala的负载均衡。
Fayson
2018/03/29
1.7K0
如何使用HAProxy实现Kerberos环境下的Impala负载均衡
如何使用java代码通过JDBC连接Impala(附Github源码)
访问Impala的方式很多(如:impala-shell、ODBC、JDBC、Beeline),也可以通过Hue的来访问。关于Beeline方式连接Impala可以参考前面的《如何使用Beeline连接Impala》,本篇文章主要讲述如何使用JAVA代码通过JDBC的方式连接Kerberos和非Kerberos环境下的Impala。
Fayson
2018/03/29
7.1K0
如何使用java代码通过JDBC连接Impala(附Github源码)
如何使用java连接Kerberos和非kerberos和kerberos的Spark1.6 ThriftServer
温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。 Fayson的github: https://github.com/fayson/cdhproject 提示:代码块部分可以左右滑动查看噢 1.文档编写目的 ---- 前面Fayson介绍了《如何在CDH中启用Spark Thrift》和《如何在Kerberos环境下的CDH集群部署Spark1.6 Thrift及spark-sql客户端》,本篇文章Fayson主要介绍如何使用Java JDBC连接非Kerberos和Kerberos环境下Sp
Fayson
2018/07/11
1.9K0
在CDP集群启用Kerberos手册
Kerberos协议主要用于计算机网络的身份鉴别(Authentication), 其特点是用户只需输入一次身份验证信息就可以凭借此验证获得的票据(ticket-granting ticket)访问多个服务,即SSO(Single Sign On)。由于在每个Client和Service之间建立了共享密钥,使得该协议具有相当的安全性。
大数据杂货铺
2021/10/09
1.7K0
如何使用java代码通过JDBC连接Hive(附github源码)
前面我们讲过《如何使用java代码通过JDBC连接Impala(附Github源码)》,本篇文章主要讲述如何使用Java代码通过JDBC的方式连接Hive。
Fayson
2018/03/29
7.3K0
如何使用java代码通过JDBC连接Hive(附github源码)
0465-如何使用SQuirreL访问Kerberos环境下的Hive
在前面Fayson的文章《0459-如何使用SQuirreL通过JDBC连接CDH的Hive(方式一)》和《0463-如何使用SQuirreL通过JDBC连接CDH的Hive(方式二)》介绍了SQuirreL的安装以及使用原生和Cloudera提供的JDBC 驱动访问Hive。本篇文章Fayson主要介绍如何使用Cloudera提供的Hive JDBC驱动访问Kerberos环境下的Hive,为什么不讲原生的JDBC驱动,因为Fayson也没有调通。
Fayson
2018/12/21
1.3K0
0465-如何使用SQuirreL访问Kerberos环境下的Hive
Kerberos 身份验证在 ChunJun 中的落地实践
Kerberos,在古希腊神话故事中,指的是一只三头犬守护在地狱之门外,禁止任何人类闯入地狱之中。
袋鼠云数栈
2022/12/16
1.8K0
相关推荐
Hadoop Delegation Tokens详解【译文】
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验