Merge PR #46: Harden UpdateCenter public route methods

P0 public-host containment: keep update.flowercore.io GET/HEAD only and preserve regression tests.
This commit was merged in pull request #46.
This commit is contained in:
2026-06-18 15:38:59 +00:00
4 changed files with 19 additions and 4 deletions

View File

@@ -43,5 +43,6 @@ shared origin cert must exist in every namespace that serves a
```powershell
kubectl.exe --kubeconfig C:\Users\AndrewStoltz\.kube\rke2.yaml -n argocd get application infra-fc-updater
kubectl.exe --kubeconfig C:\Users\AndrewStoltz\.kube\rke2.yaml -n fc-updater get deploy,svc,ingressroute,certificate,pvc
curl.exe -sk https://update.flowercore.io/api/v1/manifests/_schema
curl.exe -sk https://update.flowercore.io/
curl.exe -sk -o NUL -w "%{http_code}`n" https://update.flowercore.io/login
```

View File

@@ -266,7 +266,7 @@ spec:
entryPoints:
- websecure
routes:
- match: (Host(`update.flowercore.io`) || Host(`updates.flowercore.io`)) && (Method(`GET`) || Method(`HEAD`) || Method(`POST`) || Method(`OPTIONS`))
- match: (Host(`update.flowercore.io`) || Host(`updates.flowercore.io`)) && (Method(`GET`) || Method(`HEAD`))
kind: Rule
services:
- name: updatecenter-web

View File

@@ -1013,6 +1013,22 @@ public sealed class FleetManifestLintTests
match.Should().NotContain("Method(`POST`)");
}
[Fact]
public void UpdateCenterPublicIngress_KeepsDeliveryOnlyGetHeadMethodAllowlist()
{
var publicIngress = AppDocuments("fc-updater")
.Single(document => document.Kind == "IngressRoute" && document.Name == "updatecenter-web-public");
var route = publicIngress.MappingSequence("spec", "routes").Should().ContainSingle().Subject;
var match = ManifestNodeExtensions.Scalar(route, "match");
match.Should().Contain("Host(`update.flowercore.io`)");
match.Should().Contain("Host(`updates.flowercore.io`)");
match.Should().Contain("Method(`GET`)");
match.Should().Contain("Method(`HEAD`)");
match.Should().NotContain("Method(`POST`)");
match.Should().NotContain("Method(`OPTIONS`)");
}
[Fact]
public void DnsAndMediaIngressRoutes_MatchLiveInternalHosts()
{

View File

@@ -9,8 +9,6 @@ package bluejayinfra.public_readwrite_allowlist
public_readwrite_hosts := {
"updatecenter.iamworkin.lan",
"updates.iamworkin.lan",
"update.flowercore.io",
"updates.flowercore.io",
}
required_methods := {"GET", "HEAD", "POST", "OPTIONS"}