Repository: OpenAEV-Platform/openaev (java)

Issue:
Allow to customize the installation path of agents
## Context

Allow to customize the installation path of agents



Discussion:
Linked to https://github.com/OpenBAS-Platform/agent/issues/92

Patch:
diff --git a/openbas-api/src/main/java/io/openbas/rest/asset/endpoint/form/EndpointRegisterInput.java b/openbas-api/src/main/java/io/openbas/rest/asset/endpoint/form/EndpointRegisterInput.java
--- a/openbas-api/src/main/java/io/openbas/rest/asset/endpoint/form/EndpointRegisterInput.java
+++ b/openbas-api/src/main/java/io/openbas/rest/asset/endpoint/form/EndpointRegisterInput.java
@@ -28,5 +28,8 @@ public class EndpointRegisterInput extends EndpointInput {
   @JsonProperty("agent_installation_mode")
   private String installationMode;
 
+  @JsonProperty("agent_installation_directory")
+  private String installationDirectory;
+
   private String seenIp;
 }
diff --git a/openbas-api/src/main/java/io/openbas/rest/executor/ExecutorApi.java b/openbas-api/src/main/java/io/openbas/rest/executor/ExecutorApi.java
--- a/openbas-api/src/main/java/io/openbas/rest/executor/ExecutorApi.java
+++ b/openbas-api/src/main/java/io/openbas/rest/executor/ExecutorApi.java
@@ -330,7 +330,9 @@ public Executor registerExecutor(
               description = "Installation Mode: session, user or system service",
               required = true)
           @PathVariable
-          String installationMode)
+          String installationMode,
+      @Parameter(description = "Installation path") @RequestParam(required = false)
+          String installationPath)
       throws IOException {
     platform = Optional.ofNullable(platform).map(String::toLowerCase).orElse("");
 
@@ -342,7 +344,8 @@ public Executor registerExecutor(
       throw new UnsupportedOperationException("Invalid token");
     }
     String installCommand =
-        this.endpointService.generateInstallCommand(platform, token, installationMode);
+        this.endpointService.generateInstallCommand(
+            platform, token, installationMode, installationPath);
     return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(installCommand);
   }
 }
diff --git a/openbas-api/src/main/java/io/openbas/service/EndpointService.java b/openbas-api/src/main/java/io/openbas/service/EndpointService.java
--- a/openbas-api/src/main/java/io/openbas/service/EndpointService.java
+++ b/openbas-api/src/main/java/io/openbas/service/EndpointService.java
@@ -54,9 +54,19 @@ public class EndpointService {
   public static final String OPENBAS_AGENT_INSTALLER = "openbas-agent-installer";
   public static final String OPENBAS_AGENT_UPGRADE = "openbas-agent-upgrade";
   public static final String SERVICE = "service";
+  public static final String SERVICE_USER = "service-user";
+  public static final String SESSION_USER = "sessions-user";
 
   public static String JFROG_BASE = "https://filigran.jfrog.io/artifactory";
 
+  public static final String OPENBAS_INSTALL_DIR_WINDOWS_SERVICE =
+      ""; // Filled by the agent installer automatically
+  public static final String OPENBAS_INSTALL_DIR_WINDOWS_SERVICE_USER = "C:\\Filigran";
+  public static final String OPENBAS_INSTALL_DIR_WINDOWS_SESSION_USER = "C:\\Filigran";
+  public static final String OPENBAS_INSTALL_DIR_UNIX_SERVICE = "/opt/openbas-agent";
+  public static final String OPENBAS_INSTALL_DIR_UNIX_SERVICE_USER = "/opt/openbas-agent-service";
+  public static final String OPENBAS_INSTALL_DIR_UNIX_SESSION_USER = ".local/openbas-agent-session";
+
   @Resource private OpenBASConfig openBASConfig;
 
   @Value("${openbas.admin.token:#{null}}")
@@ -358,7 +368,10 @@ public Endpoint register(final EndpointRegisterInput input) throws IOException {
     if (agent.getParent() == null && !agent.getVersion().equals(version)) {
       AssetAgentJob assetAgentJob = new AssetAgentJob();
       assetAgentJob.setCommand(
-          generateUpgradeCommand(endpoint.getPlatform().name(), input.getInstallationMode()));
+          generateUpgradeCommand(
+              endpoint.getPlatform().name(),
+              input.getInstallationMode(),
+              input.getInstallationDirectory()));
       assetAgentJob.setAgent(agent);
       assetAgentJobRepository.save(assetAgentJob);
     }
@@ -476,8 +489,8 @@ private AgentRegisterInput toAgentEndpoint(EndpointRegisterInput input) {
     return agentInput;
   }
 
-  public String getFileOrDownloadFromJfrog(String platform, String file, String adminToken)
-      throws IOException {
+  public String getFileOrDownloadFromJfrog(
+      String platform, String file, String adminToken, String installationDir) throws IOException {
     String extension =
         switch (platform.toLowerCase()) {
           case "windows" -> "ps1";
@@ -501,16 +514,52 @@ public String getFileOrDownloadFromJfrog(String platform, String file, String ad
           "Agent installer version " + executorOpenbasBinariesVersion + " not found");
     }
 
+    if (installationDir == null) {
+      installationDir = "";
+    }
+
     return IOUtils.toString(in, StandardCharsets.UTF_8)
         .replace("${OPENBAS_URL}", openBASConfig.getBaseUrlForAgent())
         .replace("${OPENBAS_TOKEN}", adminToken)
         .replace(
             "${OPENBAS_UNSECURED_CERTIFICATE}",
             String.valueOf(openBASConfig.isUnsecuredCertificate()))
-        .replace("${OPENBAS_WITH_PROXY}", String.valueOf(openBASConfig.isWithProxy()));
+        .replace("${OPENBAS_WITH_PROXY}", String.valueOf(openBASConfig.isWithProxy()))
+        .replace("${OPENBAS_INSTALL_DIR}", installationDir);
+  }
+
+  public String generateInstallationDir(
+      String platform, String installationMode, String installationDir) {
+    if (installationDir != null && !installationDir.equals("")) {
+      return installationDir;
+    }
+    if (platform.equals("windows")) {
+      if (installationMode != null && installationMode.equals(SERVICE)) {
+        return OPENBAS_INSTALL_DIR_WINDOWS_SERVICE;
+      }
+      if (installationMode != null && installationMode.equals(SERVICE_USER)) {
+        return OPENBAS_INSTALL_DIR_WINDOWS_SERVICE_USER;
+      }
+      if (installationMode != null && installationMode.equals(SESSION_USER)) {
+        return OPENBAS_INSTALL_DIR_WINDOWS_SESSION_USER;
+      }
+      return OPENBAS_INSTALL_DIR_WINDOWS_SERVICE;
+    } else {
+      if (installationMode != null && installationMode.equals(SERVICE)) {
+        return OPENBAS_INSTALL_DIR_UNIX_SERVICE;
+      }
+      if (installationMode != null && installationMode.equals(SERVICE_USER)) {
+        return OPENBAS_INSTALL_DIR_UNIX_SERVICE_USER;
+      }
+      if (installationMode != null && installationMode.equals(SESSION_USER)) {
+        return OPENBAS_INSTALL_DIR_UNIX_SESSION_USER;
+      }
+      return OPENBAS_INSTALL_DIR_UNIX_SERVICE;
+    }
   }
 
-  public String generateInstallCommand(String platform, String token, String installationMode)
+  public String generateInstallCommand(
+      String platform, String token, String installationMode, String installationDir)
       throws IOException {
     if (token == null || token.isEmpty()) {
       throw new IllegalArgumentException("Token must not be null or empty.");
@@ -519,16 +568,18 @@ public String generateInstallCommand(String platform, String token, String insta
     if (installationMode != null && !installationMode.equals(SERVICE)) {
       installerName = installerName.concat("-").concat(installationMode);
     }
-    return getFileOrDownloadFromJfrog(platform, installerName, token);
+    installationDir = generateInstallationDir(platform, installationMode, installationDir);
+    return getFileOrDownloadFromJfrog(platform, installerName, token, installationDir);
   }
 
-  public String generateUpgradeCommand(String platform, String installationMode)
-      throws IOException {
+  public String generateUpgradeCommand(
+      String platform, String installationMode, String installationDir) throws IOException {
     String upgradeName = OPENBAS_AGENT_UPGRADE;
     if (installationMode != null && !installationMode.equals(SERVICE)) {
       upgradeName = upgradeName.concat("-").concat(installationMode);
     }
-    return getFileOrDownloadFromJfrog(platform, upgradeName, adminToken);
+    installationDir = generateInstallationDir(platform, installationMode, installationDir);
+    return getFileOrDownloadFromJfrog(platform, upgradeName, adminToken, installationDir);
   }
 
   // -- OPTIONS --


Test patch:
diff --git a/openbas-api/src/test/java/io/openbas/rest/EndpointApiTest.java b/openbas-api/src/test/java/io/openbas/rest/EndpointApiTest.java
--- a/openbas-api/src/test/java/io/openbas/rest/EndpointApiTest.java
+++ b/openbas-api/src/test/java/io/openbas/rest/EndpointApiTest.java
@@ -128,7 +128,7 @@ void given_validEndpointInput_should_upsertEndpointSuccessfully() throws Excepti
 
     Mockito.doReturn("command")
         .when(endpointService)
-        .generateUpgradeCommand(String.valueOf(Endpoint.PLATFORM_TYPE.Windows), null);
+        .generateUpgradeCommand(String.valueOf(Endpoint.PLATFORM_TYPE.Windows), null, null);
 
     // --EXECUTE--
     String response =
@@ -166,7 +166,7 @@ void given_validInputForNonExistingEndpoint_should_createAndUpsertSuccessfully()
 
     Mockito.doReturn("command")
         .when(endpointService)
-        .generateUpgradeCommand(String.valueOf(Endpoint.PLATFORM_TYPE.Windows), null);
+        .generateUpgradeCommand(String.valueOf(Endpoint.PLATFORM_TYPE.Windows), null, null);
 
     // --EXECUTE--
     String response =