ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk carries no composition rule. The catalogue functions only the node-engine's composition reaches (Resolve, Resolution's Compose, Declaration, DataItems, LeftOut, Rules and the rest, the settings, placeholder and template refusals, the rendering helpers) are copied with their tests into internal/compose/resolution; a method of a mesh-sdk shape becomes a function taking it first. The composition calls its own copies, and the captured catalogue its tests read lives here now, shared by mesh-compose's tests. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
145 lines
5.2 KiB
Go
145 lines
5.2 KiB
Go
package resolution
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
const twoSecrets = `{"module":"ca","version":"1","requires":["secret"],
|
|
"secrets":{"secret":{"root-key":"/var/lib/ca/root.key","root-pass":"/var/lib/ca/root.pass"}},
|
|
"resources":[{"id":"state","type":"directory","path":"/var/lib/ca","mode":"0700"}]}`
|
|
|
|
func vaultAndCA() map[string]mcat.Manifest {
|
|
ca, _ := decodeForTest([]byte(twoSecrets))
|
|
vault := mcat.Manifest{Module: "mesh-vault", Version: "1", Provides: mcat.FromAnywhere("secret"),
|
|
Grants: map[string]string{"secret": "/var/lib/vault/grants"},
|
|
Receives: map[string]string{"secret": "/var/lib/vault/grants/mesh.json"}}
|
|
// A second consumer of the same provision that keeps ONE file, mentioned before the one that
|
|
// keeps two: the lab found the expansion done on the first module to mention the provision,
|
|
// and the second consumer given one credential and no file.
|
|
cache := mcat.Manifest{Module: "cache", Version: "1", Requires: []string{"secret"},
|
|
Secrets: map[string]string{"secret": "/var/lib/cache/secret"}}
|
|
return shelf(vault, cache, ca)
|
|
}
|
|
|
|
func TestEachLocalNameIsANeedAFileAndAHolderOfItsOwn(t *testing.T) {
|
|
got, err := Resolve(vaultAndCA(), []string{"mesh-vault", "cache", "ca"}, workstation(), mcat.World{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var locals, cacheLocals []string
|
|
for _, n := range got.Needs {
|
|
if n.Name == "secret" && n.For == "ca" {
|
|
locals = append(locals, n.Local)
|
|
}
|
|
if n.Name == "secret" && n.For == "cache" {
|
|
cacheLocals = append(cacheLocals, n.Local)
|
|
}
|
|
}
|
|
if strings.Join(locals, ",") != "root-key,root-pass" {
|
|
t.Fatalf("two secrets from one provider are two needs: %v", got.Needs)
|
|
}
|
|
if len(cacheLocals) != 1 || cacheLocals[0] != "" {
|
|
t.Fatalf("the one-file consumer keeps one need with no local name: %v", got.Needs)
|
|
}
|
|
for i := range got.Needs {
|
|
got.Needs[i].Sealed = "sealed-" + got.Needs[i].Local
|
|
}
|
|
out, err := Declaration(got, mcat.Rendering{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
seen := map[string]string{}
|
|
for _, r := range out {
|
|
if r["type"] == "file" && strings.HasPrefix(r["path"].(string), "/var/lib/ca/root.") {
|
|
seen[r["id"].(string)] = r["sealed"].(string)
|
|
}
|
|
}
|
|
if seen["ca."+mcat.SecretID("root-key")] != "sealed-root-key" || seen["ca."+mcat.SecretID("root-pass")] != "sealed-root-pass" {
|
|
t.Fatalf("each local name is its own file with its own credential: %v", seen)
|
|
}
|
|
}
|
|
|
|
func TestAProviderSeesEachLocalNameAsAHolderOfItsOwn(t *testing.T) {
|
|
r := mcat.Resolution{Modules: []mcat.Manifest{vaultAndCA()["mesh-vault"]}}
|
|
got, err := resolutionContributions(r, mcat.SettingsBy{}, []mcat.Grant{
|
|
{Provision: "secret", Consumer: "workstation", From: "ca", Local: "root-key", Sealed: "x"},
|
|
{Provision: "secret", Consumer: "workstation", From: "ca", Local: "root-pass", Sealed: "y"},
|
|
}, map[string]string{"secret": "/var/lib/vault/grants"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
given := got["secret"]
|
|
if len(given) != 2 {
|
|
t.Fatalf("two holders: %+v", given)
|
|
}
|
|
if given[0].As != "mesh_workstation_ca_root_key" && given[0].As != "mesh_workstation_ca_root-key" {
|
|
t.Fatalf("the holder is the consumer's identity with the local name after it: %q", given[0].As)
|
|
}
|
|
if given[0].Secret == given[1].Secret {
|
|
t.Fatalf("two holders share one file on the provider: %q", given[0].Secret)
|
|
}
|
|
}
|
|
|
|
// And on the provider's machine, two files with two ids — the lab's first run had the declaration
|
|
// refused for two resources with one identity.
|
|
func TestAProviderKeepsOneFilePerHolder(t *testing.T) {
|
|
got, err := Resolve(vaultAndCA(), []string{"mesh-vault", "cache", "ca"}, workstation(), mcat.World{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out, err := Declaration(got, mcat.Rendering{Grants: []mcat.Grant{
|
|
{Provision: "secret", Consumer: "workstation", From: "ca", Local: "root-key", Sealed: "x"},
|
|
{Provision: "secret", Consumer: "workstation", From: "ca", Local: "root-pass", Sealed: "y"},
|
|
}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ids := map[string]string{}
|
|
for _, r := range out {
|
|
if id, _ := r["id"].(string); strings.Contains(id, "grant-secret") {
|
|
ids[id] = r["path"].(string)
|
|
}
|
|
}
|
|
if len(ids) != 2 {
|
|
t.Fatalf("two holders are two grant files: %v", ids)
|
|
}
|
|
}
|
|
|
|
// One file under a local name is still a local name (review C1): the need carries it, the file
|
|
// is written, and ${secret:<name>} is filled.
|
|
func TestOneLocalNameIsStillALocalName(t *testing.T) {
|
|
only, _ := decodeForTest([]byte(`{"module":"one","version":"1","requires":["secret"],
|
|
"secrets":{"secret":{"only":"/var/lib/one/only"}}}`))
|
|
vault := vaultAndCA()["mesh-vault"]
|
|
got, err := Resolve(shelf(vault, only), []string{"mesh-vault", "one"}, workstation(), mcat.World{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var found *mcat.Needed
|
|
for i, n := range got.Needs {
|
|
if n.For == "one" && n.Name == "secret" {
|
|
found = &got.Needs[i]
|
|
}
|
|
}
|
|
if found == nil || found.Local != "only" {
|
|
t.Fatalf("the one named file did not become a need under its name: %v", got.Needs)
|
|
}
|
|
found.Sealed = "sealed-only"
|
|
out, err := Declaration(got, mcat.Rendering{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var written bool
|
|
for _, r := range out {
|
|
if r["path"] == "/var/lib/one/only" && r["sealed"] == "sealed-only" {
|
|
written = true
|
|
}
|
|
}
|
|
if !written {
|
|
t.Fatal("the file under the one local name was not written")
|
|
}
|
|
}
|