forked from lix-project/lix
Merge pull request #3921 from obsidiansystems/trustless-remote-builder-simple
Trustless remote building for input-addressed drvs
This commit is contained in:
commit
b5d9ef0a4c
|
@ -258,6 +258,8 @@ static int main_build_remote(int argc, char * * argv)
|
||||||
connected:
|
connected:
|
||||||
close(5);
|
close(5);
|
||||||
|
|
||||||
|
assert(sshStore);
|
||||||
|
|
||||||
std::cerr << "# accept\n" << storeUri << "\n";
|
std::cerr << "# accept\n" << storeUri << "\n";
|
||||||
|
|
||||||
auto inputs = readStrings<PathSet>(source);
|
auto inputs = readStrings<PathSet>(source);
|
||||||
|
@ -286,23 +288,48 @@ connected:
|
||||||
uploadLock = -1;
|
uploadLock = -1;
|
||||||
|
|
||||||
auto drv = store->readDerivation(*drvPath);
|
auto drv = store->readDerivation(*drvPath);
|
||||||
|
|
||||||
|
std::optional<BuildResult> optResult;
|
||||||
|
|
||||||
|
// If we don't know whether we are trusted (e.g. `ssh://`
|
||||||
|
// stores), we assume we are. This is necessary for backwards
|
||||||
|
// compat.
|
||||||
|
bool trustedOrLegacy = ({
|
||||||
|
std::optional trusted = sshStore->isTrustedClient();
|
||||||
|
!trusted || *trusted;
|
||||||
|
});
|
||||||
|
|
||||||
|
// See the very large comment in `case wopBuildDerivation:` in
|
||||||
|
// `src/libstore/daemon.cc` that explains the trust model here.
|
||||||
|
//
|
||||||
|
// This condition mirrors that: that code enforces the "rules" outlined there;
|
||||||
|
// we do the best we can given those "rules".
|
||||||
|
if (trustedOrLegacy || drv.type().isCA()) {
|
||||||
|
// Hijack the inputs paths of the derivation to include all
|
||||||
|
// the paths that come from the `inputDrvs` set. We don’t do
|
||||||
|
// that for the derivations whose `inputDrvs` is empty
|
||||||
|
// because:
|
||||||
|
//
|
||||||
|
// 1. It’s not needed
|
||||||
|
//
|
||||||
|
// 2. Changing the `inputSrcs` set changes the associated
|
||||||
|
// output ids, which break CA derivations
|
||||||
|
if (!drv.inputDrvs.empty())
|
||||||
|
drv.inputSrcs = store->parseStorePathSet(inputs);
|
||||||
|
optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv);
|
||||||
|
auto & result = *optResult;
|
||||||
|
if (!result.success())
|
||||||
|
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||||
|
} else {
|
||||||
|
copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute);
|
||||||
|
auto res = sshStore->buildPathsWithResults({ DerivedPath::Built { *drvPath, OutputsSpec::All {} } });
|
||||||
|
// One path to build should produce exactly one build result
|
||||||
|
assert(res.size() == 1);
|
||||||
|
optResult = std::move(res[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto outputHashes = staticOutputHashes(*store, drv);
|
auto outputHashes = staticOutputHashes(*store, drv);
|
||||||
|
|
||||||
// Hijack the inputs paths of the derivation to include all the paths
|
|
||||||
// that come from the `inputDrvs` set.
|
|
||||||
// We don’t do that for the derivations whose `inputDrvs` is empty
|
|
||||||
// because
|
|
||||||
// 1. It’s not needed
|
|
||||||
// 2. Changing the `inputSrcs` set changes the associated output ids,
|
|
||||||
// which break CA derivations
|
|
||||||
if (!drv.inputDrvs.empty())
|
|
||||||
drv.inputSrcs = store->parseStorePathSet(inputs);
|
|
||||||
|
|
||||||
auto result = sshStore->buildDerivation(*drvPath, drv);
|
|
||||||
|
|
||||||
if (!result.success())
|
|
||||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
|
||||||
|
|
||||||
std::set<Realisation> missingRealisations;
|
std::set<Realisation> missingRealisations;
|
||||||
StorePathSet missingPaths;
|
StorePathSet missingPaths;
|
||||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().hasKnownOutputPaths()) {
|
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().hasKnownOutputPaths()) {
|
||||||
|
@ -311,6 +338,8 @@ connected:
|
||||||
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||||
if (!store->queryRealisation(thisOutputId)) {
|
if (!store->queryRealisation(thisOutputId)) {
|
||||||
debug("missing output %s", outputName);
|
debug("missing output %s", outputName);
|
||||||
|
assert(optResult);
|
||||||
|
auto & result = *optResult;
|
||||||
auto i = result.builtOutputs.find(outputName);
|
auto i = result.builtOutputs.find(outputName);
|
||||||
assert(i != result.builtOutputs.end());
|
assert(i != result.builtOutputs.end());
|
||||||
auto & newRealisation = i->second;
|
auto & newRealisation = i->second;
|
||||||
|
|
|
@ -17,13 +17,13 @@ nix-build build-hook.nix -A passthru.input2 \
|
||||||
--store "$TEST_ROOT/local" \
|
--store "$TEST_ROOT/local" \
|
||||||
--option system-features bar
|
--option system-features bar
|
||||||
|
|
||||||
# Now when we go to build that downstream derivation, Nix will fail
|
# Now when we go to build that downstream derivation, Nix will try to
|
||||||
# because we cannot trustlessly build input-addressed derivations with
|
# copy our already-build `input2` to the remote store. That store object
|
||||||
# `inputDrv` dependencies.
|
# is input-addressed, so this will fail.
|
||||||
|
|
||||||
file=build-hook.nix
|
file=build-hook.nix
|
||||||
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
||||||
proto=ssh-ng
|
proto=ssh-ng
|
||||||
|
|
||||||
expectStderr 1 source build-remote-trustless.sh \
|
expectStderr 1 source build-remote-trustless.sh \
|
||||||
| grepQuiet "you are not privileged to build input-addressed derivations"
|
| grepQuiet "cannot add path '[^ ]*' because it lacks a signature by a trusted key"
|
||||||
|
|
13
tests/build-remote-trustless-should-pass-2.sh
Normal file
13
tests/build-remote-trustless-should-pass-2.sh
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
source common.sh
|
||||||
|
|
||||||
|
enableFeatures "daemon-trust-override"
|
||||||
|
|
||||||
|
restartDaemon
|
||||||
|
|
||||||
|
# Remote doesn't trust us
|
||||||
|
file=build-hook.nix
|
||||||
|
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
||||||
|
proto=ssh-ng
|
||||||
|
|
||||||
|
source build-remote-trustless.sh
|
||||||
|
source build-remote-trustless-after.sh
|
|
@ -72,6 +72,7 @@ nix_tests = \
|
||||||
build-remote-content-addressed-floating.sh \
|
build-remote-content-addressed-floating.sh \
|
||||||
build-remote-trustless-should-pass-0.sh \
|
build-remote-trustless-should-pass-0.sh \
|
||||||
build-remote-trustless-should-pass-1.sh \
|
build-remote-trustless-should-pass-1.sh \
|
||||||
|
build-remote-trustless-should-pass-2.sh \
|
||||||
build-remote-trustless-should-pass-3.sh \
|
build-remote-trustless-should-pass-3.sh \
|
||||||
build-remote-trustless-should-fail-0.sh \
|
build-remote-trustless-should-fail-0.sh \
|
||||||
nar-access.sh \
|
nar-access.sh \
|
||||||
|
|
Loading…
Reference in a new issue