wireguard: allow not storing private keys in world-readable /nix/store (#27433)
* wireguard: allow not storing private keys in world-readable /nix/store
This commit is contained in:
		
							parent
							
								
									7ba1c7a9fb
								
							
						
					
					
						commit
						9b0ff955fd
					
				@ -23,8 +23,23 @@ let
 | 
			
		||||
 | 
			
		||||
      privateKey = mkOption {
 | 
			
		||||
        example = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
 | 
			
		||||
        type = types.str;
 | 
			
		||||
        description = "Base64 private key generated by wg genkey.";
 | 
			
		||||
        type = with types; nullOr str;
 | 
			
		||||
        default = null;
 | 
			
		||||
        description = ''
 | 
			
		||||
          Base64 private key generated by wg genkey.
 | 
			
		||||
 | 
			
		||||
          Warning: Consider using privateKeyFile instead if you do not
 | 
			
		||||
          want to store the key in the world-readable Nix store.
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      privateKeyFile = mkOption {
 | 
			
		||||
        example = "/private/wireguard_key";
 | 
			
		||||
        type = with types; nullOr str;
 | 
			
		||||
        default = null;
 | 
			
		||||
        description = ''
 | 
			
		||||
          Private key file as generated by wg genkey.
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      listenPort = mkOption {
 | 
			
		||||
@ -91,7 +106,22 @@ let
 | 
			
		||||
        example = "rVXs/Ni9tu3oDBLS4hOyAUAa1qTWVA3loR8eL20os3I=";
 | 
			
		||||
        type = with types; nullOr str;
 | 
			
		||||
        description = ''
 | 
			
		||||
          base64 preshared key generated by wg genpsk. Optional,
 | 
			
		||||
          Base64 preshared key generated by wg genpsk. Optional,
 | 
			
		||||
          and may be omitted. This option adds an additional layer of
 | 
			
		||||
          symmetric-key cryptography to be mixed into the already existing
 | 
			
		||||
          public-key cryptography, for post-quantum resistance.
 | 
			
		||||
 | 
			
		||||
          Warning: Consider using presharedKeyFile instead if you do not
 | 
			
		||||
          want to store the key in the world-readable Nix store.
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      presharedKeyFile = mkOption {
 | 
			
		||||
        default = null;
 | 
			
		||||
        example = "/private/wireguard_psk";
 | 
			
		||||
        type = with types; nullOr str;
 | 
			
		||||
        description = ''
 | 
			
		||||
          File pointing to preshared key as generated by wg pensk. Optional,
 | 
			
		||||
          and may be omitted. This option adds an additional layer of
 | 
			
		||||
          symmetric-key cryptography to be mixed into the already existing
 | 
			
		||||
          public-key cryptography, for post-quantum resistance.
 | 
			
		||||
@ -134,54 +164,59 @@ let
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  generateConf = name: values: pkgs.writeText "wireguard-${name}.conf" ''
 | 
			
		||||
    [Interface]
 | 
			
		||||
    PrivateKey = ${values.privateKey}
 | 
			
		||||
    ${optionalString (values.listenPort != null)   "ListenPort = ${toString values.listenPort}"}
 | 
			
		||||
 | 
			
		||||
    ${concatStringsSep "\n\n" (map (peer: ''
 | 
			
		||||
    [Peer]
 | 
			
		||||
    PublicKey = ${peer.publicKey}
 | 
			
		||||
    ${optionalString (peer.presharedKey != null) "PresharedKey = ${peer.presharedKey}"}
 | 
			
		||||
    ${optionalString (peer.allowedIPs != []) "AllowedIPs = ${concatStringsSep ", " peer.allowedIPs}"}
 | 
			
		||||
    ${optionalString (peer.endpoint != null) "Endpoint = ${peer.endpoint}"}
 | 
			
		||||
    ${optionalString (peer.persistentKeepalive != null) "PersistentKeepalive = ${toString peer.persistentKeepalive}"}
 | 
			
		||||
    '') values.peers)}
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  ipCommand = "${pkgs.iproute}/bin/ip";
 | 
			
		||||
  wgCommand = "${pkgs.wireguard}/bin/wg";
 | 
			
		||||
 | 
			
		||||
  generateUnit = name: values:
 | 
			
		||||
    # exactly one way to specify the private key must be set
 | 
			
		||||
    assert (values.privateKey != null) != (values.privateKeyFile != null);
 | 
			
		||||
    let privKey = if values.privateKeyFile != null then values.privateKeyFile else pkgs.writeText "wg-key" values.privateKey;
 | 
			
		||||
    in
 | 
			
		||||
    nameValuePair "wireguard-${name}"
 | 
			
		||||
      {
 | 
			
		||||
        description = "WireGuard Tunnel - ${name}";
 | 
			
		||||
        after = [ "network.target" ];
 | 
			
		||||
        wantedBy = [ "multi-user.target" ];
 | 
			
		||||
 | 
			
		||||
        serviceConfig = {
 | 
			
		||||
          Type = "oneshot";
 | 
			
		||||
          RemainAfterExit = true;
 | 
			
		||||
          ExecStart = lib.flatten([
 | 
			
		||||
          ExecStart = flatten([
 | 
			
		||||
            values.preSetup
 | 
			
		||||
 | 
			
		||||
            "-${ipCommand} link del dev ${name}"
 | 
			
		||||
            "${ipCommand} link add dev ${name} type wireguard"
 | 
			
		||||
            "${wgCommand} setconf ${name} ${generateConf name values}"
 | 
			
		||||
 | 
			
		||||
            (map (ip:
 | 
			
		||||
            ''${ipCommand} address add ${ip} dev ${name}''
 | 
			
		||||
            "${ipCommand} address add ${ip} dev ${name}"
 | 
			
		||||
            ) values.ips)
 | 
			
		||||
 | 
			
		||||
            ("${wgCommand} set ${name} private-key ${privKey}" +
 | 
			
		||||
            optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}")
 | 
			
		||||
 | 
			
		||||
            (map (peer:
 | 
			
		||||
            assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set
 | 
			
		||||
            let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile;
 | 
			
		||||
            in
 | 
			
		||||
            "${wgCommand} set ${name} peer ${peer.publicKey}" +
 | 
			
		||||
            optionalString (psk != null) " preshared-key ${psk}" +
 | 
			
		||||
            optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" +
 | 
			
		||||
            optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" +
 | 
			
		||||
            optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"
 | 
			
		||||
            ) values.peers)
 | 
			
		||||
 | 
			
		||||
            "${ipCommand} link set up dev ${name}"
 | 
			
		||||
 | 
			
		||||
            (flatten (map (peer: (map (ip:
 | 
			
		||||
            (map (peer: (map (ip:
 | 
			
		||||
            "${ipCommand} route add ${ip} dev ${name}"
 | 
			
		||||
            ) peer.allowedIPs)) values.peers))
 | 
			
		||||
            ) peer.allowedIPs)) values.peers)
 | 
			
		||||
 | 
			
		||||
            values.postSetup
 | 
			
		||||
          ]);
 | 
			
		||||
 | 
			
		||||
          ExecStop = [ ''${ipCommand} link del dev "${name}"'' ] ++ values.postShutdown;
 | 
			
		||||
          ExecStop = flatten([
 | 
			
		||||
            "${ipCommand} link del dev ${name}"
 | 
			
		||||
            values.postShutdown
 | 
			
		||||
          ]);
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user