summary refs log tree commit diff
path: root/nixos/modules/services/networking/strongswan.nix
blob: d6960a5df471240933b06c488377deec3e855123 (plain) (blame)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{ config, lib, pkgs, ... }:

let

  inherit (builtins) toFile;
  inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList
                mkIf mkEnableOption mkOption types;

  cfg = config.services.strongswan;

  ipsecSecrets = secrets: toFile "ipsec.secrets" (
    concatMapStringsSep "\n" (f: "include ${f}") secrets
  );

  ipsecConf = {setup, connections, ca}:
    let
      # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
      makeSections = type: sections: concatStringsSep "\n\n" (
        mapAttrsToList (sec: attrs:
          "${type} ${sec}\n" +
            (concatStringsSep "\n" ( mapAttrsToList (k: v: "  ${k}=${v}") attrs ))
        ) sections
      );
      setupConf       = makeSections "config" { inherit setup; };
      connectionsConf = makeSections "conn" connections;
      caConf          = makeSections "ca" ca;

    in
    builtins.toFile "ipsec.conf" ''
      ${setupConf}
      ${connectionsConf}
      ${caConf}
    '';

  strongswanConf = {setup, connections, ca, secrets}: toFile "strongswan.conf" ''
    charon {
      plugins {
        stroke {
          secrets_file = ${ipsecSecrets secrets}
        }
      }
    }

    starter {
      config_file = ${ipsecConf { inherit setup connections ca; }}
    }
  '';

in
{
  options.services.strongswan = {
    enable = mkEnableOption "strongSwan";

    secrets = mkOption {
      type = types.listOf types.path;
      default = [];
      example = [ "/run/keys/ipsec-foo.secret" ];
      description = ''
        A list of paths to IPSec secret files. These
        files will be included into the main ipsec.secrets file with
        the <literal>include</literal> directive. It is safer if these
        paths are absolute.
      '';
    };

    setup = mkOption {
      type = types.attrsOf types.str;
      default = {};
      example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
      description = ''
        A set of options for the ‘config setup’ section of the
        <filename>ipsec.conf</filename> file. Defines general
        configuration parameters.
      '';
    };

    connections = mkOption {
      type = types.attrsOf (types.attrsOf types.str);
      default = {};
      example = {
        "%default" = {
          keyexchange = "ikev2";
          keyingtries = "1";
        };
        roadwarrior = {
          auto       = "add";
          leftcert   = "/run/keys/moonCert.pem";
          leftid     = "@moon.strongswan.org";
          leftsubnet = "10.1.0.0/16";
          right      = "%any";
        };
      };
      description = ''
        A set of connections and their options for the ‘conn xxx’
        sections of the <filename>ipsec.conf</filename> file.
      '';
    };

    ca = mkOption {
      type = types.attrsOf (types.attrsOf types.str);
      default = {};
      example = {
        strongswan = {
          auto   = "add";
          cacert = "/run/keys/strongswanCert.pem";
          crluri = "http://crl2.strongswan.org/strongswan.crl";
        };
      };
      description = ''
        A set of CAs (certification authorities) and their options for
        the ‘ca xxx’ sections of the <filename>ipsec.conf</filename>
        file.
      '';
    };
  };

  config = with cfg; mkIf enable {
    systemd.services.strongswan = {
      description = "strongSwan IPSec Service";
      wantedBy = [ "multi-user.target" ];
      path = with pkgs; [ config.system.sbin.modprobe iproute iptables utillinux ]; # XXX Linux
      wants = [ "keys.target" ];
      after = [ "network.target" "keys.target" ];
      environment = {
        STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secrets; };
      };
      serviceConfig = {
        ExecStart  = "${pkgs.strongswan}/sbin/ipsec start --nofork";
      };
    };
  };
}