# roles/thin-client/network/wifi.nix # # 802.1X EAP-TLS WiFi via NetworkManager + wpa_supplicant backend. # Q8 decisions: EAP-TLS, per-machine client cert, AD CS 3-5y lifetime, # single Corp SSID. # # Per-host secrets (via agenix): # secrets/-wifi-client.pem.age # → decrypted to /etc/wifi/client.pem # Contains the full PKCS#12 export OR combined PEM (cert + key). # Mode 0600, owner root. # # CA cert is NOT secret — checked into the repo as a public file under # roles/thin-client/network/assets/corp-wifi-ca.pem. Replace placeholder # with real AD CS root cert. {config, lib, pkgs, ...}: let inherit (lib) mkIf mkOption types; cfg = config.az.tc; hostname = config.networking.hostName; in { options.az.tc.wifi = { ssid = mkOption { type = types.str; default = "AZ-CORP"; # TODO: real SSID description = "Corporate SSID for thin clients."; }; caCert = mkOption { type = types.path; default = ./assets/corp-wifi-ca.pem; description = '' Corporate WiFi CA certificate (PEM format, not secret — checked into the repo). Replace the placeholder with the real AD CS root cert. ''; }; }; config = mkIf cfg.enable { # Disable iwd explicitly — wpa_supplicant is the backend we use. # Note: NetworkManager with `wifi.backend = "wpa_supplicant"` automatically # sets networking.wireless.enable = true (it owns wpa_supplicant). networking.wireless.iwd.enable = false; networking.networkmanager = { enable = true; wifi.backend = "wpa_supplicant"; }; # Declarative NetworkManager profile for corp WiFi (EAP-TLS). # NixOS has no built-in `ensureProfiles` option in the # `networking.networkmanager` namespace, so we write the # `.nmconnection` file directly to the system-connections dir. # NetworkManager picks it up on restart. environment.etc."NetworkManager/system-connections/${config.az.tc.wifi.ssid}.nmconnection".source = pkgs.writeText "${config.az.tc.wifi.ssid}.nmconnection" '' [connection] id=${config.az.tc.wifi.ssid} type=wifi autoconnect=true permissions= [wifi] mode=infrastructure ssid=${config.az.tc.wifi.ssid} [wifi-security] key-mgmt=wpa-eap [802-1x] eap=tls identity=${hostname}$ ca-cert=${config.az.tc.wifi.caCert} client-cert=/etc/wifi/client.pem private-key=/etc/wifi/client.pem private-key-password= phase2-auth= [ipv4] method=auto [ipv6] method=auto ''; # `environment.etc` files are owned by root but world-readable by # default — make this profile root-only since it references the cert # path (the cert itself is root-only via agenix). systemd.tmpfiles.rules = [ "d /etc/wifi 0700 root root -" ]; # CA cert installed system-wide as trust anchor (defensive) security.pki.certificateFiles = [config.az.tc.wifi.caCert]; # Per-host client cert (via agenix) age.secrets."${hostname}-wifi-client-cert" = { file = ../../secrets/${hostname}-wifi-client-cert.age; path = "/etc/wifi/client.pem"; mode = "0600"; owner = "root"; group = "root"; }; # Directory for the cert — NetworkManager reads it as root. # Ensure wpa_supplicant doesn't try to use the cert before agenix decrypted it. systemd.services.NetworkManager-wait-online = { after = ["age-identity.service"]; wants = ["age-identity.service"]; }; }; }