Pin the node-engine at its reviewed grant, and hold the mount match to the path itself (hq ADR 0312, issue 537 review)

A path beginning with the same letters is another path, and a read-only mount
of a read-write access is still granted: the grant follows what mounts it.
This commit is contained in:
2026-10-12 13:47:17 +02:00
parent 10d4712f82
commit 30599c1858
6 changed files with 38 additions and 9 deletions
+4 -1
View File
@@ -89,7 +89,10 @@ func grantAccesses(out []map[string]any, owner map[string]string, module, accoun
return toAccount
}
// mounts says whether a container mounts path, or something below it, from the machine.
// mounts says whether a container mounts path, or something below it, from the machine. A path that merely
// begins with the same letters — /storage/media2 beside /storage/media — is another path. A read-only mount of a
// read-write access still counts: the module declared the access read-write, the engine grants the group to what
// mounts it, and a read-only mount only means that container chose not to write through it.
func mounts(container map[string]any, path string) bool {
volumes, _ := container["volumes"].([]any)
path = filepath.Clean(path)
+20
View File
@@ -152,3 +152,23 @@ func keysOf(m map[string]map[string]any) []string {
}
return out
}
// Only a container that mounts the access's path, or below it, is named: a path that begins with the same letters is
// another path. A read-only mount of a read-write access is still named — the access is read-write, and the grant
// follows what mounts it, not how.
func TestOnlyAContainerMountingThePathIsNamedReadOnlyIncluded(t *testing.T) {
m := mod("library", nil, nil, nil)
m.Accesses = []Access{{ID: "media", Path: "/storage/media", Mode: AccessReadWrite}}
m.Resources = []map[string]any{
{"id": "beside", "type": "container", "name": "beside", "image": anImage, "volumes": []any{"/storage/media2:/x"}},
{"id": "reader", "type": "container", "name": "reader", "image": anImage, "volumes": []any{"${access:media}:/media:ro"}},
}
out, err := Resolution{Node: "ace", Modules: []Manifest{m}}.Declaration(Rendering{GrantsGroups: true})
if err != nil {
t.Fatal(err)
}
grant, _ := byID(out)["library."+AccessID("/storage/media")][GrantField].(map[string]any)
if fmt.Sprint(grant["containers"]) != "[library.reader]" {
t.Errorf("the access grants %v; want the read-only mount and not /storage/media2", grant)
}
}