The private network writes nothing into the runtime's file (hq issue 190)
daemon.json and docker.service belong to the docker module, which holds node-container-runtime
and now states the registry itself through ${seat:mesh-artifact-store:reach} (hq ADR 0222). The
overlay stops generating registry-trust and registry-trust-reload. A generated resource is now
held to the collision check every module is, so a second writer cannot come back through
computed code; resolution never saw what a generator declares.
This commit is contained in:
@@ -78,18 +78,13 @@ type Generator struct {
|
||||
// keyPath is where each node keeps the private half it generated. Named rather than carried:
|
||||
// the mesh has never seen it and never will.
|
||||
keyPath string
|
||||
// registry is the mesh's artifact store as the network reaches it (host:port), or empty when
|
||||
// the mesh has none. Being on the network is what grants a machine the right to pull from it
|
||||
// (novox/hq ADR 0082), so the module that puts a machine on the network is what writes the
|
||||
// runtime's trust. (That is still a write into another module's file, the container runtime's;
|
||||
// novox/hq issue 190 has it handed to that module as a value.)
|
||||
registry string
|
||||
// No registry. Being on the network is still what grants a machine the right to pull from the
|
||||
// mesh's artifact store in the clear (novox/hq ADR 0082), but the runtime's file is the runtime's
|
||||
// module's: the private network writes nothing into it, and that module states the registry
|
||||
// itself, told where the store is reached by ${seat:mesh-artifact-store:reach} (novox/hq ADR
|
||||
// 0222, issue 190).
|
||||
}
|
||||
|
||||
// TrustRegistry names the artifact store this network's machines pull from in the clear —
|
||||
// the overlay is the transport security (ADR 0082).
|
||||
func (g *Generator) TrustRegistry(hostPort string) { g.registry = hostPort }
|
||||
|
||||
// From builds a generator over the machines that are part of the network.
|
||||
//
|
||||
// The nodes given are the ones assigned the module — not every node the mesh knows. A machine
|
||||
@@ -128,31 +123,7 @@ func (g *Generator) Resources(node string) ([]map[string]any, bool, error) {
|
||||
if err := json.Unmarshal(raw, &parsed); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
resources := parsed.Resources
|
||||
if g.registry != "" {
|
||||
trust, err := json.Marshal(map[string]any{"insecure-registries": []string{g.registry}})
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
resources = append(resources,
|
||||
map[string]any{
|
||||
// Written into, not over (novox/hq ADR 0102): the runtime's daemon file is the
|
||||
// machine's — its data directory, its logging, whatever a predecessor set — and
|
||||
// this states one fact in it. The host sets this key and keeps every other.
|
||||
// ("merge" is the operator's settings merged into this content; "into" is the
|
||||
// content written into the machine's file.) The registry speaks plain HTTP
|
||||
// because every path to it is already inside the overlay's encryption (ADR 0082).
|
||||
"id": "registry-trust", "type": "file", "path": "/etc/docker/daemon.json",
|
||||
"content": string(trust) + "\n", "mode": "0644", "merge": "json", "into": "json",
|
||||
},
|
||||
map[string]any{
|
||||
// Reloaded, not restarted: the runtime re-reads its trusted registries on a reload,
|
||||
// and a restart stops every container on the machine (measured; ADR 0102).
|
||||
"id": "registry-trust-reload", "type": "service", "unit": "docker.service",
|
||||
"state": "running", "reload-on": []string{"registry-trust"},
|
||||
})
|
||||
}
|
||||
return resources, true, nil
|
||||
return parsed.Resources, true, nil
|
||||
}
|
||||
|
||||
// Nodes are the machines this generator was built over, so a caller can say who is on the network.
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTheNetworkCarriesRegistryTrust(t *testing.T) {
|
||||
// novox/hq ADR 0082: being on the network is what grants a machine the right to pull from the
|
||||
// mesh's artifact store in the clear, so the network module writes the runtime's trust — and
|
||||
// writes nothing when the mesh has no store to trust.
|
||||
// novox/hq ADR 0222, issue 190: the runtime's file and service are the runtime's module's. The
|
||||
// private network writes nothing into either — being on it still grants the right to pull from the
|
||||
// mesh's store in the clear (ADR 0082), and the runtime's module states that trust itself.
|
||||
func TestTheNetworkWritesNothingOfTheRuntimes(t *testing.T) {
|
||||
nodes := []Node{
|
||||
{Name: "anchor", Site: "lab", Hub: true, Endpoint: "192.0.2.10:51820", Key: "k1", Address: "10.42.0.1"},
|
||||
{Name: "node2", Site: "lab", Key: "k2", Address: "10.42.0.2"},
|
||||
@@ -18,47 +16,15 @@ func TestTheNetworkCarriesRegistryTrust(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
plain, _, err := g.Resources("node2")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, r := range plain {
|
||||
if r["id"] == "registry-trust" {
|
||||
t.Fatal("trust was written with no artifact store to trust")
|
||||
for _, node := range []string{"anchor", "node2"} {
|
||||
resources, part, err := g.Resources(node)
|
||||
if err != nil || !part {
|
||||
t.Fatalf("%s: resources: %v part=%v", node, err, part)
|
||||
}
|
||||
}
|
||||
|
||||
g.TrustRegistry("anchor.internal:5000")
|
||||
trusted, part, err := g.Resources("node2")
|
||||
if err != nil || !part {
|
||||
t.Fatalf("resources: %v part=%v", err, part)
|
||||
}
|
||||
var file, service map[string]any
|
||||
for _, r := range trusted {
|
||||
switch r["id"] {
|
||||
case "registry-trust":
|
||||
file = r
|
||||
case "registry-trust-reload":
|
||||
service = r
|
||||
for _, r := range resources {
|
||||
if r["path"] == "/etc/docker/daemon.json" || r["unit"] == "docker.service" {
|
||||
t.Errorf("%s: the private network declares the runtime's %v", node, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
if file == nil || service == nil {
|
||||
t.Fatalf("the trust file or its reload is missing: %v", trusted)
|
||||
}
|
||||
if file["path"] != "/etc/docker/daemon.json" || file["merge"] != "json" || file["into"] != "json" {
|
||||
t.Fatalf("the trust is not written into daemon.json (ADR 0102): %v", file)
|
||||
}
|
||||
if content, _ := file["content"].(string); !strings.Contains(content, `"anchor.internal:5000"`) {
|
||||
t.Fatalf("the trust does not name the store: %v", file["content"])
|
||||
}
|
||||
if service["unit"] != "docker.service" {
|
||||
t.Fatalf("the reload is not the runtime's: %v", service)
|
||||
}
|
||||
// Reloaded, never restarted: a restart stops every container on the machine (ADR 0102).
|
||||
if _, restarts := service["restart-on"]; restarts {
|
||||
t.Fatalf("the runtime is restarted for its trust: %v", service)
|
||||
}
|
||||
if fmt.Sprint(service["reload-on"]) != "[registry-trust]" {
|
||||
t.Fatalf("the runtime is not reloaded for its trust: %v", service)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user