nixos/openconnect: add module

main
alyaeanyx 2 years ago
parent 9c27834e32
commit 0c066f0d0e
No known key found for this signature in database
GPG Key ID: 87D1AADCD25B8DEE
  1. 7
      nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
  2. 2
      nixos/doc/manual/release-notes/rl-2205.section.md
  3. 1
      nixos/modules/module-list.nix
  4. 135
      nixos/modules/services/networking/openconnect.nix

@ -1631,6 +1631,13 @@
<literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
A module for declarative configuration of openconnect VPN
profiles was added under
<literal>networking.openconnect</literal>.
</para>
</listitem>
<listitem>
<para>
The <literal>element-desktop</literal> package now has an

@ -569,6 +569,8 @@ In addition to numerous new and upgraded packages, this release has the followin
using `fetchgit` or `fetchhg` if the argument `fetchSubmodules`
is set to `true`.
- A module for declarative configuration of openconnect VPN profiles was added under `networking.openconnect`.
- The `element-desktop` package now has an `useKeytar` option (defaults to `true`),
which allows disabling `keytar` and in turn `libsecret` usage
(which binds to native credential managers / keychain libraries).

@ -851,6 +851,7 @@
./services/networking/ofono.nix
./services/networking/oidentd.nix
./services/networking/onedrive.nix
./services/networking/openconnect.nix
./services/networking/openvpn.nix
./services/networking/ostinato.nix
./services/networking/owamp.nix

@ -0,0 +1,135 @@
{ config, lib, options, pkgs, ... }:
with lib;
let
cfg = config.networking.openconnect;
openconnect = cfg.package;
pkcs11 = types.strMatching "pkcs11:.+" // {
name = "pkcs11";
description = "PKCS#11 URI";
};
interfaceOptions = {
options = {
gateway = mkOption {
description = "Gateway server to connect to.";
example = "gateway.example.com";
type = types.str;
};
protocol = mkOption {
description = "Protocol to use.";
example = "anyconnect";
type =
types.enum [ "anyconnect" "array" "nc" "pulse" "gp" "f5" "fortinet" ];
};
user = mkOption {
description = "Username to authenticate with.";
example = "example-user";
type = types.nullOr types.str;
};
# Note: It does not make sense to provide a way to declaratively
# set an authentication cookie, because they have to be requested
# for every new connection and would only work once.
passwordFile = mkOption {
description = ''
File containing the password to authenticate with. This
is passed to <code>openconnect</code> via the
<code>--passwd-on-stdin</code> option.
'';
default = null;
example = "/var/lib/secrets/openconnect-passwd";
type = types.nullOr types.path;
};
certificate = mkOption {
description = "Certificate to authenticate with.";
default = null;
example = "/var/lib/secrets/openconnect_certificate.pem";
type = with types; nullOr (either path pkcs11);
};
privateKey = mkOption {
description = "Private key to authenticate with.";
example = "/var/lib/secrets/openconnect_private_key.pem";
default = null;
type = with types; nullOr (either path pkcs11);
};
extraOptions = mkOption {
description = ''
Extra config to be appended to the interface config. It should
contain long-format options as would be accepted on the command
line by <code>openconnect</code>
(see https://www.infradead.org/openconnect/manual.html).
Non-key-value options like <code>deflate</code> can be used by
declaring them as booleans, i. e. <code>deflate = true;</code>.
'';
default = { };
example = {
compression = "stateless";
no-http-keepalive = true;
no-dtls = true;
};
type = with types; attrsOf (either str bool);
};
};
};
generateExtraConfig = extra_cfg:
strings.concatStringsSep "\n" (attrsets.mapAttrsToList
(name: value: if (value == true) then name else "${name}=${value}")
(attrsets.filterAttrs (_: value: value != false) extra_cfg));
generateConfig = name: icfg:
pkgs.writeText "config" ''
interface=${name}
${optionalString (icfg.user != null) "user=${icfg.user}"}
${optionalString (icfg.passwordFile != null) "passwd-on-stdin"}
${optionalString (icfg.certificate != null)
"certificate=${icfg.certificate}"}
${optionalString (icfg.privateKey != null) "sslkey=${icfg.privateKey}"}
${generateExtraConfig icfg.extraOptions}
'';
generateUnit = name: icfg: {
description = "OpenConnect Interface - ${name}";
requires = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${openconnect}/bin/openconnect --config=${
generateConfig name icfg
} ${icfg.gateway}";
StandardInput = "file:${icfg.passwordFile}";
};
};
in {
options.networking.openconnect = {
package = mkPackageOption pkgs "openconnect" { };
interfaces = mkOption {
description = "OpenConnect interfaces.";
default = { };
example = {
openconnect0 = {
gateway = "gateway.example.com";
protocol = "anyconnect";
user = "example-user";
passwordFile = "/var/lib/secrets/openconnect-passwd";
};
};
type = with types; attrsOf (submodule interfaceOptions);
};
};
config = {
systemd.services = mapAttrs' (name: value: {
name = "openconnect-${name}";
value = generateUnit name value;
}) cfg.interfaces;
};
meta.maintainers = with maintainers; [ alyaeanyx ];
}
Loading…
Cancel
Save