{ config, lib, pkgs, ... }: let inherit (lib) types; settingsFormat = pkgs.formats.toml { }; in { options.common.services.oauth2-proxy = lib.mkOption { description = "Configuration for oauth2-proxy instances."; default = { }; type = types.attrsOf ( types.submodule { options = { enable = (lib.mkEnableOption "oauth2-proxy") // { default = true; }; package = lib.mkPackageOption pkgs "oauth2-proxy" { }; environmentFile = lib.mkOption { type = with lib.types; nullOr path; default = null; }; nginx = { enable = lib.mkEnableOption ""; virtualHost = lib.mkOption { type = with lib.types; nullOr str; default = null; }; protectedLocations = lib.mkOption { type = with lib.types; listOf str; default = [ "/" ]; }; }; settings = lib.mkOption { default = { }; type = types.submodule { freeformType = settingsFormat.type; options = { proxy_prefix = lib.mkOption { type = lib.types.str; default = "/oauth2"; }; ping_path = lib.mkOption { type = lib.types.str; default = "/oauth2/ping"; }; trusted_proxy_ips = lib.mkOption { type = lib.types.str; default = "::1"; }; email_domains = lib.mkOption { type = lib.types.str; default = "*"; }; code_challenge_method = lib.mkOption { type = lib.types.str; default = "S256"; }; whitelist_domains = lib.mkOption { type = with lib.types; listOf str; default = [ "oidc.fc9f.de" ]; }; }; }; }; }; } ); }; config = { assertions = lib.flatten ( lib.flip lib.mapAttrsToList config.common.services.oauth2-proxy (name: cfg: [ ]) ); services.nginx.virtualHosts = lib.flip lib.mapAttrs' (lib.filterAttrs (name: value: value.nginx.enable) config.common.services.oauth2-proxy) ( name: cfg: lib.nameValuePair cfg.nginx.virtualHost { locations = (builtins.listToAttrs ( lib.map ( location: lib.nameValuePair location { extraConfig = '' auth_request ${config.common.services.oauth2-proxy."${name}".settings.proxy_prefix}/auth; error_page 401 403 =302 $scheme://$host${ config.common.services.oauth2-proxy."${name}".settings.proxy_prefix }/start?rd=$scheme://$host$request_uri; ''; } ) config.common.services.oauth2-proxy."${name}".nginx.protectedLocations )) // { "${config.common.services.oauth2-proxy.${name}.settings.proxy_prefix}".extraConfig = '' auth_request off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Auth-Request-Redirect $request_uri; proxy_pass http://${config.common.services.oauth2-proxy.${name}.settings.http_address}; ''; "= ${config.common.services.oauth2-proxy."${name}".settings.proxy_prefix}/auth".extraConfig = '' internal; auth_request off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Uri $request_uri; proxy_set_header Content-Length ""; proxy_pass_request_body off; proxy_pass http://${config.common.services.oauth2-proxy."${name}".settings.http_address}${ config.common.services.oauth2-proxy."${name}".settings.proxy_prefix }/auth; ''; "= ${config.common.services.oauth2-proxy."${name}".settings.proxy_prefix}/sign_out".extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Auth-Request-Redirect ${ config.common.services.oauth2-proxy.${name}.settings.oidc_issuer_url }/logout; proxy_pass http://${config.common.services.oauth2-proxy.${name}.settings.http_address}; ''; "= ${config.common.services.oauth2-proxy."${name}".settings.proxy_prefix}/useerinfo".return = "403"; }; } ); systemd.services = lib.flip lib.mapAttrs' config.common.services.oauth2-proxy ( name: cfg: let unitName = "oauth2-proxy${lib.optionalString (name != "") "-${name}"}"; in (lib.nameValuePair unitName ( let settingsSecretsReplaced = pkgs.zphaLib.replaceSecrets "${unitName}.service" ( lib.filterAttrsRecursive (name: value: value != null) cfg.settings ); settingsFile = settingsFormat.generate "${unitName}.toml" (settingsSecretsReplaced.output); in { enable = cfg.enable; # confinement.enable = true; restartTriggers = [ settingsFile ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { DynamicUser = true; ExecStart = "${lib.getExe cfg.package} --config ${settingsFile}"; Restart = "always"; EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; LoadCredential = settingsSecretsReplaced.credentials; ProtectSystem = "full"; ProtectControlGroups = true; ProtectKernelModules = true; ProtectKernelTunables = true; LockPersonality = true; DevicePolicy = "strict"; DeviceAllow = [ "/dev/stdin r" ]; SystemCallArchitectures = "native"; MemoryDenyWriteExecute = true; NoNewPrivileges = true; PrivateTmp = true; PrivateDevices = true; UMask = "077"; RestrictAddressFamilies = "AF_INET AF_INET6"; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; RemoveIPC = true; PrivateIPC = true; SystemCallFilter = [ "@system-service" "~@resources" "~@mount" "~@setuid" "~@cpu-emulation" "~@debug" "~@keyring" "~@obsolete" "~@pkey" "setrlimit" ]; }; } )) ); }; meta.maintainers = with lib.maintainers; [ zaphyra ]; }