summaryrefslogtreecommitdiffstats
path: root/nixos/tests/systemd-timesyncd-nscd-dnssec.nix
blob: cc4ca5260dfa9416ef39c75e4dba557dfea9e62c (plain)
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
# This test verifies that systemd-timesyncd can resolve the NTP server hostname when DNSSEC validation
# fails even though it is enforced in the systemd-resolved settings. It is required in order to solve
# the chicken-and-egg problem when DNSSEC validation needs the correct time to work, but to set the
# correct time, we need to connect to an NTP server, which usually requires resolving its hostname.
#
# This test does the following:
# - Sets up a DNS server (tinydns) listening on loopback, serving .ntp and fake.ntp records.
# - Configures that DNS server as a resolver and enables DNSSEC in systemd-resolved settings.
# - Configures systemd-timesyncd to use fake.ntp hostname as an NTP server.
# - Performs a regular DNS lookup, to ensure it fails due to broken DNSSEC.
# - Waits until systemd-timesyncd resolves fake.ntp by checking its debug output.
#   Here, we don't expect systemd-timesyncd to connect and synchronize time because there is no NTP
#   server running. For this test to succeed, we only need to ensure that systemd-timesyncd
#   resolves the IP address of the fake.ntp host.

let
  ntpHostname = "fake.ntp";
  ntpIP = "192.0.2.1";
  dnsIP = "127.0.0.1";
in
{
  name = "systemd-timesyncd-nscd-dnssec";
  nodes.machine =
    { lib, ... }:
    {
      # Setup a local DNS server for the NTP domain on loopback
      services.tinydns = {
        enable = true;
        ip = dnsIP;
        data = ''
          .ntp:${dnsIP}
          +.${ntpHostname}:${ntpIP}
        '';
      };

      # Enable systemd-resolved with DNSSEC and use the local DNS as a name server
      services.resolved.enable = true;
      services.resolved.settings.Resolve.DNSSEC = true;
      networking.nameservers = [ dnsIP ];

      # Configure systemd-timesyncd to use our NTP hostname
      services.timesyncd.enable = lib.mkForce true;
      services.timesyncd.servers = [ ntpHostname ];
      services.timesyncd.settings.Time.FallbackNTP = ntpHostname;

      # The debug output is necessary to determine whether systemd-timesyncd successfully resolves our NTP hostname or not
      systemd.services.systemd-timesyncd.environment.SYSTEMD_LOG_LEVEL = "debug";
    };

  testScript = ''
    machine.wait_for_unit("tinydns.service")
    machine.wait_for_unit("systemd-timesyncd.service")
    machine.fail("resolvectl query ${ntpHostname}")
    machine.wait_until_succeeds("journalctl -u systemd-timesyncd.service --grep='Resolved address ${ntpIP}:123 for ${ntpHostname}'")
  '';
}