1{ pkgs, ... }:
2let
3 # build a getent that itself doesn't see anything in /etc/hosts and
4 # /etc/nsswitch.conf, by using libredirect to steer its own requests to
5 # /dev/null.
6 # This means is /has/ to go via nscd to actually resolve any of the
7 # additionally configured hosts.
8 getent' = pkgs.writeScript "getent-without-etc-hosts" ''
9 export NIX_REDIRECTS=/etc/hosts=/dev/null:/etc/nsswitch.conf=/dev/null
10 export LD_PRELOAD=${pkgs.libredirect}/lib/libredirect.so
11 exec getent $@
12 '';
13in
14{
15 name = "nscd";
16
17 nodes.machine =
18 { pkgs, ... }:
19 {
20 imports = [ common/user-account.nix ];
21 networking.extraHosts = ''
22 2001:db8::1 somehost.test
23 192.0.2.1 somehost.test
24 '';
25
26 systemd.services.sockdump = {
27 wantedBy = [ "multi-user.target" ];
28 path = [
29 # necessary for bcc to unpack kernel headers and invoke modprobe
30 pkgs.gnutar
31 pkgs.xz.bin
32 pkgs.kmod
33 ];
34 environment.PYTHONUNBUFFERED = "1";
35
36 serviceConfig = {
37 ExecStart = "${pkgs.sockdump}/bin/sockdump /var/run/nscd/socket";
38 Restart = "on-failure";
39 RestartSec = "1";
40 Type = "simple";
41 };
42 };
43
44 specialisation = {
45 withGlibcNscd.configuration =
46 { ... }:
47 {
48 services.nscd.enableNsncd = false;
49 };
50 withUnscd.configuration =
51 { ... }:
52 {
53 services.nscd.enableNsncd = false;
54 services.nscd.package = pkgs.unscd;
55 };
56 };
57 };
58
59 testScript =
60 { nodes, ... }:
61 let
62 specialisations = "${nodes.machine.system.build.toplevel}/specialisation";
63 in
64 ''
65 # Regression test for https://github.com/NixOS/nixpkgs/issues/50273
66 def test_dynamic_user():
67 with subtest("DynamicUser actually allocates a user"):
68 assert "iamatest" in machine.succeed(
69 "systemd-run --pty --property=Type=oneshot --property=DynamicUser=yes --property=User=iamatest whoami"
70 )
71
72 # Test resolution of somehost.test with getent', to make sure we go via
73 # nscd protocol
74 def test_host_lookups():
75 with subtest("host lookups via nscd protocol"):
76 # ahosts
77 output = machine.succeed("${getent'} ahosts somehost.test")
78 assert "192.0.2.1" in output
79 assert "2001:db8::1" in output
80
81 # ahostsv4
82 output = machine.succeed("${getent'} ahostsv4 somehost.test")
83 assert "192.0.2.1" in output
84 assert "2001:db8::1" not in output
85
86 # ahostsv6
87 output = machine.succeed("${getent'} ahostsv6 somehost.test")
88 assert "192.0.2.1" not in output
89 assert "2001:db8::1" in output
90
91 # reverse lookups (hosts)
92 assert "somehost.test" in machine.succeed("${getent'} hosts 2001:db8::1")
93 assert "somehost.test" in machine.succeed("${getent'} hosts 192.0.2.1")
94
95
96 # Test host resolution via nss modules works
97 # We rely on nss-myhostname in this case, which resolves *.localhost and
98 # _gateway.
99 # We don't need to use getent' here, as non-glibc nss modules can only be
100 # discovered via nscd.
101 def test_nss_myhostname():
102 with subtest("nss-myhostname provides hostnames (ahosts)"):
103 # ahosts
104 output = machine.succeed("getent ahosts foobar.localhost")
105 assert "::1" in output
106 assert "127.0.0.1" in output
107
108 # ahostsv4
109 output = machine.succeed("getent ahostsv4 foobar.localhost")
110 assert "::1" not in output
111 assert "127.0.0.1" in output
112
113 # ahostsv6
114 output = machine.succeed("getent ahostsv6 foobar.localhost")
115 assert "::1" in output
116 assert "127.0.0.1" not in output
117
118 start_all()
119 machine.wait_for_unit("default.target")
120
121 # give sockdump some time to finish attaching.
122 machine.sleep(5)
123
124 # Test all tests with glibc-nscd.
125 test_dynamic_user()
126 test_host_lookups()
127 test_nss_myhostname()
128
129 with subtest("glibc-nscd"):
130 machine.succeed('${specialisations}/withGlibcNscd/bin/switch-to-configuration test')
131 machine.wait_for_unit("default.target")
132
133 test_dynamic_user()
134 test_host_lookups()
135 test_nss_myhostname()
136
137 with subtest("unscd"):
138 machine.succeed('${specialisations}/withUnscd/bin/switch-to-configuration test')
139 machine.wait_for_unit("default.target")
140
141 # known to fail, unscd doesn't load external NSS modules
142 # test_dynamic_user()
143
144 test_host_lookups()
145
146 # known to fail, unscd doesn't load external NSS modules
147 # test_nss_myhostname()
148 '';
149}