Prove a licence is accepted, sealed, and unreadable by the mesh
Refused until somebody says which, with both candidates and the command named. Refused again while it has no key. Then the key is given on standard input, the public half arrives saying it came from a record rather than a machine, the key itself arrives readable only by that machine — and it is nowhere in the control plane's own database, nor in what crossed the broker. And the rotation test asked for grants without receives, so the provisioner found a directory of unexplained secrets and said nothing had been granted: true, and indistinguishable from a credential never delivered.
This commit is contained in:
@@ -774,6 +774,11 @@ test("rotating a credential moves both ends, and the old one stops working", {
|
||||
`"serves":{"realdatabase":{"port":5433}},` +
|
||||
`"needs":{"superuser":"${store}/superuser"},` +
|
||||
`"grants":{"realdatabase":"${store}/grants"},` +
|
||||
// Both halves. `grants` is where each consumer's sealed password lands; `receives` is the
|
||||
// manifest saying who asked and for what. Without the second the provisioner finds a
|
||||
// directory of unexplained secrets and says nothing has been granted — which is true, and
|
||||
// reads exactly like a credential that was never delivered.
|
||||
`"receives":{"realdatabase":"${store}/grants/mesh.json"},` +
|
||||
`"listens":[{"port":5433,"from":"mesh","why":"a database the mesh provisions"}],` +
|
||||
`"resources":[` +
|
||||
`{"id":"state","type":"directory","path":"${store}","mode":"0755"},` +
|
||||
@@ -937,3 +942,78 @@ test("a route is a grant: a workload is reached by the name it asked for", {
|
||||
}
|
||||
assert.ok(gone, "the proxy still serves a name whose module was unassigned");
|
||||
});
|
||||
|
||||
test("model access is answered by a record, and the key the mesh took is one it cannot read", {
|
||||
skip, timeout: 900_000,
|
||||
}, async () => {
|
||||
// novox/hq ADR 0024. The first provision no machine answers: a hosted model is on nobody's
|
||||
// node and is reached over the public internet, so the rule that refuses two ends sharing no
|
||||
// private network must not apply to it.
|
||||
await must("anchor", `printf %s '{"module":"assistant","version":"1",` +
|
||||
`"requires":["model-access"],` +
|
||||
`"binds":{"model-access":"/etc/assistant/model.json"},` +
|
||||
`"secrets":{"model-access":"/etc/assistant/key"},` +
|
||||
`"resources":[{"id":"dir","type":"directory","path":"/etc/assistant","mode":"0755"}]}' ` +
|
||||
`> /tmp/assistant.json`);
|
||||
await must("anchor", `docker cp /tmp/assistant.json mesh-control:/assistant.json`);
|
||||
await mesh("module add /assistant.json");
|
||||
await mesh("assign laptop assistant");
|
||||
|
||||
await mesh(`licence add anthropic personal --serves '{"model":"a-model"}'`);
|
||||
await mesh(`licence add anthropic the-organisation --serves '{"model":"a-model"}'`);
|
||||
|
||||
// Refused until somebody says which, and the refusal names both candidates and the command.
|
||||
// ADR 0024 warns this will be felt — which is correct, and correct is not the same as usable.
|
||||
const refused = await on("anchor", `docker exec mesh-control /mesh-control plan laptop`);
|
||||
assert.ok(!refused.ok, `a consumer was given model access without anybody saying which:\n${refused.out}`);
|
||||
for (const want of ["personal", "the-organisation", "licence use"]) {
|
||||
assert.match(refused.out, new RegExp(want),
|
||||
`the refusal does not name ${want}:\n${refused.out}`);
|
||||
}
|
||||
|
||||
await mesh("licence use personal laptop assistant");
|
||||
|
||||
// Chosen, and still no key: the mesh has one thing to deliver and has not been given it.
|
||||
const noKey = await on("anchor", `docker exec mesh-control /mesh-control plan laptop`);
|
||||
assert.ok(!noKey.ok, `a module was planned with a licence that has no key:\n${noKey.out}`);
|
||||
assert.match(noKey.out, /licence key personal/, noKey.out);
|
||||
|
||||
// The accept verb. Given on standard input rather than as an argument, because a key in a
|
||||
// command line is a key in shell history and in every process listing taken while it ran.
|
||||
const secret = "sk-test-" + "0123456789abcdef".repeat(2);
|
||||
const accepted = await must("anchor",
|
||||
`printf %s ${quote(secret)} | docker exec -i mesh-control /mesh-control licence key personal`);
|
||||
assert.match(accepted, /sealed to 1 holder/, accepted);
|
||||
assert.doesNotMatch(accepted, new RegExp(secret),
|
||||
"the key was echoed back, so the one copy that matters is on a terminal");
|
||||
|
||||
await mesh("push laptop");
|
||||
await new Promise((r) => setTimeout(r, 15_000));
|
||||
|
||||
// What is public arrives, and says it is a record rather than leaving an empty address that a
|
||||
// reader would take for something the mesh failed to fill in.
|
||||
const bound = await must("laptop", `cat /etc/assistant/model.json`);
|
||||
assert.match(bound, /personal/, `the consumer was not told which licence it is on:\n${bound}`);
|
||||
assert.match(bound, /a-model/, `what the licence serves did not arrive:\n${bound}`);
|
||||
assert.match(bound, /not a machine/, `the binding leaves an unexplained empty address:\n${bound}`);
|
||||
|
||||
// And the key arrives, readable only by this machine.
|
||||
assert.equal((await must("laptop", `cat /etc/assistant/key`)).trim(), secret,
|
||||
"the key that arrived is not the key that was given");
|
||||
assert.match(await must("laptop", `stat -c %a /etc/assistant/key`), /^600/);
|
||||
|
||||
// The mesh cannot read it back. This is the whole argument: what is stored is unusable by
|
||||
// whoever holds it, the control plane included.
|
||||
const stored = await must("anchor",
|
||||
`docker exec mesh-store psql -U postgres -d licences -qAt ` +
|
||||
`-c "select coalesce(sealed,'') from licence_holder"`);
|
||||
assert.ok(stored.trim().length > 0, "nothing was stored, so nothing was sealed");
|
||||
assert.doesNotMatch(stored, new RegExp(secret),
|
||||
"the key is in the control plane's own database in the open");
|
||||
|
||||
// Nor is it anywhere it could have been read on the way.
|
||||
for (const where of ["/var/lib/mesh-host/declared.json", "/var/lib/mesh-host/state.json"]) {
|
||||
const held = await on("laptop", `grep -c ${quote(secret)} ${where} 2>/dev/null || echo 0`);
|
||||
assert.equal(held.out.trim(), "0", `the key is in the open in ${where}`);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user