Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#2711] feat(filesystem): Support Kerberos client authentication in gvfs #3314

Merged
merged 5 commits into from
May 11, 2024

Conversation

xloya
Copy link
Contributor

@xloya xloya commented May 9, 2024

What changes were proposed in this pull request?

Support using Kerberos authentication type to initialize Gravitino client in gvfs.

Why are the changes needed?

Fix: #2711

How was this patch tested?

Add some uts for:

  1. use principal and keytab to auth.
  2. kerberos configs for gvfs.
  3. some invalid kerberos case.

Test locally and use kerberos ticket cache to initialize gvfs. The steps are as follows:

  1. Deploy the KDC server locally, refer to the doc: https://blog.csdn.net/lo085213/article/details/105057186.
  2. Register the service account HTTP/localhost@HADOOP.COM and client account client@HADOOP.COM in the KDC server.
  3. Execute the kinit -kt client.keytab client@HADOOP.COM command locally.
  4. Use the klist command to check the environment for tickets containing client@HADOOP.COM.
  5. Write a unit test to load metalake through gvfs with the kerberos ticket cache.
    image
    image
    image

@xloya
Copy link
Contributor Author

xloya commented May 9, 2024

@qqqttt123 When I write a unit test that only configures the principal to use the ticket cache to interact with the server, it cannot run pass. Do you have any suggestions for this?

@qqqttt123
Copy link
Contributor

You should use host name instead of ip.

@qqqttt123
Copy link
Contributor

@qqqttt123 When I write a unit test that only configures the principal to use the ticket cache to interact with the server, it cannot run pass. Do you have any suggestions for this?

You should provide more error information.

@xloya
Copy link
Contributor Author

xloya commented May 10, 2024

You should use host name instead of ip.

If I use HTTP/localhost@EXAMPLE.COM as the server principal, the testAuthWithPrincipalAndKeytabNormally test will get this error:
image

Fail to get the Kerberos token
java.lang.IllegalStateException: Fail to get the Kerberos token
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenData(KerberosTokenProvider.java:64)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:365)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:295)
	at com.datastrato.gravitino.client.HTTPClient.get(HTTPClient.java:464)
	at com.datastrato.gravitino.client.RESTClient.get(RESTClient.java:165)
	at com.datastrato.gravitino.client.GravitinoClientBase.serverVersion(GravitinoClientBase.java:144)
	at com.datastrato.gravitino.client.GravitinoClientBase.checkVersion(GravitinoClientBase.java:86)
	at com.datastrato.gravitino.client.HTTPClient.performPreConnectHandler(HTTPClient.java:419)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:341)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:295)
	at com.datastrato.gravitino.client.HTTPClient.get(HTTPClient.java:464)
	at com.datastrato.gravitino.client.RESTClient.get(RESTClient.java:165)
	at com.datastrato.gravitino.client.GravitinoClientBase.loadMetalake(GravitinoClientBase.java:116)
	at com.datastrato.gravitino.client.GravitinoClient.<init>(GravitinoClient.java:48)
	at com.datastrato.gravitino.client.GravitinoClient.<init>(GravitinoClient.java:26)
	at com.datastrato.gravitino.client.GravitinoClient$ClientBuilder.build(GravitinoClient.java:149)
	at com.datastrato.gravitino.client.GravitinoClient$ClientBuilder.build(GravitinoClient.java:109)
	at com.datastrato.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem.initializeClient(GravitinoVirtualFileSystem.java:239)
	at com.datastrato.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem.initialize(GravitinoVirtualFileSystem.java:104)
	at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3354)
	at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:474)
	at org.apache.hadoop.fs.Path.getFileSystem(Path.java:361)
	at com.datastrato.gravitino.filesystem.hadoop.TestKerberosClient.testAuthWithPrincipalAndKeytabNormally(TestKerberosClient.java:130)
	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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
	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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7) - Server not found in Kerberos database)
	at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:770)
	at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
	at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
	at com.datastrato.gravitino.client.KerberosTokenProvider$1.call(KerberosTokenProvider.java:102)
	at com.datastrato.gravitino.client.KerberosTokenProvider$1.call(KerberosTokenProvider.java:87)
	at com.datastrato.gravitino.auth.KerberosUtils$1.run(KerberosUtils.java:100)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at com.datastrato.gravitino.auth.KerberosUtils.doAs(KerberosUtils.java:95)
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenInternal(KerberosTokenProvider.java:85)
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenData(KerberosTokenProvider.java:62)
	... 106 more
Caused by: KrbException: Server not found in Kerberos database (7) - Server not found in Kerberos database
	at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:73)
	at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:251)
	at sun.security.krb5.KrbTgsReq.sendAndGetCreds(KrbTgsReq.java:262)
	at sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:308)
	at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:126)
	at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:458)
	at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:693)
	... 116 more
Caused by: KrbException: Identifier doesn't match expected value (906)
	at sun.security.krb5.internal.KDCRep.init(KDCRep.java:140)
	at sun.security.krb5.internal.TGSRep.init(TGSRep.java:65)
	at sun.security.krb5.internal.TGSRep.<init>(TGSRep.java:60)
	at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:55)
	... 122 more

@xloya
Copy link
Contributor Author

xloya commented May 10, 2024

@qqqttt123 When I write a unit test that only configures the principal to use the ticket cache to interact with the server, it cannot run pass. Do you have any suggestions for this?

You should provide more error information.

The test like this:

  @Test
  public void testAuthWithTicketCacheNormally() throws Exception {
    KerberosAuthenticator kerberosAuthenticator = new KerberosAuthenticator();
    Config config = new Config(false) {};
    config.set(PRINCIPAL, KdcServerBase.getServerPrincipal());
    config.set(KEYTAB, KdcServerBase.getKeytabFile());
    kerberosAuthenticator.initialize(config);

    Configuration configuration = new Configuration(conf);
    configuration.set(
            GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_CLIENT_KERBEROS_PRINCIPAL_KEY,
            KdcServerBase.getClientPrincipal());
    configuration.unset(
            GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_CLIENT_KERBEROS_KEYTAB_FILE_PATH_KEY);

    LoginContext context = null;
    try {
      context = KerberosUtils.login(KdcServerBase.getClientPrincipal(), KdcServerBase.getKeytabFile());
      assertNull(KerberosUtils.doAs(context.getSubject(), () -> {
        // mock load metalake with kerberos ticket
        String testMetalake = "test_kerberos_ticket_normally";
        HttpRequest mockRequest =
                HttpRequest.request("/api/metalakes/" + testMetalake)
                        .withMethod(Method.GET.name())
                        .withQueryStringParameters(Collections.emptyMap());
        GravitinoMockServerBase.mockServer()
                .when(mockRequest, Times.unlimited())
                .respond(
                        httpRequest -> {
                          List<Header> headers = httpRequest.getHeaders().getEntries();
                          for (Header header : headers) {
                            if (header.getName().equalsIgnoreCase("Authorization")) {
                              byte[] tokenValue =
                                      header.getValues().get(0).getValue().getBytes(StandardCharsets.UTF_8);
                              kerberosAuthenticator.authenticateToken(tokenValue);
                            }
                          }
                          return response().withStatusCode(HttpStatus.SC_OK);
                        });
        Path newPath = new Path(managedFilesetPath.toString().replace(metalakeName, testMetalake));
        // Should auth successfully
        newPath.getFileSystem(configuration);
        return null;
      }));
    } finally {
      if (context != null) {
        context.logout();
      }
    }
  }

I wiil get this error:

Debug is  true storeKey false useTicketCache true useKeyTab false doNotPrompt true ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is true principal is client@EXAMPLE.COM tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
Acquire TGT from Cache
Principal is client@EXAMPLE.COM
null credentials from Ticket Cache
		[Krb5LoginModule] authentication failed 
Unable to obtain password from user

		[Krb5LoginModule]: Entering logout
		[Krb5LoginModule]: logged out Subject

Fail to get the Kerberos token
java.lang.IllegalStateException: Fail to get the Kerberos token
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenData(KerberosTokenProvider.java:64)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:365)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:295)
	at com.datastrato.gravitino.client.HTTPClient.get(HTTPClient.java:464)
	at com.datastrato.gravitino.client.RESTClient.get(RESTClient.java:165)
	at com.datastrato.gravitino.client.GravitinoClientBase.serverVersion(GravitinoClientBase.java:144)
	at com.datastrato.gravitino.client.GravitinoClientBase.checkVersion(GravitinoClientBase.java:86)
	at com.datastrato.gravitino.client.HTTPClient.performPreConnectHandler(HTTPClient.java:419)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:341)
	at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:295)
	at com.datastrato.gravitino.client.HTTPClient.get(HTTPClient.java:464)
	at com.datastrato.gravitino.client.RESTClient.get(RESTClient.java:165)
	at com.datastrato.gravitino.client.GravitinoClientBase.loadMetalake(GravitinoClientBase.java:116)
	at com.datastrato.gravitino.client.GravitinoClient.<init>(GravitinoClient.java:48)
	at com.datastrato.gravitino.client.GravitinoClient.<init>(GravitinoClient.java:26)
	at com.datastrato.gravitino.client.GravitinoClient$ClientBuilder.build(GravitinoClient.java:149)
	at com.datastrato.gravitino.client.GravitinoClient$ClientBuilder.build(GravitinoClient.java:109)
	at com.datastrato.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem.initializeClient(GravitinoVirtualFileSystem.java:239)
	at com.datastrato.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem.initialize(GravitinoVirtualFileSystem.java:104)
	at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3354)
	at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:474)
	at org.apache.hadoop.fs.Path.getFileSystem(Path.java:361)
	at com.datastrato.gravitino.filesystem.hadoop.TestKerberosClient.lambda$testAuthWithTicketCacheNormally$4(TestKerberosClient.java:174)
	at com.datastrato.gravitino.auth.KerberosUtils$1.run(KerberosUtils.java:100)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at com.datastrato.gravitino.auth.KerberosUtils.doAs(KerberosUtils.java:95)
	at com.datastrato.gravitino.filesystem.hadoop.TestKerberosClient.testAuthWithTicketCacheNormally(TestKerberosClient.java:151)
	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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
	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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: javax.security.auth.login.LoginException: Unable to obtain password from user

	at com.sun.security.auth.module.Krb5LoginModule.promptForPass(Krb5LoginModule.java:897)
	at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:760)
	at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:617)
	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 javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
	at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
	at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
	at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
	at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
	at com.datastrato.gravitino.auth.KerberosUtils.login(KerberosUtils.java:80)
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenInternal(KerberosTokenProvider.java:77)
	at com.datastrato.gravitino.client.KerberosTokenProvider.getTokenData(KerberosTokenProvider.java:62)
	... 111 more

@qqqttt123
Copy link
Contributor

Oh. I got it. You can't test the ticket cache in the UT. It can only be tested by hand.

@xloya
Copy link
Contributor Author

xloya commented May 10, 2024

Oh. I got it. You can't test the ticket cache in the UT. It can only be tested by hand.

Got it, I'll test it locally.

| `fs.gravitino.client.oauth2.credential` | The auth credential for the Gravitino client when using `oauth2` auth type in the Gravitino Virtual File System. | (none) | Yes if you use `oauth2` auth type | 0.5.0 |
| `fs.gravitino.client.oauth2.path` | The auth server path for the Gravitino client when using `oauth2` auth type with the Gravitino Virtual File System. Please remove the first slash `/` from the path, for example `oauth/token`. | (none) | Yes if you use `oauth2` auth type | 0.5.0 |
| `fs.gravitino.client.oauth2.scope` | The auth scope for the Gravitino client when using `oauth2` auth type with the Gravitino Virtual File System. | (none) | Yes if you use `oauth2` auth type | 0.5.0 |
| `fs.gravitino.client.kerberos.principal` | The auth principal for the Gravitino client when using `kerberos` auth type with the Gravitino Virtual File System. | (none) | Yes if you use `kerberos` auth type | 0.5.1 |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jerryshao Do we need backport this pr to branch-0.5? My initial thought is to release it in 0.5.1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should.

@xloya
Copy link
Contributor Author

xloya commented May 10, 2024

Oh. I got it. You can't test the ticket cache in the UT. It can only be tested by hand.

Got it, I'll test it locally.

@qqqttt123 I pulled up the KDC Docker image locally and registered HTTP/localhost@HADOOP.COM for server authentication and client@HADOOP.COM for client authentication. I tested that gvfs using ticket cache could load metalake from the local Gravitino Server normally.
image
image
image

@qqqttt123
Copy link
Contributor

Oh. I got it. You can't test the ticket cache in the UT. It can only be tested by hand.

Got it, I'll test it locally.

@qqqttt123 I pulled up the KDC Docker image locally and registered HTTP/localhost@HADOOP.COM for server authentication and client@HADOOP.COM for client authentication. I tested that gvfs using ticket cache could load metalake from the local Gravitino Server normally. image image image

You should add these to the segment How to test in the decription of the pull request.

docs/how-to-use-gvfs.md Outdated Show resolved Hide resolved
@xloya
Copy link
Contributor Author

xloya commented May 10, 2024

Oh. I got it. You can't test the ticket cache in the UT. It can only be tested by hand.

Got it, I'll test it locally.

@qqqttt123 I pulled up the KDC Docker image locally and registered HTTP/localhost@HADOOP.COM for server authentication and client@HADOOP.COM for client authentication. I tested that gvfs using ticket cache could load metalake from the local Gravitino Server normally. image image image

You should add these to the segment How to test in the decription of the pull request.

Done

@jerryshao jerryshao merged commit 77144d7 into apache:main May 11, 2024
22 checks passed
github-actions bot pushed a commit that referenced this pull request May 11, 2024
…vfs (#3314)

### What changes were proposed in this pull request?

Support using Kerberos authentication type to initialize Gravitino
client in gvfs.

### Why are the changes needed?

Fix: #2711 

### How was this patch tested?

Add some uts for: 
1. use principal and keytab to auth.
2. kerberos configs for gvfs.
3. some invalid kerberos case.

Test locally and use `kerberos ticket cache` to initialize gvfs. The
steps are as follows:
1. Deploy the KDC server locally, refer to the doc:
https://blog.csdn.net/lo085213/article/details/105057186.
2. Register the service account `HTTP/localhost@HADOOP.COM` and client
account `client@HADOOP.COM` in the KDC server.
3. Execute the `kinit -kt client.keytab client@HADOOP.COM` command
locally.
4. Use the `klist` command to check the environment for tickets
containing `client@HADOOP.COM`.
5. Write a unit test to load metalake through gvfs with the kerberos
ticket cache.

![image](https://github.com/datastrato/gravitino/assets/26177232/f655e687-8412-4000-bb07-bd9ccadd8387)

![image](https://github.com/datastrato/gravitino/assets/26177232/a3d36646-37ad-44b9-8cca-129a18196663)

![image](https://github.com/datastrato/gravitino/assets/26177232/df7504a2-046d-45fa-9da3-7b681ebfd7e1)

---------

Co-authored-by: xiaojiebao <xiaojiebao@xiaomi.com>
diqiu50 pushed a commit to diqiu50/gravitino that referenced this pull request Jun 13, 2024
…n in gvfs (apache#3314)

### What changes were proposed in this pull request?

Support using Kerberos authentication type to initialize Gravitino
client in gvfs.

### Why are the changes needed?

Fix: apache#2711 

### How was this patch tested?

Add some uts for: 
1. use principal and keytab to auth.
2. kerberos configs for gvfs.
3. some invalid kerberos case.

Test locally and use `kerberos ticket cache` to initialize gvfs. The
steps are as follows:
1. Deploy the KDC server locally, refer to the doc:
https://blog.csdn.net/lo085213/article/details/105057186.
2. Register the service account `HTTP/localhost@HADOOP.COM` and client
account `client@HADOOP.COM` in the KDC server.
3. Execute the `kinit -kt client.keytab client@HADOOP.COM` command
locally.
4. Use the `klist` command to check the environment for tickets
containing `client@HADOOP.COM`.
5. Write a unit test to load metalake through gvfs with the kerberos
ticket cache.

![image](https://github.com/datastrato/gravitino/assets/26177232/f655e687-8412-4000-bb07-bd9ccadd8387)

![image](https://github.com/datastrato/gravitino/assets/26177232/a3d36646-37ad-44b9-8cca-129a18196663)

![image](https://github.com/datastrato/gravitino/assets/26177232/df7504a2-046d-45fa-9da3-7b681ebfd7e1)

---------

Co-authored-by: xiaojiebao <xiaojiebao@xiaomi.com>
@xloya xloya deleted the issue-2711 branch June 20, 2024 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Subtask] Support Kerberos client authentication in gvfs
3 participants