depot/third_party/nixpkgs/nixos/modules/services/security/oauth2-proxy-nginx.nix

154 lines
5.7 KiB
Nix

{ config, lib, ... }:
let
cfg = config.services.oauth2-proxy.nginx;
in
{
options.services.oauth2-proxy.nginx = {
proxy = lib.mkOption {
type = lib.types.str;
default = config.services.oauth2-proxy.httpAddress;
defaultText = lib.literalExpression "config.services.oauth2-proxy.httpAddress";
description = ''
The address of the reverse proxy endpoint for oauth2-proxy
'';
};
domain = lib.mkOption {
type = lib.types.str;
description = ''
The domain under which the oauth2-proxy will be accesible and the path of cookies are set to.
This setting must be set to ensure back-redirects are working properly
if oauth2-proxy is configured with {option}`services.oauth2-proxy.cookie.domain`
or multiple {option}`services.oauth2-proxy.nginx.virtualHosts` that are not on the same domain.
'';
};
virtualHosts = lib.mkOption {
type =
let
vhostSubmodule = lib.types.submodule {
options = {
allowed_groups = lib.mkOption {
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of groups to allow access to this vhost, or null to allow all.";
default = null;
};
allowed_emails = lib.mkOption {
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of emails to allow access to this vhost, or null to allow all.";
default = null;
};
allowed_email_domains = lib.mkOption {
type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = "List of email domains to allow access to this vhost, or null to allow all.";
default = null;
};
};
};
oldType = lib.types.listOf lib.types.str;
convertFunc =
x:
lib.warn
"services.oauth2-proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty { } x}"
lib.genAttrs
x
(_: { });
newType = lib.types.attrsOf vhostSubmodule;
in
lib.types.coercedTo oldType convertFunc newType;
default = { };
example = {
"protected.foo.com" = {
allowed_groups = [ "admins" ];
allowed_emails = [ "boss@foo.com" ];
};
};
description = ''
Nginx virtual hosts to put behind the oauth2 proxy.
You can exclude specific locations by setting `auth_request off;` in the locations extraConfig setting.
'';
};
};
config.services.oauth2-proxy =
lib.mkIf (cfg.virtualHosts != { } && (lib.hasPrefix "127.0.0.1:" cfg.proxy))
{
enable = true;
};
config.services.nginx = lib.mkIf (cfg.virtualHosts != { } && config.services.oauth2-proxy.enable) (
lib.mkMerge (
[
{
virtualHosts.${cfg.domain}.locations."/oauth2/" = {
proxyPass = cfg.proxy;
extraConfig = ''
auth_request off;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
}
]
++ lib.optional (cfg.virtualHosts != { }) {
recommendedProxySettings = true; # needed because duplicate headers
}
++ (lib.mapAttrsToList (vhost: conf: {
virtualHosts.${vhost} = {
locations = {
"/".extraConfig = ''
# pass information via X-User and X-Email headers to backend, requires running with --set-xauthrequest flag
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
add_header Set-Cookie $auth_cookie;
'';
"/oauth2/auth" =
let
maybeQueryArg =
name: value:
if value == null then
null
else
"${name}=${lib.concatStringsSep "," (builtins.map lib.escapeURL value)}";
allArgs = lib.mapAttrsToList maybeQueryArg conf;
cleanArgs = builtins.filter (x: x != null) allArgs;
cleanArgsStr = lib.concatStringsSep "&" cleanArgs;
in
{
# nginx doesn't support passing query string arguments to auth_request,
# so pass them here instead
proxyPass = "${cfg.proxy}/oauth2/auth?${cleanArgsStr}";
extraConfig = ''
auth_request off;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
"@redirectToAuth2ProxyLogin" = {
return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
extraConfig = ''
auth_request off;
'';
};
};
extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = @redirectToAuth2ProxyLogin;
# set variables being used in locations."/".extraConfig
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $auth_cookie $upstream_http_set_cookie;
'';
};
}) cfg.virtualHosts)
)
);
}