forge: fetch the OIDC client secret from bao instead of a host-side copy
The forge's login source read its OIDC client secret from a file that `hive-forge-oidc-secret` copied out of authelia's container tree. That unit only existed where authelia ran on the forge's host (`ssoLocal`), so a forge anywhere else needed the file placed by hand. The publisher on authelia's host now carries the forge's client secret to `secret/swarm/services/<forge client id>/oidc/client`, like every other swarm service's. On the forge's host `swarm-bao-forge-oidc`, a copy of `swarm-bao-matrix-oidc`, reads it under the forge publisher's leaf (the forge host's one store identity, whose policy gains read on that one path) and writes the file `forgejo-sso-source` reads, re-running the login source when the value changes. It retries on the shared store-retry shape while the store is down or the secret is not yet published. `hive-forge-oidc-secret` is removed, `clientSecretFile` defaults to the in-container path wherever the forge runs, and the `ssoLocal` gate on the login source's resolver ordering goes with it: the login source fetches the issuer's discovery document on every forge host. Refs #5015
This commit is contained in:
parent
6bf4792d61
commit
f6ca5f1433
10 changed files with 332 additions and 159 deletions
|
|
@ -1373,16 +1373,19 @@ let
|
|||
lib.hasInfix "/ci-runner.pem ]" s && lib.hasInfix "swarm-ci-runner \"\" clientAuth" s;
|
||||
}
|
||||
{
|
||||
# The forge's host is the one writer of the controller's forge token.
|
||||
# Pinned as the whole stanza, so an added `read` fails: it copies a file
|
||||
# in and never reads one back.
|
||||
name = "the forge publisher's grant is writing the controller's forge token and nothing else";
|
||||
# The forge's host is the one writer of the controller's forge token,
|
||||
# and reads the forge's own OIDC client secret under the same leaf.
|
||||
# Pinned as two whole stanzas, so an added `read` on the token or a
|
||||
# write or wildcard on the secret fails.
|
||||
name = "the forge publisher's grant is writing the controller's forge token and reading the forge's OIDC secret, and nothing else";
|
||||
ok =
|
||||
let
|
||||
s = baoGrantHere.systemd.services.swarm-bao-forge-publisher-policy.script;
|
||||
in
|
||||
lib.hasInfix "path \"secret/data/swarm/controller/swarm-controller/forge/token\" {\n capabilities = [\"create\", \"update\"]\n}" s
|
||||
&& lib.length (lib.filter lib.isList (builtins.split "path \"" s)) == 1
|
||||
&& lib.hasInfix "path \"secret/data/swarm/services/forgejo/oidc/client\" {\n capabilities = [\"read\"]\n}" s
|
||||
&& lib.length (lib.filter lib.isList (builtins.split "path \"" s)) == 2
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/*" s)
|
||||
&& lib.hasInfix "auth/cert/certs/swarm-forge-publisher" s
|
||||
&& lib.hasInfix "allowed_common_names=swarm-forge-publisher" s
|
||||
&& lib.hasInfix "token_policies=swarm-forge-publisher" s;
|
||||
|
|
@ -1413,6 +1416,16 @@ let
|
|||
"swarm-bao-forge-publisher-policy"
|
||||
];
|
||||
}
|
||||
{
|
||||
# The forge's OIDC client secret by name: the forge publisher reads it,
|
||||
# and the secret publisher writes it under its `swarm/services/*` grant,
|
||||
# which names no service.
|
||||
name = "no granting unit but the forge publisher's names the forge's OIDC secret";
|
||||
ok =
|
||||
lib.filter (
|
||||
u: lib.hasInfix "swarm/services/forgejo/oidc/client" baoGrantHere.systemd.services.${u}.script
|
||||
) grantingUnitNames == [ "swarm-bao-forge-publisher-policy" ];
|
||||
}
|
||||
{
|
||||
name = "the PKI unit signs the forge publisher's leaf under its own subject";
|
||||
ok =
|
||||
|
|
|
|||
Loading…
Reference in a new issue