move ssh function as trustHost to correct file
This commit is contained in:
parent
2cd5ae5c7c
commit
10e5bf933e
2 changed files with 71 additions and 80 deletions
|
@ -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 ?: "" }
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 ?: "" }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue