bridge: load the token file as a systemd credential
A root-only token file (uploaded before activation, also read by the forge's hook as root) could not be read by the ci-bridge user. e2e now uses a 0400 root-owned token.
2 files changed,  +13, -3
M nix/module.nix
+5, -1
 1@@ -300,6 +300,10 @@ in
 2           User = "ci-bridge";
 3           StateDirectory = "ci-bridge";
 4           ReadWritePaths = [ cfg.bridge.spoolDir ];
 5+          # The token file may be root-only (it is uploaded before the user
 6+          # exists, and the forge's hook reads it too): load it as a
 7+          # credential, %d being the unit's credentials directory.
 8+          LoadCredential = optionals (cfg.bridge.tokenFile != null) [ "token:${cfg.bridge.tokenFile}" ];
 9           ExecStart = lib.escapeShellArgs (
10             [
11               exe
12@@ -311,7 +315,7 @@ in
13               "--forge-host=${cfg.bridge.forgeHost}"
14             ]
15             ++ flag "owner-did" cfg.bridge.ownerDid
16-            ++ flag "token-file" cfg.bridge.tokenFile
17+            ++ optionals (cfg.bridge.tokenFile != null) [ "--token-file=%d/token" ]
18           );
19           Restart = "always";
20           RestartSec = 5;
M nix/tests/e2e.nix
+8, -2
 1@@ -43,7 +43,7 @@ let
 2   '';
 3   hook = pkgs.writeShellScript "post-receive" ''
 4     exec ${self.packages.${pkgs.stdenv.hostPlatform.system}.ci}/bin/ci bridge notify \
 5-      --spool /var/lib/ci-bridge/spool --server http://127.0.0.1:8475 --token-file ${token}
 6+      --spool /var/lib/ci-bridge/spool --server http://127.0.0.1:8475 --token-file /etc/ci/bridge-token
 7   '';
 8   node =
 9     { pasta }:
10@@ -60,6 +60,12 @@ let
11         source = "${keys}/age-identity";
12         mode = "0600";
13       };
14+      # root-only, as the fleet uploads it: the bridge (user ci-bridge) must
15+      # get it as a credential, and the forge's hook (root) reads the file
16+      environment.etc."ci/bridge-token" = {
17+        source = token;
18+        mode = "0400";
19+      };
20 
21       # soft-serve as the forge runs it (root, /var/soft/data, a custom hook)
22       systemd.services.soft-serve = {
23@@ -83,7 +89,7 @@ let
24           enable = true;
25           forgeHost = "git.test";
26           ownerDid = "did:plc:test";
27-          tokenFile = "${token}";
28+          tokenFile = "/etc/ci/bridge-token";
29         };
30         runner = {
31           enable = true;