1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{ lib, config, pkgs, ... }:

let
  failedNormal = config: pkgs.writeText "failed.nix" ''
    let utils = builtins.storePath ${config.system.build.extraUtils}; in
    derivation {
      name = "failed";
      system = builtins.currentSystem;
      PATH = "''${utils}/bin";
      builder = "''${utils}/bin/sh";
      args = [ "-c" "mkdir dir; echo test > dir/file" ];
    }
  '';

  failedBuiltin = pkgs.writeText "failed.nix" ''
    derivation {
      name = "failed";
      system = builtins.currentSystem;
      builder = "builtin:fetchurl";
      url = "http://localhost/foo";
      outputHashMode = "flat";
    }
  '';
in
{
  name = "chown-to-user";

  nodes = {
    machine = { config, lib, pkgs, ... }: {
      virtualisation.writableStore = true;
      virtualisation.additionalPaths = [ config.system.build.extraUtils ];

      users.users.test = {
        isNormalUser = true;
        group = "test";
      };
      users.groups.test = {};
      nix.nrBuildUsers = 1;
    };
  };

  testScript = { nodes, ... }: ''
    import re

    machine.wait_for_unit("multi-user.target")

    # builds using the daemon chown tempdirs
    out = machine.fail("runuser -u test -- nix-build ${failedNormal nodes.machine} --keep-failed 2>&1")
    dir = re.search("keeping build directory '(.+?)'", out)
    assert dir
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}").strip() == "root:nixbld:755"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b").strip() == "test:test:700"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b/dir").strip() == "test:test:755"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b/dir/file").strip() == "test:test:644"

    # builds not using the daemon do not chown tempdirs
    out = machine.fail("NIX_REMOTE=local nix-build ${failedNormal nodes.machine} --keep-failed 2>&1")
    dir = re.search("keeping build directory '(.+?)'", out)
    assert dir
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}").strip() == "root:nixbld:755"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b").strip() == "nixbld1:nixbld:700"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b/dir").strip() == "nixbld1:nixbld:755"
    assert machine.succeed(f"stat -c %U:%G:%a {dir[1]}/b/dir/file").strip() == "nixbld1:nixbld:644"

    # builds using builtin builders using the daemon do not keep tempdirs
    out = machine.fail("runuser -u test -- nix-build ${failedBuiltin} --keep-failed 2>&1")
    dir = re.search("keeping build directory '(.+?)'", out)
    assert not dir

    # builds using builtin builders not using the daemon do not keep tempdirs
    out = machine.fail("NIX_REMOTE=local nix-build ${failedBuiltin} --keep-failed 2>&1")
    dir = re.search("keeping build directory '(.+?)'", out)
    assert not dir
  '';
}