Adds Download endpoint for client bundle
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package com.litoralregas.openvpn.openvpn;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public record OpenVpnBundleDownload(
|
||||
String filename,
|
||||
long size,
|
||||
InputStream inputStream
|
||||
) {
|
||||
}
|
||||
@@ -137,4 +137,13 @@ public class OpenVpnService {
|
||||
|
||||
return sshService.executeOnConfiguredVps(command);
|
||||
}
|
||||
|
||||
public OpenVpnBundleDownload downloadClientBundle(String clientName) {
|
||||
String filename = clientName + ".tar.gz";
|
||||
|
||||
return sshService.downloadFileFromConfiguredVps(
|
||||
"/var/litoral_regas_openvpn/clients/" + filename,
|
||||
filename
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,10 @@ import com.litoralregas.openvpn.openvpn.IpAllocationService;
|
||||
import com.litoralregas.openvpn.openvpn.OpenVpnService;
|
||||
import com.litoralregas.openvpn.ssh.SshService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -18,14 +22,12 @@ public class RouterController {
|
||||
|
||||
private final RouterService service;
|
||||
private final DeploymentService deploymentService;
|
||||
private final SshService sshService;
|
||||
private final IpAllocationService ipAllocationService;
|
||||
private final OpenVpnService openVpnService;
|
||||
|
||||
public RouterController(RouterService service, DeploymentService deploymentService, SshService sshService, IpAllocationService ipAllocationService, OpenVpnService openVpnService) {
|
||||
public RouterController(RouterService service, DeploymentService deploymentService, IpAllocationService ipAllocationService, OpenVpnService openVpnService) {
|
||||
this.service = service;
|
||||
this.deploymentService = deploymentService;
|
||||
this.sshService = sshService;
|
||||
this.ipAllocationService = ipAllocationService;
|
||||
this.openVpnService = openVpnService;
|
||||
}
|
||||
@@ -45,7 +47,6 @@ public class RouterController {
|
||||
return service.findById(id);
|
||||
}
|
||||
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public void delete(@PathVariable UUID id) {
|
||||
service.delete(id);
|
||||
@@ -154,4 +155,28 @@ public class RouterController {
|
||||
return DeploymentResponse.from(failed);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/bundle")
|
||||
public ResponseEntity<InputStreamResource> downloadBundle(@PathVariable UUID id) {
|
||||
Router router = service.findById(id);
|
||||
|
||||
if (router.getStatus() != RouterStatus.PROVISIONED) {
|
||||
throw new IllegalStateException("Router is not provisioned yet");
|
||||
}
|
||||
|
||||
var allocation = ipAllocationService.findByRouterId(id);
|
||||
|
||||
var bundle = openVpnService.downloadClientBundle(
|
||||
allocation.getClientName()
|
||||
);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(
|
||||
HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + bundle.filename() + "\""
|
||||
)
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(bundle.size())
|
||||
.body(new InputStreamResource(bundle.inputStream()));
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
package com.litoralregas.openvpn.ssh;
|
||||
|
||||
import com.jcraft.jsch.*;
|
||||
import com.litoralregas.openvpn.openvpn.OpenVpnBundleDownload;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Service
|
||||
public class SshService {
|
||||
private final VpsSshProperties properties;
|
||||
|
||||
public SshService(VpsSshProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -23,6 +28,70 @@ public class SshService {
|
||||
);
|
||||
}
|
||||
|
||||
public OpenVpnBundleDownload downloadFileFromConfiguredVps(
|
||||
String remotePath,
|
||||
String filename
|
||||
) {
|
||||
return downloadFile(
|
||||
properties.getHost(),
|
||||
properties.getPort(),
|
||||
properties.getUsername(),
|
||||
properties.getPassword(),
|
||||
remotePath,
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
public OpenVpnBundleDownload downloadFile(
|
||||
String host,
|
||||
int port,
|
||||
String username,
|
||||
String password,
|
||||
String remotePath,
|
||||
String filename
|
||||
) {
|
||||
try {
|
||||
JSch jsch = new JSch();
|
||||
|
||||
Session session = jsch.getSession(username, host, port);
|
||||
session.setPassword(password);
|
||||
session.setConfig("StrictHostKeyChecking", "no");
|
||||
session.connect(10_000);
|
||||
|
||||
ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
|
||||
channel.connect(10_000);
|
||||
|
||||
SftpATTRS attrs = channel.lstat(remotePath);
|
||||
long size = attrs.getSize();
|
||||
|
||||
InputStream inputStream = channel.get(remotePath);
|
||||
|
||||
InputStream wrapped = new FilterInputStream(inputStream) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
} finally {
|
||||
channel.disconnect();
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return new OpenVpnBundleDownload(
|
||||
filename,
|
||||
size,
|
||||
wrapped
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to download file from VPS: " + remotePath,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public SshCommandResult execute(
|
||||
String host,
|
||||
int port,
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user