vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / ghostunnel.nix
blobb8d3cc3629790f4cacfa2d77491a851a8ea9d0a2
1 { config, lib, pkgs, ... }:
2 let
3   inherit (lib)
4     attrValues
5     concatMap
6     concatStringsSep
7     escapeShellArg
8     literalExpression
9     mapAttrs'
10     mkDefault
11     mkEnableOption
12     mkPackageOption
13     mkIf
14     mkOption
15     nameValuePair
16     optional
17     types
18     ;
20   mainCfg = config.services.ghostunnel;
22   module = { config, name, ... }:
23     {
24       options = {
26         listen = mkOption {
27           description = ''
28             Address and port to listen on (can be HOST:PORT, unix:PATH).
29           '';
30           type = types.str;
31         };
33         target = mkOption {
34           description = ''
35             Address to forward connections to (can be HOST:PORT or unix:PATH).
36           '';
37           type = types.str;
38         };
40         keystore = mkOption {
41           description = ''
42             Path to keystore (combined PEM with cert/key, or PKCS12 keystore).
44             NB: storepass is not supported because it would expose credentials via `/proc/*/cmdline`.
46             Specify this or `cert` and `key`.
47           '';
48           type = types.nullOr types.str;
49           default = null;
50         };
52         cert = mkOption {
53           description = ''
54             Path to certificate (PEM with certificate chain).
56             Not required if `keystore` is set.
57           '';
58           type = types.nullOr types.str;
59           default = null;
60         };
62         key = mkOption {
63           description = ''
64             Path to certificate private key (PEM with private key).
66             Not required if `keystore` is set.
67           '';
68           type = types.nullOr types.str;
69           default = null;
70         };
72         cacert = mkOption {
73           description = ''
74             Path to CA bundle file (PEM/X509). Uses system trust store if `null`.
75           '';
76           type = types.nullOr types.str;
77         };
79         disableAuthentication = mkOption {
80           description = ''
81             Disable client authentication, no client certificate will be required.
82           '';
83           type = types.bool;
84           default = false;
85         };
87         allowAll = mkOption {
88           description = ''
89             If true, allow all clients, do not check client cert subject.
90           '';
91           type = types.bool;
92           default = false;
93         };
95         allowCN = mkOption {
96           description = ''
97             Allow client if common name appears in the list.
98           '';
99           type = types.listOf types.str;
100           default = [];
101         };
103         allowOU = mkOption {
104           description = ''
105             Allow client if organizational unit name appears in the list.
106           '';
107           type = types.listOf types.str;
108           default = [];
109         };
111         allowDNS = mkOption {
112           description = ''
113             Allow client if DNS subject alternative name appears in the list.
114           '';
115           type = types.listOf types.str;
116           default = [];
117         };
119         allowURI = mkOption {
120           description = ''
121             Allow client if URI subject alternative name appears in the list.
122           '';
123           type = types.listOf types.str;
124           default = [];
125         };
127         extraArguments = mkOption {
128           description = "Extra arguments to pass to `ghostunnel server`";
129           type = types.separatedString " ";
130           default = "";
131         };
133         unsafeTarget = mkOption {
134           description = ''
135             If set, does not limit target to localhost, 127.0.0.1, [::1], or UNIX sockets.
137             This is meant to protect against accidental unencrypted traffic on
138             untrusted networks.
139           '';
140           type = types.bool;
141           default = false;
142         };
144         # Definitions to apply at the root of the NixOS configuration.
145         atRoot = mkOption {
146           internal = true;
147         };
148       };
150       # Clients should not be authenticated with the public root certificates
151       # (afaict, it doesn't make sense), so we only provide that default when
152       # client cert auth is disabled.
153       config.cacert = mkIf config.disableAuthentication (mkDefault null);
155       config.atRoot = {
156         assertions = [
157           { message = ''
158               services.ghostunnel.servers.${name}: At least one access control flag is required.
159               Set at least one of:
160                 - services.ghostunnel.servers.${name}.disableAuthentication
161                 - services.ghostunnel.servers.${name}.allowAll
162                 - services.ghostunnel.servers.${name}.allowCN
163                 - services.ghostunnel.servers.${name}.allowOU
164                 - services.ghostunnel.servers.${name}.allowDNS
165                 - services.ghostunnel.servers.${name}.allowURI
166             '';
167             assertion = config.disableAuthentication
168               || config.allowAll
169               || config.allowCN != []
170               || config.allowOU != []
171               || config.allowDNS != []
172               || config.allowURI != []
173               ;
174           }
175         ];
177         systemd.services."ghostunnel-server-${name}" = {
178           after = [ "network.target" ];
179           wants = [ "network.target" ];
180           wantedBy = [ "multi-user.target" ];
181           serviceConfig = {
182             Restart = "always";
183             AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
184             DynamicUser = true;
185             LoadCredential = optional (config.keystore != null) "keystore:${config.keystore}"
186               ++ optional (config.cert != null) "cert:${config.cert}"
187               ++ optional (config.key != null) "key:${config.key}"
188               ++ optional (config.cacert != null) "cacert:${config.cacert}";
189            };
190           script = concatStringsSep " " (
191             [ "${mainCfg.package}/bin/ghostunnel" ]
192             ++ optional (config.keystore != null) "--keystore=$CREDENTIALS_DIRECTORY/keystore"
193             ++ optional (config.cert != null) "--cert=$CREDENTIALS_DIRECTORY/cert"
194             ++ optional (config.key != null) "--key=$CREDENTIALS_DIRECTORY/key"
195             ++ optional (config.cacert != null) "--cacert=$CREDENTIALS_DIRECTORY/cacert"
196             ++ [
197               "server"
198               "--listen ${config.listen}"
199               "--target ${config.target}"
200             ] ++ optional config.allowAll "--allow-all"
201               ++ map (v: "--allow-cn=${escapeShellArg v}") config.allowCN
202               ++ map (v: "--allow-ou=${escapeShellArg v}") config.allowOU
203               ++ map (v: "--allow-dns=${escapeShellArg v}") config.allowDNS
204               ++ map (v: "--allow-uri=${escapeShellArg v}") config.allowURI
205               ++ optional config.disableAuthentication "--disable-authentication"
206               ++ optional config.unsafeTarget "--unsafe-target"
207               ++ [ config.extraArguments ]
208           );
209         };
210       };
211     };
216   options = {
217     services.ghostunnel.enable = mkEnableOption "ghostunnel";
219     services.ghostunnel.package = mkPackageOption pkgs "ghostunnel" { };
221     services.ghostunnel.servers = mkOption {
222       description = ''
223         Server mode ghostunnels (TLS listener -> plain TCP/UNIX target)
224       '';
225       type = types.attrsOf (types.submodule module);
226       default = {};
227     };
228   };
230   config = mkIf mainCfg.enable {
231     assertions = lib.mkMerge (map (v: v.atRoot.assertions) (attrValues mainCfg.servers));
232     systemd = lib.mkMerge (map (v: v.atRoot.systemd) (attrValues mainCfg.servers));
233   };
235   meta.maintainers = with lib.maintainers; [
236     roberth
237   ];