grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / security / oauth2-proxy-nginx.nix
blob2dffeb993803ffc141e833d9ee9a3c6626bcc0ab
1 { config, lib, ... }:
2 let
3   cfg = config.services.oauth2-proxy.nginx;
4 in
6   options.services.oauth2-proxy.nginx = {
7     proxy = lib.mkOption {
8       type = lib.types.str;
9       default = config.services.oauth2-proxy.httpAddress;
10       defaultText = lib.literalExpression "config.services.oauth2-proxy.httpAddress";
11       description = ''
12         The address of the reverse proxy endpoint for oauth2-proxy
13       '';
14     };
16     domain = lib.mkOption {
17       type = lib.types.str;
18       description = ''
19         The domain under which the oauth2-proxy will be accesible and the path of cookies are set to.
20         This setting must be set to ensure back-redirects are working properly
21         if oauth2-proxy is configured with {option}`services.oauth2-proxy.cookie.domain`
22         or multiple {option}`services.oauth2-proxy.nginx.virtualHosts` that are not on the same domain.
23       '';
24     };
26     virtualHosts = lib.mkOption {
27       type = let
28         vhostSubmodule = lib.types.submodule {
29           options = {
30             allowed_groups = lib.mkOption {
31               type = lib.types.nullOr (lib.types.listOf lib.types.str);
32               description = "List of groups to allow access to this vhost, or null to allow all.";
33               default = null;
34             };
35             allowed_emails = lib.mkOption {
36               type = lib.types.nullOr (lib.types.listOf lib.types.str);
37               description = "List of emails to allow access to this vhost, or null to allow all.";
38               default = null;
39             };
40             allowed_email_domains = lib.mkOption {
41               type = lib.types.nullOr (lib.types.listOf lib.types.str);
42               description = "List of email domains to allow access to this vhost, or null to allow all.";
43               default = null;
44             };
45           };
46         };
47         oldType = lib.types.listOf lib.types.str;
48         convertFunc = x:
49           lib.warn "services.oauth2-proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
50           lib.genAttrs x (_: {});
51         newType = lib.types.attrsOf vhostSubmodule;
52       in lib.types.coercedTo oldType convertFunc newType;
53       default = {};
54       example = {
55         "protected.foo.com" = {
56           allowed_groups = ["admins"];
57           allowed_emails = ["boss@foo.com"];
58         };
59       };
60       description = ''
61         Nginx virtual hosts to put behind the oauth2 proxy.
62         You can exclude specific locations by setting `auth_request off;` in the locations extraConfig setting.
63       '';
64     };
65   };
67   config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != {} && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
68     enable = true;
69   };
71   config.services.nginx = lib.mkIf (cfg.virtualHosts != {} && config.services.oauth2-proxy.enable) (lib.mkMerge ([
72     {
73       virtualHosts.${cfg.domain}.locations."/oauth2/" = {
74         proxyPass = cfg.proxy;
75         extraConfig = ''
76           auth_request off;
77           proxy_set_header X-Scheme                $scheme;
78           proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
79         '';
80       };
81     }
82   ] ++ lib.optional (cfg.virtualHosts != {}) {
83     recommendedProxySettings = true; # needed because duplicate headers
84   } ++ (lib.mapAttrsToList (vhost: conf: {
85     virtualHosts.${vhost} = {
86       locations = {
87         "/".extraConfig = ''
88           # pass information via X-User and X-Email headers to backend, requires running with --set-xauthrequest flag
89           proxy_set_header X-User  $user;
90           proxy_set_header X-Email $email;
92           # if you enabled --cookie-refresh, this is needed for it to work with auth_request
93           add_header Set-Cookie $auth_cookie;
94         '';
96         "/oauth2/auth" = let
97           maybeQueryArg = name: value:
98             if value == null then null
99             else "${name}=${lib.concatStringsSep "," (builtins.map lib.escapeURL value)}";
100           allArgs = lib.mapAttrsToList maybeQueryArg conf;
101           cleanArgs = builtins.filter (x: x != null) allArgs;
102           cleanArgsStr = lib.concatStringsSep "&" cleanArgs;
103         in {
104           # nginx doesn't support passing query string arguments to auth_request,
105           # so pass them here instead
106           proxyPass = "${cfg.proxy}/oauth2/auth?${cleanArgsStr}";
107           extraConfig = ''
108             auth_request off;
109             proxy_set_header X-Scheme         $scheme;
110             # nginx auth_request includes headers but not body
111             proxy_set_header Content-Length   "";
112             proxy_pass_request_body           off;
113           '';
114         };
116         "@redirectToAuth2ProxyLogin" = {
117           return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
118           extraConfig = ''
119             auth_request off;
120           '';
121         };
122       };
124       extraConfig = ''
125         auth_request /oauth2/auth;
126         error_page 401 = @redirectToAuth2ProxyLogin;
128         # set variables being used in locations."/".extraConfig
129         auth_request_set $user   $upstream_http_x_auth_request_user;
130         auth_request_set $email  $upstream_http_x_auth_request_email;
131         auth_request_set $auth_cookie $upstream_http_set_cookie;
132       '';
133     };
134   }) cfg.virtualHosts)));