move ssh function as trustHost to correct file

This commit is contained in:
ansgarz 2022-03-18 22:39:52 +01:00
parent 2cd5ae5c7c
commit 10e5bf933e
2 changed files with 71 additions and 80 deletions

View file

@ -2,13 +2,11 @@ package org.domaindrivenarchitecture.provs.framework.ubuntu.git.base
import org.domaindrivenarchitecture.provs.framework.core.Prov import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.core.ProvResult import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.isHostKnown
import org.domaindrivenarchitecture.provs.framework.core.echoCommandForText
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.* import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.KNOWN_HOSTS_FILE
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.trustHost
import java.io.File import java.io.File
val knownHostsFile = "~/.ssh/known_hosts"
fun Prov.gitClone(repo: String, path: String, pullIfExisting: Boolean = true): ProvResult = task { fun Prov.gitClone(repo: String, path: String, pullIfExisting: Boolean = true): ProvResult = task {
val dir = cmdNoEval("basename $repo .git").out?.trim() val dir = cmdNoEval("basename $repo .git").out?.trim()
@ -49,68 +47,6 @@ fun Prov.trustGitlab() = task {
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
""".trimIndent() """.trimIndent()
addTextToFile("\n" + gitlabFingerprints + "\n", File(knownHostsFile)) addTextToFile("\n" + gitlabFingerprints + "\n", File(KNOWN_HOSTS_FILE))
} }
/**
* Adds ssh keys for specified host (which also can be an ip-address) to ssh-file "known_hosts"
* Either add the specified rsaFingerprints or - if null - add automatically retrieved keys.
* Note: adding keys automatically is vulnerable to a man-in-the-middle attack and not considered secure.
*/
// todo: consider making function public and moving to ssh package
private fun Prov.trustHost(host: String, fingerprintsOfKeysToBeAdded: Set<String>?) = task {
if (isHostKnown(host)) {
return@task ProvResult(true, out = "Host already known")
}
if (!checkFile(knownHostsFile)) {
createDir(".ssh")
createFile(knownHostsFile, null)
}
if (fingerprintsOfKeysToBeAdded == null) {
// auto add keys
cmd("ssh-keyscan $host >> $knownHostsFile")
} else {
// logic based on https://serverfault.com/questions/447028/non-interactive-git-clone-ssh-fingerprint-prompt
val actualKeys = findSshKeys(host)
if (actualKeys == null || actualKeys.size == 0) {
return@task ProvResult(false, out = "No valid keys found for host: $host")
}
val actualFingerprints = getFingerprintsForKeys(actualKeys)
for (fingerprintToBeAdded in fingerprintsOfKeysToBeAdded) {
var indexOfKeyFound = -1
// search for fingerprint in actual fingerprints
for ((i, actualFingerprint) in actualFingerprints.withIndex()) {
if (actualFingerprint.contains(fingerprintToBeAdded)) {
indexOfKeyFound = i
break
}
}
if (indexOfKeyFound == -1) {
return@task ProvResult(
false,
err = "Fingerprint ($fingerprintToBeAdded) could not be found in actual fingerprints: $actualFingerprints"
)
}
cmd(echoCommandForText(actualKeys.get(indexOfKeyFound) + "\n") + " >> $knownHostsFile")
}
ProvResult(true)
}
}
/**
* Returns a list of valid ssh keys for the given host (host can also be an ip address)
*/
private fun Prov.findSshKeys(host: String): List<String>? {
return cmd("ssh-keyscan $host 2>/dev/null").out?.split("\n")?.filter { x -> "" != x }
}
/**
* Returns a list of fingerprints of the given sshKeys; the returning list has same size and order as the specified list of sshKeys
*/
private fun Prov.getFingerprintsForKeys(sshKeys: List<String>): List<String> {
return sshKeys.map { x -> cmd("echo \"$x\" | ssh-keygen -lf -").out ?: "" }
}

View file

@ -1,11 +1,18 @@
package org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base package org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base
import org.domaindrivenarchitecture.provs.framework.core.Prov import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.core.echoCommandForText
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDir 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.filesystem.base.createSecretFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair
const val KNOWN_HOSTS_FILE = "~/.ssh/known_hosts"
/** /**
* installs ssh keys for active user * installs ssh keys for active user
*/ */
@ -16,19 +23,6 @@ fun Prov.configureSshKeys(sshKeys: KeyPair) = task {
} }
/**
* Specifies a host or Ip to be trusted
*
* ATTENTION:
* This method is NOT secure as a man-in-the-middle could compromise the connection.
* Don't use this for critical systems resp. environments
*/
@Suppress("unused")
fun Prov.trustServer(hostOrIp: String) = task {
cmd("ssh-keyscan $hostOrIp >> ~/.ssh/known_hosts")
}
/** /**
* Checks if the specified hostname or Ip is in a known_hosts file * Checks if the specified hostname or Ip is in a known_hosts file
* *
@ -38,3 +32,64 @@ fun Prov.isHostKnown(hostOrIp: String) : Boolean {
return cmdNoEval("ssh-keygen -F $hostOrIp").out?.isNotEmpty() ?: false return cmdNoEval("ssh-keygen -F $hostOrIp").out?.isNotEmpty() ?: false
} }
/**
* Adds ssh keys for specified host (which also can be an ip-address) to ssh-file "known_hosts"
* Either add the specified rsaFingerprints or - if null - add automatically retrieved keys.
* Note: adding keys automatically is vulnerable to a man-in-the-middle attack, thus considered insecure and not recommended.
*/
fun Prov.trustHost(host: String, fingerprintsOfKeysToBeAdded: Set<String>?) = task {
if (isHostKnown(host)) {
return@task ProvResult(true, out = "Host already known")
}
if (!checkFile(KNOWN_HOSTS_FILE)) {
createDir(".ssh")
createFile(KNOWN_HOSTS_FILE, null)
}
if (fingerprintsOfKeysToBeAdded == null) {
// auto add keys
cmd("ssh-keyscan $host >> $KNOWN_HOSTS_FILE")
} else {
// logic based on https://serverfault.com/questions/447028/non-interactive-git-clone-ssh-fingerprint-prompt
val actualKeys = findSshKeys(host)
if (actualKeys == null || actualKeys.size == 0) {
return@task ProvResult(false, out = "No valid keys found for host: $host")
}
val actualFingerprints = getFingerprintsForKeys(actualKeys)
for (fingerprintToBeAdded in fingerprintsOfKeysToBeAdded) {
var indexOfKeyFound = -1
// search for fingerprint in actual fingerprints
for ((i, actualFingerprint) in actualFingerprints.withIndex()) {
if (actualFingerprint.contains(fingerprintToBeAdded)) {
indexOfKeyFound = i
break
}
}
if (indexOfKeyFound == -1) {
return@task ProvResult(
false,
err = "Fingerprint ($fingerprintToBeAdded) could not be found in actual fingerprints: $actualFingerprints"
)
}
cmd(echoCommandForText(actualKeys.get(indexOfKeyFound) + "\n") + " >> $KNOWN_HOSTS_FILE")
}
ProvResult(true)
}
}
/**
* Returns a list of valid ssh keys for the given host (host can also be an ip address)
*/
private fun Prov.findSshKeys(host: String): List<String>? {
return cmd("ssh-keyscan $host 2>/dev/null").out?.split("\n")?.filter { x -> "" != x }
}
/**
* Returns a list of fingerprints of the given sshKeys; the returning list has same size and order as the specified list of sshKeys
*/
private fun Prov.getFingerprintsForKeys(sshKeys: List<String>): List<String> {
return sshKeys.map { x -> cmd("echo \"$x\" | ssh-keygen -lf -").out ?: "" }
}