python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / networking / openconnect.nix
blob469f0a3bc3bb6d973fc6be885db218f64c2cb7fe
1 { config, lib, options, pkgs, ... }:
2 with lib;
3 let
4   cfg = config.networking.openconnect;
5   openconnect = cfg.package;
6   pkcs11 = types.strMatching "pkcs11:.+" // {
7     name = "pkcs11";
8     description = "PKCS#11 URI";
9   };
10   interfaceOptions = {
11     options = {
12       autoStart = mkOption {
13         default = true;
14         description = lib.mdDoc "Whether this VPN connection should be started automatically.";
15         type = types.bool;
16       };
18       gateway = mkOption {
19         description = lib.mdDoc "Gateway server to connect to.";
20         example = "gateway.example.com";
21         type = types.str;
22       };
24       protocol = mkOption {
25         description = lib.mdDoc "Protocol to use.";
26         example = "anyconnect";
27         type =
28           types.enum [ "anyconnect" "array" "nc" "pulse" "gp" "f5" "fortinet" ];
29       };
31       user = mkOption {
32         description = lib.mdDoc "Username to authenticate with.";
33         example = "example-user";
34         type = types.nullOr types.str;
35       };
37       # Note: It does not make sense to provide a way to declaratively
38       # set an authentication cookie, because they have to be requested
39       # for every new connection and would only work once.
40       passwordFile = mkOption {
41         description = lib.mdDoc ''
42           File containing the password to authenticate with. This
43           is passed to `openconnect` via the
44           `--passwd-on-stdin` option.
45         '';
46         default = null;
47         example = "/var/lib/secrets/openconnect-passwd";
48         type = types.nullOr types.path;
49       };
51       certificate = mkOption {
52         description = lib.mdDoc "Certificate to authenticate with.";
53         default = null;
54         example = "/var/lib/secrets/openconnect_certificate.pem";
55         type = with types; nullOr (either path pkcs11);
56       };
58       privateKey = mkOption {
59         description = lib.mdDoc "Private key to authenticate with.";
60         example = "/var/lib/secrets/openconnect_private_key.pem";
61         default = null;
62         type = with types; nullOr (either path pkcs11);
63       };
65       extraOptions = mkOption {
66         description = lib.mdDoc ''
67           Extra config to be appended to the interface config. It should
68           contain long-format options as would be accepted on the command
69           line by `openconnect`
70           (see https://www.infradead.org/openconnect/manual.html).
71           Non-key-value options like `deflate` can be used by
72           declaring them as booleans, i. e. `deflate = true;`.
73         '';
74         default = { };
75         example = {
76           compression = "stateless";
78           no-http-keepalive = true;
79           no-dtls = true;
80         };
81         type = with types; attrsOf (either str bool);
82       };
83     };
84   };
85   generateExtraConfig = extra_cfg:
86     strings.concatStringsSep "\n" (attrsets.mapAttrsToList
87       (name: value: if (value == true) then name else "${name}=${value}")
88       (attrsets.filterAttrs (_: value: value != false) extra_cfg));
89   generateConfig = name: icfg:
90     pkgs.writeText "config" ''
91       interface=${name}
92       ${optionalString (icfg.user != null) "user=${icfg.user}"}
93       ${optionalString (icfg.passwordFile != null) "passwd-on-stdin"}
94       ${optionalString (icfg.certificate != null)
95       "certificate=${icfg.certificate}"}
96       ${optionalString (icfg.privateKey != null) "sslkey=${icfg.privateKey}"}
98       ${generateExtraConfig icfg.extraOptions}
99     '';
100   generateUnit = name: icfg: {
101     description = "OpenConnect Interface - ${name}";
102     requires = [ "network-online.target" ];
103     after = [ "network.target" "network-online.target" ];
104     wantedBy = optional icfg.autoStart "multi-user.target";
106     serviceConfig = {
107       Type = "simple";
108       ExecStart = "${openconnect}/bin/openconnect --config=${
109           generateConfig name icfg
110         } ${icfg.gateway}";
111       StandardInput = "file:${icfg.passwordFile}";
113       ProtectHome = true;
114     };
115   };
116 in {
117   options.networking.openconnect = {
118     package = mkPackageOption pkgs "openconnect" { };
120     interfaces = mkOption {
121       description = lib.mdDoc "OpenConnect interfaces.";
122       default = { };
123       example = {
124         openconnect0 = {
125           gateway = "gateway.example.com";
126           protocol = "anyconnect";
127           user = "example-user";
128           passwordFile = "/var/lib/secrets/openconnect-passwd";
129         };
130       };
131       type = with types; attrsOf (submodule interfaceOptions);
132     };
133   };
135   config = {
136     systemd.services = mapAttrs' (name: value: {
137       name = "openconnect-${name}";
138       value = generateUnit name value;
139     }) cfg.interfaces;
140   };
142   meta.maintainers = with maintainers; [ alyaeanyx ];