feat: oauth2-proxy

This commit is contained in:
Patrick 2024-03-19 00:46:35 +01:00
parent 61946abd8b
commit 624808fcca
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
17 changed files with 289 additions and 19 deletions

View file

@ -20,6 +20,7 @@
yourspotify = "sptfy";
apispotify = "apisptfy";
kanidm = "auth";
oauth2-proxy = "oauth2";
};
in "${domains.${hostName}}.${config.secrets.secrets.global.domains.web}";
# TODO hard coded elisabeth nicht so schön
@ -64,16 +65,94 @@ in {
(blockOf "vaultwarden" {maxBodySize = "1G";})
(blockOf "forgejo" {maxBodySize = "1G";})
(blockOf "immich" {maxBodySize = "5G";})
(
blockOf "adguardhome"
(lib.mkMerge
[
(
blockOf "adguardhome"
{
}
)
{
virtualHosts.${domainOf "adguardhome"} = {
locations."/".extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
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
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
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/oauth2/auth?allowed_groups=adguardhome_access";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
}
])
(lib.mkMerge [
(blockOf "oauth2-proxy" {})
{
virtualHostExtraConfig = ''
allow ${config.secrets.secrets.global.net.privateSubnetv4};
allow ${config.secrets.secrets.global.net.privateSubnetv6};
deny all ;
'';
virtualHosts.${domainOf "oauth2-proxy"} = {
locations."/".extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
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
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
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/oauth2/auth";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
}
)
])
(blockOf "paperless" {maxBodySize = "5G";})
(blockOf "ttrss" {port = 80;})
(blockOf "yourspotify" {port = 80;})
@ -179,6 +258,7 @@ in {
in
{}
// mkContainer "adguardhome" {}
// mkContainer "oauth2-proxy" {}
// mkContainer "vaultwarden" {}
// mkContainer "ddclient" {}
// mkContainer "ollama" {}

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> X25519 23FVuMgnvk6uz0HeokrJvQriQMhbnQrzSqrGMLAuLQ0
Rr6NqDi6GPYe/ttFe0pJjc4q4yG3f8PYRf1CYz43Nlo
-> piv-p256 XTQkUA A6eV+SQvNKx7KdBjE3VZr3FN4UcvNtrzu5M6E39a0kyT
hqNraFWXEZi/y8oh12eARpqG0lqbKbl/nEyBHaVrf1M
-> piv-p256 ZFgiIw A8KtgxgZfyjlPZMTjfMF/hM/AVaLuJSMHMNjsgPj9esB
ulY//QiAV5LWF5ytgclyl9MI8RtQsmJrZOl7GByOEsk
-> piv-p256 5vmPtQ Avqrc9ag13E8hB4znx8RSEMWQ1HtlTWf3fqUsg9oZtWi
gq5O9+tS2mazr9B5hzcXu/9H7N5kHPAjeffqbgRcXNk
-> piv-p256 ZFgiIw Aq1t4sN2K/eCs5sER0UrG5pvpg/0GbBcI55VQkW5du4e
ds8/Hd+yB628RAAzgZx1FK7u63XDsAF24//rHM/hEYM
-> 4r7hpz-grease $[jc"i f0kC pV+ t":]
9c3YRD+ZAUz+n6D1QFLJa7Lht7UZ8jHnRqa3BTWYlyo0o7Fo2khySVu31QUulGQn
nOonQVqhSo+Xli56voLAreMwSNCLmND51H5xy6txfA
--- 81bqCX4ison7wBIJw3Y0r6+DpKZsizu3qyZaDLDI6ek
²x_<דkP*LªFèC;gÜ®Ÿ1XZ<>Bï.ôIcÒœ’ç]ÒðM1y-‰;<05>Íâ¶<%… "ÿ**—2¦¾¬<C2BE>„@.@°

View file

@ -0,0 +1,15 @@
age-encryption.org/v1
-> X25519 8hIhP1nlR5z4Sk15LdISVf/9SYsGK5KhwMrlPnmIJgg
KTepeuDQaAOMK1gvNxHOTPjL7SphLGCtEpHvXbPiKk8
-> piv-p256 XTQkUA A7jgBkaMKAkBJqCVDUuOSzp6GZyDlU2NfiNZnJak9TVy
oy5WTHr9YtEovcjCpBzo1H1LsHj1B3zNSBBKeGpwduI
-> piv-p256 ZFgiIw Av/mFUoy4d+wr1OICrbKSf95K8i5abaOixkyVJMlI8r8
IbRAvpictJMvQin6NcLVzhZdB7637PRWhH0hqiWYgCE
-> piv-p256 5vmPtQ Al8w47I8tiYFHtgZO/RGYehoP7pAARW+ZslbU5I4iwTC
cRom9vNm04N2yGdnjQegWm3MsDBIi1uXExGF1Bz+K58
-> piv-p256 ZFgiIw Axp4AzWo1yCR0gAaYx4i88+nIGnutkwsX0GGecvE7BiN
i6UmA1TgfHqOKMjEuOHyF3WNUkYYfDZIHPPjoWqpSwo
-> K]@eH@U9-grease *[ Rk;n
+mpDtu7YRdf8
--- Kqc6c3+xpw8HtP0VJfDjujseDhs4NX4Yk9u1/fO+dSg
Ý#lj³f_ÆäÔ b<ðJwŒÜœa<15>FZ“ßÁF<C381>Êr'å/ ÖLL<4C>Xš·Û*)\óv`ú&=Ê3˜àUL…t1„ßšï5XŠ/¨šjÖÿ¥>yô}íš&`

View file

@ -0,0 +1,18 @@
age-encryption.org/v1
-> X25519 qMjJ4MnL4DXTo8ZGMwrNqIs/MXOeNMJN0EmdaDmNiRE
Y53jpcDeuKJco1Hn/SV9zOhGsG4l8EwOtWa41nPnHQQ
-> piv-p256 XTQkUA AmR3DeZhBej8l2wE0c+YFU/9huQOxF8u9ywmrIsBJdlT
vlMngpmAfsHlczNnYbK9BHsHsRhRkzROsmB/nv9IYGg
-> piv-p256 ZFgiIw AiF+VwhC3PFR0a+gAqHegAROpKXjTzHWq4/OSQ63x6g4
Hj8YHUklAGOYf/08CowvFFy73X51eKI12aozBsIW6wI
-> piv-p256 5vmPtQ A4zshisuH4R7fjUTR1A8OfaHQMnOuB27PkHSbo8/UoEJ
MwOocx7FZqmoCYnVAAWN8feRbS9jpImBr93TfX3gwd8
-> piv-p256 ZFgiIw Av7hUs3HIkOuxLGZMabSFU+fCGwyoroO309I0PhuJC9r
FhvTAwtHpW+g4MFLhxchg6+147zN0MLVfPKrHfaimq4
-> -K03YU%-grease =5
k6FjepBttAZSJp0hzk+WcTZ+kebQkKmbOCLZ2yp+lA6GQoNGhirdlm7In5SY5hoO
swHJWPPi3F3Atbf8hmEB4WU
--- NSt/Ot08yHqlDunM/P7XP78EBCALeFBOm0KYbdMhwew
nÈÜ?)p)&È*‹Ÿ”þ±+Uëtk| ñæÙö=û¢89D2.£Ò
Rzþ§L<C2A7>D4!F¿Û¥£Òž»Oö¢M•ñ¿àÂy£þ/që-ÐmÙC>ÆÁÿ*¦ºö
ú„÷ÿÚÂ

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINhR0E6eLN6HVm7s4Nl8G6gVlicWSF4egzCsSWc7d+Ld

View file

@ -11,17 +11,13 @@
trusted-users = ["root"];
system-features = ["recursive-nix" "repl-flake" "big-parallel"];
substituters = [
"https://nix-config.cachix.org"
"https://nix-community.cachix.org"
"https://colmena.cachix.org"
"https://cache.nixos.org"
"https://nixpkgs-wayland.cachix.org"
"https://ai.cachix.org"
];
trusted-public-keys = [
"nix-config.cachix.org-1:Vd6raEuldeIZpttVQfrUbLvXJHzzzkS0pezXCVVjDG4="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"colmena.cachix.org-1:7BzpDnjjH8ki2CT3f6GdOk7QAzPOl+1t3LvTLXqYcSg="
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA="
"ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc="

View file

@ -31,6 +31,7 @@
mongodb = uidGid 221;
authelia-main = uidGid 222;
kanidm = uidGid 223;
oauth2_proxy = uidGid 224;
paperless = uidGid 315;
systemd-oom = uidGid 300;
systemd-coredump = uidGid 301;

View file

@ -40,12 +40,6 @@
];
dhcp.enabled = false;
ratelimit = 60;
users = [
{
name = "patrick";
password = "$2y$10$cmdb7U/qbtUvrcFeKQvr6.BPrm/UwCiP.gBW2jG0Aq24hnzd2co4m";
}
];
filters = [
{
name = "AdGuard DNS filter";

View file

@ -131,7 +131,7 @@ in {
# XXX: PKCE is currently not supported by gitea/forgejo,
# see https://github.com/go-gitea/gitea/issues/21376.
systemd.services.forgejo = {
serviceConfig.RestartSec = "600"; # Retry every 10 minutes
serviceConfig.RestartSec = "60"; # Retry every minute
preStart = let
exe = lib.getExe config.services.forgejo.package;
providerName = "kanidm";

View file

@ -41,6 +41,11 @@ in {
mode = "440";
group = "kanidm";
};
oauth2-proxy = {
generator.script = "alnum";
mode = "440";
group = "kanidm";
};
oauth2-forgejo = {
generator.script = "alnum";
mode = "440";
@ -121,6 +126,21 @@ in {
groups."forgejo.admins" = {
members = ["administrator"];
};
systems.oauth2.oauth2-proxy = {
displayName = "Oauth2-Proxy";
originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/";
basicSecretFile = config.age.secrets.oauth2-proxy.path;
scopeMaps."adguardhome.access" = ["openid" "email" "profile"];
preferShortUsername = true;
claimMaps.groups = {
joinType = "array";
valuesByGroup."adguardhome.access" = ["adguardhome_access"];
};
};
groups."adguardhome.access" = {
};
systems.oauth2.forgejo = {
displayName = "Forgejo";
originUrl = "https://git.${config.secrets.secrets.global.domains.web}/";

View file

@ -0,0 +1,90 @@
{
config,
nodes,
...
}: {
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [3000];
};
age.secrets.oauth2-cookie-secret = {
rekeyFile = config.node.secretsDir + "/cookie-secret.age";
mode = "440";
group = "oauth2_proxy";
};
services.oauth2_proxy = {
enable = true;
cookie.domain = ".${config.secrets.secrets.global.domains.web}";
cookie.secure = true;
cookie.expire = "30m";
cookie.secret = null;
clientSecret = null;
reverseProxy = true;
httpAddress = "0.0.0.0:3000";
redirectURL = "https://oauth2.${config.secrets.secrets.global.domains.web}/oauth2/callback";
setXauthrequest = true;
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".${config.secrets.secrets.global.domains.web}";
set-authorization-header = true;
pass-access-token = true;
skip-jwt-bearer-tokens = true;
upstream = "static://202";
oidc-issuer-url = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy";
provider-display-name = "Kanidm";
#client-secret-file = config.age.secrets.oauth2-client-secret.path;
};
provider = "oidc";
scope = "openid email";
loginURL = "https://auth.${config.secrets.secrets.global.domains.web}/ui/oauth2";
redeemURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token";
validateURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy/userinfo";
clientID = "oauth2-proxy";
email.domains = ["*"];
};
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
RestartSec = "60"; # Retry every minute
};
systemd.services.oauth2_proxy.serviceConfig.EnvironmentFile = [
config.age.secrets.oauth2-cookie-secret.path
config.age.secrets.oauth2-client-secret-env.path
];
# Mirror the original oauth2 secret
age.secrets.oauth2-client-secret = {
inherit (nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy) rekeyFile;
mode = "440";
group = "oauth2_proxy";
};
# Mirror the original oauth2 secret, but prepend OAUTH2_PROXY_CLIENT_SECRET=
# so it can be used as an EnvironmentFile
# Using the normal secret file option does not work as
# it includes the newline terminating the file which
# makes kanidm reject the secret
age.secrets.oauth2-client-secret-env = {
generator.dependencies = [
nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy
];
generator.script = {
lib,
decrypt,
deps,
...
}: ''
echo -n "OAUTH2_PROXY_CLIENT_SECRET="
${decrypt} ${lib.escapeShellArg (lib.head deps).file}
'';
mode = "440";
group = "oauth2_proxy";
};
}

Binary file not shown.

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> X25519 g1vqWzZctykJkoxT61vjFHJUqeNOKSg0bf3wCYB7MDc
D4JZnpctpgjZaIn5WK3/hpY9R5XhQHWnHFJ+Uh48ZIs
-> piv-p256 XTQkUA A64jIlHXaqPB+WBfZFOrOihV6EF7Y2yt5BxVtGydv/E/
JJ/yeiDQSl2NINj2sSN/TUzdNhgmrtI6NcPcp45tLSk
-> piv-p256 ZFgiIw AmP5WWw0UADOv+ilwqnbRYtq4sQUPPIAANFNjf33yqKr
B5FRnKIDqLPAlFzrpZXjoiH6BhE51GRocvGhRrGFEv0
-> piv-p256 5vmPtQ AoFOKSUyPwm3C/KmrC7z38CFMXr/Ct9mzvil7bHjg4jV
hFV3hQGKo8zPOybLDnRYlyeNTX5kFb8AOwBrgZ0JTb0
-> piv-p256 ZFgiIw A8SpfqzsNh/My9UQSiBNFKH8p29bLNs3NfbBkAQbbr+0
xeittOKnGG63GDguhqN2fYMg0LiLkqU3b7XStbDrrNY
-> y-grease x#'<Q
2zNxND7dipOrQT2lnYqzR3Nfl3ovQ7RJXiuUbsGuDp9tyPCxZ6I2DgclkMmt9VYu
qNm5aDYTLJpNfPhJniEtkBi+Yw
--- BA6/EyC1xL8JXy/dwpqrTyHT2SRbsyvlAHq32w8yIDE
û<EFBFBD>EëåD!¿dJUEŽÁ<C5BD>Zw5H#£i7<69>}­1»ÙãhÈ3÷«P1Õ<31>Q<EFBFBD>]gñ2à!YÈLmw×E¯ÒNò™Žd*Ì«È›

View file

@ -0,0 +1 @@
+OFa4ZrDnLty45PNocVJ7uhzU8JAaZiqZxCP9dENu1c=

View file

@ -0,0 +1,17 @@
age-encryption.org/v1
-> X25519 ajsHkFAv6DGIBXK+TXNexcF46v9OSL56zJU++ESh2Ec
rlt3Qc5FpGQ4Uy7djHxXinaRj+vGzRD15ePectg3V5o
-> piv-p256 XTQkUA A5b2vQKPUK7CMtZtkqk7Sljxs3t+7T0xyok+W7NQIQhV
ouEoWuNAgUWZs/CmDwwO33S8sBF+vx09HwVi+k5xduM
-> piv-p256 ZFgiIw Agm3uergfR/G0r1jgJa6SQvL4s08DGLiIQytODbhtWpN
mk0MjBvUwoxHzTidlJY3wm9jimJiTi05rqFk6pWiz+s
-> piv-p256 5vmPtQ AgEl043vCMOGb7VMLrXZzFqJXqzpEts1dQ2BxKGWRQ0I
gqIxevnt+BQajswMvOnbhOCPoNeGjs6z+9Q2brXHXnw
-> piv-p256 ZFgiIw AjQwtNB6n1WgESAuFpUN8gfbDe13iTJiKwvn74gSTipx
KVmS8Q/hNZ454y9/CRS8s54yvIZtVc3IPMtBgDM/vLg
-> I[Qt/-grease Rux=WTOi _asi.\- YgMq{
BIULAuvdBWYTVL2OKUZSry4BEUaJaPxhuj6szwhGillSGRJEETf1AdTuhq2UyU4W
KRwUpEwJG6X/98y90H+ZxbEAcT4nzpq9mvc
--- cz5LsXdzqSnzi5YSj7mnRRIWjIouvBithyGjWSy2nCw
Šû°1IÇ~ƒ(Á“ø»õYNü²kqœ¸7ŒÍ³F•i³Ñ‰±¹ì3c
hu°h£7.t Ñ©•({‰ÞDÌQjÌø!h<>ìÐO<C390>i

View file

@ -13,6 +13,11 @@
# Use xterm-256color because copying terminfo-kitty is painful.
term = "xterm-256color";
# make kitty go brrrr
repaint_delay = 8;
input_delay = 0;
sync_to_monitor = "no";
# Do not wait for inherited child processes.
close_on_child_death = "yes";