From 12c80d7c2ef793040933e669cffda8629106b801 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 3 Nov 2026 11:38:03 +0100 Subject: [PATCH] The node-engine carries a module's own secrets sealed by the vault when its manifest says they are the core's credentials, pinned at mesh-sdk 4f141ff (issue 774, the operator 2026-11-03) --- go.mod | 2 +- go.sum | 2 ++ internal/compose/composed_test.go | 2 +- internal/compose/credentials.go | 4 ++-- internal/compose/credentials_test.go | 2 +- internal/compose/node_test.go | 2 +- .../compose/resolution/core_credentials.go | 8 +++---- .../resolution/core_credentials_test.go | 22 +++++++++---------- 8 files changed, 23 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 7ec0e0a..5c8d904 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/novox/mesh-host go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261102191058-f02f142af128 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261103103643-4f141ff08892 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 golang.org/x/crypto v0.57.0 diff --git a/go.sum b/go.sum index 43cc4ec..0fd448a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261102191058-f02f142af128 h1:aI1DhZAuqVBXbybSqhLNOGX5rUOrn9T0cHNCDUQF7IQ= git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261102191058-f02f142af128/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261103103643-4f141ff08892 h1:XWorhIHDVECRCYzGbkaexEpJ7v03B9LrZ8IVy7vkUKs= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261103103643-4f141ff08892/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/internal/compose/composed_test.go b/internal/compose/composed_test.go index 35091c1..09e36a7 100644 --- a/internal/compose/composed_test.go +++ b/internal/compose/composed_test.go @@ -188,7 +188,7 @@ func TestCompositionsAreTheDeclarationSplitByModule(t *testing.T) { // 1943/AC1: the upgrade policies and sources a composition's value may name are the catalogue's own words. func TestTheComposedPoliciesAreTheCatalogues(t *testing.T) { for _, p := range []string{catalogue.PolicyRoll, catalogue.PolicyTogether, catalogue.PolicyRecord} { - for _, from := range []string{catalogue.FromPerson, catalogue.FromModule, catalogue.FromBus, catalogue.FromData, catalogue.FromDefault} { + for _, from := range []string{catalogue.FromPerson, catalogue.FromModule, "the bus", catalogue.FromData, catalogue.FromDefault} { // "the bus": an older reader's word, still read v := delivery.ComposedDigest{Digest: "sha256:" + strings.Repeat("a", 64), Judgement: delivery.JudgedNeither, Policy: p, PolicyFrom: from} if _, err := delivery.EncodeComposedDigest(v); err != nil { t.Errorf("%s from %s: %v", p, from, err) diff --git a/internal/compose/credentials.go b/internal/compose/credentials.go index 374302d..e05339c 100644 --- a/internal/compose/credentials.go +++ b/internal/compose/credentials.go @@ -386,13 +386,13 @@ type CoreBoxWanted struct { Name string } -// coreModulesOf is every module of the plan on the core's list whose own secrets this machine's declaration carries, with their +// coreModulesOf is every module of the plan whose manifest says its own secrets are the core's credentials, whose own secrets this machine's declaration carries, with their // plain own secret names, sorted: one handed to the provisioner has its secrets from the vault through the client, and one issued // outside the mesh is never the vault's to seal here. func coreModulesOf(modules []catalogue.Manifest, handed func(catalogue.Manifest) bool) map[string][]string { out := map[string][]string{} for _, m := range modules { - if !resolution.CarriesVaultSealed(m.Module) || (handed != nil && handed(m)) { + if !resolution.CarriesVaultSealed(m) || (handed != nil && handed(m)) { continue } var names []string diff --git a/internal/compose/credentials_test.go b/internal/compose/credentials_test.go index dde374e..0ab188b 100644 --- a/internal/compose/credentials_test.go +++ b/internal/compose/credentials_test.go @@ -295,7 +295,7 @@ func aValidKey(t *testing.T, name string) string { return keyOf(t, name) } func TestACoreBoxTheInputHoldsNoneOfIsReturnedToKeepAndNothingIsWritten(t *testing.T) { mk := func() Input { in := aMesh(t) - in.Catalogue["nats"] = catalogue.Manifest{Module: "nats", Version: "1", + in.Catalogue["nats"] = catalogue.Manifest{Module: "nats", Version: "1", CoreCredentials: true, OwnSecrets: catalogue.OwnSecrets{"broker": {Path: "/var/lib/mesh/nats/broker", Taken: catalogue.TakenAtStart}}} laptop := nodeOf(t, &in, "laptop") laptop.Assigned = append(laptop.Assigned, "nats") diff --git a/internal/compose/node_test.go b/internal/compose/node_test.go index 5dcbee4..1d2c67b 100644 --- a/internal/compose/node_test.go +++ b/internal/compose/node_test.go @@ -168,7 +168,7 @@ func TestWhatASendWouldMakeIsNamedAsForeseenAndNeverInvented(t *testing.T) { in.Issued[0].ForProvider = "" in.Catalogue["assistant"] = anAssistant() in.Catalogue["web"] = aWebModule() - in.Catalogue["nats"] = catalogue.Manifest{Module: "nats", Version: "1", + in.Catalogue["nats"] = catalogue.Manifest{Module: "nats", Version: "1", CoreCredentials: true, OwnSecrets: catalogue.OwnSecrets{"broker": {Path: "/var/lib/mesh/nats/broker", Taken: catalogue.TakenAtStart}}} anchor := nodeOf(t, &in, "anchor") anchor.Assigned = append(anchor.Assigned, "assistant", "web", "nats") diff --git a/internal/compose/resolution/core_credentials.go b/internal/compose/resolution/core_credentials.go index 6b667f3..a584b7d 100644 --- a/internal/compose/resolution/core_credentials.go +++ b/internal/compose/resolution/core_credentials.go @@ -2,14 +2,14 @@ package resolution import ( "encoding/json" - "slices" mcat "git.novox.be/novox/mesh-sdk/go/catalogue" ) -// CarriesVaultSealed says whether module's own secrets are the core's credentials. -func CarriesVaultSealed(module string) bool { - return slices.Contains(mcat.CoreCredentialModules, module) +// CarriesVaultSealed says whether a module's own secrets are the core's credentials, as its manifest says +// (core-credentials): no list of modules is kept here. +func CarriesVaultSealed(m mcat.Manifest) bool { + return mcat.CarriesCoreCredentials(m) } // vaultSealedOf is the vault's box for one of module's own secrets, if the rendering was given one. diff --git a/internal/compose/resolution/core_credentials_test.go b/internal/compose/resolution/core_credentials_test.go index 6c7ffd2..4a3692c 100644 --- a/internal/compose/resolution/core_credentials_test.go +++ b/internal/compose/resolution/core_credentials_test.go @@ -1,24 +1,24 @@ package resolution import ( - "reflect" "testing" mcat "git.novox.be/novox/mesh-sdk/go/catalogue" ) +// The core's own credentials are what a module's manifest says (core-credentials, issue 774): no module is on a list. func TestTheCoresOwnCredentialsAreTheBusTheProvisionerAndItsClient(t *testing.T) { - if want := []string{"mesh-provisioner", "mesh-provisioner-client", "nats"}; !reflect.DeepEqual(mcat.CoreCredentialModules, want) { - t.Fatalf("the core's modules are %v, want %v (mesh-vault's CoreModules is the same list)", mcat.CoreCredentialModules, want) - } - for _, m := range []string{"nats", "mesh-provisioner", "mesh-provisioner-client"} { - if !CarriesVaultSealed(m) { - t.Errorf("%s is not on the list", m) + for raw, core := range map[string]bool{ + `{"module":"nats","version":"1","core-credentials":true}`: true, + `{"module":"nats","version":"1"}`: false, + `{"module":"postgres","version":"1"}`: false, + } { + m, err := mcat.Decode([]byte(raw)) + if err != nil { + t.Fatal(err) } - } - for _, m := range []string{"postgres", "mesh-vault", "mesh-controller", ""} { - if CarriesVaultSealed(m) { - t.Errorf("%s is on the list", m) + if CarriesVaultSealed(m) != core { + t.Errorf("%s: carries the core's credentials %v", raw, !core) } } }