OOZIE-3539 Support http proxy/basic authentication in the command line client (zsombor via asalamon74)
diff --git a/client/src/main/java/org/apache/oozie/cli/OozieCLI.java b/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
index 3507461..f2c37ad 100644
--- a/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
+++ b/client/src/main/java/org/apache/oozie/cli/OozieCLI.java
@@ -18,8 +18,35 @@
 
 package org.apache.oozie.cli;
 
-import com.google.common.annotations.VisibleForTesting;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.TreeMap;
+import java.util.concurrent.Callable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionBuilder;
@@ -30,6 +57,7 @@
 import org.apache.oozie.BuildInfo;
 import org.apache.oozie.client.ApiJarLoader;
 import org.apache.oozie.client.AuthOozieClient;
+import org.apache.oozie.client.AuthOozieClient.AuthType;
 import org.apache.oozie.client.BulkResponse;
 import org.apache.oozie.client.BundleJob;
 import org.apache.oozie.client.CoordinatorAction;
@@ -55,32 +83,9 @@
 import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 
-import javax.xml.bind.JAXBException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.concurrent.Callable;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.google.common.annotations.VisibleForTesting;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * Oozie command line utility.
@@ -173,6 +178,8 @@
     public static final String INSTRUMENTATION_OPTION = "instrumentation";
 
     public static final String AUTH_OPTION = "auth";
+    public static final String USERNAME = "username";
+    public static final String PASSWORD = "password";
 
     public static final String VERBOSE_OPTION = "verbose";
     public static final String VERBOSE_DELIMITER = "\t";
@@ -260,8 +267,10 @@
      * @param options the collection of options to add auth options
      */
     protected void addAuthOptions(Options options) {
-        Option auth = new Option(AUTH_OPTION, true, "select authentication type [SIMPLE|KERBEROS]");
+        Option auth = new Option(AUTH_OPTION, true, "select authentication type [SIMPLE|BASIC|KERBEROS]");
         options.addOption(auth);
+        options.addOption(new Option(USERNAME, true, "username for BASIC authentication"));
+        options.addOption(new Option(PASSWORD, true, "password for BASIC authentication"));
     }
 
     /**
@@ -369,7 +378,7 @@
         Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode");
         Option action = new Option(ACTION_OPTION, true,
                 "coordinator rerun/kill on action ids (requires -rerun/-kill); coordinator log retrieval on action ids"
-                        + "(requires -log)");
+                        + " (requires -log)");
         Option date = new Option(DATE_OPTION, true,
                 "coordinator/bundle rerun on action dates (requires -rerun); "
                 + "coordinator log retrieval on action dates (requires -log)");
@@ -908,7 +917,13 @@
         return changeValue;
     }
 
-    protected void addHeader(OozieClient wc) {
+    protected void addHeader(OozieClient wc, CommandLine commandLine) {
+        String username = commandLine.getOptionValue(USERNAME);
+        String password = commandLine.getOptionValue(PASSWORD);
+        if (username != null && password != null) {
+            String encoded = Base64.getEncoder().encodeToString((username + ':' + password).getBytes(StandardCharsets.UTF_8));
+            wc.setHeader("Authorization", "Basic " + encoded);
+        }
         for (Map.Entry entry : System.getProperties().entrySet()) {
             String key = (String) entry.getKey();
             if (key.startsWith(WS_HEADER_PREFIX)) {
@@ -923,8 +938,22 @@
      *
      * @param commandLine the command line object
      * @return auth option
+     * @throws OozieCLIException if wrong authentication parameters are used.
      */
-    protected String getAuthOption(CommandLine commandLine) {
+    protected String getAuthOption(CommandLine commandLine) throws OozieCLIException {
+        if (commandLine.hasOption(USERNAME)) {
+            if (commandLine.hasOption(PASSWORD)) {
+                return AuthType.BASIC.name();
+            } else {
+                throw new OozieCLIException(
+                        "No " + PASSWORD + " specified, it is required, if " + USERNAME + " is set!");
+            }
+        } else {
+            if (commandLine.hasOption(PASSWORD)) {
+                throw new OozieCLIException(
+                        "No " + USERNAME + " specified, it is required, if " + PASSWORD + " is set!");
+            }
+        }
         String authOpt = commandLine.getOptionValue(AUTH_OPTION);
         if (authOpt == null) {
             authOpt = System.getenv(ENV_OOZIE_AUTH);
@@ -932,6 +961,10 @@
         if (commandLine.hasOption(DEBUG_OPTION)) {
             System.out.println(" Auth type : " + authOpt);
         }
+        if (AuthType.BASIC.name().equalsIgnoreCase(authOpt)) {
+            throw new OozieCLIException(
+                    "BASIC authentication requires -" + USERNAME + " and -" + PASSWORD + " to set!");
+        }
         return authOpt;
     }
 
@@ -959,7 +992,7 @@
      */
     protected XOozieClient createXOozieClient(CommandLine commandLine) throws OozieCLIException {
         XOozieClient wc = new AuthOozieClient(getOozieUrl(commandLine), getAuthOption(commandLine));
-        addHeader(wc);
+        addHeader(wc, commandLine);
         setDebugMode(wc,commandLine.hasOption(DEBUG_OPTION));
         setRetryCount(wc);
         return wc;
diff --git a/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java b/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java
index 600bbd3..7f65854 100644
--- a/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java
+++ b/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java
@@ -64,7 +64,7 @@
     public static final int AUTH_TOKEN_CACHE_FILENAME_MAXLENGTH = 255;
 
     public enum AuthType {
-        KERBEROS, SIMPLE
+        KERBEROS, SIMPLE, BASIC
     }
 
     private String authOption = null;
@@ -321,7 +321,7 @@
             catch (IllegalArgumentException iae) {
                 throw new OozieClientException(OozieClientException.AUTHENTICATION,
                         "Invalid options provided for auth: " + authOption
-                        + ", (" + AuthType.KERBEROS + " or " + AuthType.SIMPLE + " expected.)");
+                        + ", (" + AuthType.KERBEROS + " or " + AuthType.SIMPLE + " or " + AuthType.BASIC + " expected.)");
             }
             catch (InstantiationException | IllegalAccessException ex) {
                 throw new OozieClientException(OozieClientException.AUTHENTICATION,
@@ -368,6 +368,7 @@
         Map<String, Class<? extends Authenticator>> authClasses = new HashMap<>();
         authClasses.put(AuthType.KERBEROS.toString(), KerberosAuthenticator.class);
         authClasses.put(AuthType.SIMPLE.toString(), PseudoAuthenticator.class);
+        authClasses.put(AuthType.BASIC.toString(), BasicAuthenticator.class);
         authClasses.put(null, KerberosAuthenticator.class);
         return authClasses;
     }
diff --git a/docs/src/site/markdown/AG_Install.md b/docs/src/site/markdown/AG_Install.md
index 100f7c5..f18528f 100644
--- a/docs/src/site/markdown/AG_Install.md
+++ b/docs/src/site/markdown/AG_Install.md
@@ -1448,4 +1448,9 @@
 
 [::Go back to Oozie Documentation Index::](index.html)
 
+## Oozie behind a trusted proxy
 
+Oozie can be configured to work behind a proxy server - eg Apache Knox - which handles the Kerberos authentication
+for the incoming requests. In this case, the command line client can be configured to use basic authentication -
+and a custom user name and password - to authenticate with Knox. It has the advantage, that the client doesn't need
+Kerberos to be set up.
diff --git a/docs/src/site/markdown/DG_CommandLineTool.md b/docs/src/site/markdown/DG_CommandLineTool.md
index 31d52f8..b0373bc 100644
--- a/docs/src/site/markdown/DG_CommandLineTool.md
+++ b/docs/src/site/markdown/DG_CommandLineTool.md
@@ -43,7 +43,7 @@
           -allruns              Get workflow jobs corresponding to a coordinator action
                                 including all the reruns
           -auditlog <arg>       job audit log
-          -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+          -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
           -change <arg>         change a coordinator or bundle job
           -config <arg>         job configuration file '.xml' or '.properties'
           -configcontent <arg>  job configuration
@@ -90,6 +90,7 @@
           -oozie <arg>          Oozie URL
           -order <arg>          order to show coord actions (default ascending order, 'desc'
                                 for descending order, requires -info)
+          -password <arg>       password for BASIC authentication
           -poll <arg>           poll Oozie until a job reaches a terminal state or a timeout
                                 occurs
           -refresh              re-materialize the coordinator rerun actions (requires
@@ -114,6 +115,7 @@
           -timezone <arg>       use time zone with the specified ID (default GMT).
                                 See 'oozie info -timezones' for a list
           -update <arg>         Update coord definition and properties
+          -username <arg>       username for BASIC authentication
           -validatejar <arg>    generate and check job definition
           -value <arg>          new endtime/concurrency/pausetime value for changing a
                                 coordinator job
@@ -124,7 +126,7 @@
 
 ```
 oozie jobs <OPTIONS>          : jobs status
-           -auth <arg>          select authentication type [SIMPLE|KERBEROS]
+           -auth <arg>          select authentication type [SIMPLE|BASIC|KERBEROS]
            -bulk <arg>          key-value pairs to filter bulk jobs response. e.g.
                                 bundle=<B>\;coordinators=<C>\;actionstatus=<S>\;startcreatedtime=
                                 <SC>\;endcreatedtime=<EC>\;startscheduledtime=<SS>\;endscheduledt
@@ -146,13 +148,16 @@
                                 'coordinator' or 'bundle' or 'wf'(default))
            -kill                bulk kill operation
            -len <arg>           number of jobs (default '100')
-           -localtime           use local time (same as passing your time zone to -timezone). Overrides -timezone option
+           -localtime           use local time (same as passing your time zone to -timezone).
+                                Overrides -timezone option
            -offset <arg>        jobs offset (default '1')
            -oozie <arg>         Oozie URL
+           -password <arg>      password for BASIC authentication
            -resume              bulk resume operation
            -suspend             bulk suspend operation
            -timezone <arg>      use time zone with the specified ID (default GMT).
                                 See 'oozie info -timezones' for a list
+           -username <arg>      username for BASIC authentication
            -verbose             verbose mode
 ```
 
@@ -160,7 +165,7 @@
 
 ```
 oozie admin <OPTIONS>         : admin operations
-            -auth <arg>         select authentication type [SIMPLE|KERBEROS]
+            -auth <arg>         select authentication type [SIMPLE|BASIC|KERBEROS]
             -configuration      show Oozie system configuration
             -doas <arg>         doAs user, impersonates as the specified user
             -instrumentation    show Oozie system instrumentation
@@ -168,6 +173,7 @@
             -metrics            show Oozie system metrics
             -oozie <arg>        Oozie URL
             -osenv              show Oozie system OS environment
+            -password <arg>     password for BASIC authentication
             -purge <arg>        purge old oozie workflow, coordinator and bundle records from
                                 DB (parameter unit: day)
             -queuedump          show Oozie server queue elements
@@ -179,26 +185,31 @@
             -status             show the current system status
             -systemmode <arg>   Supported in Oozie-2.0 or later versions ONLY. Change oozie
                                 system mode [NORMAL|NOWEBSERVICE|SAFEMODE]
+            -username <arg>     username for BASIC authentication
             -version            show Oozie server build version
 ```
 
 ### Oozie validate command
 
 ```
-oozie validate <OPTIONS> <ARGS>   : validate a workflow, coordinator, bundle XML file
-                     -auth <arg>    select authentication type [SIMPLE|KERBEROS]
-                     -oozie <arg>   Oozie URL
+oozie validate <OPTIONS> <ARGS> : validate a workflow, coordinator, bundle XML file
+               -auth <arg>       select authentication type [SIMPLE|BASIC|KERBEROS]
+               -oozie <arg>      Oozie URL
+               -password <arg>   password for BASIC authentication
+               -username <arg>   username for BASIC authentication
 ```
 
 ### Oozie SLA operation commands
 
 ```
 oozie sla <OPTIONS>           : sla operations (Deprecated with Oozie 4.0)
-          -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+          -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
           -filter <arg>         filter of SLA events. e.g., jobid=<J>\;appname=<A>
           -len <arg>            number of results (default '100', max '1000')
           -offset <arg>         start offset (default '0')
           -oozie <arg>          Oozie URL
+          -password <arg>       password for BASIC authentication
+          -username <arg>       username for BASIC authentication
 ```
 
 ### Oozie Pig submit command
@@ -206,27 +217,31 @@
 ```
 oozie pig <OPTIONS> -X <ARGS> : submit a pig job, everything after '-X' are pass-through parameters to pig, any '-D' arguments
                                 after '-X' are put in <configuration>
-          -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+          -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
           -config <arg>         job configuration file '.properties'
           -D <property=value>   set/override value for given property
           -doas <arg>           doAs user, impersonates as the specified user
           -file <arg>           pig script
           -oozie <arg>          Oozie URL
           -P <property=value>   set parameters for script
+          -password <arg>       password for BASIC authentication
+          -username <arg>       username for BASIC authentication
 ```
 
 ### Oozie Hive submit command
 
 ```
-oozie hive <OPTIONS> -X <ARGS> : submit a hive job, everything after '-X' are pass-through parameters to hive, any '-D' arguments
- after '-X' are put in <configuration>
-           -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+oozie hive <OPTIONS> -X<ARGS>  : submit a hive job, everything after '-X' are pass-through parameters to hive,
+                                 any '-D' arguments after '-X' are put in <configuration>
+           -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
            -config <arg>         job configuration file '.properties'
            -D <property=value>   set/override value for given property
            -doas <arg>           doAs user, impersonates as the specified user
            -file <arg>           hive script
            -oozie <arg>          Oozie URL
            -P <property=value>   set parameters for script
+           -password <arg>       password for BASIC authentication
+           -username <arg>       username for BASIC authentication
 ```
 
 ### Oozie Sqoop submit command
@@ -234,12 +249,14 @@
 ```
 oozie sqoop <OPTIONS> -X <ARGS> : submit a sqoop job, everything after '-X' are pass-through parameters to sqoop, any '-D'
  arguments after '-X' are put in <configuration>
-            -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+            -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
             -command <command>    sqoop command
             -config <arg>         job configuration file '.properties'
             -D <property=value>   set/override value for given property
             -doas <arg>           doAs user, impersonates as the specified user
             -oozie <arg>          Oozie URL
+            -password <arg>       password for BASIC authentication
+            -username <arg>       username for BASIC authentication
 ```
 
 ### Oozie info command
@@ -253,11 +270,13 @@
 
 ```
 oozie mapreduce <OPTIONS>           : submit a mapreduce job
-                -auth <arg>           select authentication type [SIMPLE|KERBEROS]
+                -auth <arg>           select authentication type [SIMPLE|BASIC|KERBEROS]
                 -config <arg>         job configuration file '.properties'
                 -D <property=value>   set/override value for given property
                 -doas <arg>           doAs user, impersonates as the specified user
                 -oozie <arg>          Oozie URL
+                -password <arg>       password for BASIC authentication
+                -username <arg>       username for BASIC authentication
 ```
 
 ## Common CLI Options
@@ -268,7 +287,9 @@
 pseudo/simple authentication and Kerberos HTTP SPNEGO authentication.
 
 To perform a specific authentication, the `auth` option with authentication type requests Oozie client to run the
-specified authentication mechanism only. Oozie client provides two types `simple` and `kerberos` which supports `pseudo/simple` and `Kerberos`.
+specified authentication mechanism only. Oozie client provides three types `simple`, `basic` and `kerberos` which
+supports `pseudo/simple` and `Kerberos`. Basic authentication can be used, when the server sits behind a proxy
+which accepts basic authentication, and use Kerberos to authorize to Oozie itself.
 
 For pseudo/simple authentication the `oozie` CLI uses the user name of the current OS user.
 
@@ -281,7 +302,7 @@
 Once authentication is performed successfully the received authentication token is cached in the user home directory
 in the `.oozie-auth-token` file with owner-only permissions. Subsequent requests reuse the cached token while valid.
 
-The use of the cache file can be disabled by invoking the `oozie` CLI with the `-Doozie.auth.token.cache`false=
+The use of the cache file can be disabled by invoking the `oozie` CLI with the `-Doozie.auth.token.cache`=false
 option.
 
 To use an custom authentication mechanism, a Hadoop-Auth `Authenticator` implementation must be specified with the
diff --git a/release-log.txt b/release-log.txt
index 9758249..c5b56e2 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
 -- Oozie 5.2.0 release (trunk - unreleased)
 
+OOZIE-3539 Support http proxy/basic authentication in the command line client (zsombor via asalamon74)
 OOZIE-3468 [build] Use modernizer plugin (asalamon74 via kmarton)
 OOZIE-3535 mapreduce.job.acl-view-job property in Oozie workflow.xml not taking full effect (kmarton via asalamon74)
 OOZIE-3496 Upgrade ActiveMQ to 5.15.9 (asalamon74 via kmarton)