hive-forge: read the webhook host from the option the target is built from
`swarm.domain` is not the value swarm-controller addresses this hive with — `swarm-controller.nix` builds `SWARM_CONTROLLER_PUBLIC_URL` from `swarm.ui.domain`, which merely defaults to it and is documented as overridable. Allowing the one and being delivered the other would work until someone takes that option up, then fail as a refused delivery with nothing naming the cause. Also states why the entry is NOT gated on `deploy.swarm-ui.enable`, which is what makes the controller register the hooks at all: in a spread deployment the forge and the swarm UI are different hosts, so that per-host flag is false exactly where the allow-list entry is needed. The comment-block lint caught the prose at 35 lines; trimmed to the parts a reader cannot re-derive.
This commit is contained in:
parent
584c99ce13
commit
b9919164e4
1 changed files with 29 additions and 25 deletions
|
|
@ -9,6 +9,13 @@ let
|
|||
gatewayCfg = config.services.hyperhive.gateway;
|
||||
hyperhiveDomain = config.services.hyperhive.domain;
|
||||
swarmDomain = config.services.hyperhive.swarm.domain;
|
||||
# The host the swarm-controller's webhooks actually target. NOT
|
||||
# `swarm.domain`: `swarm-controller.nix` builds `SWARM_CONTROLLER_PUBLIC_URL`
|
||||
# from `swarm.ui.domain`, which merely *defaults* to the swarm domain and is
|
||||
# documented as overridable. Reading the other one would be right until
|
||||
# someone takes that option up, and then wrong in a way whose only symptom is
|
||||
# a refused delivery.
|
||||
swarmUiDomain = config.services.hyperhive.swarm.ui.domain;
|
||||
tlsCfg = config.services.hyperhive.deploy.hive-controller.tls;
|
||||
networkCfg = config.services.hyperhive.network;
|
||||
|
||||
|
|
@ -807,41 +814,38 @@ in
|
|||
# forge.darkest.space, etc.) were failing every sync
|
||||
# attempt without this.
|
||||
migrations.ALLOWED_DOMAINS = "*";
|
||||
# `ALLOWED_HOST_LIST` is forgejo's webhook SSRF allow-list, and
|
||||
# it's a STRICT whitelist (only listed hosts deliver). Its
|
||||
# default is the `external` builtin: all public unicast IPs are
|
||||
# allowed, private/loopback denied. We must KEEP `external` so
|
||||
# user-repo webhooks to public hosts (github, slack, …) keep
|
||||
# working, and ADD the hive gateway host on top: the config-PR +
|
||||
# knowledge webhooks target `https://<hyperhive domain>/webhook/*`,
|
||||
# which resolves to a private (RFC-1918) gateway IP that
|
||||
# `external` alone would deny (so they'd only ever be caught by
|
||||
# the 5-min poll fallback). Naming the single gateway host is
|
||||
# `ALLOWED_HOST_LIST` is forgejo's webhook SSRF allow-list: a
|
||||
# STRICT whitelist whose `external` builtin allows public unicast
|
||||
# IPs and denies private/loopback. `external` STAYS so user-repo
|
||||
# webhooks to github/slack keep working; the hyperhive hosts are
|
||||
# added on top, because their webhooks target a private (RFC-1918)
|
||||
# gateway IP `external` alone denies — naming the two hosts is
|
||||
# tighter than the broad `private` builtin.
|
||||
#
|
||||
# ⚠️ The SWARM domain is on this list too, and leaving it off is
|
||||
# what made every swarm-controller delivery fail. Those webhooks
|
||||
# target `https://<swarm domain>/webhook/forge/*` — a different
|
||||
# host from the hive's, resolving to the same private gateway IP,
|
||||
# so `external` denies it and the hive entry does not cover it.
|
||||
# Measured from the sender's own log, which names both the host
|
||||
# and the rule:
|
||||
# TWO hosts, not one. The hive's carries the config-PR + knowledge
|
||||
# hooks; the swarm's carries swarm-controller's, and leaving it
|
||||
# off denied every one of those:
|
||||
# deny '<swarm host>(10.42.0.1:443)' — webhook can only call
|
||||
# allowed HTTP servers
|
||||
#
|
||||
# deny 'constellation.darkest.space(10.42.0.1:443)'
|
||||
# webhook can only call allowed HTTP servers
|
||||
# (check your webhook.ALLOWED_HOST_LIST setting)
|
||||
# ⚠️ `swarm.ui.domain`, NOT `swarm.domain`: swarm-controller.nix
|
||||
# builds its `SWARM_CONTROLLER_PUBLIC_URL` from the former, which
|
||||
# only *defaults* to the latter and is documented as overridable.
|
||||
#
|
||||
# `optional` because a hive with no swarm has no such domain, and
|
||||
# `unique` because an all-local deployment can legitimately set
|
||||
# both to the same string — a duplicate entry is harmless to
|
||||
# forgejo but reads as a mistake.
|
||||
# Not gated on `deploy.swarm-ui.enable`, even though that is what
|
||||
# makes the controller register the hooks: in a spread deployment
|
||||
# the forge and the UI are different hosts, so that per-host flag
|
||||
# is false exactly where this entry is needed.
|
||||
#
|
||||
# `unique` because an all-local swarm legitimately serves both
|
||||
# from one name.
|
||||
webhook.ALLOWED_HOST_LIST = lib.concatStringsSep "," (
|
||||
lib.unique (
|
||||
[
|
||||
"external"
|
||||
hyperhiveDomain
|
||||
]
|
||||
++ lib.optional (swarmDomain != null) swarmDomain
|
||||
++ lib.optional (swarmDomain != null) swarmUiDomain
|
||||
)
|
||||
);
|
||||
log.LEVEL = "Warn";
|
||||
|
|
|
|||
Loading…
Reference in a new issue