From a1f271caf02dc86e9a9ff956b224eed569ad2d07 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 22 Mar 2025 16:30:35 +0100 Subject: [PATCH] feat: add openid connect to actual --- hosts/sire/guests/actual.nix | 31 ++++++++++++++++++ hosts/ward/guests/kanidm.nix | 18 ++++++++++ .../ward-kanidm/kanidm-oauth2-actual.age | Bin 0 -> 416 bytes secrets/global.nix.age | Bin 3532 -> 3609 bytes ...0fc8c655b6-actual-oauth2-client-secret.age | 8 +++++ ...bbf8cfc65e0d83c02-kanidm-oauth2-actual.age | 7 ++++ 6 files changed, 64 insertions(+) create mode 100644 secrets/generated/ward-kanidm/kanidm-oauth2-actual.age create mode 100644 secrets/rekeyed/sire-actual/cdf5433be3f5150b4dbe650fc8c655b6-actual-oauth2-client-secret.age create mode 100644 secrets/rekeyed/ward-kanidm/60542dbad9f5a1dbbf8cfc65e0d83c02-kanidm-oauth2-actual.age diff --git a/hosts/sire/guests/actual.nix b/hosts/sire/guests/actual.nix index 26c208b..40e56a1 100644 --- a/hosts/sire/guests/actual.nix +++ b/hosts/sire/guests/actual.nix @@ -1,11 +1,14 @@ { config, globals, + lib, + pkgs, nodes, ... }: let actualDomain = "finance.${globals.domains.me}"; + client_id = "actual"; in { wireguard.proxy-sentinel = { @@ -13,6 +16,11 @@ in firewallRuleForNode.sentinel.allowedTCPPorts = [ config.services.actual.settings.port ]; }; + # Mirror the original oauth2 secret + age.secrets.actual-oauth2-client-secret = { + inherit (nodes.ward-kanidm.config.age.secrets.kanidm-oauth2-actual) rekeyFile; + }; + environment.persistence."/persist".directories = [ { directory = "/var/lib/private/actual"; @@ -25,6 +33,29 @@ in settings.trustedProxies = [ nodes.sentinel.config.wireguard.proxy-sentinel.ipv4 ]; }; + # NOTE: state: to enable openid, we need to call their enable-openid script once + # which COPIES this data to the database :( so changing these values later will + # require manual intervention. + systemd.services.actual = { + serviceConfig.ExecStart = lib.mkForce [ + (pkgs.writeShellScript "start-actual" '' + export ACTUAL_OPENID_CLIENT_SECRET=$(< "$CREDENTIALS_DIRECTORY"/oauth2-client-secret) + exec ${lib.getExe config.services.actual.package} + '') + ]; + serviceConfig.LoadCredential = [ + "oauth2-client-secret:${config.age.secrets.actual-oauth2-client-secret.path}" + ]; + environment = { + ACTUAL_OPENID_ENFORCE = "true"; + ACTUAL_TOKEN_EXPIRATION = "openid-provider"; + + ACTUAL_OPENID_DISCOVERY_URL = "https://${globals.services.kanidm.domain}/oauth2/openid/${client_id}/.well-known/openid-configuration"; + ACTUAL_OPENID_CLIENT_ID = client_id; + ACTUAL_OPENID_SERVER_HOSTNAME = "https://${actualDomain}"; + }; + }; + globals.services.actual.domain = actualDomain; globals.monitoring.http.actual = { url = "https://${actualDomain}/"; diff --git a/hosts/ward/guests/kanidm.nix b/hosts/ward/guests/kanidm.nix index 010bfa2..7995222 100644 --- a/hosts/ward/guests/kanidm.nix +++ b/hosts/ward/guests/kanidm.nix @@ -35,6 +35,7 @@ in age.secrets.kanidm-admin-password = mkRandomSecret; age.secrets.kanidm-idm-admin-password = mkRandomSecret; + age.secrets.kanidm-oauth2-actual = mkRandomSecret; age.secrets.kanidm-oauth2-forgejo = mkRandomSecret; age.secrets.kanidm-oauth2-grafana = mkRandomSecret; age.secrets.kanidm-oauth2-immich = mkRandomSecret; @@ -136,6 +137,23 @@ in ]; }; + # Actual + groups."actual.access" = { }; + systems.oauth2.actual = { + displayName = "Actual Budget"; + originUrl = "https://${globals.services.actual.domain}/openid/callback"; + originLanding = "https://${globals.services.actual.domain}/"; + basicSecretFile = config.age.secrets.kanidm-oauth2-actual.path; + preferShortUsername = true; + # XXX: RS256 is used instead of ES256 so additionally we need legacy crypto + enableLegacyCrypto = true; + scopeMaps."actual.access" = [ + "openid" + "email" + "profile" + ]; + }; + # Firezone groups."firezone.access" = { }; systems.oauth2.firezone = { diff --git a/secrets/generated/ward-kanidm/kanidm-oauth2-actual.age b/secrets/generated/ward-kanidm/kanidm-oauth2-actual.age new file mode 100644 index 0000000000000000000000000000000000000000..654c68ecf3715d35382485c103141c307375b527 GIT binary patch literal 416 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR2FFfuhYv{Xnh^$*JptT6R0E!2)kHum#3 zwajpGa&${f&Gtxks_=8J%B%>tD0VXqD(5Q5G0yUEH}S5@&-64e4=O42GYyP#G6@TH z4lFGz&`*y40;F9fJl4@S) zk!@^|<(cMDW?tk|WNPf@uOAi=k({5E8EG2KmFVkh6sBFOt?%a(XzuD`=@^iknd6jS zksYp|?ww*aVtT-*#E8VN8I5g3MD`i&x;-n|xJLS&DU&@;+t1Kq6;~ewVxCK+Z-^rZs zXJwe&c4PS}p$lJr?@`jLoiXuqafb#+@17|or}M8$|9pP);L(e*e7w3-WX>JlQ^!^E HPQ3>J{XdjB literal 0 HcmV?d00001 diff --git a/secrets/global.nix.age b/secrets/global.nix.age index 83d2b51c43b27b83c6496ad57bf476040c39cc58..43d79534b94bf1d07df44e820945152ae8d57a3a 100644 GIT binary patch literal 3609 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%0D$SKi0Y@CXvARti z%G?Ao;5F^8I<-Lfr)7aN|7E*x6H(8jgUww3o~r5o&# zTh5+&cn9a9T3&T01#cYAMN)SC>)!OET0TV&&&nxb4xxtBenL zKPT!4(B|5j&TGSIvg+a~u`t5!{7S{3QjkXr?jWh}wlc7*~xf6NLe zh(Fk;-e|Fc@15G_eVUsZaOxE`9A!DT=;V7K=DgAOK!L3iIM1e$qNrIFj1hTxiOq<6 zX3A!P1q+ucG@ODpXeJSTlU%|c)5u8dwMJ%wC!2Z1bKkqd;sA#qRtt;(;iAzMFU)}o z%i%Apq}Ri43SY=ukMY|hmPZB4H|IP?jIh!?U?8yI<~c&V+9t?&u2@Kd?UC89%=Lr@ zZ^Q7Rm?JstjbfdYlabsR-O| zFFAGDNGn4qs=PK)jyz!3&9GD>fj6B-6j2443V*w?LW!FZ_m}fZMt)?+0)c2$PEG7V zJ2mEXS6b4|P#2G~k2X3fJ G12URRc!#P0 diff --git a/secrets/rekeyed/sire-actual/cdf5433be3f5150b4dbe650fc8c655b6-actual-oauth2-client-secret.age b/secrets/rekeyed/sire-actual/cdf5433be3f5150b4dbe650fc8c655b6-actual-oauth2-client-secret.age new file mode 100644 index 0000000..033e9dc --- /dev/null +++ b/secrets/rekeyed/sire-actual/cdf5433be3f5150b4dbe650fc8c655b6-actual-oauth2-client-secret.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 11F4Ig 1NNgSEVlsAXLFuOa+DtVdIjqDyEPaQtruPjdGGDi9Tk +kVlPzNbF0smCXrUCp1bpJsX7tF1yzDOT7zaJTjYN5lk +-> TEO5r\@)-grease Su(^^ Vb1Y3i aBSP +ZzrXeIeghzGXua8A8Yl1B19VhtPw8jsPKt3T6HatyGplBrFWMq8ipW/Sg8lT+B6p +1c05R0oSRxc8ZPMJm+MlveZA1qIU7a/TZ5qKZA +--- tM9Q029kJaGbozrNPUdzGL9o6E5KCyH7iXWzZK/ws7E +܋|tDND~n60[f̆;D0FmE'2[Ks"Nr*&W,0` \ No newline at end of file diff --git a/secrets/rekeyed/ward-kanidm/60542dbad9f5a1dbbf8cfc65e0d83c02-kanidm-oauth2-actual.age b/secrets/rekeyed/ward-kanidm/60542dbad9f5a1dbbf8cfc65e0d83c02-kanidm-oauth2-actual.age new file mode 100644 index 0000000..82f4c59 --- /dev/null +++ b/secrets/rekeyed/ward-kanidm/60542dbad9f5a1dbbf8cfc65e0d83c02-kanidm-oauth2-actual.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 QciEZQ VcWKLWPg9nAruDvA/KXaDefLu8SF7PbMH/FJRfHteFc +1AvjkdFCx+2nqE9qvQr6/2AqxUuLgm2q9krLZ1FVqA4 +-> V]-grease gujG %5pig +jiipvJVY7Td0OMyhH7nTdSf4EBwcKQ +--- eaCRPI5enSnNczltwLy4EPgf1FRgUiBxL8BoA8vekh8 +̖mI["O!05giSCZJ* ZP*S^@`j /? \ No newline at end of file