Skip to content

Commit

Permalink
[#5384] Added simple authentication to the Gravitino CLI (#5610)
Browse files Browse the repository at this point in the history
### What changes were proposed in this pull request?

Added simple authentication to the Gravitino CLI

### Why are the changes needed?

To support authentication.

Fix: #5384

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

No, but adds authentication to the CLI.

### How was this patch tested?

Tested locally.
  • Loading branch information
justinmclean authored Dec 5, 2024
1 parent 1fee89c commit ac575f5
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.gravitino.cli.commands.Command;

/* Gravitino Command line */
public class GravitinoCommandLine extends TestableCommandLine {
Expand All @@ -43,6 +44,8 @@ public class GravitinoCommandLine extends TestableCommandLine {
private boolean ignore = false;
private String ignoreEnv;
private boolean ignoreSet = false;
private String authEnv;
private boolean authSet = false;

public static final String CMD = "gcli"; // recommended name
public static final String DEFAULT_URL = "http://localhost:8090";
Expand Down Expand Up @@ -151,15 +154,19 @@ private void executeCommand() {
*/
private void handleMetalakeCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
if (line.hasOption(GravitinoOptions.AUDIT)) {
newMetalakeAudit(url, ignore, metalake).handle();
} else {
newMetalakeDetails(url, ignore, metalake, outputFormat).handle();
newMetalakeDetails(url, ignore, outputFormat, metalake).handle();
}
} else if (CommandActions.LIST.equals(command)) {
newListMetalakes(url, ignore, outputFormat).handle();
Expand Down Expand Up @@ -196,10 +203,14 @@ private void handleMetalakeCommand() {
*/
private void handleCatalogCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.LIST.equals(command)) {
newListCatalogs(url, ignore, metalake).handle();
return;
Expand All @@ -211,7 +222,7 @@ private void handleCatalogCommand() {
if (line.hasOption(GravitinoOptions.AUDIT)) {
newCatalogAudit(url, ignore, metalake, catalog).handle();
} else {
newCatalogDetails(url, ignore, metalake, catalog, outputFormat).handle();
newCatalogDetails(url, ignore, outputFormat, metalake, catalog).handle();
}
} else if (CommandActions.CREATE.equals(command)) {
String comment = line.getOptionValue(GravitinoOptions.COMMENT);
Expand Down Expand Up @@ -248,10 +259,14 @@ private void handleCatalogCommand() {
*/
private void handleSchemaCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String catalog = name.getCatalogName();

Command.setAuthenicationMode(auth, userName);

if (CommandActions.LIST.equals(command)) {
newListSchema(url, ignore, metalake, catalog).handle();
return;
Expand Down Expand Up @@ -288,11 +303,15 @@ private void handleSchemaCommand() {
*/
private void handleTableCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String catalog = name.getCatalogName();
String schema = name.getSchemaName();

Command.setAuthenicationMode(auth, userName);

if (CommandActions.LIST.equals(command)) {
newListTables(url, ignore, metalake, catalog, schema).handle();
return;
Expand Down Expand Up @@ -345,10 +364,14 @@ private void handleTableCommand() {
/** Handles the command execution for Users based on command type and the command line options. */
protected void handleUserCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String user = line.getOptionValue(GravitinoOptions.USER);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
newUserDetails(url, ignore, metalake, user).handle();
} else if (CommandActions.LIST.equals(command)) {
Expand Down Expand Up @@ -376,10 +399,14 @@ protected void handleUserCommand() {
/** Handles the command execution for Group based on command type and the command line options. */
protected void handleGroupCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String group = line.getOptionValue(GravitinoOptions.GROUP);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
newGroupDetails(url, ignore, metalake, group).handle();
} else if (CommandActions.LIST.equals(command)) {
Expand Down Expand Up @@ -407,9 +434,13 @@ protected void handleGroupCommand() {
/** Handles the command execution for Tags based on command type and the command line options. */
protected void handleTagCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();

Command.setAuthenicationMode(auth, userName);

String[] tags = line.getOptionValues(GravitinoOptions.TAG);
if (tags != null) {
tags = Arrays.stream(tags).distinct().toArray(String[]::new);
Expand Down Expand Up @@ -465,10 +496,14 @@ private String getOneTag(String[] tags) {
/** Handles the command execution for Roles based on command type and the command line options. */
protected void handleRoleCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String role = line.getOptionValue(GravitinoOptions.ROLE);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
newRoleDetails(url, ignore, metalake, role).handle();
} else if (CommandActions.LIST.equals(command)) {
Expand All @@ -486,13 +521,17 @@ protected void handleRoleCommand() {
*/
private void handleColumnCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String catalog = name.getCatalogName();
String schema = name.getSchemaName();
String table = name.getTableName();
String column = name.getColumnName();

Command.setAuthenicationMode(auth, userName);

if (CommandActions.LIST.equals(command)) {
newListColumns(url, ignore, metalake, catalog, schema, table).handle();
} else if (CommandActions.CREATE.equals(command)) {
Expand Down Expand Up @@ -599,10 +638,14 @@ private void handleHelpCommand() {
*/
private void handleOwnerCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String entityName = line.getOptionValue(GravitinoOptions.NAME);

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
newOwnerDetails(url, ignore, metalake, entityName, entity).handle();
} else if (CommandActions.SET.equals(command)) {
Expand All @@ -626,12 +669,16 @@ private void handleOwnerCommand() {
*/
private void handleTopicCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String catalog = name.getCatalogName();
String schema = name.getSchemaName();
String topic = name.getTopicName();

Command.setAuthenicationMode(auth, userName);

if (CommandActions.LIST.equals(command)) {
newListTopics(url, ignore, metalake, catalog, schema).handle();
} else if (CommandActions.DETAILS.equals(command)) {
Expand Down Expand Up @@ -664,12 +711,16 @@ private void handleTopicCommand() {
*/
private void handleFilesetCommand() {
String url = getUrl();
String auth = getAuth();
String userName = line.getOptionValue(GravitinoOptions.LOGIN);
FullName name = new FullName(line);
String metalake = name.getMetalakeName();
String catalog = name.getCatalogName();
String schema = name.getSchemaName();
String fileset = name.getFilesetName();

Command.setAuthenicationMode(auth, userName);

if (CommandActions.DETAILS.equals(command)) {
newFilesetDetails(url, ignore, metalake, catalog, schema, fileset).handle();
} else if (CommandActions.LIST.equals(command)) {
Expand Down Expand Up @@ -742,4 +793,41 @@ public String getUrl() {
// Return the default localhost URL
return DEFAULT_URL;
}

/**
* Retrieves the Gravitinno authentication from the command line options or the GRAVITINO_AUTH
* environment variable or the Gravitio config file.
*
* @return The Gravitinno authentication, or null if not found.
*/
public String getAuth() {

// If specified on the command line use that
if (line.hasOption(GravitinoOptions.SIMPLE)) {
return GravitinoOptions.SIMPLE;
}

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

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

// Check if the metalake name 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;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class GravitinoConfig {
private String metalake;
private String url;
private boolean ignore;
private String authentication;

/**
* Creates a GravitinoConfig object with a specified config file. If no file is provided, it
Expand All @@ -62,13 +63,14 @@ public boolean fileExists() {
}

/**
* Reads the configuration file and loads the 'metalake' and 'URL' properties. If the file is not
* found, it is ignored as the config file is optional.
* Reads the configuration file and loads the 'metalake', 'URL' and other properties. If the file
* is not found, it is ignored as the config file is optional.
*/
public void read() {
String metalakeKey = "metalake";
String urlKey = "URL";
String ignoreKey = "ignore";
String authKey = "auth";
Properties prop = new Properties();

try (FileInputStream stream = new FileInputStream(configFile)) {
Expand All @@ -89,6 +91,9 @@ public void read() {
if (prop.containsKey(ignoreKey)) {
ignore = prop.getProperty(ignoreKey).equals("true");
}
if (prop.containsKey(authKey)) {
authentication = prop.getProperty(authKey);
}
}

/**
Expand Down Expand Up @@ -126,4 +131,13 @@ public boolean getIgnore() {
public String getConfigFile() {
return configFile;
}

/**
* Retrieves the Gravitino authentication stored in the configuration.
*
* @return The Gravitino authentication or null if not set.
*/
public String getGravitinoAuth() {
return authentication;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class GravitinoOptions {
public static final String ROLE = "role";
public static final String AUDIT = "audit";
public static final String FORCE = "force";
public static final String SIMPLE = "simple";
public static final String LOGIN = "login";
public static final String COLUMNFILE = "columnfile";
public static final String INDEX = "index";
public static final String DISTRIBUTION = "distribution";
Expand All @@ -74,6 +76,8 @@ public Options options() {
options.addOption(createArgOption("m", METALAKE, "metalake name"));
options.addOption(createSimpleOption("i", IGNORE, "ignore client/sever version check"));
options.addOption(createSimpleOption("a", AUDIT, "display audit information"));
options.addOption(createSimpleOption(null, SIMPLE, "simple authentication"));
options.addOption(createArgOption(null, LOGIN, "user name"));
options.addOption(createSimpleOption("x", INDEX, "display index information"));
options.addOption(createSimpleOption("d", DISTRIBUTION, "display distribution information"));
options.addOption(createSimpleOption(PARTITION, "display partition information"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ protected MetalakeAudit newMetalakeAudit(String url, boolean ignore, String meta
}

protected MetalakeDetails newMetalakeDetails(
String url, boolean ignore, String metalake, String outputFormat) {
return new MetalakeDetails(url, ignore, metalake, outputFormat);
String url, boolean ignore, String outputFormat, String metalake) {
return new MetalakeDetails(url, ignore, outputFormat, metalake);
}

protected ListMetalakes newListMetalakes(String url, boolean ignore, String outputFormat) {
Expand Down Expand Up @@ -192,8 +192,8 @@ protected CatalogAudit newCatalogAudit(
}

protected CatalogDetails newCatalogDetails(
String url, boolean ignore, String metalake, String catalog, String outputFormat) {
return new CatalogDetails(url, ignore, metalake, catalog, outputFormat);
String url, boolean ignore, String outputFormat, String metalake, String catalog) {
return new CatalogDetails(url, ignore, outputFormat, metalake, catalog);
}

protected ListCatalogs newListCatalogs(String url, boolean ignore, String metalake) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ public class CatalogDetails extends Command {
*
* @param url The URL of the Gravitino server.
* @param ignoreVersions If true don't check the client/server versions match.
* @param outputFormat The output format.
* @param metalake The name of the metalake.
* @param catalog The name of the catalog.
* @param outputFormat The output format.
*/
public CatalogDetails(
String url, boolean ignoreVersions, String metalake, String catalog, String outputFormat) {
String url, boolean ignoreVersions, String outputFormat, String metalake, String catalog) {

super(url, ignoreVersions, outputFormat);
this.metalake = metalake;
this.catalog = catalog;
Expand Down
Loading

0 comments on commit ac575f5

Please sign in to comment.