This is an automated email from the ASF dual-hosted git repository.

amagyar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new aa8e1531f KNOX-2752 knoxcli should support batch alias creation (#583)
aa8e1531f is described below

commit aa8e1531f970d5477d60f7ea2c669657b5bf077a
Author: Attila Magyar <[email protected]>
AuthorDate: Thu Jun 9 18:15:11 2022 +0200

    KNOX-2752 knoxcli should support batch alias creation (#583)
---
 .../java/org/apache/knox/gateway/util/KnoxCLI.java | 146 +++++++++++++++++----
 .../org/apache/knox/gateway/util/KnoxCLITest.java  |  60 +++++++++
 2 files changed, 178 insertions(+), 28 deletions(-)

diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index 778729e03..c49127a2d 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -32,10 +32,12 @@ import java.nio.file.Paths;
 import java.security.KeyStoreException;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -109,6 +111,7 @@ public class KnoxCLI extends Configured implements Tool {
       "   [" + CertCreateCommand.USAGE + "]\n" +
       "   [" + CertExportCommand.USAGE + "]\n" +
       "   [" + AliasCreateCommand.USAGE + "]\n" +
+      "   [" + BatchAliasCreateCommand.USAGE + "]\n" +
       "   [" + AliasDeleteCommand.USAGE + "]\n" +
       "   [" + AliasListCommand.USAGE + "]\n" +
       "   [" + RedeployCommand.USAGE + "]\n" +
@@ -252,6 +255,12 @@ public class KnoxCLI extends Configured implements Tool {
           printKnoxShellUsage();
           return -1;
         }
+      } else if (args[i].equals("create-aliases")) {
+        command = new BatchAliasCreateCommand();
+        if (args.length < 3 || "--help".equals(alias)) {
+          printKnoxShellUsage();
+          return -1;
+        }
       } else if (args[i].equals("create-cert")) {
         command = new CertCreateCommand();
         if ((args.length > i + 1) && args[i + 1].equals("--help")) {
@@ -281,13 +290,22 @@ public class KnoxCLI extends Configured implements Tool {
       } else if (args[i].equals("list-alias")) {
         command = new AliasListCommand();
       } else if (args[i].equals("--value")) {
-        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+        if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
           printKnoxShellUsage();
           return -1;
         }
         this.value = args[++i];
-        if ( command instanceof MasterCreateCommand ) {
+        if (command instanceof MasterCreateCommand) {
           this.master = this.value;
+        } else if (command instanceof BatchAliasCreateCommand) {
+          ((BatchAliasCreateCommand) command).addValue(value);
+        }
+      } else if (args[i].equals("--alias")) {
+        if (command instanceof BatchAliasCreateCommand) {
+          ((BatchAliasCreateCommand) command).addName(args[++i]);
+        } else {
+          printKnoxShellUsage();
+          return -1;
         }
       } else if ( args[i].equals("version") ) {
         command = new VersionCommand();
@@ -905,32 +923,6 @@ public class KnoxCLI extends Configured implements Tool {
    public String getUsage() {
      return USAGE + ":\n\n" + DESC;
    }
-
-    protected char[] promptUserForPassword() {
-      char[] password = null;
-      Console c = System.console();
-      if (c == null) {
-        System.err
-            .println("No console to fetch password from user.Consider setting 
via --generate or --value.");
-        System.exit(1);
-      }
-
-      boolean noMatch;
-      do {
-        char[] newPassword1 = c.readPassword("Enter password: ");
-        char[] newPassword2 = c.readPassword("Enter password again: ");
-        noMatch = !Arrays.equals(newPassword1, newPassword2);
-        if (noMatch) {
-          c.format("Passwords don't match. Try again.%n");
-        } else {
-          password = Arrays.copyOf(newPassword1, newPassword1.length);
-        }
-        Arrays.fill(newPassword1, ' ');
-        Arrays.fill(newPassword2, ' ');
-      } while (noMatch);
-      return password;
-    }
-
  }
 
  public class AliasDeleteCommand extends Command {
@@ -977,6 +969,104 @@ public class KnoxCLI extends Configured implements Tool {
 
  }
 
+  public class BatchAliasCreateCommand extends Command {
+    public static final String USAGE = "create-aliases " +
+            "--alias alias1 [--value value1] " +
+            "--alias alias2 [--value value2] " +
+            "--alias aliasN [--value valueN] ... " +
+            "[--cluster clustername] " +
+            "[--generate]";
+    public static final String DESC = "The create-aliases command will create 
multiple aliases\n"
+            + "and secret pairs within the same credential store for the\n"
+            + "indicated --cluster otherwise within the gateway\n"
+            + "credential store. The actual secret may be specified via\n"
+            + "the --value option or --generate (will create a random secret\n"
+            + "for you) or user will be prompt to provide password.";
+
+    private List<String> names = new ArrayList<>();
+    private List<String> values = new ArrayList<>();
+
+    public void addName(String alias) {
+      if (names.contains(alias)) {
+        out.println("Duplicated alias " + alias);
+        System.exit(1);
+      }
+      names.add(alias);
+      values.add(null);
+    }
+
+    public void addValue(String value) {
+      values.set(values.size() -1, value);
+    }
+
+    @Override
+    public void execute() throws Exception {
+      Map<String, String> aliases = toMap();
+      List<String> generated = new ArrayList<>();
+      AliasService as = getAliasService();
+      if (cluster == null) {
+        cluster = "__gateway";
+      }
+      for (Map.Entry<String, String> entry : aliases.entrySet()) {
+        if (entry.getValue() == null) {
+          if (Boolean.parseBoolean(generate)) {
+            entry.setValue(PasswordUtils.generatePassword(16));
+            generated.add(entry.getKey());
+          } else {
+            entry.setValue(new String(promptUserForPassword()));
+          }
+        }
+      }
+      as.addAliasesForCluster(cluster, aliases);
+      if (!generated.isEmpty()) {
+        out.println(generated.size() + " alias(es) have been successfully 
generated: " + generated);
+      }
+      List<String> created = new ArrayList<>(aliases.keySet());
+      created.removeAll(generated);
+      if (!created.isEmpty()) {
+        out.println(created.size() + " alias(es) have been successfully 
created: " + created);
+      }
+    }
+
+    private Map<String, String> toMap() {
+      Map<String,String> aliases = new LinkedHashMap<>();
+      for (int i = 0; i < names.size(); i++) {
+        aliases.put(names.get(i), values.get(i));
+      }
+      return aliases;
+    }
+
+    @Override
+    public String getUsage() {
+      return USAGE + ":\n\n" + DESC;
+    }
+  }
+
+  public static char[] promptUserForPassword() {
+    char[] password = null;
+    Console c = System.console();
+    if (c == null) {
+      System.err
+              .println("No console to fetch password from user.Consider 
setting via --generate or --value.");
+      System.exit(1);
+    }
+
+    boolean noMatch;
+    do {
+      char[] newPassword1 = c.readPassword("Enter password: ");
+      char[] newPassword2 = c.readPassword("Enter password again: ");
+      noMatch = !Arrays.equals(newPassword1, newPassword2);
+      if (noMatch) {
+        c.format("Passwords don't match. Try again.%n");
+      } else {
+        password = Arrays.copyOf(newPassword1, newPassword1.length);
+      }
+      Arrays.fill(newPassword1, ' ');
+      Arrays.fill(newPassword2, ' ');
+    } while (noMatch);
+    return password;
+  }
+
  public class MasterCreateCommand extends Command {
   public static final String USAGE = "create-master [--force] [--master 
mastersecret] [--generate]";
   public static final String DESC = "The create-master command persists the 
master secret in a file located at:\n" +
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java 
b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
index 674c48c1e..9c488f6e3 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
@@ -881,6 +881,66 @@ public class KnoxCLITest {
     assertThat(outContent.toString(StandardCharsets.UTF_8.name()), 
containsString("admin"));
   }
 
+  @Test
+  public void testCreateMultipleAliasesInOneBatch() throws Exception {
+    outContent.reset();
+    String[] args1 = { "create-aliases",
+            "--alias", "alias1", "--value", "testvalue1",
+            "--alias", "alias2", "--value", "testvalue2",
+            "--alias", "alias3", "--value", "testvalue3",
+            "--cluster", "cluster1",
+            "--master", "master" };
+    int rc;
+    KnoxCLI cli = new KnoxCLI();
+    cli.setConf(new GatewayConfigImpl());
+    rc = cli.run(args1);
+    assertEquals(0, rc);
+    assertTrue(outContent.toString(StandardCharsets.UTF_8.name()), 
outContent.toString(StandardCharsets.UTF_8.name()).contains(
+            "3 alias(es) have been successfully created: [alias1, alias2, 
alias3]"));
+  }
+
+  @Test
+  public void testCreateAndGenerateMultipleAliasesInOneBatch1() throws 
Exception {
+    outContent.reset();
+    String[] args1 = { "create-aliases",
+            "--alias", "alias1", "--value", "testvalue1",
+            "--alias", "alias2", "--value", "testvalue2",
+            "--alias", "alias3",
+            "--generate",
+            "--cluster", "cluster1",
+            "--master", "master" };
+    int rc;
+    KnoxCLI cli = new KnoxCLI();
+    cli.setConf(new GatewayConfigImpl());
+    rc = cli.run(args1);
+    assertEquals(0, rc);
+    assertTrue(outContent.toString(StandardCharsets.UTF_8.name()), 
outContent.toString(StandardCharsets.UTF_8.name()).contains(
+            "2 alias(es) have been successfully created: [alias1, alias2]"));
+    assertTrue(outContent.toString(StandardCharsets.UTF_8.name()), 
outContent.toString(StandardCharsets.UTF_8.name()).contains(
+            "1 alias(es) have been successfully generated: [alias3]"));
+  }
+
+  @Test
+  public void testCreateAndGenerateMultipleAliasesInOneBatch2() throws 
Exception {
+    outContent.reset();
+    String[] args1 = { "create-aliases",
+            "--alias", "alias1", "--value", "testvalue1",
+            "--alias", "alias2",
+            "--alias", "alias3",
+            "--generate",
+            "--cluster", "cluster1",
+            "--master", "master" };
+    int rc;
+    KnoxCLI cli = new KnoxCLI();
+    cli.setConf(new GatewayConfigImpl());
+    rc = cli.run(args1);
+    assertEquals(0, rc);
+    assertTrue(outContent.toString(StandardCharsets.UTF_8.name()), 
outContent.toString(StandardCharsets.UTF_8.name()).contains(
+            "2 alias(es) have been successfully generated: [alias2, alias3]"));
+    assertTrue(outContent.toString(StandardCharsets.UTF_8.name()), 
outContent.toString(StandardCharsets.UTF_8.name()).contains(
+            "1 alias(es) have been successfully created: [alias1]"));
+  }
+
   private class GatewayConfigMock extends GatewayConfigImpl{
     private String confDir;
     public void setConfDir(String location) {

Reply via email to