From 6c9042b4d21874c3f1a5c0ab11d5ac8f77e03af6 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 12 Mar 2024 23:01:43 +0100 Subject: [PATCH] feat: enable OIDC in paperless --- hosts/sire/guests/paperless.nix | 41 +++++++++++-- hosts/ward/guests/kanidm.nix | 57 +++++++----------- .../ward-kanidm/kanidm-oauth2-paperless.age | 11 ++++ secrets/global.nix.age | Bin 2340 -> 2374 bytes ...1662208-paperless-oauth2-client-secret.age | 7 +++ ...4d5ca74f5092d3-kanidm-oauth2-paperless.age | Bin 0 -> 319 bytes 6 files changed, 77 insertions(+), 39 deletions(-) create mode 100644 secrets/generated/ward-kanidm/kanidm-oauth2-paperless.age create mode 100644 secrets/rekeyed/sire-paperless/07944f6e713f88e307284d3d01662208-paperless-oauth2-client-secret.age create mode 100644 secrets/rekeyed/ward-kanidm/90858ec737eadb4ec04d5ca74f5092d3-kanidm-oauth2-paperless.age diff --git a/hosts/sire/guests/paperless.nix b/hosts/sire/guests/paperless.nix index 375ccf9..234fb87 100644 --- a/hosts/sire/guests/paperless.nix +++ b/hosts/sire/guests/paperless.nix @@ -2,6 +2,7 @@ config, lib, nodes, + pkgs, ... }: let sentinelCfg = nodes.sentinel.config; @@ -47,6 +48,13 @@ in { group = "paperless"; }; + # Mirror the original oauth2 secret + age.secrets.paperless-oauth2-client-secret = { + inherit (nodes.ward-kanidm.config.age.secrets.kanidm-oauth2-paperless) rekeyFile; + mode = "440"; + group = "paperless"; + }; + environment.persistence."/persist".directories = [ { directory = "/var/lib/paperless"; @@ -56,11 +64,6 @@ in { } ]; - # TODO: workaround for https://github.com/paperless-ngx/paperless-ngx/discussions/5606 - systemd.services.paperless-web.script = lib.mkBefore '' - mkdir -p /tmp/paperless - ''; - services.paperless = { enable = true; address = "0.0.0.0"; @@ -73,6 +76,24 @@ in { PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessDomain}"; PAPERLESS_TRUSTED_PROXIES = sentinelCfg.meta.wireguard.proxy-sentinel.ipv4; + # Authentication via kanidm + PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect"; + PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON { + openid_connect = { + OAUTH_PKCE_ENABLED = "True"; + APPS = [ + rec { + provider_id = "kanidm"; + name = "Kanidm"; + client_id = "paperless"; + # secret will be added dynamically + #secret = ""; + settings.server_url = "https://${sentinelCfg.networking.providedDomains.kanidm}/oauth2/openid/${client_id}/.well-known/openid-configuration"; + } + ]; + }; + }; + # Ghostscript is entirely bug-free. PAPERLESS_OCR_USER_ARGS = builtins.toJSON { continue_on_soft_render_error = true; @@ -109,6 +130,16 @@ in { mode = "0700"; }; + # Add secret to PAPERLESS_SOCIALACCOUNT_PROVIDERS + systemd.services.paperless-web.script = lib.mkBefore '' + oidcSecret=$(< ${config.age.secrets.paperless-oauth2-client-secret.path}) + export PAPERLESS_SOCIALACCOUNT_PROVIDERS=$( + ${pkgs.jq}/bin/jq <<< "$PAPERLESS_SOCIALACCOUNT_PROVIDERS" \ + --compact-output \ + --arg oidcSecret "$oidcSecret" '.openid_connect.APPS.[0].secret = $oidcSecret' + ) + ''; + systemd.services.paperless-backup = let cfg = config.systemd.services.paperless-consumer; in { diff --git a/hosts/ward/guests/kanidm.nix b/hosts/ward/guests/kanidm.nix index ee73899..12b970e 100644 --- a/hosts/ward/guests/kanidm.nix +++ b/hosts/ward/guests/kanidm.nix @@ -7,6 +7,12 @@ sentinelCfg = nodes.sentinel.config; kanidmDomain = "auth.${domains.me}"; kanidmPort = 8300; + + mkRandomSecret = { + generator.script = "alnum"; + mode = "440"; + group = "kanidm"; + }; in { meta.wireguard-proxy.sentinel.allowedTCPPorts = [kanidmPort]; @@ -22,41 +28,14 @@ in { group = "kanidm"; }; - age.secrets.kanidm-admin-password = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; + age.secrets.kanidm-admin-password = mkRandomSecret; + age.secrets.kanidm-idm-admin-password = mkRandomSecret; - age.secrets.kanidm-idm-admin-password = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; - - age.secrets.kanidm-oauth2-immich = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; - - age.secrets.kanidm-oauth2-grafana = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; - - age.secrets.kanidm-oauth2-forgejo = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; - - age.secrets.kanidm-oauth2-web-sentinel = { - generator.script = "alnum"; - mode = "440"; - group = "kanidm"; - }; + age.secrets.kanidm-oauth2-forgejo = mkRandomSecret; + age.secrets.kanidm-oauth2-grafana = mkRandomSecret; + age.secrets.kanidm-oauth2-immich = mkRandomSecret; + age.secrets.kanidm-oauth2-paperless = mkRandomSecret; + age.secrets.kanidm-oauth2-web-sentinel = mkRandomSecret; nodes.sentinel = { networking.providedDomains.kanidm = kanidmDomain; @@ -130,6 +109,16 @@ in { scopeMaps."immich.access" = ["openid" "email" "profile"]; }; + # Paperless + groups."paperless.access" = {}; + systems.oauth2.paperless = { + displayName = "Paperless"; + originUrl = "https://${sentinelCfg.networking.providedDomains.paperless}/"; + basicSecretFile = config.age.secrets.kanidm-oauth2-paperless.path; + preferShortUsername = true; + scopeMaps."paperless.access" = ["openid" "email" "profile"]; + }; + # Grafana groups."grafana.access" = {}; groups."grafana.editors" = {}; diff --git a/secrets/generated/ward-kanidm/kanidm-oauth2-paperless.age b/secrets/generated/ward-kanidm/kanidm-oauth2-paperless.age new file mode 100644 index 0000000..9b65904 --- /dev/null +++ b/secrets/generated/ward-kanidm/kanidm-oauth2-paperless.age @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> X25519 hzkY1fcGtdk9GFrYskb/0fFAAgD4hAwtyd23quaPCD8 +akEojVvE36WwAGv9aZFWZLbBvhIeZjOaSncWtVfwAn4 +-> piv-p256 xqSe8Q A2icKgRBVKO9BjUUSNDLds1Eq+DL1+wfLy0r4U1Q8YNP +630Lq8Y4XgZcDFGa4deEHGXTE3qkxPHgev7i4mKtM+o +-> dI-grease _8iXML( +22JTt6b8FjyMsaFuddGHWGgurfZBbpMTUhIHzTn7RC9/RxQblyAWinMlZjcDyGAP ++wQYeeqG0aIyFgasJLMuu1IRBQaEmRKVTiGRgh7Sm5FHnF0u6aAu0pj/iOX2xbw +--- 04iwf902sMdNHLYmynps8wNLhwrYNoK0w99KdPz7SO0 +ye=$quհM/\û}u4ȚjYTo,_ lOfS24S +T;7p{6 \ No newline at end of file diff --git a/secrets/global.nix.age b/secrets/global.nix.age index ac37e4535dbb7f80677e022482010513c9b6117a..73f90c006118a3d9321c2d543504ea234548cc32 100644 GIT binary patch delta 2367 zcmV-F3BdNG62=mcAb&%8Qg~rjaaT%mbx~S%H*0lBRdaSkZBbNBS4&e)N_uZKXGnH2 zaYkWQO$tmkMlp0SH#cE#GFWplFLE#|F=|?9R&Z!;R7z8Ccy)SfF=taYL1%0-Sqd#a zAaH4REpRe5HXwL$Q)M_&AVDxsVPbT0QAO za6t+!J|H_;R84kNEoX9NVRK~)F?M!ORZvAVc1J^XQ*3!`Hg|SdRXIyzNHR=oIBYUX zF>FtGbXaL_R)2U+a8yx7XERT3Lwa^dY-40nRx2`V3N0-yAXZvYdNw#=ZB0jTHE2gc zIB8ICa5qwRa5qjbW@R`qSy^;bS4mVvR%}Xh3M2&5P*s#{XwBopuhm2)>oNVhVFdFV zV11EQDP~z@!_=)m*M%Yi_2)DqmA{M}QRq0j#h~m``hU$5Dm>fe>sEs4-%R-Nd!!nW z?rK@KD``}~@^FMKBsPjG*xWQJF~nE6DRKyxU#g;&J}WvrD=kUGcc$&n6CfLytII5S z%1f`$#s0%m-H?kyV1y;5S_{4fF>cTwKpj3|(>t=q)-(HqpKUzY@3r$PgEVBbX*t z|2;h>jql7H(`h->2nYMfB#sVV68TaV73D|u7Jp@JPSW%;xMWr{`AtVE2*T@$x}dK! z2XgVlijVoo=Itp)7^6smTn>kIUC{Lq&Re6{r*jYJ(J3Ekl*uebwWQ>w2(#A8BZyF` z*eLsp4tgNoI+WE<1;H!=N7}GgWS9ER9(kP(8h8_KE)VD(bHPS8+>p8qNmMj2;u$DCXU+|8S=QN`C%V$n1<-?dMkWK02Eml@ zb$MqO(ErtOWs$-n;K#Nq#Ivx+3OTI{Uw>2Ci9#>~nq#f$1nr%iR-{y5hu=?QaXLi; zLG^c67AS#HVW6@Lq8`SU(i>t!Bim$H=oHe{k_+ou0;?{6Ed@MO^{kcC?6*L%JGV|7 zvIu8A{pn8?1*;lOccF4vTaq@VS|FKKplp8KD-V5H${jCdMmSx8TIrVmZ`4*1=X|J&9ZMJ#~wS7EFE^;XTWi zV;`q=W~Y^%mT?}EU)KsxhZgGa+b~Q_x5d5uB1XeG$kTB{j~o7x-HyAXa2pNgf=+qR z1Yj>WZl19?F9wAfJ4ccCY^}=orho8=l`QRSaJ&OeW+!g@tFH%Y2z8kg8=B z(}{z19jEfz4F+`R0px%v^?~y9O)68zzC_4@_*b`9&j}!?L&$Gefs(Ygb@eq^ zOl9Re2v}4IThRbR!FK2hNeQhd0%KxnX)@?Ihx%z?=7CM0ej9B{&1>oYS6;ZjN&j)= zG8N~itHGb(lyT__wtr}mY;`nEV#ef?u6K6>eu|3|lT&`)$wlA0K`HOsB2E$&S)JjD z`@iTc0exxly*1EJ?yQPaHUTfVaE32=EL;L$Fa{v6$aD(l5+9H& z%(^pV$SLVFpbj%G4nJ}71|B0bJ5Lv1Z3-HWSR~9&Qy%*5U+MrXh$Gc^8Y*&Ibpr+( zu|&NIp-!#EKrxTrG72-9c{vzNup`FcYiYr~P4Gv>RNB37*k#P_LpJBkGOe6ttxpZD zJEt_MuYU?5st>=0J#n^HBxL(xR~X#>l)N_xlc4~%J1Z4#(@`uRoQF3QpG4s#XMwmi z)nx7TWMNe0wB3uKF=p(}-BX%V(&vGo{#i297cUvu3rqA1b4*z;EHc7z2c^Q9m*phd z)de9I#qG}v35SK_YJGwLR?L^ma^z3dcAm>BJ2-U+{t{sESfjCw{eai=2o94yLF$kH lEDlME8^CT)FGnZjp|#@NN>)UlPk0}o7})Fbo(^+xI?-?HI_v-d delta 2333 zcmV+&3F7v~5~LE4Ab%?_VlqooVt8yTQf^`}I5uKtFm7mebTCO*X?0a}ZZAheb2VpA zS5k3SRSITyL@Q`GFhzMWVq#KsWNCCSO>1Z~Zb^DoXe%*gGdEBxY(pz`R7^2OSqd#a zAaH4REpRe5HXwL$Q)M_&AVD~1FGy-aLQ8c;YEUpnQDikMRDVM-R!~WKP%w8ZL1Z^! zR8?zrc{epVV^az@XgM@tZAW!OFKIVMP%kh=WNboVc5YW?R#8SuGjuUUQ*=*iR7`X- zGG_`cJ|I&XGG=;rabrX{F=tI{YIJK*3PO5!T1iJTRZBQQRy1`{ zM0RmmN=bNPN@z<}XKZCgI5$;DFKAO_cV|s;SxIGZSW{V2Zb4aWcx^a&X>(UGRSHXI za8wE{EiE8=Q)DtPb5=NZY%z3NIcH=uS7SmlXgFsvT7NS$Gj~B!Gf-+!Qc6-!N@y?& zBrNRN(pKVbK6~}Bct7Dslo+Yq@~Zjp1=EPU{nx;>Z#u`M#~6Czl8pCzFaT^TN}#ee zWMc^zWwgKE*pY0iS0K(;1+;IYI)hbVo<`TwF-yQVlKBYT?|Cl}*$MOW8B!w` z|G|3!Y<~xVGQA1k5V9L%L>RbomJDpa z18vk)jT?i*B2UM`Wa8u|-LaVZ%o&UuOD6l&MvHeDo4jUBGWW5^oZ)ss!QwhjYEK1Y zT(lCOgRkwW%xjNmIM$dmm{1um)hDk^On=3hgck##1cREn+zMX@aHu`)1NnC~k98XUg;^fm+Jsp~j#`mn-9MbbK^1 zCcBA8CrNt>Bcx!u_-fSMSEyHeXwc%StI#qceSFSin}nEefoA1@NRVqM*<*C7A%Dys z1{_ugic0~4@h;1|O#KIMzl3(dvweAt0$BNYEXo{kr>jX8EMfcTk-lyNRQG2`*V7f5 zo_cLBJ>f>JAo30t3-yfFzjg+J$|)7+9IzR=C3;*_zHCOUmS&TT2pQS$bG%#VLJZF| z)@C_@PIjOz@2<(caBVk|OWhj@Pk&`?@m9#~o4eD2vecc%;~y&r^Az!jcvDxvkKyVV z!s{p13~KCg0_jzASGVIXJmZRE+3_h=o$@;GU=|8P$!D6}bc3AB4rq~eYUAQYKaLQ_PLw_oy$iyY% z+wI&Ym=eOB{Xg30`+LZ)ylTU!p5@UiV3MgXhydJ?f zbP%=q3trtT7_Wyc(>7S7e<#WoyDIT&?f|iduqr1}LaRA@5|L_I@o^zGFt|K#cB=)b zz%Yo9^3;wRL)F=8EI6r-j(@bIe9}d_=$s^8eKQA4Fr#uCR&7|CHg)lJsB*@nOnICB zMxy+s1Wjv#bs1lhb@oKcmME{ejb;QhHFD5^6sZ%cjHliW8acFap zR^G-Y`Gfv8n$s?Dv(IiFRx4MiBzR3XY(qhRG=hZM&9KRG?*l&e!+%zoO%kT$yl7GA z4A?H4;-lN#OVRNnDbeq!affUag0!F0s_v_TX6phrkFB}dEddUGsOdO3+XY>2-!p|4 zv%>g=fU;Qwb~tm+!~wQ4z0kr3t+hzzwkdh`91I{i2EJaB)EEO!Et%Ztq+=nnQJM+p*3{=Xf5{c+Q=`7vNavtH<2szlKZyA)m4U!_e+B& zpxEThtjfmvv;#$kUj~6yj^8c}3ad6hAgOO=KJrINOw6_{zo_X;=sZtsN5i48RK$c~ zPao}sUpNLev)Z9$H@D{O>bRmCQZ!!r^O9XLIj=?}1Ah<-0>xUA^6nhwraMW^#^1m& z{$L>O;CbC#h^6migDaEYnB4)y!x(xcN>ZRCVw`?OW%T<|ckhNA zku%-|i%K{&53Y=@nE;>(rcfAy9?Ox6CK-JBQ^@pXvmw%3O;qJ(Mr^EAlRHp{ONVam zo3G(ASbrf$4TDPjYwsiMyu*y#8iD8-ylQqID{kI@aCz^R(m(HzYHb5eio{MhvB7ofzsiu1`7RVe7H5H^-y ssh-ed25519 vqFVQw q5QZqkI20/kI0xMQ3sRewA122Cm13qfE0LhuFr9K6g8 +0qWz+XFjeyiNnGlAfffoL/iZdwS9NzXOYyl7FmUY2hI +-> 2FQ(N@-grease + +--- AVDxWkWApQ6FCrAwGvzg9u3RklcWZeQFg2iqqqeNQ2E +^|^ 1D"Zм/`Jۯu'PvU,)Ew\gdA /MX@2 \ No newline at end of file diff --git a/secrets/rekeyed/ward-kanidm/90858ec737eadb4ec04d5ca74f5092d3-kanidm-oauth2-paperless.age b/secrets/rekeyed/ward-kanidm/90858ec737eadb4ec04d5ca74f5092d3-kanidm-oauth2-paperless.age new file mode 100644 index 0000000000000000000000000000000000000000..6bcb6a2b093b13ded537379250152bb521186cff GIT binary patch literal 319 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+OwM$T3REyKsH!k@ z%E@x^Hz+nYDfV$nPBHQQM z$}hGo%&hQotSm6ib$5143pWn2%r?pj)i%j8@dVrEsidK0ubW1q~f;1h0^%%!WVtKeNylH+WaXzJ$V>k*Ki zlW!2{Sr(b^6pe_~EzTrbvUp7s^=P3YO# zt5degm$m-iy|v2qfh#KS?Qo5Fn`5qNbVc)V_7C-Wm2GPTb@yj26t7v&uDK{otK_$x P)1vSD`qow5T(}MZ^5t?D literal 0 HcmV?d00001