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

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new ece32dbc76 [Feature] --auth option in hop-server.sh to correctly 
enable/disable authentication (#6040)
ece32dbc76 is described below

commit ece32dbc76b176d027d8e442628dda8e357cbc5f
Author: lance <[email protected]>
AuthorDate: Thu Nov 27 19:43:28 2025 +0800

    [Feature] --auth option in hop-server.sh to correctly enable/disable 
authentication (#6040)
    
    * whether authentication is enabled for the Hop Server via --auth
    
    Signed-off-by: lance <[email protected]>
    
    * Minor improvements
    
    - Align the XML tag content to the command, so true/false and not Y/N
    - The XML value was overwritten by the CLI because of the default value
    - Update docker scripts and add ENV variable to enable/disable
    - Update default provided hop-server.xml
    - Add the new option to the docs
    
    ---------
    
    Signed-off-by: lance <[email protected]>
    Co-authored-by: Hans Van Akelyen <[email protected]>
---
 .../static/src/main/resources/hop-server.xml       |   1 +
 docker/Dockerfile                                  |   2 +
 docker/resources/load-and-execute.sh               |   1 +
 .../modules/ROOT/pages/docker-container.adoc       |   4 +
 .../modules/ROOT/pages/hop-server/index.adoc       |  11 +-
 .../java/org/apache/hop/server/HopServerMeta.java  |  15 ++
 .../main/java/org/apache/hop/www/HopServer.java    |  10 +
 .../main/java/org/apache/hop/www/WebServer.java    | 232 ++++++++-------------
 8 files changed, 129 insertions(+), 147 deletions(-)

diff --git a/assemblies/static/src/main/resources/hop-server.xml 
b/assemblies/static/src/main/resources/hop-server.xml
index 7e9379e16c..967c29778b 100644
--- a/assemblies/static/src/main/resources/hop-server.xml
+++ b/assemblies/static/src/main/resources/hop-server.xml
@@ -23,6 +23,7 @@
         <hostname>localhost</hostname>
         <port>8181</port>
         <shutdownPort>8182</shutdownPort>
+        <enable_auth>true</enable_auth>
     </hop-server>
 
     <!-- Join the web server thread and wait until it's finished.
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 9bf4a645eb..3441250525 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -65,6 +65,8 @@ ENV HOP_OPTIONS=-XX:+AggressiveHeap
 # Path to custom entrypoint extension script file - optional
 # e.g. to fetch Hop project files from S3 or gitlab
 ENV HOP_CUSTOM_ENTRYPOINT_EXTENSION_SHELL_FILE_PATH=
+# Enable or disable the auth
+ENV HOP_SERVER_AUTH=true
 # The server user
 ENV HOP_SERVER_USER=cluster
 # The server password
diff --git a/docker/resources/load-and-execute.sh 
b/docker/resources/load-and-execute.sh
index c1c1f02f13..8def03b7fb 100755
--- a/docker/resources/load-and-execute.sh
+++ b/docker/resources/load-and-execute.sh
@@ -53,6 +53,7 @@ write_server_config() {
   echo "    <shutdownPort>${HOP_SERVER_SHUTDOWNPORT}</shutdownPort>" 
>>${HOP_SERVER_XML}
   echo "    <username>${HOP_SERVER_USER}</username>" >>${HOP_SERVER_XML}
   echo "    <password>${HOP_SERVER_PASS}</password>" >>${HOP_SERVER_XML}
+  echo "    <enable_auth>${HOP_SERVER_AUTH}</enable_auth>" >>${HOP_SERVER_XML}
 
   # If an SSL configuration is needed we need to include it here
   #
diff --git a/docs/hop-tech-manual/modules/ROOT/pages/docker-container.adoc 
b/docs/hop-tech-manual/modules/ROOT/pages/docker-container.adoc
index 3ae2f2fb06..84ca471f71 100644
--- a/docs/hop-tech-manual/modules/ROOT/pages/docker-container.adoc
+++ b/docs/hop-tech-manual/modules/ROOT/pages/docker-container.adoc
@@ -166,6 +166,10 @@ Below are the variables you can use for a **long-lived** 
container, running Hop
 | `8079`
 | The port the server shutdown listener will listen to.
 
+|```HOP_SERVER_AUTH```
+| `true`
+| Disable/Enable the authentication used for hop server
+
 |```HOP_SERVER_USER```
 |`cluster`
 | The username to log into the Hop server.
diff --git a/docs/hop-user-manual/modules/ROOT/pages/hop-server/index.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/hop-server/index.adoc
index e35dcc4e03..f53e851737 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/hop-server/index.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/hop-server/index.adoc
@@ -39,16 +39,19 @@ On Windows, this is `hop-server.bat`, on Mac and Linux, run 
`./hop-server.sh`.
 
 [source,bash]
 ----
-Usage: <main class> [-k] [-gs] [-e=<environmentOption>] [-id=<id>]
+Usage: <main class> [-ahV] [-gs] [-e=<environmentOption>] [-id=<id>]
                     [-j=<projectOption>] [-l=<level>] [-n=<serverName>]
                     [-p=<password>] [-ps=<pipelineName>] [-u=<username>]
                     [-ws=<workflowName>] [-s=<systemProperties>[,
                     <systemProperties>...]]... [<parameters>...]
+Run a Hop server
       [<parameters>...]   One XML configuration file or a hostname and port
+  -a, --auth              Does the Hop web server have authentication enabled
   -e, --environment=<environmentOption>
                           The name of the lifecycle environment to use
   -gs, --general-status
                           List the general status of the server
+  -h, --help              Show this help message and exit.
       -id=<id>            Specify the ID of the pipeline or workflow to query
   -j, --project=<projectOption>
                           The name of the project to use
@@ -68,6 +71,7 @@ Usage: <main class> [-k] [-gs] [-e=<environmentOption>] 
[-id=<id>]
   -u, --userName=<username>
                           The server user name.  Required for administrative
                             operations only, not for starting the server.
+  -V, --version           Print version information and exit.
   -ws, --workflow-status=<workflowName>
                           List the status of the workflow with this name (also
                             specify the -id option)
@@ -84,6 +88,11 @@ The available Hop Server options are:
 |--help
 |This help text
 
+|-a
+|--auth
+|Default: true +
+Allows you to disable the authentication needed to access the server
+
 |-p
 |--password
 |The server password.
diff --git a/engine/src/main/java/org/apache/hop/server/HopServerMeta.java 
b/engine/src/main/java/org/apache/hop/server/HopServerMeta.java
index cbf157e229..1c191ee085 100644
--- a/engine/src/main/java/org/apache/hop/server/HopServerMeta.java
+++ b/engine/src/main/java/org/apache/hop/server/HopServerMeta.java
@@ -157,6 +157,9 @@ public class HopServerMeta extends HopMetadataBase 
implements Cloneable, IXml, I
   @HopMetadataProperty(password = true)
   private String password;
 
+  /** enable authentication */
+  @HopMetadataProperty private boolean enableAuth;
+
   @HopMetadataProperty private String proxyHostname;
 
   @HopMetadataProperty private String proxyPort;
@@ -225,6 +228,8 @@ public class HopServerMeta extends HopMetadataBase 
implements Cloneable, IXml, I
     this.shutdownPort = shutdownPort;
     this.username = username;
     this.password = password;
+    // default true
+    this.enableAuth = true;
 
     this.proxyHostname = proxyHostname;
     this.proxyPort = proxyPort;
@@ -243,6 +248,11 @@ public class HopServerMeta extends HopMetadataBase 
implements Cloneable, IXml, I
     this.username = XmlHandler.getTagValue(node, "username");
     this.password =
         Encr.decryptPasswordOptionallyEncrypted(XmlHandler.getTagValue(node, 
"password"));
+
+    // if the enable_auth tag is empty or enable_auth=true, then it's true; 
otherwise false.
+    String authValue = XmlHandler.getTagValue(node, "enable_auth");
+    this.enableAuth = Utils.isEmpty(authValue) || 
"true".equalsIgnoreCase(authValue);
+
     this.proxyHostname = XmlHandler.getTagValue(node, "proxy_hostname");
     this.proxyPort = XmlHandler.getTagValue(node, "proxy_port");
     this.nonProxyHosts = XmlHandler.getTagValue(node, "non_proxy_hosts");
@@ -275,6 +285,10 @@ public class HopServerMeta extends HopMetadataBase 
implements Cloneable, IXml, I
     xml.append(
         XmlHandler.addTagValue(
             "password", Encr.encryptPasswordIfNotUsingVariables(password), 
false));
+
+    // if the enable_auth tag is empty or enable_auth=Y, then it's true; 
otherwise false.
+    xml.append(CONST_SPACE).append(XmlHandler.addTagValue("enable_auth", 
enableAuth));
+
     xml.append(CONST_SPACE).append(XmlHandler.addTagValue("proxy_hostname", 
proxyHostname));
     xml.append(CONST_SPACE).append(XmlHandler.addTagValue("proxy_port", 
proxyPort));
     xml.append(CONST_SPACE).append(XmlHandler.addTagValue("non_proxy_hosts", 
nonProxyHosts));
@@ -309,6 +323,7 @@ public class HopServerMeta extends HopMetadataBase 
implements Cloneable, IXml, I
     this.proxyPort = hopServer.proxyPort;
     this.nonProxyHosts = hopServer.nonProxyHosts;
     this.sslMode = hopServer.sslMode;
+    this.enableAuth = hopServer.enableAuth;
   }
 
   public String toString() {
diff --git a/engine/src/main/java/org/apache/hop/www/HopServer.java 
b/engine/src/main/java/org/apache/hop/www/HopServer.java
index e9c7bac30c..ff2ab19888 100644
--- a/engine/src/main/java/org/apache/hop/www/HopServer.java
+++ b/engine/src/main/java/org/apache/hop/www/HopServer.java
@@ -139,6 +139,11 @@ public class HopServer implements Runnable, 
IHasHopMetadataProvider, IHopCommand
       description = "The name of the server to start as defined in the 
metadata.")
   private String serverName;
 
+  @CommandLine.Option(
+      names = {"-a", "--auth"},
+      description = "Does the Hop web server have authentication enabled")
+  private Boolean enableAuth;
+
   private WebServer webServer;
   private HopServerConfig config;
   private boolean allOK;
@@ -303,6 +308,11 @@ public class HopServer implements Runnable, 
IHasHopMetadataProvider, IHopCommand
       config.setVariables(variables);
       config.setMetadataProvider(metadataProvider);
 
+      // enable auth
+      if (this.enableAuth != null) {
+        config.getHopServer().setEnableAuth(this.enableAuth);
+      }
+
       // See if we need to add the metadata folder (legacy)
       //
       addMetadataFolderProvider();
diff --git a/engine/src/main/java/org/apache/hop/www/WebServer.java 
b/engine/src/main/java/org/apache/hop/www/WebServer.java
index 485faa80a5..a3c90552b3 100644
--- a/engine/src/main/java/org/apache/hop/www/WebServer.java
+++ b/engine/src/main/java/org/apache/hop/www/WebServer.java
@@ -25,10 +25,13 @@ import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.HopEnvironment;
 import org.apache.hop.core.encryption.Encr;
 import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginException;
 import org.apache.hop.core.extension.ExtensionPointHandler;
 import org.apache.hop.core.extension.HopExtensionPoint;
 import org.apache.hop.core.logging.ILogChannel;
@@ -77,19 +80,26 @@ public class WebServer {
   private static final int DEFAULT_DETECTION_TIMER = 20000;
   private static final Class<?> PKG = WebServer.class;
   public static final String CONST_WEB_SERVER_LOG_CONFIG_OPTIONS = 
"WebServer.Log.ConfigOptions";
-  private ILogChannel log;
-  private IVariables variables;
-  private Server server;
+  @Getter @Setter private ILogChannel log;
 
-  private PipelineMap pipelineMap;
-  private WorkflowMap workflowMap;
+  /** value of variables */
+  @Setter @Getter private IVariables variables;
 
-  private String hostname;
-  private int port;
+  @Getter @Setter private Server server;
+  @Getter @Setter private PipelineMap pipelineMap;
+  @Setter @Getter private WorkflowMap workflowMap;
+
+  /** the hostname */
+  @Setter @Getter private String hostname;
+
+  @Setter @Getter private int port;
   private final int shutdownPort;
 
   private String passwordFile;
   private final WebServerShutdownHook webServerShutdownHook;
+
+  /** Can be used to override the default shutdown behavior of performing a 
System.exit */
+  @Setter
   private IWebServerShutdownHandler webServerShutdownHandler =
       new DefaultWebServerShutdownHandler();
 
@@ -177,71 +187,85 @@ public class WebServer {
     this(log, pipelineMap, workflowMap, hostname, port, shutdownPort, join, 
null, null);
   }
 
-  public Server getServer() {
-    return server;
-  }
-
-  public void setServer(Server server) {
-    this.server = server;
-  }
-
   public void startServer() throws Exception {
     server = new Server();
-
-    Constraint.Builder constraintBuilder =
-        new Constraint.Builder()
-            .name(Authenticator.BASIC_AUTH)
-            .authorization(Constraint.Authorization.SPECIFIC_ROLE)
-            .transport(Constraint.Transport.ANY);
-
-    // Set up the security handler, optionally with JAAS
-    //
-    ConstraintSecurityHandler securityHandler = new 
ConstraintSecurityHandler();
-    securityHandler.setAuthenticationType(Authenticator.BASIC_AUTH);
-
-    if (System.getProperty("loginmodulename") != null
-        && System.getProperty("java.security.auth.login.config") != null) {
-      constraintBuilder.roles("*");
-      JAASLoginService jaasLoginService = new JAASLoginService("Hop");
-      
jaasLoginService.setLoginModuleName(System.getProperty("loginmodulename"));
-      securityHandler.setLoginService(jaasLoginService);
-    } else {
-      constraintBuilder.roles("default");
-      HashLoginService hashLoginService;
-      HopServerMeta hopServer = 
pipelineMap.getHopServerConfig().getHopServer();
-      if (!Utils.isEmpty(hopServer.getPassword())) {
-        hashLoginService = new HashLoginService("Hop");
-        UserStore userStore = new UserStore();
-        userStore.addUser(
-            hopServer.getUsername(),
-            new Password(hopServer.getPassword()),
-            new String[] {"default"});
-        hashLoginService.setUserStore(userStore);
+    HopServerMeta hopServer = pipelineMap.getHopServerConfig().getHopServer();
+
+    Handler innerHandler;
+
+    if (hopServer.isEnableAuth()) {
+      Constraint.Builder constraintBuilder =
+          new Constraint.Builder()
+              .name(Authenticator.BASIC_AUTH)
+              .authorization(Constraint.Authorization.SPECIFIC_ROLE)
+              .transport(Constraint.Transport.ANY);
+
+      ConstraintSecurityHandler securityHandler = new 
ConstraintSecurityHandler();
+      securityHandler.setAuthenticationType(Authenticator.BASIC_AUTH);
+
+      // basic authentication
+      if (System.getProperty("loginmodulename") != null
+          && System.getProperty("java.security.auth.login.config") != null) {
+        constraintBuilder.roles("*");
+        JAASLoginService jaasLoginService = new JAASLoginService("Hop");
+        
jaasLoginService.setLoginModuleName(System.getProperty("loginmodulename"));
+        securityHandler.setLoginService(jaasLoginService);
       } else {
-        // See if there is a hop.pwd file in the HOP_HOME directory:
-        if (Utils.isEmpty(passwordFile)) {
-          passwordFile = Const.getHopLocalServerPasswordFile();
+        constraintBuilder.roles("default");
+        HashLoginService hashLoginService;
+        if (!Utils.isEmpty(hopServer.getPassword())) {
+          hashLoginService = new HashLoginService("Hop");
+          UserStore userStore = new UserStore();
+          userStore.addUser(
+              hopServer.getUsername(),
+              new Password(hopServer.getPassword()),
+              new String[] {"default"});
+          hashLoginService.setUserStore(userStore);
+        } else {
+          if (Utils.isEmpty(passwordFile)) {
+            passwordFile = Const.getHopLocalServerPasswordFile();
+          }
+          hashLoginService = new HashLoginService("Hop");
+          PropertyUserStore userStore = new PropertyUserStore();
+          
userStore.setConfig(ResourceFactory.of(server).newResource(passwordFile));
+          hashLoginService.setUserStore(userStore);
         }
-        hashLoginService = new HashLoginService("Hop");
-        PropertyUserStore userStore = new PropertyUserStore();
-        
userStore.setConfig(ResourceFactory.of(server).newResource(passwordFile));
-        hashLoginService.setUserStore(userStore);
+        securityHandler.setLoginService(hashLoginService);
       }
-      securityHandler.setLoginService(hashLoginService);
+
+      ConstraintMapping constraintMapping = new ConstraintMapping();
+      constraintMapping.setPathSpec("/*");
+      constraintMapping.setConstraint(constraintBuilder.build());
+      securityHandler.setConstraintMappings(new ConstraintMapping[] 
{constraintMapping});
+
+      // create context handler collection
+      ContextHandlerCollection contexts = createContexts();
+      ResourceHandler resourceHandler = new ResourceHandler();
+      resourceHandler.setBaseResourceAsString("temp");
+
+      securityHandler.setHandler(new Handler.Sequence(resourceHandler, 
contexts));
+      innerHandler = securityHandler;
+      log.logBasic("Hop Server: Basic authentication is ENABLED");
+    } else {
+      ContextHandlerCollection contexts = createContexts();
+      ResourceHandler resourceHandler = new ResourceHandler();
+      resourceHandler.setBaseResourceAsString("temp");
+
+      innerHandler = new Handler.Sequence(resourceHandler, contexts);
+      log.logBasic("Hop Server: Basic authentication is DISABLED 
(enableAuth=false)");
     }
 
-    ConstraintMapping constraintMapping = new ConstraintMapping();
-    constraintMapping.setPathSpec("/*");
-    constraintMapping.setConstraint(constraintBuilder.build());
+    server.setHandler(innerHandler);
 
-    securityHandler.setConstraintMappings(new ConstraintMapping[] 
{constraintMapping});
+    // Start execution
+    createListeners();
+    server.start();
+  }
 
-    // Add all the servlets defined in hop-servlets.xml ...
-    //
+  private ContextHandlerCollection createContexts() throws HopPluginException {
     ContextHandlerCollection contexts = new ContextHandlerCollection();
 
     // Root
-    //
     ServletContextHandler root =
         new ServletContextHandler(GetRootServlet.CONTEXT_PATH, 
ServletContextHandler.SESSIONS);
     contexts.addHandler(root);
@@ -252,7 +276,6 @@ public class WebServer {
     PluginRegistry pluginRegistry = PluginRegistry.getInstance();
     List<IPlugin> plugins = 
pluginRegistry.getPlugins(HopServerPluginType.class);
     for (IPlugin plugin : plugins) {
-
       IHopServerPlugin servlet = pluginRegistry.loadClass(plugin, 
IHopServerPlugin.class);
       servlet.setup(pipelineMap, workflowMap);
       servlet.setJettyMode(true);
@@ -274,13 +297,7 @@ public class WebServer {
         "com.sun.jersey.config.property.packages", "org.apache.hop.www.jaxrs");
     root.addServlet(jerseyServletHolder, "/api/*");
 
-    // Allow png files to be shown for pipelines and workflows...
-    //
-    ResourceHandler resourceHandler = new ResourceHandler();
-    resourceHandler.setBaseResourceAsString("temp");
-    // add all handlers/contexts to server
-
-    // set up static servlet
+    // Static resources
     ServletHolder staticHolder = new ServletHolder("static", 
DefaultServlet.class);
     // baseResource maps to the path relative to where hop-server is started
     Resource staticResource = 
ResourceFactory.of(server).newResource("static/");
@@ -290,13 +307,7 @@ public class WebServer {
     root.addServlet(staticHolder, "/static/*");
 
     root.addServlet(new ServletHolder(rootServlet), "/*");
-
-    securityHandler.setHandler(new Handler.Sequence(resourceHandler, 
contexts));
-    server.setHandler(securityHandler);
-
-    // Start execution
-    createListeners();
-    server.start();
+    return contexts;
   }
 
   public String getContextPath(IHopServerPlugin servlet) {
@@ -449,20 +460,6 @@ public class WebServer {
     return isValid;
   }
 
-  /**
-   * @return the hostname
-   */
-  public String getHostname() {
-    return hostname;
-  }
-
-  /**
-   * @param hostname the hostname to set
-   */
-  public void setHostname(String hostname) {
-    this.hostname = hostname;
-  }
-
   public String getPasswordFile() {
     return passwordFile;
   }
@@ -471,63 +468,6 @@ public class WebServer {
     this.passwordFile = passwordFile;
   }
 
-  public ILogChannel getLog() {
-    return log;
-  }
-
-  public void setLog(ILogChannel log) {
-    this.log = log;
-  }
-
-  public PipelineMap getPipelineMap() {
-    return pipelineMap;
-  }
-
-  public void setPipelineMap(PipelineMap pipelineMap) {
-    this.pipelineMap = pipelineMap;
-  }
-
-  public WorkflowMap getWorkflowMap() {
-    return workflowMap;
-  }
-
-  public void setWorkflowMap(WorkflowMap workflowMap) {
-    this.workflowMap = workflowMap;
-  }
-
-  public int getPort() {
-    return port;
-  }
-
-  public void setPort(int port) {
-    this.port = port;
-  }
-
-  /**
-   * Gets variables
-   *
-   * @return value of variables
-   */
-  public IVariables getVariables() {
-    return variables;
-  }
-
-  /**
-   * @param variables The variables to set
-   */
-  public void setVariables(IVariables variables) {
-    this.variables = variables;
-  }
-
-  /**
-   * Can be used to override the default shutdown behavior of performing a 
System.exit
-   *
-   * @param webServerShutdownHandler
-   */
-  public void setWebServerShutdownHandler(IWebServerShutdownHandler 
webServerShutdownHandler) {
-    this.webServerShutdownHandler = webServerShutdownHandler;
-  }
-
   public int defaultDetectionTimer() {
     String sDetectionTimer = 
System.getProperty(Const.HOP_SERVER_DETECTION_TIMER);
 

Reply via email to