Add SSH command execution service

This commit is contained in:
litoral05
2026-05-05 11:13:51 +01:00
parent b71030dba8
commit 6b7b85da19
6 changed files with 135 additions and 0 deletions
+5
View File
@@ -65,6 +65,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
</dependencies>
<build>
@@ -78,4 +78,34 @@ public class RouterController {
return DeploymentResponse.from(failedDeployment);
}
}
@PostMapping("/{id}/remove")
public DeploymentResponse remove(@PathVariable UUID id) {
Router router = service.findById(id);
var deployment = deploymentService.startDeployment(router, DeploymentAction.REMOVE);
try {
service.forceStatus(id, RouterStatus.PROVISIONING); // or REMOVING if you want later
// simulate removal
var finished = deploymentService.finishSuccess(
deployment,
"Removal completed successfully"
);
service.forceStatus(id, RouterStatus.REMOVED);
return DeploymentResponse.from(finished);
} catch (Exception e) {
var failed = deploymentService.finishFailure(
deployment,
e.getMessage()
);
service.forceStatus(id, RouterStatus.FAILED);
return DeploymentResponse.from(failed);
}
}
}
@@ -0,0 +1,8 @@
package com.litoralregas.openvpn.ssh;
public record SshCommandResult(
int exitCode,
String stdout,
String stderr
) {
}
@@ -0,0 +1,58 @@
package com.litoralregas.openvpn.ssh;
import com.jcraft.jsch.*;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
@Service
public class SshService {
public SshCommandResult execute(
String host,
int port,
String username,
String password,
String command
) {
Session session = null;
ChannelExec channel = null;
try {
JSch jsch = new JSch();
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(10_000);
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
channel.setOutputStream(stdout);
channel.setErrStream(stderr);
channel.connect();
while (!channel.isClosed()) {
Thread.sleep(100);
}
return new SshCommandResult(
channel.getExitStatus(),
stdout.toString(StandardCharsets.UTF_8),
stderr.toString(StandardCharsets.UTF_8)
);
} catch (Exception e) {
return new SshCommandResult(-1, "", e.getMessage());
} finally {
if (channel != null) channel.disconnect();
if (session != null) session.disconnect();
}
}
}
@@ -0,0 +1,25 @@
package com.litoralregas.openvpn.ssh;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/ssh-test")
public class SshTestController {
private final SshService sshService;
public SshTestController(SshService sshService) {
this.sshService = sshService;
}
@PostMapping
public SshCommandResult test(@RequestBody SshTestRequest request) {
return sshService.execute(
request.host(),
request.port(),
request.username(),
request.password(),
"whoami && hostname"
);
}
}
@@ -0,0 +1,9 @@
package com.litoralregas.openvpn.ssh;
public record SshTestRequest(
String host,
int port,
String username,
String password
) {
}