mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-09-25 09:55:52 +00:00
Merge branch 'jump-server' into 17-release
This commit is contained in:
@@ -235,8 +235,8 @@ public class BrowserFileTransferOperation {
|
||||
}
|
||||
}
|
||||
|
||||
var noExt = target.getFileName().equals(target.getExtension());
|
||||
return FilePath.of(target.getBaseName() + " (" + 1 + ")" + (noExt ? "" : "." + target.getExtension()));
|
||||
var ext = target.getExtension();
|
||||
return FilePath.of(target.getBaseName() + " (" + 1 + ")" + (ext.isPresent() ? "." + ext.get() : ""));
|
||||
}
|
||||
|
||||
private void handleSingleAcrossFileSystems(FileEntry source) throws Exception {
|
||||
|
||||
@@ -85,7 +85,7 @@ public abstract class BrowserIconFileType {
|
||||
|
||||
var name = entry.getPath().getFileName();
|
||||
var ext = entry.getPath().getExtension();
|
||||
return (ext != null && endings.contains("." + ext.toLowerCase(Locale.ROOT))) || endings.contains(name);
|
||||
return (ext.isPresent() && endings.contains("." + ext.get().toLowerCase(Locale.ROOT))) || endings.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,6 +41,7 @@ public enum DocumentationLink {
|
||||
TUNNELS("guide/ssh-tunnels"),
|
||||
HYPERV("guide/hyperv"),
|
||||
SSH_MACS("guide/ssh#no-matching-mac-found"),
|
||||
SSH_JUMP_SERVERS("guide/ssh#jump-servers"),
|
||||
KEEPASSXC("guide/password-manager#keepassxc"),
|
||||
PASSWORD_MANAGER("guide/password-manager"),
|
||||
VNC_CLIENTS("guide/vnc#external-clients"),;
|
||||
|
||||
@@ -31,6 +31,7 @@ public class ShellDialects {
|
||||
public static ShellDialect CONSTRAINED_POWERSHELL;
|
||||
public static ShellDialect OVH_BASTION;
|
||||
public static ShellDialect HETZNER_BOX;
|
||||
public static ShellDialect JUMP_SERVER;
|
||||
|
||||
public static List<ShellDialect> getStartableDialects() {
|
||||
return ALL.stream()
|
||||
@@ -96,6 +97,7 @@ public class ShellDialects {
|
||||
CONSTRAINED_POWERSHELL = byId("constrainedPowershell");
|
||||
OVH_BASTION = byId("ovhBastion");
|
||||
HETZNER_BOX = byId("hetznerBox");
|
||||
JUMP_SERVER = byId("jumpServer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ public class ShellView {
|
||||
|
||||
public FilePath writeTextFileDeterministic(FilePath base, String text) throws Exception {
|
||||
var hash = Math.abs(text.hashCode());
|
||||
var target = FilePath.of(base.getBaseName().toString() + "-" + hash + "." + base.getExtension());
|
||||
var ext = base.getExtension();
|
||||
var target = FilePath.of(base.getBaseName().toString() + "-" + hash + (ext.isPresent() ? "." + ext.get() : ""));
|
||||
if (fileExists(target)) {
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class FilePath {
|
||||
@@ -156,13 +153,13 @@ public final class FilePath {
|
||||
return FilePath.of(value.substring(0, split));
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
var name = FileNames.getFileName(value);
|
||||
public Optional<String> getExtension() {
|
||||
var name = getFileName();
|
||||
var split = name.split("\\.");
|
||||
if (split.length == 0) {
|
||||
return null;
|
||||
if (split.length < 2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return split[split.length - 1];
|
||||
return Optional.of(split[split.length - 1]);
|
||||
}
|
||||
|
||||
public FilePath join(String... parts) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.xpipe.core.util;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@Jacksonized
|
||||
@AllArgsConstructor
|
||||
public class KeyValue {
|
||||
String key;
|
||||
String value;
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import io.xpipe.app.util.SecretRetrievalStrategy;
|
||||
import io.xpipe.app.util.Validators;
|
||||
import io.xpipe.core.process.*;
|
||||
import io.xpipe.core.store.FileNames;
|
||||
import io.xpipe.core.store.FilePath;
|
||||
import io.xpipe.core.util.KeyValue;
|
||||
import io.xpipe.core.util.ValidationException;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
@@ -18,6 +20,7 @@ import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
@JsonSubTypes({
|
||||
@@ -32,12 +35,15 @@ import java.io.IOException;
|
||||
@JsonSubTypes.Type(value = SshIdentityStrategy.OtherExternal.class)
|
||||
})
|
||||
public interface SshIdentityStrategy {
|
||||
|
||||
default void checkComplete() throws ValidationException {}
|
||||
|
||||
void prepareParent(ShellControl parent) throws Exception;
|
||||
|
||||
void buildCommand(CommandBuilder builder);
|
||||
|
||||
List<KeyValue> configOptions(ShellControl parent) throws Exception;
|
||||
|
||||
default SecretRetrievalStrategy getAskpassStrategy() {
|
||||
return new SecretRetrievalStrategy.None();
|
||||
}
|
||||
@@ -50,9 +56,13 @@ public interface SshIdentityStrategy {
|
||||
public void prepareParent(ShellControl parent) {}
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
public void buildCommand(CommandBuilder builder) {}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
// Don't use any agent keys to prevent too many authentication failures
|
||||
builder.add("-oIdentitiesOnly=yes").add("-oIdentityAgent=none").add("-oIdentityFile=none");
|
||||
return List.of(new KeyValue("IdentitiesOnly", "yes"), new KeyValue("IdentityAgent", "none"), new KeyValue("IdentityFile", "none"),
|
||||
new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +104,11 @@ public interface SshIdentityStrategy {
|
||||
var pidEnvVariable = System.getenv("SSH_AGENT_PID");
|
||||
return pidEnvVariable;
|
||||
});
|
||||
}
|
||||
|
||||
builder.add("-oIdentitiesOnly=no");
|
||||
builder.add("-oIdentityFile=none");
|
||||
if (forwardAgent) {
|
||||
builder.add(1, "-A");
|
||||
}
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("ForwardAgent", forwardAgent ? "yes" : "no"), new KeyValue("IdentityFile", "none"), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +140,6 @@ public interface SshIdentityStrategy {
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
builder.add("-oIdentitiesOnly=no");
|
||||
builder.add("-oIdentityFile=none");
|
||||
builder.environment("SSH_AUTH_SOCK", parent -> {
|
||||
if (parent.getOsType().equals(OsType.WINDOWS)) {
|
||||
return getPageantWindowsPipe(parent);
|
||||
@@ -140,9 +147,11 @@ public interface SshIdentityStrategy {
|
||||
|
||||
return null;
|
||||
});
|
||||
if (forwardAgent) {
|
||||
builder.add(1, "-A");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("ForwardAgent", forwardAgent ? "yes" : "no"), new KeyValue("IdentityFile", "none"), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
|
||||
private String getPageantWindowsPipe(ShellControl parent) throws Exception {
|
||||
@@ -191,12 +200,11 @@ public interface SshIdentityStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
builder.add("-oIdentitiesOnly=no");
|
||||
builder.add("-oIdentityFile=none");
|
||||
if (forwardAgent) {
|
||||
builder.add(1, "-A");
|
||||
}
|
||||
public void buildCommand(CommandBuilder builder) {}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("ForwardAgent", forwardAgent ? "yes" : "no"), new KeyValue("IdentityFile", "none"), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,8 +228,6 @@ public interface SshIdentityStrategy {
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
builder.add("-oIdentitiesOnly=no");
|
||||
builder.add("-oIdentityFile=none");
|
||||
builder.environment("SSH_AUTH_SOCK", sc -> {
|
||||
if (sc.getOsType() == OsType.WINDOWS) {
|
||||
return null;
|
||||
@@ -230,9 +236,11 @@ public interface SshIdentityStrategy {
|
||||
var r = sc.executeSimpleStringCommand("gpgconf --list-dirs agent-ssh-socket");
|
||||
return r;
|
||||
});
|
||||
if (forwardAgent) {
|
||||
builder.add(1, "-A");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("ForwardAgent", forwardAgent ? "yes" : "no"), new KeyValue("IdentityFile", "none"), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,29 +312,24 @@ public interface SshIdentityStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
if (file == null) {
|
||||
return;
|
||||
public void buildCommand(CommandBuilder builder) {}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "yes"), new KeyValue("IdentityAgent", "none"),
|
||||
new KeyValue("IdentityFile", resolveFilePath(parent).toString()), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
|
||||
private FilePath resolveFilePath(ShellControl sc) throws Exception {
|
||||
var s = file.toAbsoluteFilePath(sc);
|
||||
// The ~ is supported on all platforms, so manually replace it here for Windows
|
||||
if (s.startsWith("~")) {
|
||||
s = s.resolveTildeHome(sc.getOsType().getUserHomeDirectory(sc));
|
||||
}
|
||||
|
||||
builder.add("-i")
|
||||
.add(sc -> {
|
||||
if (sc == null) {
|
||||
return "\"" + file.toAbsoluteFilePath(null) + "\"";
|
||||
}
|
||||
|
||||
var s = file.toAbsoluteFilePath(sc);
|
||||
// The ~ is supported on all platforms, so manually replace it here for Windows
|
||||
if (s.startsWith("~")) {
|
||||
s = s.resolveTildeHome(sc.getOsType().getUserHomeDirectory(sc));
|
||||
}
|
||||
var resolved = sc.getShellDialect()
|
||||
.evaluateExpression(sc, s.toString())
|
||||
.readStdoutOrThrow();
|
||||
return sc.getShellDialect().fileArgument(resolved);
|
||||
})
|
||||
.add("-oIdentitiesOnly=yes")
|
||||
.add("-oIdentityAgent=none");
|
||||
var resolved = sc.getShellDialect()
|
||||
.evaluateExpression(sc, s.toString())
|
||||
.readStdoutOrThrow();
|
||||
return FilePath.of(resolved);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -406,17 +409,14 @@ public interface SshIdentityStrategy {
|
||||
var path = sc.view().getLibraryPath();
|
||||
builder.fixedEnvironment("LD_LIBRARY_PATH", dir + ":" + path);
|
||||
}
|
||||
})
|
||||
.add("-oIdentityFile=none")
|
||||
.add("-I")
|
||||
.add(sc -> {
|
||||
if (sc == null) {
|
||||
return "<ykcs path>";
|
||||
}
|
||||
|
||||
return sc.getShellDialect().fileArgument(getFile(sc));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("PKCS11Provider", getFile(parent)),
|
||||
new KeyValue("IdentityFile", "none"), new KeyValue("IdentityAgent", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@Value
|
||||
@@ -450,8 +450,11 @@ public interface SshIdentityStrategy {
|
||||
builder.fixedEnvironment("LD_LIBRARY_PATH", dir + ":" + path);
|
||||
}
|
||||
});
|
||||
builder.add("-oIdentityFile=none");
|
||||
builder.add("-I").addFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("PKCS11Provider", file), new KeyValue("IdentityFile", "none"), new KeyValue("IdentityAgent", "none"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,12 +470,11 @@ public interface SshIdentityStrategy {
|
||||
public void prepareParent(ShellControl parent) {}
|
||||
|
||||
@Override
|
||||
public void buildCommand(CommandBuilder builder) {
|
||||
if (forwardAgent) {
|
||||
builder.add(1, "-A");
|
||||
}
|
||||
builder.add("-oIdentityFile=none");
|
||||
builder.add("-oIdentitiesOnly=no");
|
||||
public void buildCommand(CommandBuilder builder) {}
|
||||
|
||||
@Override
|
||||
public List<KeyValue> configOptions(ShellControl parent) throws Exception {
|
||||
return List.of(new KeyValue("IdentitiesOnly", "no"), new KeyValue("ForwardAgent", forwardAgent ? "yes" : "no"), new KeyValue("IdentityFile", "none"), new KeyValue("PKCS11Provider", "none"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+2
@@ -1470,3 +1470,5 @@ vncConnections=VNC connections
|
||||
passwordManagerIdentity=Password manager identity
|
||||
passwordManagerIdentity.displayName=Password manager identity
|
||||
passwordManagerIdentity.displayDescription=Retrieve the credentials of an identity from your password manager
|
||||
useAsJumpServer=Jump server
|
||||
useAsJumpServerDescription=This system is a jump server to be used with ProxyJump
|
||||
|
||||
Reference in New Issue
Block a user