diff --git a/02-DECISIONS/0147-a-module-anchors-the-meshs-authority.md b/02-DECISIONS/0147-a-module-anchors-the-meshs-authority.md index e0e19a0..b480a3e 100644 --- a/02-DECISIONS/0147-a-module-anchors-the-meshs-authority.md +++ b/02-DECISIONS/0147-a-module-anchors-the-meshs-authority.md @@ -113,6 +113,34 @@ the authority it was bound to, checked in the control plane's own test suite — that verified anything. That is a weaker thing than the paragraph above describes, and it stays written this way until the bed runs. +> **Progressive insight — 2026-09-30. It has now been run, on the live mesh rather than in the bed.** +> The paragraph above said nothing had verified anything, and something has. The module was registered +> from the catalogue, assigned to a workstation, and checked in the form this section prescribes — the +> authority's own API, so the handshake needs nothing else in the mesh to be right: +> +> ``` +> $ curl -sS -o /dev/null -w '%{http_code}' https://:9000/health +> 200 +> subject=CN=Step Online CA +> issuer=O=Mesh Internal CA, CN=Mesh Internal CA Intermediate CA +> Verify return code: 0 (ok) +> ``` +> +> **Both halves.** Unassigning and pushing removed the anchor, emptied the trust store of the mesh's +> authority, and returned the plain client to *unable to get local issuer certificate* — then assigning +> again restored it. The negative half is what distinguishes the anchor working from something else +> having trusted it, and it is the half nothing had ever exercised. +> +> **One thing this found that is not in the module.** The removal only works because the *host* removes +> the service before the script: stopping the unit is what deletes the certificate and refreshes the +> bundles, and it needs the script it calls to still exist. Nothing in the module states that ordering; +> the symmetry this record claims rests on it. +> +> Run on the live mesh because that is where a change is verified now +> ([ADR 0149](0149-the-live-mesh-is-the-test-bed.md)), and the bed still cannot raise a foundation. The +> evidence is [issue 129](../04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/02-resolution.md). +> It ran on **one** machine; three others still trust nothing of the mesh's. + ## Consequences The predecessor's authority can be retired from a machine once this module is assigned to it, diff --git a/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/00-report.md b/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/00-report.md index abb3825..742c87a 100644 --- a/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/00-report.md +++ b/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/00-report.md @@ -1,7 +1,8 @@ --- -status: diagnosing +status: resolved opened: 2026-09-26 -located-in: [mesh-catalog ca-trust] +located-in: [mesh-catalog modules/ca-trust] +fixed-by: the ca-trust module registered from the catalogue and assigned to a workstation; verified in both directions 2026-09-30 (02-resolution.md) --- # 129 — nothing makes a machine trust the mesh's own certificate authority diff --git a/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/02-resolution.md b/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/02-resolution.md new file mode 100644 index 0000000..671d196 --- /dev/null +++ b/04-ISSUES/129-nothing-makes-a-machine-trust-the-meshs-authority/02-resolution.md @@ -0,0 +1,86 @@ +# 129 — resolved: the workstation trusts the mesh, and stops when told to + +*Done and measured on the machine, 2026-09-30.* + +## What was done + +Three steps, not the one the plan expected — the module was merged and had never been registered +(see [the diagnosis](01-diagnosis.md)): + +1. **Registered** `ca-trust` from the catalogue. No artifact to build: it declares a directory, a + script, a unit and a service, and no image. +2. **Assigned** it to the workstation the issue was opened on, and pushed. +3. **Verified** with a plain client, then **unassigned and pushed again** to exercise removal, then + assigned and pushed once more. + +The host's own account of arriving: + +``` +created ca-trust.state (/var/lib/ca-trust) +created ca-trust.anchor (/var/lib/ca-trust/anchor) +created ca-trust.unit (/etc/systemd/system/mesh-ca-trust.service) +updated ca-trust.trust (mesh-ca-trust.service): boot disabled to enabled, stopped to running +``` + +## It works, by the check the report asked for + +The report's own reproduction, with no flags and nothing installed by hand: + +``` +$ curl -sS -o /dev/null -w '%{http_code}' https://git.novox.internal/ +200 +$ openssl s_client -connect git.novox.internal:443 -servername git.novox.internal +issuer=O=Mesh Internal CA, CN=Mesh Internal CA Intermediate CA +Verify return code: 0 (ok) +$ trust list | grep -A2 Mesh + label: Mesh Internal CA Root CA + trust: anchor + category: authority +``` + +Four internal names, all verifying: `git` 200, `umami` 200, `keycloak` 302, `drive` 302. Before this, +every one of them was `curl: (60) … unable to get local issuer certificate (20)`. + +**And the consequence the report named specifically**: git over HTTPS to the mesh's forge, which it said +had forced the working clone URL to be ssh-only. + +``` +$ git ls-remote https://git.novox.internal/novox/hq.git HEAD +76fbe323ea3401fcdadbf500c61bd3fa5a0a8603 HEAD +``` + +## Removal is symmetric, which nothing had ever shown + +[ADR 0147](../../02-DECISIONS/0147-a-module-anchors-the-meshs-authority.md) says the module anchors the +authority *and takes it away again*. That half had never run. Unassigning and pushing: + +``` +removed ca-trust.trust (mesh-ca-trust.service) +removed ca-trust.unit (/etc/systemd/system/mesh-ca-trust.service) +removed ca-trust.anchor (/var/lib/ca-trust/anchor) +removed ca-trust.state (/var/lib/ca-trust) +``` + +Then: the anchor file gone, `trust list` naming no authority of the mesh's, and the plain client back to +`unable to get local issuer certificate (20)`. A machine that leaves the mesh stops trusting it, as the +record claims. + +**The order is what makes it work, and is worth saying.** The service is removed *first*, so systemd +runs the unit's `ExecStop` — which is what deletes the certificate and refreshes the bundles — while the +script it calls still exists. Had the script or the state directory gone first, stopping the unit would +have had nothing to run, and the anchor would have been left behind with nothing declaring it. Nothing +in the module says this; it is the host's removal order that makes the module's symmetry real. + +## What this leaves + +- **One machine, not four.** `novox`, `g14` and `ace` still trust nothing of the mesh's. The report's + reasoning — that being on the private network is what makes a machine one that speaks to the mesh's + names — argues for all of them, and ADR 0147 is written for a module assigned per machine rather than + a fact carried to every machine on the network. Whether it should instead arrive the way the roster + and the registry trust do is a real question and is not this record's to answer. +- **`service-manager` reports `degraded` on this machine** and the module ran anyway. Worth knowing that + the capability gate passes on a degraded service manager, since a module whose whole delivery is a + unit is the kind that would be worst served by one. +- **The predecessor's authority is still in the trust store**, beside the mesh's now rather than instead + of it. The report notes that it cannot be retired while anything on the machine speaks TLS to a mesh + name; that is no longer true here, and retiring it is its own piece of work.