mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-04-23 16:09:20 -04:00
Rework encryption
This commit is contained in:
@@ -2,6 +2,7 @@ package io.xpipe.ext.base.identity;
|
||||
|
||||
import io.xpipe.app.ext.ShellStore;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategyHelper;
|
||||
|
||||
@@ -58,10 +59,10 @@ public class IdentityChoice {
|
||||
var options = new OptionsBuilder()
|
||||
.nameAndDescription(userChoiceTranslationKey)
|
||||
.addComp(new IdentitySelectComp(ref, user, pass, identityStrategy, allowCustomUserInput), user)
|
||||
.nonNullIf(inPlaceSelected.and(new SimpleBooleanProperty(requireUserInput)))
|
||||
.nonNullIf(inPlaceSelected)
|
||||
.nameAndDescription(passwordChoiceTranslationKey)
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true, true), pass)
|
||||
.nonNullIf(inPlaceSelected.and(new SimpleBooleanProperty(requirePassword)))
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true), pass)
|
||||
.nonNullIf(inPlaceSelected)
|
||||
.disable(refSelected)
|
||||
.hide(refSelected)
|
||||
.name("keyAuthentication")
|
||||
@@ -72,8 +73,7 @@ public class IdentityChoice {
|
||||
gateway != null ? gateway : new SimpleObjectProperty<>(),
|
||||
identityStrategy,
|
||||
null,
|
||||
false,
|
||||
true),
|
||||
false),
|
||||
identityStrategy)
|
||||
.nonNullIf(inPlaceSelected.and(new SimpleBooleanProperty(keyInput)))
|
||||
.disable(refSelected)
|
||||
@@ -89,8 +89,8 @@ public class IdentityChoice {
|
||||
return IdentityValue.InPlace.builder()
|
||||
.identityStore(LocalIdentityStore.builder()
|
||||
.username(user.get())
|
||||
.password(pass.get())
|
||||
.sshIdentity(identityStrategy.get())
|
||||
.password(EncryptedValue.CurrentKey.of(pass.get()))
|
||||
.sshIdentity(EncryptedValue.CurrentKey.of(identityStrategy.get()))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -71,8 +71,6 @@ public class IdentityMigrationDeserializer extends DelegatingDeserializer {
|
||||
identityStore.put("type", "localIdentity");
|
||||
if (user != null && user.isTextual()) {
|
||||
identityStore.set("username", user);
|
||||
} else {
|
||||
int a = 0;
|
||||
}
|
||||
identityStore.set("password", password);
|
||||
identityStore.set("sshIdentity", identity);
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.PlatformThread;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategy;
|
||||
|
||||
@@ -63,13 +64,13 @@ public class IdentitySelectComp extends Comp<CompStructure<HBox>> {
|
||||
var id = canSync
|
||||
? SyncedIdentityStore.builder()
|
||||
.username(inPlaceUser.getValue())
|
||||
.password(password.getValue())
|
||||
.sshIdentity(identityStrategy.getValue())
|
||||
.password(EncryptedValue.VaultKey.of(password.getValue()))
|
||||
.sshIdentity(EncryptedValue.VaultKey.of(identityStrategy.getValue()))
|
||||
.build()
|
||||
: LocalIdentityStore.builder()
|
||||
.username(inPlaceUser.getValue())
|
||||
.password(password.getValue())
|
||||
.sshIdentity(identityStrategy.getValue())
|
||||
.password(EncryptedValue.CurrentKey.of(password.getValue()))
|
||||
.sshIdentity(EncryptedValue.CurrentKey.of(identityStrategy.getValue()))
|
||||
.build();
|
||||
StoreCreationComp.showCreation(
|
||||
id,
|
||||
|
||||
@@ -16,16 +16,16 @@ import lombok.experimental.SuperBuilder;
|
||||
public abstract class IdentityStore implements SelfReferentialStore, DataStore {
|
||||
|
||||
String username;
|
||||
SecretRetrievalStrategy password;
|
||||
SshIdentityStrategy sshIdentity;
|
||||
|
||||
public abstract SecretRetrievalStrategy getPassword();
|
||||
|
||||
public abstract SshIdentityStrategy getSshIdentity();
|
||||
|
||||
@Override
|
||||
public void checkComplete() throws Throwable {
|
||||
if (password != null) {
|
||||
password.checkComplete();
|
||||
}
|
||||
if (sshIdentity != null) {
|
||||
sshIdentity.checkComplete();
|
||||
}
|
||||
Validators.nonNull(getPassword());
|
||||
Validators.nonNull(getSshIdentity());
|
||||
getPassword().checkComplete();
|
||||
getSshIdentity().checkComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface IdentityValue {
|
||||
return new InPlace(identityStore);
|
||||
}
|
||||
|
||||
void checkComplete(boolean requireUser, boolean requirePassword, boolean requireKey) throws Throwable;
|
||||
void checkComplete(boolean requireUser) throws Throwable;
|
||||
|
||||
IdentityStore unwrap();
|
||||
|
||||
@@ -36,24 +36,12 @@ public interface IdentityValue {
|
||||
LocalIdentityStore identityStore;
|
||||
|
||||
@Override
|
||||
public void checkComplete(boolean requireUser, boolean requirePassword, boolean requireKey) throws Throwable {
|
||||
public void checkComplete(boolean requireUser) throws Throwable {
|
||||
Validators.nonNull(identityStore);
|
||||
identityStore.checkComplete();
|
||||
if (requireUser) {
|
||||
Validators.nonNull(identityStore.getUsername());
|
||||
}
|
||||
if (requirePassword) {
|
||||
Validators.nonNull(identityStore.getPassword());
|
||||
}
|
||||
if (identityStore.getPassword() != null) {
|
||||
identityStore.getPassword().checkComplete();
|
||||
}
|
||||
if (requireKey) {
|
||||
Validators.nonNull(identityStore.getSshIdentity());
|
||||
}
|
||||
if (identityStore.getSshIdentity() != null) {
|
||||
identityStore.getSshIdentity().checkComplete();
|
||||
}
|
||||
identityStore.checkComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,25 +64,13 @@ public interface IdentityValue {
|
||||
DataStoreEntryRef<IdentityStore> ref;
|
||||
|
||||
@Override
|
||||
public void checkComplete(boolean requireUser, boolean requirePassword, boolean requireKey) throws Throwable {
|
||||
public void checkComplete(boolean requireUser) throws Throwable {
|
||||
Validators.nonNull(ref);
|
||||
Validators.isType(ref, IdentityStore.class);
|
||||
ref.getStore().checkComplete();
|
||||
if (requireUser) {
|
||||
Validators.nonNull(ref.getStore().getUsername());
|
||||
}
|
||||
if (requirePassword) {
|
||||
Validators.nonNull(ref.getStore().getPassword());
|
||||
}
|
||||
if (ref.getStore().getPassword() != null) {
|
||||
ref.getStore().getPassword().checkComplete();
|
||||
}
|
||||
if (requireKey) {
|
||||
Validators.nonNull(ref.getStore().getSshIdentity());
|
||||
}
|
||||
if (ref.getStore().getSshIdentity() != null) {
|
||||
ref.getStore().getSshIdentity().checkComplete();
|
||||
}
|
||||
ref.getStore().checkComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.xpipe.app.ext.DataStoreCreationCategory;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import lombok.Value;
|
||||
@@ -58,8 +59,9 @@ public class LocalIdentityConvertAction implements ActionProvider {
|
||||
var st = ref.getStore();
|
||||
var synced = SyncedIdentityStore.builder()
|
||||
.username(st.getUsername())
|
||||
.password(st.getPassword())
|
||||
.sshIdentity(st.getSshIdentity())
|
||||
.password(EncryptedValue.VaultKey.of(st.getPassword()))
|
||||
.sshIdentity(EncryptedValue.VaultKey.of(st.getSshIdentity()))
|
||||
.perUser(false)
|
||||
.build();
|
||||
StoreCreationComp.showCreation(synced, DataStoreCreationCategory.IDENTITY, dataStoreEntry -> {}, true);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package io.xpipe.ext.base.identity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategy;
|
||||
import io.xpipe.app.util.Validators;
|
||||
import io.xpipe.core.util.ValidationException;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import lombok.Value;
|
||||
@@ -13,4 +17,18 @@ import lombok.extern.jackson.Jacksonized;
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class LocalIdentityStore extends IdentityStore {}
|
||||
public class LocalIdentityStore extends IdentityStore {
|
||||
|
||||
EncryptedValue.CurrentKey<SecretRetrievalStrategy> password;
|
||||
EncryptedValue.CurrentKey<SshIdentityStrategy> sshIdentity;
|
||||
|
||||
@Override
|
||||
public SecretRetrievalStrategy getPassword() {
|
||||
return password != null ? password.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshIdentityStrategy getSshIdentity() {
|
||||
return sshIdentity != null ? sshIdentity.getValue() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.xpipe.app.comp.store.StoreEntryWrapper;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.GuiDialog;
|
||||
import io.xpipe.app.storage.*;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategyHelper;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
@@ -39,19 +40,19 @@ public class LocalIdentityStoreProvider extends IdentityStoreProvider {
|
||||
.addString(user)
|
||||
.name("passwordAuthentication")
|
||||
.description("passwordAuthenticationDescription")
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true, true), pass)
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true), pass)
|
||||
.name("keyAuthentication")
|
||||
.description("keyAuthenticationDescription")
|
||||
.longDescription("base:sshKey")
|
||||
.sub(
|
||||
SshIdentityStrategyHelper.identity(new SimpleObjectProperty<>(), identity, null, false, true),
|
||||
SshIdentityStrategyHelper.identity(new SimpleObjectProperty<>(), identity, null, false),
|
||||
identity)
|
||||
.bind(
|
||||
() -> {
|
||||
return LocalIdentityStore.builder()
|
||||
.username(user.get())
|
||||
.password(pass.get())
|
||||
.sshIdentity(identity.get())
|
||||
.password(EncryptedValue.CurrentKey.of(pass.get()))
|
||||
.sshIdentity(EncryptedValue.CurrentKey.of(identity.get()))
|
||||
.build();
|
||||
},
|
||||
store)
|
||||
|
||||
@@ -49,8 +49,7 @@ public class SshIdentityStrategyHelper {
|
||||
Property<DataStoreEntryRef<ShellStore>> proxy,
|
||||
Property<SshIdentityStrategy.File> fileProperty,
|
||||
Predicate<Path> perUserFile,
|
||||
boolean allowSync,
|
||||
boolean allowUserSecretKey) {
|
||||
boolean allowSync) {
|
||||
var keyPath = new SimpleStringProperty(
|
||||
fileProperty.getValue() != null && fileProperty.getValue().getFile() != null
|
||||
? fileProperty.getValue().getFile().toAbsoluteFilePath(null)
|
||||
@@ -77,7 +76,7 @@ public class SshIdentityStrategyHelper {
|
||||
.name("keyPassword")
|
||||
.description("sshConfigHost.identityPassphraseDescription")
|
||||
.sub(
|
||||
SecretRetrievalStrategyHelper.comp(keyPasswordProperty, true, allowUserSecretKey),
|
||||
SecretRetrievalStrategyHelper.comp(keyPasswordProperty, true),
|
||||
keyPasswordProperty)
|
||||
.nonNull()
|
||||
.bind(
|
||||
@@ -92,8 +91,7 @@ public class SshIdentityStrategyHelper {
|
||||
Property<DataStoreEntryRef<ShellStore>> proxy,
|
||||
Property<SshIdentityStrategy> strategyProperty,
|
||||
Predicate<Path> perUserFile,
|
||||
boolean allowSync,
|
||||
boolean allowUserSecretKey) {
|
||||
boolean allowSync) {
|
||||
SshIdentityStrategy strat = strategyProperty.getValue();
|
||||
var file = new SimpleObjectProperty<>(
|
||||
strat instanceof SshIdentityStrategy.File f
|
||||
@@ -110,7 +108,7 @@ public class SshIdentityStrategyHelper {
|
||||
map.put(AppI18n.observable("base.none"), new OptionsBuilder());
|
||||
map.put(
|
||||
AppI18n.observable("base.keyFile"),
|
||||
fileIdentity(proxy, file, perUserFile, allowSync, allowUserSecretKey));
|
||||
fileIdentity(proxy, file, perUserFile, allowSync));
|
||||
map.put(AppI18n.observable("base.sshAgent"), agent(agent));
|
||||
map.put(AppI18n.observable("base.pageant"), new OptionsBuilder());
|
||||
map.put(gpgFeature.suffixObservable("base.gpgAgent"), new OptionsBuilder());
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package io.xpipe.ext.base.identity;
|
||||
|
||||
import io.xpipe.app.ext.UserScopeStore;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategy;
|
||||
import io.xpipe.app.util.Validators;
|
||||
import io.xpipe.core.util.ValidationException;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
@@ -18,8 +21,20 @@ import lombok.extern.jackson.Jacksonized;
|
||||
@ToString(callSuper = true)
|
||||
public class SyncedIdentityStore extends IdentityStore implements UserScopeStore {
|
||||
|
||||
EncryptedValue<SecretRetrievalStrategy> password;
|
||||
EncryptedValue<SshIdentityStrategy> sshIdentity;
|
||||
boolean perUser;
|
||||
|
||||
@Override
|
||||
public SecretRetrievalStrategy getPassword() {
|
||||
return password != null ? password.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshIdentityStrategy getSshIdentity() {
|
||||
return sshIdentity != null ? sshIdentity.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkComplete() throws Throwable {
|
||||
super.checkComplete();
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.DataStoreCreationCategory;
|
||||
import io.xpipe.app.ext.GuiDialog;
|
||||
import io.xpipe.app.storage.*;
|
||||
import io.xpipe.app.util.EncryptedValue;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.SecretRetrievalStrategyHelper;
|
||||
import io.xpipe.app.util.Validator;
|
||||
@@ -59,13 +60,13 @@ public class SyncedIdentityStoreProvider extends IdentityStoreProvider {
|
||||
.addString(user)
|
||||
.name("passwordAuthentication")
|
||||
.description("passwordAuthenticationDescription")
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true, true), pass)
|
||||
.sub(SecretRetrievalStrategyHelper.comp(pass, true), pass)
|
||||
.name("keyAuthentication")
|
||||
.description("keyAuthenticationDescription")
|
||||
.longDescription("base:sshKey")
|
||||
.sub(
|
||||
SshIdentityStrategyHelper.identity(
|
||||
new SimpleObjectProperty<>(), identity, path -> perUser.get(), true, true),
|
||||
new SimpleObjectProperty<>(), identity, path -> perUser.get(), true),
|
||||
identity)
|
||||
.check(val -> Validator.create(val, AppI18n.observable("keyNotSynced"), identity, i -> {
|
||||
var wrong = i instanceof SshIdentityStrategy.File f
|
||||
@@ -83,8 +84,8 @@ public class SyncedIdentityStoreProvider extends IdentityStoreProvider {
|
||||
() -> {
|
||||
return SyncedIdentityStore.builder()
|
||||
.username(user.get())
|
||||
.password(pass.get())
|
||||
.sshIdentity(identity.get())
|
||||
.password(perUser.get() ? EncryptedValue.CurrentKey.of(pass.get()) : EncryptedValue.VaultKey.of(pass.get()))
|
||||
.sshIdentity(perUser.get() ? EncryptedValue.CurrentKey.of(identity.get()) : EncryptedValue.VaultKey.of(identity.get()))
|
||||
.perUser(perUser.get())
|
||||
.build();
|
||||
},
|
||||
|
||||
@@ -54,7 +54,7 @@ public class IncusContainerStore
|
||||
install.checkComplete();
|
||||
Validators.nonNull(containerName);
|
||||
if (identity != null) {
|
||||
identity.checkComplete(false, false, false);
|
||||
identity.checkComplete(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class LxdContainerStore
|
||||
cmd.checkComplete();
|
||||
Validators.nonNull(containerName);
|
||||
if (identity != null) {
|
||||
identity.checkComplete(false, false, false);
|
||||
identity.checkComplete(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user