mesh/merge-gate head 5a7ec3775b98 merged into trunk 53fd32618916 beside mesh-controller#346@c711e622 — pass: builds mesh-host → ace, g14, novox, shanks; no…
mesh/repo-check head 5a7ec3775b98 merged into trunk 53fd32618916 beside mesh-controller#346@c711e622 — pass: [release feat/57-config-and-provisioning, judg…
mesh/delivery stopped: its walk plan-1792114347281764422 was stopped by a person (mesh-controller): mesh-host#114 merged into the release branch feat/57-…
mesh/delivery-group group 57-config-and-provisioning stopped: a member was stopped
The node-engine renders the feature's templates, collections and moved providers' files, on the SDK the feature's modules build on (feature 57, config and provisioning).
113 lines
3.9 KiB
Go
113 lines
3.9 KiB
Go
package apply
|
|
|
|
// A core credential the vault sealed to this machine (novox/hq ADR 0349 §16, issue 755): the controller carries the
|
|
// vault's box (ADR 0206) in the declaration and cannot open it; this machine opens it with its sealing key and writes
|
|
// the value, as it writes a value the controller sealed.
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/seal"
|
|
|
|
"github.com/novox/mesh-host/internal/declaration"
|
|
"github.com/novox/mesh-host/internal/identity"
|
|
"github.com/novox/mesh-host/internal/store"
|
|
)
|
|
|
|
// vaultSealedTo is what the vault answers the controller: the value in the ADR 0206 box, sealed to the machine's
|
|
// sealing key as SPKI PEM.
|
|
func vaultSealedTo(t *testing.T, key identity.SealingKey, value string) seal.Box {
|
|
t.Helper()
|
|
pub, err := key.PublicPEM()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
box, err := seal.Seal(value, pub)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return box
|
|
}
|
|
|
|
func vaultSealedFile(t *testing.T, path string, box seal.Box) *declaration.Declaration {
|
|
t.Helper()
|
|
raw := map[string]any{"declaration": 1, "resources": []map[string]any{
|
|
{"id": "broker", "type": "file", "path": path, "vault-sealed": box},
|
|
}}
|
|
body, _ := json.Marshal(raw)
|
|
d, err := declaration.Parse(body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return d
|
|
}
|
|
|
|
func boxOpener(key identity.SealingKey) Unseal {
|
|
return func(sealed string) ([]byte, error) { return key.Open(sealed) }
|
|
}
|
|
|
|
func TestAFileTheVaultSealedToThisMachineIsOpenedAndWrittenUnreadableToOthers(t *testing.T) {
|
|
key, err := identity.GenerateSealingKey()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
path := t.TempDir() + "/broker"
|
|
d := vaultSealedFile(t, path, vaultSealedTo(t, key, "the-provisioners-bus-password"))
|
|
report, state, err := Apply(context.Background(), archHost(t), d, store.State{},
|
|
store.OriginCarried, noServices, nil, boxOpener(key))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
on, err := os.ReadFile(path)
|
|
if err != nil || string(on) != "the-provisioners-bus-password" {
|
|
t.Fatalf("the file holds %q, %v", on, err)
|
|
}
|
|
if info, _ := os.Stat(path); info.Mode().Perm() != 0o600 {
|
|
t.Errorf("a credential landed mode %o", info.Mode().Perm())
|
|
}
|
|
said, _ := json.Marshal(report)
|
|
kept, _ := json.Marshal(state)
|
|
for what, blob := range map[string][]byte{"the report": said, "the node's state": kept} {
|
|
if strings.Contains(string(blob), "the-provisioners-bus-password") {
|
|
t.Fatalf("%s carries the value in the clear", what)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAVaultBoxSealedToAnotherMachineIsRefusedAndNothingWritten(t *testing.T) {
|
|
mine, _ := identity.GenerateSealingKey()
|
|
theirs, _ := identity.GenerateSealingKey()
|
|
path := t.TempDir() + "/broker"
|
|
d := vaultSealedFile(t, path, vaultSealedTo(t, theirs, "not for you"))
|
|
if _, _, err := Apply(context.Background(), archHost(t), d, store.State{},
|
|
store.OriginCarried, noServices, nil, boxOpener(mine)); err == nil {
|
|
t.Fatal("a box sealed to another machine was applied")
|
|
}
|
|
if _, err := os.Stat(path); err == nil {
|
|
t.Fatal("something was written before the failure")
|
|
}
|
|
}
|
|
|
|
func TestAVaultSealedFileSaysWhatIsInItOnce(t *testing.T) {
|
|
key, _ := identity.GenerateSealingKey()
|
|
box, _ := json.Marshal(vaultSealedTo(t, key, "x"))
|
|
for what, extra := range map[string]string{
|
|
"content": `"content":"a"`, "sealed": `"sealed":"b"`, "bytes": `"bytes":"Yw=="`,
|
|
"secrets": `"content":"${secret:x}","secrets":{"x":"c"}`, "into": `"into":"json","content":"{}"`,
|
|
} {
|
|
_, err := declaration.Parse([]byte(`{"declaration":1,"resources":[{"id":"f","type":"file","path":"/etc/x",` +
|
|
`"vault-sealed":` + string(box) + `,` + extra + `}]}`))
|
|
if err == nil {
|
|
t.Errorf("a vault-sealed file that also says %s was accepted", what)
|
|
}
|
|
}
|
|
if _, err := declaration.Parse([]byte(`{"declaration":1,"resources":[{"id":"f","type":"file","path":"/etc/x",` +
|
|
`"vault-sealed":{"v":2,"eph":"a","iv":"b","tag":"c","ct":"d"}}]}`)); err == nil {
|
|
t.Error("a box of a version the SDK does not open was accepted")
|
|
}
|
|
}
|