如何在Hadoop mapReduce中获取Kerberos而不是委派令牌?

如何在Hadoop mapReduce中获取Kerberos而不是委派令牌?,hadoop,kerberos,Hadoop,Kerberos,我是一个Java用户,在向Hadoop mapReduce提交作业时,它使用Kerberos对Hadoop进行身份验证,成功后,将创建委派令牌,并将其与作业提交一起传递给Hadoop,而不是Kerberos票证(出于Hadoop所述的安全原因)。现在作业以我的身份运行,但作业本身需要使用Kerberos向Hadoop之外的其他服务发送请求。现在我在Hadoop上没有kerberos TGT,也无法获得服务票证 无论如何,我都可以通过Kerberos工作票吗?(我知道这可能很危险,因为我们不想传递

我是一个Java用户,在向Hadoop mapReduce提交作业时,它使用Kerberos对Hadoop进行身份验证,成功后,将创建委派令牌,并将其与作业提交一起传递给Hadoop,而不是Kerberos票证(出于Hadoop所述的安全原因)。现在作业以我的身份运行,但作业本身需要使用Kerberos向Hadoop之外的其他服务发送请求。现在我在Hadoop上没有kerberos TGT,也无法获得服务票证

无论如何,我都可以通过Kerberos工作票吗?(我知道这可能很危险,因为我们不想传递秘密),JobConf可以将字符串对传递给Hadoop,但我必须将TGT转换为json字符串,并在作业运行期间还原它

或者是否可以使用授权令牌改革TGT

我试着用谷歌搜索,但没有多少信息,有人能帮我吗?多谢各位

**编辑:*

如果不将TGT传递给Hadoop,似乎没有简单的方法可以做到这一点,因此我将尝试以下方法,通过作业配置映射将TGT作为字符串传递给Hadoop(仅字符串),并在作业在Hadoop中运行时将字符串转换回TGT对象。问题是我将通过网络传递凭据,这不是一种最佳实践,也是Hadoop没有通过Kerberos实现安全性的原因之一。如果我可以重新使用传递给Hadoop的经过修改的TGT来获取服务票证,我将尽可能地加密TGT字符串以避免安全问题

因此,在本地计算机中启动作业之前,代码如下:

import sun.security.krb5.Credentials;  

Credentials tgt = Credentials.acquireTGTFromCache(null, null); // Make sure kinit is done before this

String tgtStr = tgt.convertToJsonString(); //Need to implement this

Job job = new Job("Test");
JobConf jobConf = job.getJobConf();
jobConf.set("tgtStr", tgtStr);
job.addTask(Test.class, "run", null);
job.submit();
job.waitForCompletion(true);
Configuration conf = TaskContext.get().getConfiguration();
String tgtStr = conf.get("tgtStr");
Credentials tgt = reformTGTFromString(tgtStr);//Need to implement this
Credentials serviceTicket = Credentials.acquireServiceCreds(servicePrincipal, tgt); //This is to get any service ticket
那么Hadoop要运行的作业中的函数如下所示:

import sun.security.krb5.Credentials;  

Credentials tgt = Credentials.acquireTGTFromCache(null, null); // Make sure kinit is done before this

String tgtStr = tgt.convertToJsonString(); //Need to implement this

Job job = new Job("Test");
JobConf jobConf = job.getJobConf();
jobConf.set("tgtStr", tgtStr);
job.addTask(Test.class, "run", null);
job.submit();
job.waitForCompletion(true);
Configuration conf = TaskContext.get().getConfiguration();
String tgtStr = conf.get("tgtStr");
Credentials tgt = reformTGTFromString(tgtStr);//Need to implement this
Credentials serviceTicket = Credentials.acquireServiceCreds(servicePrincipal, tgt); //This is to get any service ticket
所以我需要实现两个函数,将TGT对象(Credentials.class)流式处理为字符串,然后将其重新转换为对象


有人知道更好的解决办法吗?谢谢。

首先,您的帐户必须启用委派。服务票证必须申请可转寄的票证。如果这都是真的,Hadoop必须从
GSSContext
中检索委派凭证,并代表您构建一个新凭证。有了新的TGT,它将能够执行进一步的步骤。使用Wireshark检查hadoop的票证。

如果您还没有这样做,请查看上的设计

或者是否可以使用授权令牌改革TGT? 不,委派令牌是由Hadoop名称节点发布的,虽然它基于Kerberos身份验证,但它是独立的,您不能从中派生Kerberos TGT

在最初的设计中,我们考虑只使用Kerberos(不使用任何附加令牌),这会使您的计划变得简单,但出于以下原因,我们决定不使用Kerberos:

性能:

  • 数千个M/R任务可能需要同时获取Kerberos票证 同时
  • Kerberos凭据需要在到期前续订 对于计划作业,这将是一个问题
  • 委派令牌不依赖于Kerberos,可以与边缘使用的非Kerberos身份验证机制(如SSL)耦合

在您的情况下,您可以使用私有分布式缓存并发送可转发的TGT。我认为这将是好的,但需要考虑更多。显然,您需要确保您的实现是安全的,您的票证具有最少必要的生存期,如果可能,使用IP通道绑定,并将票证的使用限制为仅授权进程

通过使用Base64编码器分解凭据字段并将其转换为字符串,形成一个JSON字符串并使用配置映射或RVM建议的分布式缓存将其传递给Hadoop,然后在Hadoop上运行的作业中重新构造凭据对象,我可以取回Kerberos TGT并使用它成功获取任何服务票证。因此,这种方法是有效的,这里唯一需要非常小心的是对通过网络传递的密钥进行加密。

感谢您的解释,因此对于从委托服务票证构造新凭证,GSSContext需要原始票证,对吗?如何将本地获得的服务票传递给Hadoop?如果我错了,请纠正我。谢谢。我在Hadoop方面没有经验,但你必须检查Hadoop是否可以访问
GSSContext
,并将凭据保存在某个地方。事情就是这样。谢谢你的建议,我的计划是以一种安全的方式(希望如此)将TGT传递给Hadoop,以测试它是否有效。我编辑了这篇文章,提供了更多关于实现的细节,还有更多的见解吗?谢谢。你应该考虑使用分布式缓存,而不是把TGT放在工作ID中。这样会更安全。我不记得jobconf上的访问权限是什么。否则,可能会记录作业配置属性。因此,分布式缓存可能比jobconf更安全。通过分解凭据字段并使用Base64编码器将其转换为字符串,形成JSON字符串并使用配置映射或RVM建议的分布式缓存将其传递给Hadoop,然后在Hadoop上运行的作业中改革凭据对象,我可以取回Kerberos TGT,并使用它成功地获得任何服务票证。所以这种方法是有效的,这里唯一需要非常小心的是通过网络传递的密钥的加密;可以只将服务票证传递给Hadoop,然后使用适当配置的帐户请求票证传递给特定的服务。