Skip to content

Commit

Permalink
[#5384] Support Kerberos authentication in the Gravitino CLI. (#5766)
Browse files Browse the repository at this point in the history
### What changes were proposed in this pull request?

Support Kerberos authentication.

### Why are the changes needed?

To add support for Kerberos authentication.

Fix: #5384

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Tested locally.
  • Loading branch information
justinmclean authored Dec 6, 2024
1 parent 99a999a commit 70838ef
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ public String getUrl() {
return urlEnv;
}

// Check if the metalake name is specified in the configuration file
// Check if the Gravitino URL is specified in the configuration file
if (config.fileExists()) {
config.read();
String configURL = config.getGravitinoURL();
Expand All @@ -806,24 +806,24 @@ public String getAuth() {
return GravitinoOptions.SIMPLE;
}

// Cache the Gravitino URL environment variable
// Cache the Gravitino authentication type environment variable
if (authEnv == null && !authSet) {
authEnv = System.getenv("GRAVITINO_AUTH");
authSet = true;
}

// If set return the Gravitino URL environment variable
// If set return the Gravitino authentication type environment variable
if (authEnv != null) {
return authEnv;
}

// Check if the metalake name is specified in the configuration file
// Check if the authentication type is specified in the configuration file
GravitinoConfig config = new GravitinoConfig(null);
if (config.fileExists()) {
config.read();
String configAuth = config.getGravitinoAuth();
if (configAuth != null) {
return configAuth;
String configAuthType = config.getGravitinoAuthType();
if (configAuthType != null) {
return configAuthType;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ public class GravitinoConfig {
private String metalake;
private String url;
private boolean ignore;
private String authentication;
private String authType;
private OAuthData oauth;
private KerberosData kerberos;

/**
* Creates a GravitinoConfig object with a specified config file. If no file is provided, it
Expand Down Expand Up @@ -93,7 +94,18 @@ public void read() {
ignore = prop.getProperty(ignoreKey).equals("true");
}
if (prop.containsKey(authKey)) {
authentication = prop.getProperty(authKey);
authType = prop.getProperty(authKey);
}

if (authKey.equals("oauth")) {
oauth =
new OAuthData(
prop.getProperty("serverURI"),
prop.getProperty("credential"),
prop.getProperty("token"),
prop.getProperty("scope"));
} else if (authKey.equals("kerberos")) {
kerberos = new KerberosData(prop.getProperty("principal"), prop.getProperty("keytabFile"));
}

if (authKey.equals("oauth")) {
Expand Down Expand Up @@ -143,20 +155,29 @@ public String getConfigFile() {
}

/**
* Retrieves the Gravitino authentication stored in the configuration.
* Retrieves the Gravitino authentication type stored in the configuration.
*
* @return The Gravitino authentication or null if not set.
* @return The Gravitino authentication type or null if not set.
*/
public String getGravitinoAuth() {
return authentication;
public String getGravitinoAuthType() {
return authType;
}

/**
* Retrieves the Gravitino oAuth authentication configuration.
* Retrieves the Gravitino OAuth configuration.
*
* @return The Gravitino authentication or null if not set.
* @return The Gravitino OAuth data or null if not set.
*/
public OAuthData getOAuth() {
return oauth;
}

/**
* Retrieves the Gravitino kerberos configuration.
*
* @return The Gravitino Kerberos data or null if not set.
*/
public KerberosData getKerberos() {
return kerberos;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.gravitino.cli;

public class KerberosData {
protected final String principal;
protected final String keytabFile;

/**
* Constructs an {@code KerberosData} instance with the specified principal and keytab file.
*
* @param principal the Kerberos principal (e.g. a user or service identity)
* @param keytabFile the path to the keytab file
*/
public KerberosData(String principal, String keytabFile) {
this.principal = principal;
this.keytabFile = keytabFile;
}

/**
* Returns the Kerberos principal associated with this {@code KerberosData}.
*
* @return the principal
*/
public String getPrincipal() {
return principal;
}

/**
* Returns the keytab file path associated with this {@code KerberosData}.
*
* @return the keytab file path
*/
public String getKeytabFile() {
return keytabFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@

import static org.apache.gravitino.client.GravitinoClientBase.Builder;

import java.io.File;
import org.apache.gravitino.cli.GravitinoConfig;
import org.apache.gravitino.cli.KerberosData;
import org.apache.gravitino.cli.OAuthData;
import org.apache.gravitino.cli.outputs.PlainFormat;
import org.apache.gravitino.cli.outputs.TableFormat;
import org.apache.gravitino.client.DefaultOAuth2TokenProvider;
import org.apache.gravitino.client.GravitinoAdminClient;
import org.apache.gravitino.client.GravitinoClient;
import org.apache.gravitino.client.GravitinoClientBase;
import org.apache.gravitino.client.KerberosTokenProvider;
import org.apache.gravitino.exceptions.NoSuchMetalakeException;

/* The base for all commands. */
Expand All @@ -41,6 +44,7 @@ public abstract class Command {

private static final String SIMPLE_AUTH = "simple";
private static final String OAUTH_AUTH = "oauth";
private static final String KERBEROS_AUTH = "kerberos";

private final String url;
private final boolean ignoreVersions;
Expand Down Expand Up @@ -139,6 +143,16 @@ protected <T extends GravitinoClientBase> Builder<T> constructClient(Builder<T>
.build();

builder = builder.withOAuth(tokenProvider);
} else if (authentication.equals(KERBEROS_AUTH)) {
GravitinoConfig config = new GravitinoConfig(null);
KerberosData kerberos = config.getKerberos();
KerberosTokenProvider tokenProvider =
KerberosTokenProvider.builder()
.withClientPrincipal(kerberos.getPrincipal())
.withKeyTabFile(new File(kerberos.getKeytabFile()))
.build();

builder = builder.withKerberosAuth(tokenProvider);
} else {
System.err.println("Unsupported authentication type " + authentication);
}
Expand Down
9 changes: 9 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ token=test
scope=token/test
```

Kerberos authentication can also be configured via the configuration file.

```text
# Authentication
auth=kerberos
principal=user/[email protected]
keytabFile=file.keytab
```

### Potentially unsafe operations

For operations that delete data or rename a metalake the user with be prompted to make sure they wish to run this command. The `--force` option can be specified to override this behaviour.
Expand Down

0 comments on commit 70838ef

Please sign in to comment.