From 87df8b9dc3f5ef4f1b6e97581406216a03ef8401 Mon Sep 17 00:00:00 2001 From: az Date: Thu, 20 Apr 2023 09:47:14 +0200 Subject: [PATCH] fix gopassBridge by gopassInitStoreFolder --- .../provs/desktop/domain/DesktopService.kt | 4 +- .../provs/desktop/infrastructure/Gopass.kt | 32 ++++++---- .../framework/ubuntu/install/base/Install.kt | 2 +- .../infrastructure/GopassBridgeKtTest.kt | 63 +++++-------------- .../desktop/infrastructure/GopassKtTest.kt | 40 +++++------- .../provs/test/TestSetup.kt | 2 +- 6 files changed, 55 insertions(+), 88 deletions(-) diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt index db4fb55..1f4cced 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt @@ -151,11 +151,13 @@ fun Prov.provisionBasicDesktop( installFirefox() installGopass() + configureGopass(publicGpgKey = gpg?.publicKey) installGopassBridgeJsonApi() downloadGopassBridge() - installRedshift() + installRedshift() configureRedshift() + configureNoSwappiness() configureBash() installVirtualBoxGuestAdditions() diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/Gopass.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/Gopass.kt index 8d2ad62..d648574 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/Gopass.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/Gopass.kt @@ -2,9 +2,11 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure import org.domaindrivenarchitecture.provs.framework.core.Prov import org.domaindrivenarchitecture.provs.framework.core.ProvResult +import org.domaindrivenarchitecture.provs.framework.core.Secret import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.* import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalled +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.gpgFingerprint import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFromURL @@ -34,29 +36,34 @@ fun Prov.installGopass( if (result.success) { cmd("sudo dpkg -i $path/gopass_${version}_linux_amd64.deb") // Cross-check if installation was successful - addResultToEval(ProvResult(checkGopassVersion(version))) + return@taskWithResult ProvResult(checkGopassVersion(version)) } else { - addResultToEval(ProvResult(false, err = "Gopass could not be installed. " + result.err)) + return@taskWithResult ProvResult(false, err = "Gopass could not be installed. " + result.err) } } -fun Prov.configureGopass(gopassRootFolder: String? = null) = taskWithResult() { +fun Prov.configureGopass(gopassRootFolder: String? = null, publicGpgKey: Secret? = null) = taskWithResult { + val configFile = ".config/gopass/config.yml" - val defaultRootFolder = userHome() + ".password-store" - val rootFolder = gopassRootFolder ?: defaultRootFolder if (checkFile(configFile)) { return@taskWithResult ProvResult(true, out = "Gopass already configured in file $configFile") } if ((gopassRootFolder != null) && (!gopassRootFolder.startsWith("/"))) { - return@taskWithResult ProvResult(false, err = "Gopass cannot be initialized with a relative path or path starting with ~") + return@taskWithResult ProvResult(false, err = "Gopass cannot be initialized with a relative path or path starting with ~ ($gopassRootFolder)") } - // use default - createDir(rootFolder) + + val defaultRootFolder = userHome() + ".password-store" + val gopassRoot = gopassRootFolder ?: defaultRootFolder + + // initialize root store + val fingerprint = publicGpgKey?.let { gpgFingerprint(it.plain()) } + gopassInitStoreFolder(gopassRoot, fingerprint) + createDirs(".config/gopass") - createFile(configFile, gopassConfig(rootFolder)) + createFile(configFile, gopassConfig(gopassRoot)) // auto-completion configureBashForUser() @@ -69,9 +76,8 @@ fun Prov.gopassMountStore(storeName: String, path: String) = task { } -@Suppress("unused") -fun Prov.gopassInitStore(storeName: String, indexOfRecepientKey: Int = 0) = task { - cmd("printf \"$indexOfRecepientKey\\n\" | gopass init --store=$storeName") +fun Prov.gopassInitStoreFolder(path: String, gpgFingerprint: String? = null ) = task { + createFile("$path/.gpg-id", gpgFingerprint ?: "_replace_this_by_a_fingerprint_of_a_public_gpg_key_") } @@ -105,4 +111,4 @@ internal fun Prov.checkGopassVersion(version: String): Boolean { internal fun Prov.gopassVersion(): String? { val result = cmdNoEval("gopass -v") return if (!result.success) null else result.out -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt index a831aea..88bcbea 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt @@ -73,7 +73,7 @@ fun Prov.isPackageInstalled(packageName: String): Boolean { /** - * Removes a package including its configuration and data files + * Removes a package including its configuration and data file */ @Suppress("unused") // used externally fun Prov.aptPurge(packageName: String): Boolean { diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridgeKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridgeKtTest.kt index c467085..c553868 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridgeKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridgeKtTest.kt @@ -1,16 +1,12 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure -import org.domaindrivenarchitecture.provs.framework.core.Prov -import org.domaindrivenarchitecture.provs.framework.core.ProvResult import org.domaindrivenarchitecture.provs.framework.core.Secret import org.domaindrivenarchitecture.provs.framework.core.docker.exitAndRmContainer import org.domaindrivenarchitecture.provs.framework.core.local import org.domaindrivenarchitecture.provs.framework.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.configureGpgKeys import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest import org.domaindrivenarchitecture.provs.test.tags.NonCi import org.domaindrivenarchitecture.provs.test_keys.privateGPGSnakeoilKey @@ -27,11 +23,10 @@ internal class GopassBridgeKtTest { fun test_downloadGopassBridge() { // given local().exitAndRmContainer("provs_test") - val a = defaultTestContainer() - a.aptInstallCurl() + val prov = defaultTestContainer() // when - val res = a.downloadGopassBridge() + val res = prov.downloadGopassBridge() // then assertTrue(res.success) @@ -42,26 +37,20 @@ internal class GopassBridgeKtTest { fun test_install_and_configure_GopassBridgeJsonApi() { // given local().exitAndRmContainer("provs_test") - val a = defaultTestContainer() - val preparationResult = a.task { - aptInstallCurl() + val prov = defaultTestContainer() + val preparationResult = prov.task { configureGpgKeys( KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), trust = true, skipIfExistin = false ) installGopass() - if (!chk("gopass ls")) { - // configure/init gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } + configureGopass(publicGpgKey = Secret(publicGPGSnakeoilKey())) } assertTrue(preparationResult.success) // when - val res = a.task { + val res = prov.task { installGopassBridgeJsonApi() configureGopassBridgeJsonApi() } @@ -70,33 +59,26 @@ internal class GopassBridgeKtTest { assertTrue(res.success) } - @ContainerTest + @ExtensiveContainerTest @Test @NonCi @Disabled // long running test (> 1 min); if needed enable test and run manually fun test_install_GopassBridgeJsonApi_with_incompatible_gopass_jsonapi_version_installed() { // given - val a = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) - val preparationResult = a.task { - aptInstallCurl() - + val prov = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) + val preparationResult = prov.task { configureGpgKeys( KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), trust = true, skipIfExistin = false ) installGopass("1.11.0", enforceVersion = true, "1ec9e0dfcfd9bcc241943e1a7d92f31bf3e66bb16f61ae5d079981325c31baa6") - if (!chk("gopass ls")) { - // configure gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } + configureGopass(publicGpgKey = Secret(publicGPGSnakeoilKey())) } assertTrue(preparationResult.success) // when - val res = a.task { + val res = prov.task { installGopassBridgeJsonApi() configureGopassBridgeJsonApi() } @@ -105,32 +87,26 @@ internal class GopassBridgeKtTest { assertFalse(res.success) } - @ContainerTest + @ExtensiveContainerTest @Test @NonCi - @Disabled // long running test (> 1 min); if needed enable test and run manually + @Disabled // long running test (> 1 min); if needed, enable test and run manually fun test_install_GopassBridgeJsonApi_with_incompatible_gopass_version_installed() { // given - val a = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) - val preparationResult = a.task { - aptInstallCurl() + val prov = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) + val preparationResult = prov.task { configureGpgKeys( KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), trust = true, skipIfExistin = false ) installGopass("1.9.0", enforceVersion = true, "fe13ef810d7fe200495107161e99eac081368aa0ce5e53971b1bd47a64eba4db") - if (!chk("gopass ls")) { - // configure gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } + configureGopass(publicGpgKey = Secret(publicGPGSnakeoilKey())) } assertTrue(preparationResult.success) // when - val res = a.task { + val res = prov.task { installGopassBridgeJsonApi() configureGopassBridgeJsonApi() } @@ -138,9 +114,4 @@ internal class GopassBridgeKtTest { // then assertFalse(res.success) } - - private fun Prov.aptInstallCurl() = task { - cmd("apt-get update", sudo = true) - aptInstall("curl") - } } diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassKtTest.kt index 98b0927..482fbec 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassKtTest.kt @@ -1,10 +1,8 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure -import org.domaindrivenarchitecture.provs.framework.core.Secret import org.domaindrivenarchitecture.provs.framework.core.remote import org.domaindrivenarchitecture.provs.test.defaultTestContainer import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.configureGpgKeys import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.gpgFingerprint @@ -12,8 +10,6 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.secret.secretSources. import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.test_keys.privateGPGSnakeoilKey -import org.domaindrivenarchitecture.provs.test_keys.publicGPGSnakeoilKey import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.* import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest import org.junit.jupiter.api.Assertions.assertFalse @@ -36,32 +32,23 @@ internal class GopassKtTest { @ExtensiveContainerTest fun test_installAndConfigureGopassAndMountStore() { // given - val a = defaultTestContainer() + val prov = defaultTestContainer() val gopassRootDir = ".password-store" - a.aptInstall("wget git gnupg") - a.createDir(gopassRootDir, "~/") - a.cmd("git init", "~/$gopassRootDir") - val fpr = a.gpgFingerprint(publicGPGSnakeoilKey()) - println("+++++++++++++++++++++++++++++++++++++ $fpr +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") - a.createFile("~/" + gopassRootDir + "/.gpg-id", fpr) - - a.createDir("exampleStoreFolder", "~/") - a.createFile("~/exampleStoreFolder/.gpg-id", fpr) - - a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), true) // when - val res = a.installGopass() - val res2 = a.configureGopass(a.userHome() + gopassRootDir) - val res3 = a.gopassMountStore("exampleStore", "~/exampleStoreFolder") + val res = prov.task("test_installAndConfigureGopassAndMountStore") { + installGopass() + configureGopass(prov.userHome() + gopassRootDir) + gopassInitStoreFolder("~/exampleStoreFolder") + gopassMountStore("exampleStore", "~/exampleStoreFolder") + prov.cmd("gopass ls") + } // then - a.fileContent("~/.config/gopass/config.yml") // displays the content in the logs + prov.fileContent("~/.config/gopass/config.yml") // displays the content in the logs assertTrue(res.success) - assertTrue(res2.success) - assertTrue(res3.success) - assertTrue(a.fileContainsText("~/.config/gopass/config.yml", "/home/testuser/.password-store")) - assertTrue(a.fileContainsText("~/.config/gopass/config.yml", "exampleStore")) + assertTrue(prov.fileContainsText("~/.config/gopass/config.yml", "/home/testuser/.password-store")) + assertTrue(prov.fileContainsText("~/.config/gopass/config.yml", "exampleStore")) } @Test @@ -74,10 +61,10 @@ internal class GopassKtTest { val privateKey = GopassSecretSource("path-to/priv.key").secret() // given - val a = remote(host, user) + val prov = remote(host, user) // when - val res = a.task { + val res = prov.task { configureGpgKeys( KeyPair( pubKey, @@ -101,3 +88,4 @@ internal class GopassKtTest { assertTrue(res.success) } } + diff --git a/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt b/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt index e7427b8..3e9468f 100644 --- a/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt +++ b/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt @@ -16,7 +16,7 @@ const val defaultTestContainerName = "provs_test" private lateinit var prov: Prov fun defaultTestContainer(startMode: ContainerStartMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE): Prov { - if (!::prov.isInitialized || !testLocal().containerRuns(defaultTestContainerName)) { prov = initDefaultTestContainer(startMode) } + if (!::prov.isInitialized || !testLocal().containerRuns(defaultTestContainerName) || (startMode == ContainerStartMode.CREATE_NEW_KILL_EXISTING)) { prov = initDefaultTestContainer(startMode) } return prov }