wip(sgx): firefly-sparda-fetch service + timer (DISABLED)
End-to-end FinTS pipeline against Sparda Südwest is wired up but disabled — aqbanking 6.8.2's `-P pinfile` flag does not consume the file content correctly on this build (verified: pinfile bytes match the manually-typed PIN exactly, yet the bank receives a wrong PIN). Three rejected attempts locked the access at Sparda; do not re-arm the timer until the auth path is replaced (likely python-fints). What works: - aqbanking config and FinTS dialog (manual PIN entry) - getaccsepa workaround for HKCAZ "Mussfeld 9160" rejection - custom CSV profile (decimal amounts + IBAN columns) wired in - Firefly importer auto-upload settings + sops secret slot - inbox + profile-symlink tmpfiles What's broken: - Headless PIN delivery via aqbanking-cli -P - Timer left wantedBy=[] so it cannot fire post-deploy Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
55bef14076
commit
74af9fd5ac
1 changed files with 110 additions and 6 deletions
|
|
@ -2,8 +2,24 @@
|
||||||
let
|
let
|
||||||
domain = "firefly.hoyer.world";
|
domain = "firefly.hoyer.world";
|
||||||
importDomain = "firefly-import.hoyer.world";
|
importDomain = "firefly-import.hoyer.world";
|
||||||
aqHome = "/var/lib/firefly-aqbanking";
|
importerHome = "/var/lib/firefly-iii-data-importer";
|
||||||
inbox = "/var/lib/firefly-iii-data-importer/inbox";
|
inbox = "${importerHome}/inbox";
|
||||||
|
configFile = "${importerHome}/sparda-config.json";
|
||||||
|
|
||||||
|
bankCode = "55090500";
|
||||||
|
userId = "5987838198";
|
||||||
|
giroAccountId = "3";
|
||||||
|
|
||||||
|
# aqbanking 6.8.2 ships only an "import" profile and a "full" export
|
||||||
|
# profile that renders amounts as fractions ("-499/100"). Firefly's CSV
|
||||||
|
# importer needs decimal amounts and benefits from localIban/remoteIban
|
||||||
|
# columns, so derive a profile that combines "full"'s columns with
|
||||||
|
# decimal value formatting.
|
||||||
|
fireflyCsvProfile = pkgs.runCommand "aqbanking-csv-firefly-profile" { } ''
|
||||||
|
sed 's/name="full"/name="firefly"/; s/valueFormat="rational"/valueFormat="float"/' \
|
||||||
|
${pkgs.aqbanking}/share/aqbanking/imexporters/csv/profiles/full.conf > $out
|
||||||
|
'';
|
||||||
|
|
||||||
vhostBase = {
|
vhostBase = {
|
||||||
enableACME = false;
|
enableACME = false;
|
||||||
useACMEHost = "internal.hoyer.world";
|
useACMEHost = "internal.hoyer.world";
|
||||||
|
|
@ -20,15 +36,98 @@ in
|
||||||
sopsFile = ../../../.secrets/sgx/firefly.yaml;
|
sopsFile = ../../../.secrets/sgx/firefly.yaml;
|
||||||
owner = "firefly-iii-data-importer";
|
owner = "firefly-iii-data-importer";
|
||||||
};
|
};
|
||||||
|
"firefly/auto_import_secret" = {
|
||||||
|
sopsFile = ../../../.secrets/sgx/firefly.yaml;
|
||||||
|
owner = "firefly-iii-data-importer";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.aqbanking ];
|
environment.systemPackages = [ pkgs.aqbanking ];
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd = {
|
||||||
"d ${aqHome} 0700 firefly-iii-data-importer firefly-iii-data-importer -"
|
tmpfiles.rules = [
|
||||||
"d ${inbox} 0700 firefly-iii-data-importer firefly-iii-data-importer -"
|
"d ${inbox} 0700 firefly-iii-data-importer nginx -"
|
||||||
|
"d ${importerHome}/.aqbanking/imexporters/csv/profiles 0700 firefly-iii-data-importer nginx -"
|
||||||
|
"L+ ${importerHome}/.aqbanking/imexporters/csv/profiles/firefly.conf - - - - ${fireflyCsvProfile}"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.firefly-sparda-fetch = {
|
||||||
|
description = "Fetch Sparda transactions via FinTS and trigger Firefly auto-import";
|
||||||
|
after = [
|
||||||
|
"network-online.target"
|
||||||
|
"phpfpm-firefly-iii-data-importer.service"
|
||||||
|
];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
path = with pkgs; [
|
||||||
|
aqbanking
|
||||||
|
curl
|
||||||
|
coreutils
|
||||||
|
];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = "firefly-iii-data-importer";
|
||||||
|
Group = "nginx";
|
||||||
|
RuntimeDirectory = "firefly-sparda-fetch";
|
||||||
|
LoadCredential = [
|
||||||
|
"pin:${config.sops.secrets."firefly/sparda_pin".path}"
|
||||||
|
"secret:${config.sops.secrets."firefly/auto_import_secret".path}"
|
||||||
|
];
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ReadWritePaths = [ importerHome ];
|
||||||
|
ProtectHome = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
TimeoutStartSec = "3min";
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
pinfile=$RUNTIME_DIRECTORY/pinfile
|
||||||
|
umask 077
|
||||||
|
printf 'PIN_%s_%s = "%s"\n' "${bankCode}" "${userId}" \
|
||||||
|
"$(<"$CREDENTIALS_DIRECTORY/pin")" >"$pinfile"
|
||||||
|
|
||||||
|
ts=$(date +%Y%m%d-%H%M%S)
|
||||||
|
ctx=$RUNTIME_DIRECTORY/ctx-$ts.aqb
|
||||||
|
out=${inbox}/sparda-$ts.csv
|
||||||
|
|
||||||
|
# Refresh SEPA account list — Atruvia/Sparda rejects HKCAZ
|
||||||
|
# ("Mussfeld 9160") if this metadata isn't fresh in the dialog.
|
||||||
|
aqhbci-tool4 -n -A -P "$pinfile" getaccsepa -u ${giroAccountId}
|
||||||
|
|
||||||
|
fromdate=$(date --date='35 days ago' +%Y%m%d)
|
||||||
|
aqbanking-cli -n -A -P "$pinfile" request \
|
||||||
|
--transactions --fromdate="$fromdate" \
|
||||||
|
--aid=${giroAccountId} -c "$ctx"
|
||||||
|
|
||||||
|
aqbanking-cli export \
|
||||||
|
--exporter=csv --profile=firefly \
|
||||||
|
-c "$ctx" -o "$out"
|
||||||
|
|
||||||
|
secret=$(<"$CREDENTIALS_DIRECTORY/secret")
|
||||||
|
curl -fsS -X POST \
|
||||||
|
"https://${importDomain}/autoupload?secret=$secret" \
|
||||||
|
-F "json=@${configFile}" \
|
||||||
|
-F "importable=@$out"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Timer disabled while we work around aqbanking 6.8.2's broken
|
||||||
|
# `-P pinfile` handling. The fetch service authenticates with a wrong
|
||||||
|
# PIN against the bank — three runs locked the access at Sparda. Do
|
||||||
|
# not re-enable until the auth path is replaced (likely python-fints).
|
||||||
|
timers.firefly-sparda-fetch = {
|
||||||
|
wantedBy = [ ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "daily";
|
||||||
|
Persistent = true;
|
||||||
|
RandomizedDelaySec = "1h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
firefly-iii = {
|
firefly-iii = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -54,6 +153,10 @@ in
|
||||||
FIREFLY_III_URL = "https://${domain}";
|
FIREFLY_III_URL = "https://${domain}";
|
||||||
VANITY_URL = "https://${importDomain}";
|
VANITY_URL = "https://${importDomain}";
|
||||||
TZ = "Europe/Berlin";
|
TZ = "Europe/Berlin";
|
||||||
|
CAN_POST_FILES = "true";
|
||||||
|
CAN_POST_AUTOIMPORT = "true";
|
||||||
|
IMPORT_DIR_ALLOWLIST = inbox;
|
||||||
|
AUTO_IMPORT_SECRET_FILE = config.sops.secrets."firefly/auto_import_secret".path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -62,4 +165,5 @@ in
|
||||||
${importDomain} = vhostBase;
|
${importDomain} = vhostBase;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue