This commit is contained in:
crschnick
2026-03-06 12:24:10 +00:00
parent c5515a791f
commit 5c1dc58c29
12 changed files with 93 additions and 42 deletions

View File

@@ -9,6 +9,7 @@ import io.xpipe.app.platform.Validator;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ShellControl;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import io.xpipe.core.OsType;
@@ -31,7 +32,7 @@ import java.util.List;
@Value
@Jacksonized
@Builder
public class CustomAgentStrategy implements SshIdentityStrategy {
public class CustomAgentStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(
@@ -104,9 +105,7 @@ public class CustomAgentStrategy implements SshIdentityStrategy {
}
@Override
public void buildCommand(CommandBuilder builder) {}
private String getIdentityAgent(ShellControl sc) throws Exception {
public FilePath determinetAgentSocketLocation(ShellControl sc) throws Exception {
if (!sc.isLocal() || sc.getOsType() == OsType.WINDOWS) {
return null;
}
@@ -117,13 +116,16 @@ public class CustomAgentStrategy implements SshIdentityStrategy {
agent = AppPrefs.get().defaultSshAgentSocket().getValue();
}
if (agent != null) {
return agent.resolveTildeHome(sc.view().userHome()).toString();
return agent.resolveTildeHome(sc.view().userHome());
}
}
return null;
}
@Override
public void buildCommand(CommandBuilder builder) {}
@Override
public List<KeyValue> configOptions(ShellControl sc) throws Exception {
var file = SshIdentityStrategy.getPublicKeyPath(sc, publicKey);
@@ -133,7 +135,7 @@ public class CustomAgentStrategy implements SshIdentityStrategy {
new KeyValue("IdentityFile", file.isPresent() ? file.get().toString() : "none"),
new KeyValue("PKCS11Provider", "none")));
var agent = getIdentityAgent(sc);
var agent = determinetAgentSocketLocation(sc);
if (agent != null) {
l.add(new KeyValue("IdentityAgent", "\"" + agent + "\""));
}

View File

@@ -7,6 +7,7 @@ import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import io.xpipe.core.OsType;
@@ -27,7 +28,7 @@ import java.util.List;
@Jacksonized
@Builder
@JsonTypeName("gpgAgent")
public class GpgAgentStrategy implements SshIdentityStrategy {
public class GpgAgentStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(Property<GpgAgentStrategy> p, SshIdentityStrategyChoiceConfig config) {
@@ -81,9 +82,7 @@ public class GpgAgentStrategy implements SshIdentityStrategy {
}
@Override
public void buildCommand(CommandBuilder builder) {}
private String getIdentityAgent(ShellControl sc) throws Exception {
public FilePath determinetAgentSocketLocation(ShellControl sc) throws Exception {
if (sc.getOsType() == OsType.WINDOWS) {
return null;
}
@@ -93,9 +92,12 @@ public class GpgAgentStrategy implements SshIdentityStrategy {
return null;
}
return r;
return FilePath.of(r);
}
@Override
public void buildCommand(CommandBuilder builder) {}
@Override
public List<KeyValue> configOptions(ShellControl sc) throws Exception {
var file = SshIdentityStrategy.getPublicKeyPath(sc, publicKey);
@@ -105,7 +107,7 @@ public class GpgAgentStrategy implements SshIdentityStrategy {
new KeyValue("IdentityFile", file.isPresent() ? file.get().toString() : "none"),
new KeyValue("PKCS11Provider", "none")));
var agent = getIdentityAgent(sc);
var agent = determinetAgentSocketLocation(sc);
if (agent != null) {
l.add(new KeyValue("IdentityAgent", "\"" + agent + "\""));
}

View File

@@ -5,6 +5,7 @@ import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ShellControl;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import io.xpipe.core.OsType;
@@ -24,7 +25,7 @@ import java.util.List;
@Value
@Jacksonized
@Builder
public class OpenSshAgentStrategy implements SshIdentityStrategy {
public class OpenSshAgentStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(
@@ -63,9 +64,7 @@ public class OpenSshAgentStrategy implements SshIdentityStrategy {
}
@Override
public void buildCommand(CommandBuilder builder) {}
private String getIdentityAgent(ShellControl sc) throws Exception {
public FilePath determinetAgentSocketLocation(ShellControl sc) throws Exception {
if (sc.getOsType() == OsType.WINDOWS) {
return null;
}
@@ -73,13 +72,16 @@ public class OpenSshAgentStrategy implements SshIdentityStrategy {
if (AppPrefs.get() != null) {
var socket = AppPrefs.get().defaultSshAgentSocket().getValue();
if (socket != null) {
return socket.resolveTildeHome(sc.view().userHome()).toString();
return socket.resolveTildeHome(sc.view().userHome());
}
}
return null;
}
@Override
public void buildCommand(CommandBuilder builder) {}
@Override
public List<KeyValue> configOptions(ShellControl sc) throws Exception {
var file = SshIdentityStrategy.getPublicKeyPath(sc, publicKey);
@@ -89,7 +91,7 @@ public class OpenSshAgentStrategy implements SshIdentityStrategy {
new KeyValue("IdentityFile", file.isPresent() ? file.get().toString() : "none"),
new KeyValue("PKCS11Provider", "none")));
var agent = getIdentityAgent(sc);
var agent = determinetAgentSocketLocation(sc);
if (agent != null) {
l.add(new KeyValue("IdentityAgent", "\"" + agent + "\""));
}

View File

@@ -3,6 +3,7 @@ package io.xpipe.app.cred;
import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ShellControl;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import javafx.beans.property.Property;
@@ -20,7 +21,7 @@ import java.util.List;
@Value
@Jacksonized
@Builder
public class OtherExternalAgentStrategy implements SshIdentityStrategy {
public class OtherExternalAgentStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(
@@ -54,6 +55,11 @@ public class OtherExternalAgentStrategy implements SshIdentityStrategy {
}
}
@Override
public FilePath determinetAgentSocketLocation(ShellControl parent) throws Exception {
return null;
}
@Override
public void buildCommand(CommandBuilder builder) {}

View File

@@ -8,6 +8,7 @@ import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.util.LocalExec;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import io.xpipe.core.OsType;
@@ -30,7 +31,7 @@ import java.util.List;
@Value
@Jacksonized
@Builder
public class PageantStrategy implements SshIdentityStrategy {
public class PageantStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(Property<PageantStrategy> p, SshIdentityStrategyChoiceConfig config) {
@@ -95,16 +96,17 @@ public class PageantStrategy implements SshIdentityStrategy {
}
@Override
public void buildCommand(CommandBuilder builder) {}
private String getIdentityAgent(ShellControl sc) {
public FilePath determinetAgentSocketLocation(ShellControl sc) throws Exception {
if (sc.isLocal() && sc.getOsType() == OsType.WINDOWS) {
return getPageantWindowsPipe();
return FilePath.of(getPageantWindowsPipe());
}
return null;
}
@Override
public void buildCommand(CommandBuilder builder) {}
@Override
public List<KeyValue> configOptions(ShellControl sc) throws Exception {
var file = SshIdentityStrategy.getPublicKeyPath(sc, publicKey);
@@ -114,7 +116,7 @@ public class PageantStrategy implements SshIdentityStrategy {
new KeyValue("IdentityFile", file.isPresent() ? file.get().toString() : "none"),
new KeyValue("PKCS11Provider", "none")));
var agent = getIdentityAgent(sc);
var agent = determinetAgentSocketLocation(sc);
if (agent != null) {
l.add(new KeyValue("IdentityAgent", "\"" + agent + "\""));
}

View File

@@ -14,6 +14,7 @@ import io.xpipe.app.process.ShellControl;
import io.xpipe.app.pwman.PasswordManagerKeyConfiguration;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.Validators;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
@@ -33,7 +34,7 @@ import java.util.List;
@Value
@Jacksonized
@Builder
public class PasswordManagerAgentStrategy implements SshIdentityStrategy {
public class PasswordManagerAgentStrategy implements SshIdentityAgentStrategy {
@SuppressWarnings("unused")
public static OptionsBuilder createOptions(
@@ -111,6 +112,11 @@ public class PasswordManagerAgentStrategy implements SshIdentityStrategy {
}
}
@Override
public FilePath determinetAgentSocketLocation(ShellControl parent) throws Exception {
return null;
}
@Override
public void buildCommand(CommandBuilder builder) {
var config = getConfig();

View File

@@ -30,7 +30,7 @@ public class SshAgentKeyList {
}
}
public static Entry findAgentIdentity(DataStoreEntryRef<ShellStore> ref, SshIdentityStrategy strategy, String identifier) throws Exception {
public static Entry findAgentIdentity(DataStoreEntryRef<ShellStore> ref, SshIdentityAgentStrategy strategy, String identifier) throws Exception {
var list = listAgentIdentities(ref, strategy).stream().filter(entry -> {
return entry.getName().equalsIgnoreCase(identifier) || entry.getPublicKey().equalsIgnoreCase(identifier);
}).toList();
@@ -47,11 +47,12 @@ public class SshAgentKeyList {
return list.getFirst();
}
public static List<Entry> listAgentIdentities(DataStoreEntryRef<ShellStore> ref, SshIdentityStrategy strategy) throws Exception {
public static List<Entry> listAgentIdentities(DataStoreEntryRef<ShellStore> ref, SshIdentityAgentStrategy strategy) throws Exception {
var session = ref.getStore().getOrStartSession();
strategy.prepareParent(session);
var out = session.command(CommandBuilder.of().add("ssh-add", "-L")).readStdoutOrThrow();
var socket = strategy.determinetAgentSocketLocation(session);
var out = session.command(CommandBuilder.of().add("ssh-add", "-L").fixedEnvironment("SSH_AUTH_SOCK", socket != null ? socket.toString() : null)).readStdoutOrThrow();
var pattern = Pattern.compile("([^ ]+) ([^ ]+) (.+)");
var lines = out.lines().toList();
var list = new ArrayList<Entry>();

View File

@@ -29,11 +29,11 @@ import java.util.List;
public class SshAgentKeyListComp extends SimpleRegionBuilder {
private final ObservableValue<DataStoreEntryRef<ShellStore>> ref;
private final ObservableValue<? extends SshIdentityStrategy> sshIdentityStrategy;
private final ObservableValue<? extends SshIdentityAgentStrategy> sshIdentityStrategy;
private final StringProperty value;
private final boolean useKeyNames;
public SshAgentKeyListComp(ObservableValue<DataStoreEntryRef<ShellStore>> ref, ObservableValue<? extends SshIdentityStrategy> sshIdentityStrategy, StringProperty value,
public SshAgentKeyListComp(ObservableValue<DataStoreEntryRef<ShellStore>> ref, ObservableValue<? extends SshIdentityAgentStrategy> sshIdentityStrategy, StringProperty value,
boolean useKeyNames
) {
this.ref = ref;

View File

@@ -26,9 +26,9 @@ import java.util.List;
public class SshAgentTestComp extends SimpleRegionBuilder {
private final ObservableValue<? extends SshIdentityStrategy> sshIdentityStrategy;
private final ObservableValue<? extends SshIdentityAgentStrategy> sshIdentityStrategy;
public SshAgentTestComp(ObservableValue<? extends SshIdentityStrategy> sshIdentityStrategy) {this.sshIdentityStrategy = sshIdentityStrategy;}
public SshAgentTestComp(ObservableValue<? extends SshIdentityAgentStrategy> sshIdentityStrategy) {this.sshIdentityStrategy = sshIdentityStrategy;}
@Override
protected Region createSimple() {

View File

@@ -0,0 +1,24 @@
package io.xpipe.app.cred;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.xpipe.app.ext.ValidationException;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.OsFileSystem;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.secret.SecretNoneStrategy;
import io.xpipe.app.secret.SecretRetrievalStrategy;
import io.xpipe.core.FilePath;
import io.xpipe.core.KeyValue;
import io.xpipe.core.OsType;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public interface SshIdentityAgentStrategy extends SshIdentityStrategy {
void prepareParent(ShellControl parent) throws Exception;
FilePath determinetAgentSocketLocation(ShellControl parent) throws Exception;
}

View File

@@ -1,5 +1,6 @@
package io.xpipe.app.pwman;
import io.xpipe.app.cred.SshIdentityAgentStrategy;
import io.xpipe.app.cred.SshIdentityStrategy;
import java.nio.file.Path;
@@ -24,7 +25,7 @@ public interface PasswordManagerKeyConfiguration {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return strategy.getSshIdentityStrategy(publicKey, forward);
}
@@ -58,7 +59,7 @@ public interface PasswordManagerKeyConfiguration {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return null;
}
@@ -80,7 +81,7 @@ public interface PasswordManagerKeyConfiguration {
boolean supportsAgentKeyNames();
SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward);
SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward);
Path getDefaultSocketLocation();

View File

@@ -52,7 +52,7 @@ public interface PasswordManagerKeyStrategy {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return null;
}
}
@@ -112,8 +112,8 @@ public interface PasswordManagerKeyStrategy {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return new SshIdentityStrategy() {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return new SshIdentityAgentStrategy() {
@Override
public void prepareParent(ShellControl parent) throws Exception {
if (parent.isLocal()) {
@@ -121,6 +121,11 @@ public interface PasswordManagerKeyStrategy {
}
}
@Override
public FilePath determinetAgentSocketLocation(ShellControl parent) throws Exception {
return socket != null ? socket.resolveTildeHome(parent.view().userHome()) : null;
}
@Override
public void buildCommand(CommandBuilder builder) {}
@@ -170,7 +175,7 @@ public interface PasswordManagerKeyStrategy {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return OpenSshAgentStrategy.builder().build();
}
}
@@ -198,14 +203,14 @@ public interface PasswordManagerKeyStrategy {
}
@Override
public SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
public SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward) {
return PageantStrategy.builder().build();
}
}
boolean useAgent();
SshIdentityStrategy getSshIdentityStrategy(String publicKey, boolean forward);
SshIdentityAgentStrategy getSshIdentityStrategy(String publicKey, boolean forward);
static List<Class<?>> getClasses() {
var l = new ArrayList<Class<?>>();