The provisioner's client (ADR 0349 §4) fills a module's templates and needs the node-engine to write them: it must not hold the right to write the machine's files itself. A second local socket accepts a write only from the account the declaration names as the provisioner client's (SO_PEERCRED, same namespaces), only for a clean path the declaration names as filled, under the apply's own locks, and writes it through the apply as the declared file would be, firing restart-on, reload-on and container reads. Issue 668. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
package declaration
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Defends novox/hq ADR 0349 §4 (issue 668): the declaration names the account the provisioner's client runs as,
|
|
// the only one whose write of a filled file the node-engine accepts. Read here before any controller sends it.
|
|
|
|
func TestTheDeclarationNamesTheProvisionersAccount(t *testing.T) {
|
|
d, err := Parse([]byte(`{"declaration":1,"provisioner_account":"mesh-node-provisioner","filled_files":["/etc/a"],
|
|
"resources":[{"id":"a","type":"file","path":"/etc/a","content":"a","owner-at-runtime":"owned"}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if d.Provisioner != "mesh-node-provisioner" {
|
|
t.Errorf("the provisioner's account read as %q", d.Provisioner)
|
|
}
|
|
d, err = Parse([]byte(`{"declaration":1,"resources":[{"id":"a","type":"file","path":"/etc/a","content":"a"}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if d.Provisioner != "" {
|
|
t.Errorf("a declaration naming no account names %q", d.Provisioner)
|
|
}
|
|
}
|
|
|
|
func TestAProvisionersAccountThatIsNoAccountIsRefused(t *testing.T) {
|
|
for name, account := range map[string]string{"root": "root", "not a name": "a b", "a path": "../x"} {
|
|
_, err := Parse([]byte(`{"declaration":1,"provisioner_account":"` + account + `",
|
|
"resources":[{"id":"a","type":"file","path":"/etc/a","content":"a"}]}`))
|
|
if err == nil || !strings.Contains(err.Error(), "provisioner_account") {
|
|
t.Errorf("%s: want a refusal naming provisioner_account, got %v", name, err)
|
|
}
|
|
}
|
|
}
|