diff --git a/README.md b/README.md index 8c4c119..83166a0 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ kanidm system oauth2 show-basic-secret grafana # Generate new oauth2 app for proxied webapps kanidm group create web-sentinel-access kanidm group create web-sentinel-adguardhome-access -kanidm system oauth2 create web-sentinel "Web services" https://sentinel.${personalDomain} +kanidm system oauth2 create web-sentinel "Web services" https://oauth2.${personalDomain} kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid profile email kanidm system oauth2 update-sup-scope-map web-sentinel web-sentinel-adguardhome-access access_adguardhome kanidm system oauth2 show-basic-secret web-sentinel diff --git a/hosts/sentinel/oauth2.nix b/hosts/sentinel/oauth2.nix index dc5e732..7a7048a 100644 --- a/hosts/sentinel/oauth2.nix +++ b/hosts/sentinel/oauth2.nix @@ -7,7 +7,7 @@ extra.oauth2_proxy = { enable = true; cookieDomain = config.repo.secrets.local.personalDomain; - authProxyDomain = "sentinel.${config.repo.secrets.local.personalDomain}"; + portalDomain = "oauth2.${config.repo.secrets.local.personalDomain}"; }; age.secrets.oauth2-proxy-secret = { @@ -18,7 +18,7 @@ services.oauth2_proxy = { provider = "oidc"; - scope = "openid"; + scope = "openid email"; loginURL = "https://${config.proxiedDomains.kanidm}/ui/oauth2"; redeemURL = "https://${config.proxiedDomains.kanidm}/oauth2/token"; validateURL = "https://${config.proxiedDomains.kanidm}/oauth2/openid/web-sentinel/userinfo"; diff --git a/modules/extra.nix b/modules/extra.nix index 97aa425..b852c18 100644 --- a/modules/extra.nix +++ b/modules/extra.nix @@ -100,8 +100,21 @@ in { sslCiphers = "EECDH+AESGCM:EDH+AESGCM:!aNULL"; sslDhparam = config.age.secrets."dhparams.pem".path; commonHttpConfig = '' - error_log syslog:server=unix:/dev/log; - access_log syslog:server=unix:/dev/log; + log_format json_combined escape=json '{' + '"time": $msec,' + '"remote_addr":"$remote_addr",' + '"status":$status,' + '"method":"$request_method",' + '"host":"$host",' + '"uri":"$request_uri",' + '"request_size":$request_length,' + '"response_size":$body_bytes_sent,' + '"response_time":$request_time,' + '"referrer":"$http_referer",' + '"user_agent":"$http_user_agent"' + '}'; + error_log syslog:server=unix:/dev/log,nohostname; + access_log syslog:server=unix:/dev/log,nohostname json_combined; ssl_ecdh_curve secp384r1; ''; }; diff --git a/modules/oauth2-proxy.nix b/modules/oauth2-proxy.nix index 19439a4..81d7b16 100644 --- a/modules/oauth2-proxy.nix +++ b/modules/oauth2-proxy.nix @@ -24,25 +24,12 @@ in { cookieDomain = mkOption { type = types.str; - description = mdDoc "The domain under which to store the credetial cookie."; + description = mdDoc "The domain under which to store the credential cookie, and to which redirects will be allowed."; }; - authProxyDomain = mkOption { + portalDomain = mkOption { type = types.str; - description = mdDoc '' - The domain under which to expose the oauth2 proxy. - This must be a subdomain at or below the level of `cookieDomain`. - ''; - }; - - nginx.virtualHosts = mkOption { - default = {}; - description = - mdDoc '' - ''; - type = - types.attrsOf (types.submodule { - }); + description = mdDoc "A domain on which to setup the oauth2 callback."; }; }; @@ -81,7 +68,7 @@ in { ''; locations."/oauth2/" = { - proxyPass = "https://${cfg.authProxyDomain}"; + proxyPass = "http://oauth2_proxy"; extraConfig = '' proxy_set_header X-Scheme $scheme; proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; @@ -90,7 +77,7 @@ in { locations."= /oauth2/auth" = { proxyPass = - "https://${cfg.authProxyDomain}" + "http://oauth2_proxy/oauth2/auth" + optionalString (config.oauth2.allowedGroups != []) "?allowed_groups=${concatStringsSep "," config.oauth2.allowedGroups}"; extraConfig = '' @@ -121,8 +108,11 @@ in { setXauthrequest = true; extraConfig = { + # Enable PKCE + code-challenge-method = "S256"; # Share the cookie with all subpages whitelist-domain = ".${cfg.cookieDomain}"; + redirect-url = "https://${cfg.portalDomain}/oauth2/callback"; set-authorization-header = true; pass-access-token = true; skip-jwt-bearer-tokens = true; @@ -134,6 +124,7 @@ in { systemd.services.oauth2_proxy.serviceConfig = { RuntimeDirectory = "oauth2_proxy"; RuntimeDirectoryMode = "0750"; + UMask = "007"; # TODO remove once https://github.com/oauth2-proxy/oauth2-proxy/issues/2141 is fixed }; users.groups.oauth2_proxy.members = ["nginx"]; @@ -147,32 +138,11 @@ in { ''; }; - virtualHosts.${cfg.authProxyDomain} = { + virtualHosts.${cfg.portalDomain} = { forceSSL = true; - useACMEHost = config.lib.extra.matchingWildcardCert cfg.authProxyDomain; - - locations."/".extraConfig = '' - deny all; - return 404; - ''; - - locations."/oauth2/" = { - proxyPass = "http://oauth2_proxy"; - extraConfig = '' - proxy_set_header X-Scheme $scheme; - proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - ''; - }; - - locations."= /oauth2/auth" = { - proxyPass = "http://oauth2_proxy"; - extraConfig = '' - proxy_set_header X-Scheme $scheme; - # nginx auth_request includes headers but not body - proxy_set_header Content-Length ""; - proxy_pass_request_body off; - ''; - }; + useACMEHost = config.lib.extra.matchingWildcardCert cfg.portalDomain; + oauth2.enable = true; + locations."/".proxyPass = "http://oauth2_proxy"; }; }; };