1

我编写了一个使用 keytabs 访问 hadoop 的代码,但我希望它只使用凭据而不是 keytabs,有没有办法做到这一点?以下是我目前正在使用的代码 -

public static void loginToHDFSUsingKeytab(Configuration hdfsConf) {

    hdfsConf.set("hadoop.security.authentication", "kerberos");
    hdfsConf.set("dfs.namenode.kerberos.principal", nameNodePrincipal);

    UserGroupInformation.setConfiguration(hdfsConf);
    try {
        UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(loginUser, keytab);
        UserGroupInformation.setLoginUser(ugi);
        System.out.println("Logged in successfully.");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我遇到几个线程说有一种方法叫做

UserGroupInformation.loginUserFromSubject(主题)

但我在 UserGroupInformation 类中看不到该方法。我尝试了 2.2.0 和 3.1.1 版本的 hadoop-commons,但是这两种方法都不可用。

更新 :

我尝试使用 JAAS 和以下代码进行身份验证:

public static void main(String args[]) throws Exception {

        System.setProperty("kerberos.security.enabled", "true");
        System.setProperty("java.security.auth.login.config", jaasFilePath);
        // System.setProperty("javax.security.auth.login.name", loginUser);
        // System.setProperty("javax.security.auth.login.password", password);

        Configuration conf = new Configuration();
        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
        conf.set("hadoop.security.authentication", "kerberos");
        conf.set("dfs.namenode.kerberos.principal", nameNodePrincipal);
        loginWithPassword(activeNamenodeURI, conf);
        // usingKeytabs(conf);
    }


    private static void loginWithPassword(final String args, final Configuration conf) throws Exception {

        LoginContext loginContext = new LoginContext("com.sun.security.jgss.initiate", new CallbackHandler() {
            @Override
            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

                for (Callback callback : callbacks) {
                    System.out.println("inside handle method" + callback.getClass());
                    if (callback instanceof NameCallback) {
                        NameCallback nameCallback = (NameCallback) callback;
                        nameCallback.setName(loginUser);
                    } else if (callback instanceof PasswordCallback) {
                        System.out.println(">>>>>>>>>>>>>>> password : " + password);
                        PasswordCallback passwordCallback = (PasswordCallback) callback;
                        passwordCallback.setPassword(password.toCharArray());
                    } else {
                        System.out.println("exception  ");
                        throw new UnsupportedCallbackException(callback);
                    }
                }
            }
        });
        loginContext.login();

        Subject mySubject = loginContext.getSubject();
        
        Subject.doAs(mySubject, new PrivilegedExceptionAction() {
            public Object run() throws Exception {
                System.out.println("inside run");
                System.out.println("##################System.getProperty(\"java.security.auth.login.config\") : "
                        + System.getProperty("java.security.auth.login.config"));
                FileSystem fs = null;
                try {
                    fs = FileSystem.get(new URI(activeNamenodeURI), conf);
                    FileStatus[] df = fs.listStatus(new Path("/"));
                    for (FileStatus status : df) {
                        System.out.println(status.getPath().toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return conf;
            }
        });

    }

JAAS 文件内容是 -

com.sun.security.jgss.initiate {

  com.sun.security.auth.module.Krb5LoginModule required
  principal="user1@DOMAIN"
  tryFirstPass=true
  debug=true;

};

以下是控制台上的输出和错误 -

Debug is  true storeKey false useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is flbuser@IMPETUS tryFirstPass is true useFirstPass is false storePass is false clearPass is false
Password from shared state is null
        [Krb5LoginModule] tryFirstPass failed with:Password can not be obtained from sharedstate 
inside handle methodclass javax.security.auth.callback.NameCallback
inside handle methodclass javax.security.auth.callback.PasswordCallback
>>>>>>>>>>>>>>> password : user1
        [Krb5LoginModule] user entered username: user1

principal is user1@DOMAIN
Commit Succeeded 

inside run
##################System.getProperty("java.security.auth.login.config") : /user/jaas.conf
log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled.  Available:[TOKEN, KERBEROS]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.apache.hadoop.ipc.RemoteException.instantiateException(RemoteException.java:106)
    at org.apache.hadoop.ipc.RemoteException.unwrapRemoteException(RemoteException.java:73)
    at org.apache.hadoop.hdfs.DFSClient.listPaths(DFSClient.java:1662)
    at org.apache.hadoop.hdfs.DFSClient.listPaths(DFSClient.java:1643)
    at org.apache.hadoop.hdfs.DistributedFileSystem.listStatusInternal(DistributedFileSystem.java:640)
    at org.apache.hadoop.hdfs.DistributedFileSystem.access$600(DistributedFileSystem.java:92)
    at org.apache.hadoop.hdfs.DistributedFileSystem$14.doCall(DistributedFileSystem.java:702)
    at org.apache.hadoop.hdfs.DistributedFileSystem$14.doCall(DistributedFileSystem.java:698)
    at org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81)
    at org.apache.hadoop.hdfs.DistributedFileSystem.listStatus(DistributedFileSystem.java:698)
    at com.test.KerberosLogin$2.run(KerberosLogin.java:140)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at com.test.KerberosLogin.loginWithPassword(KerberosLogin.java:132)
    at com.test.KerberosLogin.main(KerberosLogin.java:101)
Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled.  Available:[TOKEN, KERBEROS]
    at org.apache.hadoop.ipc.Client.call(Client.java:1347)
    at org.apache.hadoop.ipc.Client.call(Client.java:1300)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:206)
    at com.sun.proxy.$Proxy7.getListing(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:186)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
    at com.sun.proxy.$Proxy7.getListing(Unknown Source)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.getListing(ClientNamenodeProtocolTranslatorPB.java:482)
    at org.apache.hadoop.hdfs.DFSClient.listPaths(DFSClient.java:1660)
    ... 12 more

它仍然没有工作,任何帮助将不胜感激。

4

1 回答 1

2

您的错误是告诉尚未将 JAAS 配置为使用 kerberos。

你应该看看Jaas。它是 Java 的安全范例。为 kerberos 配置时,它仅依赖于您的 kerberos 令牌出现在正确的位置。您可以通过密钥表或您的凭据启动您的 kerberos 令牌来启动此操作。它基本上确保安全发生在您的代码之外,让您只专注于编码。

这里有一些示例代码可以帮助您入门。此配置依赖于您在运行应用程序之前使用 keytab 创建票证缓存(kinit与 keytab/principle 一起使用)。这不是一个很好的方法,但它很快就开始了。

Client {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=false
  useTicketCache=true
  doNotPrompt=true;
};

完成该配置后,我建议您转而在 Jaas 中使用 keytab。这是您可能需要考虑的更多配置设置。

您想朝着以下方向发展。这样keytab就可以“工作”。仅供参考,这不是一个运行示例,只是我知道的设置的快速复制粘贴。

Client {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  useTicketCache=false
  keyTab=/some/path/to/keytab
  principal=host/testhost.eng.sun.com
  renewTGT=true
};
于 2021-11-11T14:33:25.360 回答