vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / stunnel.nix
blob9f9068c8e0779c3a87e5b792113bcc9efa4e0b72
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.services.stunnel;
8   yesNo = val: if val then "yes" else "no";
10   verifyRequiredField = type: field: n: c: {
11     assertion = hasAttr field c;
12     message =  "stunnel: \"${n}\" ${type} configuration - Field ${field} is required.";
13   };
15   verifyChainPathAssert = n: c: {
16     assertion = (c.verifyHostname or null) == null || (c.verifyChain || c.verifyPeer);
17     message =  "stunnel: \"${n}\" client configuration - hostname verification " +
18       "is not possible without either verifyChain or verifyPeer enabled";
19   };
21   removeNulls = mapAttrs (_: filterAttrs (_: v: v != null));
22   mkValueString = v:
23     if v == true then "yes"
24     else if v == false then "no"
25     else generators.mkValueStringDefault {} v;
26   generateConfig = c:
27     generators.toINI {
28       mkSectionName = id;
29       mkKeyValue = k: v: "${k} = ${mkValueString v}";
30     } (removeNulls c);
36   ###### interface
38   options = {
40     services.stunnel = {
42       enable = mkOption {
43         type = types.bool;
44         default = false;
45         description = "Whether to enable the stunnel TLS tunneling service.";
46       };
48       user = mkOption {
49         type = with types; nullOr str;
50         default = "nobody";
51         description = "The user under which stunnel runs.";
52       };
54       group = mkOption {
55         type = with types; nullOr str;
56         default = "nogroup";
57         description = "The group under which stunnel runs.";
58       };
60       logLevel = mkOption {
61         type = types.enum [ "emerg" "alert" "crit" "err" "warning" "notice" "info" "debug" ];
62         default = "info";
63         description = "Verbosity of stunnel output.";
64       };
66       fipsMode = mkOption {
67         type = types.bool;
68         default = false;
69         description = "Enable FIPS 140-2 mode required for compliance.";
70       };
72       enableInsecureSSLv3 = mkOption {
73         type = types.bool;
74         default = false;
75         description = "Enable support for the insecure SSLv3 protocol.";
76       };
79       servers = mkOption {
80         description = ''
81           Define the server configurations.
83           See "SERVICE-LEVEL OPTIONS" in {manpage}`stunnel(8)`.
84         '';
85         type = with types; attrsOf (attrsOf (nullOr (oneOf [bool int str])));
86         example = {
87           fancyWebserver = {
88             accept = 443;
89             connect = 8080;
90             cert = "/path/to/pem/file";
91           };
92         };
93         default = { };
94       };
96       clients = mkOption {
97         description = ''
98           Define the client configurations.
100           By default, verifyChain and OCSPaia are enabled and a CAFile is provided from pkgs.cacert.
102           See "SERVICE-LEVEL OPTIONS" in {manpage}`stunnel(8)`.
103         '';
104         type = with types; attrsOf (attrsOf (nullOr (oneOf [bool int str])));
106         apply = let
107           applyDefaults = c:
108             {
109               CAFile = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
110               OCSPaia = true;
111               verifyChain = true;
112             } // c;
113           setCheckHostFromVerifyHostname = c:
114             # To preserve backward-compatibility with the old NixOS stunnel module
115             # definition, allow "verifyHostname" as an alias for "checkHost".
116             c // {
117               checkHost = c.checkHost or c.verifyHostname or null;
118               verifyHostname = null; # Not a real stunnel configuration setting
119             };
120           forceClient = c: c // { client = true; };
121         in mapAttrs (_: c: forceClient (setCheckHostFromVerifyHostname (applyDefaults c)));
123         example = {
124           foobar = {
125             accept = "0.0.0.0:8080";
126             connect = "nixos.org:443";
127             verifyChain = false;
128           };
129         };
130         default = { };
131       };
132     };
133   };
136   ###### implementation
138   config = mkIf cfg.enable {
140     assertions = concatLists [
141       (singleton {
142         assertion = (length (attrValues cfg.servers) != 0) || ((length (attrValues cfg.clients)) != 0);
143         message = "stunnel: At least one server- or client-configuration has to be present.";
144       })
146       (mapAttrsToList verifyChainPathAssert cfg.clients)
147       (mapAttrsToList (verifyRequiredField "client" "accept") cfg.clients)
148       (mapAttrsToList (verifyRequiredField "client" "connect") cfg.clients)
149       (mapAttrsToList (verifyRequiredField "server" "accept") cfg.servers)
150       (mapAttrsToList (verifyRequiredField "server" "cert") cfg.servers)
151       (mapAttrsToList (verifyRequiredField "server" "connect") cfg.servers)
152     ];
154     environment.systemPackages = [ pkgs.stunnel ];
156     environment.etc."stunnel.cfg".text = ''
157       ${ optionalString (cfg.user != null) "setuid = ${cfg.user}" }
158       ${ optionalString (cfg.group != null) "setgid = ${cfg.group}" }
160       debug = ${cfg.logLevel}
162       ${ optionalString cfg.fipsMode "fips = yes" }
163       ${ optionalString cfg.enableInsecureSSLv3 "options = -NO_SSLv3" }
165       ; ----- SERVER CONFIGURATIONS -----
166       ${ generateConfig cfg.servers }
168       ; ----- CLIENT CONFIGURATIONS -----
169       ${ generateConfig cfg.clients }
170     '';
172     systemd.services.stunnel = {
173       description = "stunnel TLS tunneling service";
174       after = [ "network.target" ];
175       wants = [ "network.target" ];
176       wantedBy = [ "multi-user.target" ];
177       restartTriggers = [ config.environment.etc."stunnel.cfg".source ];
178       serviceConfig = {
179         ExecStart = "${pkgs.stunnel}/bin/stunnel ${config.environment.etc."stunnel.cfg".source}";
180         Type = "forking";
181       };
182     };
184     meta.maintainers = with maintainers; [
185       # Server side
186       lschuermann
187       # Client side
188       das_j
189     ];
190   };