From a4bb1d228cab7534894dc8434d1be255bf32894c Mon Sep 17 00:00:00 2001 From: az Date: Sat, 10 Sep 2022 16:41:36 +0200 Subject: [PATCH] add recognition of ssh key type to determine ssh file names --- .../provs/desktop/domain/DesktopConfig.kt | 3 +- .../provs/desktop/domain/DesktopService.kt | 5 +-- .../framework/ubuntu/keys/ProvisionKeys.kt | 10 +++++- .../provs/framework/ubuntu/keys/base/Ssh.kt | 11 +++--- .../provs/framework/ubuntu/user/UserConfig.kt | 7 +++- .../ubuntu/keys/ProvisionKeysTest.kt | 2 +- .../provs/framework/ubuntu/keys/TestKeys.kt | 17 +++++++-- .../framework/ubuntu/keys/base/SshKtTest.kt | 35 +++++++++++++++---- .../ubuntu/user/ProvisionUserKtTest.kt | 2 +- 9 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopConfig.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopConfig.kt index 9a7347d..5d93bd5 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopConfig.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopConfig.kt @@ -2,11 +2,12 @@ package org.domaindrivenarchitecture.provs.desktop.domain import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPairSource import kotlinx.serialization.Serializable +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.SshKeyPairSource @Serializable data class DesktopConfig( - val ssh: KeyPairSource? = null, + val ssh: SshKeyPairSource? = null, val gpg: KeyPairSource? = null, val gitUserName: String? = null, val gitEmail: String? = null, 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 680025c..79939be 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt @@ -7,6 +7,7 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.git.provisionGit import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptPurge import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.SshKeyPair import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.gpgFingerprint import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.provisionKeys import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.currentUserCanSudo @@ -31,7 +32,7 @@ internal fun provisionDesktopCmd(prov: Prov, cmd: DesktopCliCommand) { */ internal fun Prov.provisionDesktop( desktopType: DesktopType = DesktopType.BASIC, - ssh: KeyPair? = null, + ssh: SshKeyPair? = null, gpg: KeyPair? = null, gitUserName: String? = null, gitEmail: String? = null, @@ -115,7 +116,7 @@ fun Prov.provisionOfficeDesktop(onlyModules: List?) { fun Prov.provisionBasicDesktop( gpg: KeyPair?, - ssh: KeyPair?, + ssh: SshKeyPair?, gitUserName: String?, gitEmail: String?, onlyModules: List? diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeys.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeys.kt index 876e69f..7e9f98c 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeys.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeys.kt @@ -21,11 +21,19 @@ class KeyPairSource(val sourceType: SecretSourceType, val publicKey: String, val } } +@Serializable +class SshKeyPairSource(val sourceType: SecretSourceType, val publicKey: String, val privateKey: String) { + fun keyPair() : SshKeyPair { + val pub = sourceType.secret(publicKey) + val priv = sourceType.secret(privateKey) + return SshKeyPair(pub, priv) + } +} /** * provisions gpg and/or ssh keys for the current user */ -fun Prov.provisionKeys(gpgKeys: KeyPair? = null, sshKeys: KeyPair? = null) = task { +fun Prov.provisionKeys(gpgKeys: KeyPair? = null, sshKeys: SshKeyPair? = null) = task { gpgKeys?.let { configureGpgKeys(it, true) } sshKeys?.let { configureSshKeys(it) } ProvResult(true) // dummy diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/Ssh.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/Ssh.kt index b506d64..4eb39ea 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/Ssh.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/Ssh.kt @@ -7,19 +7,18 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.check import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDir import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createSecretFile -import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.SshKeyPair const val KNOWN_HOSTS_FILE = "~/.ssh/known_hosts" - /** - * installs ssh keys for active user + * Installs ssh keys for active user; ssh filenames depend on the ssh key type, e.g. for public key file: "id_rsa.pub", "id_id_ed25519.pub", etc */ -fun Prov.configureSshKeys(sshKeys: KeyPair) = task { +fun Prov.configureSshKeys(sshKeys: SshKeyPair) = task { createDir(".ssh", "~/") - createSecretFile("~/.ssh/id_rsa.pub", sshKeys.publicKey, "644") - createSecretFile("~/.ssh/id_rsa", sshKeys.privateKey, "600") + createSecretFile("~/.ssh/id_${sshKeys.sshAlgorithmName}.pub", sshKeys.publicKey, "644") + createSecretFile("~/.ssh/id_${sshKeys.sshAlgorithmName}", sshKeys.privateKey, "600") } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/UserConfig.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/UserConfig.kt index e841ca6..75d5b2a 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/UserConfig.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/UserConfig.kt @@ -2,7 +2,12 @@ package org.domaindrivenarchitecture.provs.framework.ubuntu.user import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPairSource import kotlinx.serialization.Serializable +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.SshKeyPairSource @Serializable -class UserConfig(val userName: String, val gitEmail: String? = null, val gpg: KeyPairSource? = null, val ssh: KeyPairSource? = null) +class UserConfig( + val userName: String, + val gitEmail: String? = null, + val gpg: KeyPairSource? = null, + val ssh: SshKeyPairSource? = null) diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeysTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeysTest.kt index 612b0f5..425f2ee 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeysTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/ProvisionKeysTest.kt @@ -17,7 +17,7 @@ internal class ProvisionKeysTest { // when val res = a.provisionKeys( KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), - KeyPair(Secret(publicSSHSnakeoilKey()), Secret(privateSSHSnakeoilKey())) + SshKeyPair(Secret(publicSSHRSASnakeoilKey()), Secret(privateSSHRSASnakeoilKey())) ) // then diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/TestKeys.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/TestKeys.kt index bdd2d7e..7f0a8f1 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/TestKeys.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/TestKeys.kt @@ -129,11 +129,11 @@ i+XV3Dazj3nq/DxUB0neLU/r1afAEiqZAkI= -----END PGP PRIVATE KEY BLOCK-----""".trimIndent() } -fun publicSSHSnakeoilKey(): String { +fun publicSSHRSASnakeoilKey(): String { return """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOtQOq8a/Z7SdZVPrh+Icaq5rr+Qg1TZP4IPuRoFgfujUztQ2dy5DfTEbabJ0qHyo+PKwBDQorVohrW7CwvCEVQQh2NLuGgnukBN2ut5Lam7a/fZBoMjAyTvD4bXyEsUr/Bl5CLoBDkKM0elUxsc19ndzSofnDWeGyQjJIWlkNkVk/ybErAnIHVE+D+g3UxwA+emd7BF72RPqdVN39Eu4ntnxYzX0eepc8rkpFolVn6+Ai4CYHE4FaJ7bJ9WGPbwLuDl0pw/Cp3ps17cB+JlQfJ2spOq0tTVk+GcdGnt+mq0WaOnvVeQsGJ2O1HpY3VqQd1AsC2UOyHhAQ00pw7Pi9 snake@oil.com""" } -fun privateSSHSnakeoilKey(): String { +fun privateSSHRSASnakeoilKey(): String { return """ -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAzrUDqvGv2e0nWVT64fiHGqua6/kINU2T+CD7kaBYH7o1M7UN @@ -163,4 +163,17 @@ fun privateSSHSnakeoilKey(): String { OUxwE8Su4WnoQc7WjkTG0M3FECAu7TEcF9uqdcEsW+4+JMAhE5oo -----END RSA PRIVATE KEY----- """.trimIndent() +} + +fun publicED25519SnakeOilKey(): String { + return """ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGL6JP3FhUZrVIfA9EzcJdlXwq3MHG6+QEFDFeNCxmOE snake@oil.com""" +} +fun privateED25519SnakeOilKey(): String { + return """-----BEGIN OPENSSH PRIVATE KEY----- + b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW + QyNTUxOQAAACBi+iT9xYVGa1SHwPRM3CXZV8KtzBxuvkBBQxXjQsZjhAAAAJBoEaYdaBGm + HQAAAAtzc2gtZWQyNTUxOQAAACBi+iT9xYVGa1SHwPRM3CXZV8KtzBxuvkBBQxXjQsZjhA + AAAEB6dfLASdiUR6KzQVydw16iXN1ImqoLoe+I24G4K386J2L6JP3FhUZrVIfA9EzcJdlX + wq3MHG6+QEFDFeNCxmOEAAAACmVyaWtAbUtJREUBAgM= + -----END OPENSSH PRIVATE KEY-----""".trimIndent() } \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/SshKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/SshKtTest.kt index d1b4f57..8d5e999 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/SshKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/keys/base/SshKtTest.kt @@ -1,25 +1,48 @@ package org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base import org.domaindrivenarchitecture.provs.framework.core.Secret -import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.privateSSHSnakeoilKey -import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.publicSSHSnakeoilKey +import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.fileContent +import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.* import org.domaindrivenarchitecture.provs.test.defaultTestContainer import org.domaindrivenarchitecture.provs.test.tags.ContainerTest +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue internal class SshKtTest { @ContainerTest - fun configureSshKeys() { + fun configureSshKeys_for_ssh_type_rsa() { // given - val a = defaultTestContainer() + val prov = defaultTestContainer() // when - val res = a.configureSshKeys(KeyPair(Secret(publicSSHSnakeoilKey()), Secret(privateSSHSnakeoilKey()))) + val res = prov.configureSshKeys(SshKeyPair(Secret(publicSSHRSASnakeoilKey()), Secret(privateSSHRSASnakeoilKey()))) // then assertTrue(res.success) + val publicSshKeyFileContent = prov.fileContent("~/.ssh/id_rsa.pub") + assertEquals(publicSSHRSASnakeoilKey() + "\n", publicSshKeyFileContent) + + val privateSshKeyFileContent = prov.fileContent("~/.ssh/id_rsa") + assertEquals(privateSSHRSASnakeoilKey() + "\n", privateSshKeyFileContent) + } + + @ContainerTest + fun configureSshKeys_for_ssh_type_ed25519() { + // given + val prov = defaultTestContainer() + + // when + val res = prov.configureSshKeys(SshKeyPair(Secret(publicED25519SnakeOilKey()), Secret(privateED25519SnakeOilKey()))) + + // then + assertTrue(res.success) + + val publicSshKeyFileContent = prov.fileContent("~/.ssh/id_ed25519.pub") + assertEquals(publicED25519SnakeOilKey() + "\n", publicSshKeyFileContent) + + val privateSshKeyFileContent = prov.fileContent("~/.ssh/id_ed25519") + assertEquals(privateED25519SnakeOilKey() + "\n", privateSshKeyFileContent) } } \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/ProvisionUserKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/ProvisionUserKtTest.kt index e77f260..6202749 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/ProvisionUserKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/user/ProvisionUserKtTest.kt @@ -29,7 +29,7 @@ internal class ProvisionUserKtTest { "testuser", "test@mail.com", KeyPairSource(SecretSourceType.PLAIN, publicGPGSnakeoilKey(), privateGPGSnakeoilKey()), - KeyPairSource(SecretSourceType.PLAIN, publicSSHSnakeoilKey(), privateSSHSnakeoilKey()) + SshKeyPairSource(SecretSourceType.PLAIN, publicSSHRSASnakeoilKey(), privateSSHRSASnakeoilKey()) ) )