Skip to content

Harden load balancers served from project namespaces #1107

Closed

Description

@scotwells

Gateways can now serve load balancers that live in a project's namespace (#1106). Review turned up hardening that should land before projects can write those load balancers directly. None of it is reachable until the platform starts writing into project namespaces.

Part of network load balancers.

Work

  • Address squatting. A project can claim any address no one else serves yet, and the gateways will advertise it. Only accept addresses from the platform's allocated load balancer pools.
  • Trusted gateway namespaces. A namespace is treated as trusted only because it holds a gateway. Anyone able to create a gateway in a project namespace would skip every check. Trust only the configured gateway namespace, or test that projects can't create gateways.
  • Missing permission fails quietly. If the gateway's role lacks read access to networks, it logs and then stops serving every load balancer. Fail the startup check instead.
  • Project deletion can hang. If no gateway node remains, a deleting project load balancer keeps its finalizer and the project namespace stays in Terminating.
  • Optional rollout switch. A flag to turn project-namespace serving on per location, so staging can use it before stable sites do.
  • Tests for a project or load balancer deleted mid-flight, a network deleted after acceptance, and a gateway appearing in a project namespace.
  • Scale. Each load balancer change lists every load balancer in every project to find address conflicts. Index by address if it gets slow.

Activity

  1. self-assigned this
    on Oct 26, 2026
  2. self-assigned this
    on Oct 28, 2026
  3. privateip commented on Oct 28, 2026

    @privateip
    Collaborator

    Verdict: valid, checked against main at 389a297. Each item holds in the code #1106 added:

    • Address squatting. tenantVIPConflicts (internal/controller/servicescope.go) only refuses an address another service already serves. Nothing checks a project's VIP against an allocated range, so the first claim on any unused address is accepted and advertised.
    • Trusted gateway namespaces. listServedNetworkServices and servingGateways treat every namespace that holds a NetworkGateway as a gateway namespace. A NetworkGateway created in a project namespace makes that namespace's services trusted, so the VPC ownership and VIP checks in acceptedCondition (internal/controller/networkservice_controller.go) are skipped.
    • Missing permission fails quietly. checkWatchPermissions (cmd/galactic-gateway/main.go) only logs a denied watch. Without vpcs access the first project service starts a VPC informer that never syncs, which blocks every reconciler.
    • Project deletion can hang. NetworkServiceReconciler.Reconcile returns before reconcileDelete when nodeServingGateway finds no gateway for this node. With no NetworkGateway left, nothing removes galactic.datum.net/networkservice-teardown, so the namespace stays in Terminating.
    • Rollout switch. No setting turns project-namespace serving on or off. Every gateway serves those services as soon as it runs Serve load balancers from project namespaces #1106.
    • Tests. servicescope_test.go has no cases for deletion mid-flight, a VPC deleted after acceptance, or a gateway in a project namespace.
    • Scale. acceptedCondition lists every NetworkService in the cluster for each project service it reconciles. This is a cost note, not a defect.

    These were confirmed by reading the code. A fix plan follows.

  4. privateip commented on Oct 28, 2026

    @privateip
    Collaborator

    Fix plan:

    The gateway gets three settings:

    • GALACTIC_GATEWAY_PROJECT_SERVICES turns project-namespace serving on. It defaults to false.
    • GALACTIC_GATEWAY_NAMESPACE names the one trusted gateway namespace. The DaemonSet sets it from the pod's namespace.
    • GALACTIC_GATEWAY_PROJECT_VIP_PREFIXES lists the allocated load balancer prefixes. It is required when the switch is on.

    How each item is handled:

    1. Address squatting. A project service with a VIP outside those prefixes gets Accepted=False with reason VIPOutsidePool.
    2. Trusted namespaces. With the switch on, only the configured namespace counts as a gateway namespace, and a NetworkGateway in any other namespace is ignored. With the switch off, a gateway serves only services in its own namespace, as it did before Serve load balancers from project namespaces #1106.
    3. Missing permission. A denied watch now fails startup instead of only logging. The vpcs check runs only when the switch is on.
    4. Deletion hang. When no gateway serves a deleting service, any gateway process withdraws its advertisements and removes the finalizer.
    5. Rollout switch. Handled by GALACTIC_GATEWAY_PROJECT_SERVICES above.
    6. Tests. Fake-client unit tests cover a service deleted mid-flight, a VPC deleted after acceptance, a gateway created in a project namespace, an address outside the pool, the switch turned off, and a deletion with no gateway left.
    7. Scale. Deferred: the issue asks for an index only once the full list gets slow.

    Rollout: before the platform writes load balancers into project namespaces, the staging infra overlay must turn the switch on and set the prefixes.

  5. added theissue type on Oct 28, 2026
  6. privateip commented on Oct 28, 2026

    @privateip
    Collaborator

    One addition to the plan: turning GALACTIC_GATEWAY_PROJECT_SERVICES off after it was on left project services' advertisements in place, because the orphan sweep keeps any advertisement whose service still exists. With the switch off, the sweep now withdraws every project service's advertisements. TestTenantService_SwitchedOffWithdrawsRoutes covers this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions