refactor(orchestrator): fail closed unconditionally, drop topology opt-out
tracker-policy-pr / check-pr (pull_request) Successful in 7s
test / integration-docker (pull_request) Successful in 15s
test / unit (pull_request) Successful in 39s
test / integration-firecracker (pull_request) Successful in 3m55s
test / coverage (pull_request) Successful in 22s
test / publish-infra (pull_request) Has been skipped
prd-number / assign-numbers (push) Failing after 21s
test / integration-docker (push) Successful in 22s
lint / lint (push) Successful in 56s
Update Quality Badges / update-badges (push) Successful in 53s
test / unit (push) Successful in 1m52s
test / integration-firecracker (push) Successful in 5m2s
test / coverage (push) Successful in 16s
test / publish-infra (push) Successful in 1m56s
tracker-policy-pr / check-pr (pull_request) Successful in 7s
test / integration-docker (pull_request) Successful in 15s
test / unit (pull_request) Successful in 39s
test / integration-firecracker (pull_request) Successful in 3m55s
test / coverage (pull_request) Successful in 22s
test / publish-infra (pull_request) Has been skipped
prd-number / assign-numbers (push) Failing after 21s
test / integration-docker (push) Successful in 22s
lint / lint (push) Successful in 56s
Update Quality Badges / update-badges (push) Successful in 53s
test / unit (push) Successful in 1m52s
test / integration-firecracker (push) Successful in 5m2s
test / coverage (push) Successful in 16s
test / publish-infra (push) Successful in 1m56s
Remove the empty-key opt-out codex flagged: ControlPlaneProvisioning no longer lets the orchestrator start without a signing key when a backend declares an "isolated" topology. Host separation is not the safety condition — the gateway (and any other caller) must reach the control-plane listener for /resolve, so an open orchestrator would still grant them full `cli`. The signing key is now mandatory for every backend. Drops the now-purposeless Topology/COLOCATED machinery (no backend declared a non-default topology) and the contractual test_orchestrator_key_allows_empty_when_isolated. Updates the PRD's invariant 4 and lifecycle docstring accordingly. Docs/behaviour only otherwise. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #482.
This commit is contained in:
@@ -59,9 +59,8 @@ class Orchestrator(abc.ABC):
|
||||
|
||||
# The shared control-plane auth provisioning contract (#476). Every backend
|
||||
# gets its signing key + gateway token through this one seam rather than
|
||||
# re-deriving the wiring; the default topology is co-located + fail-closed,
|
||||
# so a backend need not redeclare it (a truly isolated control plane would
|
||||
# override this with a different `Topology`).
|
||||
# re-deriving the wiring; it is fail-closed for every backend — the
|
||||
# orchestrator never starts without its signing key.
|
||||
provisioning: ControlPlaneProvisioning = ControlPlaneProvisioning()
|
||||
|
||||
def ensure_built(self) -> None:
|
||||
|
||||
+11
-38
@@ -26,7 +26,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
|
||||
from . import orchestrator_auth
|
||||
from .orchestrator_auth import ROLE_GATEWAY
|
||||
@@ -39,8 +39,8 @@ from .paths import (
|
||||
|
||||
|
||||
class ProvisioningError(RuntimeError):
|
||||
"""A control-plane auth invariant would be violated (e.g. starting a
|
||||
co-located control plane without its signing key — which would run OPEN)."""
|
||||
"""A control-plane auth invariant would be violated (e.g. starting the
|
||||
orchestrator without its signing key — which would run OPEN)."""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -99,31 +99,6 @@ CONTROL_PLANE = TrustDomain(
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Topology:
|
||||
"""Where a backend runs the two planes, so the provisioning seam can decide
|
||||
whether an open control plane is dangerous — the backend declares this
|
||||
instead of hardcoding the decision in its launcher.
|
||||
|
||||
`data_plane_shares_control_host` — the gateway runs on the same host/VM as
|
||||
the orchestrator, so an open orchestrator would hand the co-located gateway
|
||||
full `cli`. The default, and what makes the signing key mandatory. Every
|
||||
current backend is co-located (docker/macOS: two containers on one host;
|
||||
firecracker: two VMs on one host, agents L3-isolated); an isolated control
|
||||
plane on a separate trusted host may declare False.
|
||||
|
||||
`combined_guest` — both planes in one guest (the retired combined infra VM).
|
||||
Informational; kept so a future combined backend declares it."""
|
||||
|
||||
data_plane_shares_control_host: bool = True
|
||||
combined_guest: bool = False
|
||||
|
||||
|
||||
# The default posture: data plane co-located with the control plane. Fail-closed
|
||||
# — the signing key is mandatory. A backend opts out only by declaring otherwise.
|
||||
COLOCATED = Topology(data_plane_shares_control_host=True)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ControlPlaneProvisioning:
|
||||
"""The one seam every backend launcher uses to provision control-plane auth,
|
||||
@@ -131,22 +106,22 @@ class ControlPlaneProvisioning:
|
||||
round: the orchestrator gets the raw key (`orchestrator_key`), the gateway
|
||||
gets a minted `gateway` token (`gateway_token`), the host CLI mints its own
|
||||
`cli` token from the same host-canonical key, and the orchestrator never
|
||||
starts open where its gateway is co-located."""
|
||||
starts open."""
|
||||
|
||||
domain: TrustDomain = CONTROL_PLANE
|
||||
topology: Topology = field(default=COLOCATED)
|
||||
|
||||
def orchestrator_key(self) -> str:
|
||||
"""The raw signing key the orchestrator process must receive (carry it in
|
||||
`domain.key_env`). Fail-closed: raises rather than return "" for a
|
||||
co-located topology, since an empty key runs the server open and hands
|
||||
the co-located gateway full `cli`."""
|
||||
`domain.key_env`). Fail-closed: raises rather than return "", since an
|
||||
empty key runs the server open — and being on a separate host does not
|
||||
stop the gateway from reaching the control plane (it must, for
|
||||
`/resolve`), so an open orchestrator would treat that gateway as `cli`."""
|
||||
key = self.domain.signing_key()
|
||||
if not key and self.topology.data_plane_shares_control_host:
|
||||
if not key:
|
||||
raise ProvisioningError(
|
||||
f"refusing to start the {self.domain.name} orchestrator without "
|
||||
"a signing key: its gateway shares this host/VM, so an open "
|
||||
"orchestrator would grant that gateway full `cli` (#476)"
|
||||
"a signing key: an open orchestrator authenticates no one and "
|
||||
"grants every caller that reaches it full `cli` (#476)"
|
||||
)
|
||||
return key
|
||||
|
||||
@@ -161,7 +136,5 @@ __all__ = [
|
||||
"ProvisioningError",
|
||||
"TrustDomain",
|
||||
"CONTROL_PLANE",
|
||||
"Topology",
|
||||
"COLOCATED",
|
||||
"ControlPlaneProvisioning",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user