From 2a7fbd57ccce6a309aebc13b076eaee096987a86 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 26 Aug 2015 13:43:02 +0200 Subject: [PATCH] Allow the machines file to specify host public keys It's easier for the Hydra provisioner to put host public keys in the machines file than to separately manage the known_hosts file (especially when the provisioner runs on a different machine). --- configure.ac | 2 +- src/hydra-queue-runner/build-remote.cc | 22 +++++++++++++------- src/hydra-queue-runner/hydra-queue-runner.cc | 6 ++++-- src/hydra-queue-runner/state.hh | 1 + 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 971b502d..3051dd6e 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,7 @@ AC_PROG_LN_S AC_PROG_LIBTOOL AC_PROG_CXX -CXXFLAGS+=" -std=c++0x" +CXXFLAGS+=" -std=c++11" dnl Optional dependencies to build the manual, normally not needed dnl since the tarball comes with the PDF and HTML manuals. diff --git a/src/hydra-queue-runner/build-remote.cc b/src/hydra-queue-runner/build-remote.cc index 92a6fb28..1f3ccd5f 100644 --- a/src/hydra-queue-runner/build-remote.cc +++ b/src/hydra-queue-runner/build-remote.cc @@ -26,8 +26,7 @@ static void append(Strings & dst, const Strings & src) } -static void openConnection(const string & sshName, const string & sshKey, - int stderrFD, Child & child) +static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Child & child) { Pipe to, from; to.create(); @@ -45,11 +44,18 @@ static void openConnection(const string & sshName, const string & sshKey, throw SysError("cannot dup stderr"); Strings argv; - if (sshName == "localhost") + if (machine->sshName == "localhost") argv = {"nix-store", "--serve", "--write"}; else { - argv = {"ssh", sshName}; - if (sshKey != "" && sshKey != "-") append(argv, {"-i", sshKey}); + argv = {"ssh", machine->sshName}; + if (machine->sshKey != "") append(argv, {"-i", machine->sshKey}); + if (machine->sshPublicHostKey != "") { + Path fileName = tmpDir + "/host-key"; + auto p = machine->sshName.find("@"); + string host = p != string::npos ? string(machine->sshName, p + 1) : machine->sshName; + writeFile(fileName, host + " " + machine->sshPublicHostKey + "\n"); + append(argv, {"-oUserKnownHostsFile=" + fileName}); + } append(argv, { "-x", "-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes" , "--", "nix-store", "--serve", "--write" }); @@ -136,8 +142,11 @@ void State::buildRemote(std::shared_ptr store, AutoCloseFD logFD(open(result.logFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666)); if (logFD == -1) throw SysError(format("creating log file ‘%1%’") % result.logFile); + nix::Path tmpDir = createTempDir(); + AutoDelete tmpDirDel(tmpDir, true); + Child child; - openConnection(machine->sshName, machine->sshKey, logFD, child); + openConnection(machine, tmpDir, logFD, child); logFD.close(); @@ -277,5 +286,4 @@ void State::buildRemote(std::shared_ptr store, /* Shut down the connection. */ child.to.close(); child.pid.wait(true); - } diff --git a/src/hydra-queue-runner/hydra-queue-runner.cc b/src/hydra-queue-runner/hydra-queue-runner.cc index dc363077..553c80de 100644 --- a/src/hydra-queue-runner/hydra-queue-runner.cc +++ b/src/hydra-queue-runner/hydra-queue-runner.cc @@ -40,12 +40,12 @@ void State::parseMachines(const std::string & contents) line = trim(string(line, 0, line.find('#'))); auto tokens = tokenizeString>(line); if (tokens.size() < 3) continue; - tokens.resize(7); + tokens.resize(8); auto machine = std::make_shared(); machine->sshName = tokens[0]; machine->systemTypes = tokenizeString(tokens[1], ","); - machine->sshKey = tokens[2]; + machine->sshKey = tokens[2] == "-" ? string("") : tokens[2]; if (tokens[3] != "") string2Int(tokens[3], machine->maxJobs); else @@ -57,6 +57,8 @@ void State::parseMachines(const std::string & contents) machine->mandatoryFeatures = tokenizeString(tokens[6], ","); for (auto & f : machine->mandatoryFeatures) machine->supportedFeatures.insert(f); + if (tokens[7] != "" && tokens[7] != "-") + machine->sshPublicHostKey = base64Decode(tokens[7]); /* Re-use the State object of the previous machine with the same name. */ diff --git a/src/hydra-queue-runner/state.hh b/src/hydra-queue-runner/state.hh index e5f50e36..5e1bcd0b 100644 --- a/src/hydra-queue-runner/state.hh +++ b/src/hydra-queue-runner/state.hh @@ -205,6 +205,7 @@ struct Machine std::set systemTypes, supportedFeatures, mandatoryFeatures; unsigned int maxJobs = 1; float speedFactor = 1.0; + std::string sshPublicHostKey; struct State { typedef std::shared_ptr ptr;