package broker import ( "slices" "strings" "testing" ) // 1697/AC1: the composed accounts give a node-engine exactly the four reads of one object by its name, the controller the // one write, and no other principal anything of the bucket. func TestTheDeclarationBucketIsWrittenByTheControllerAndReadByNameByANodeEngine(t *testing.T) { // 1697/AC1 node, err := PermissionsFor(Principal{Kind: KindNode, Node: "alpha", PasswordHash: "x"}) if err != nil { t.Fatal(err) } var mine []string for _, s := range node.Publish { if strings.Contains(s, DeclarationFilesStream) || strings.Contains(s, "$O."+DeclarationFilesBucket) { mine = append(mine, s) } } want := []string{ "$JS.API.CONSUMER.CREATE.OBJ_declaration-files.*.$O.declaration-files.C.*", "$JS.API.CONSUMER.DELETE.OBJ_declaration-files.*", "$JS.API.DIRECT.GET.OBJ_declaration-files.$O.declaration-files.M.*", "$JS.FC.OBJ_declaration-files.>", } if !slices.Equal(mine, want) { t.Fatalf("a node-engine may publish %q of the bucket, want exactly %q", mine, want) } // What would make a list or a write: none of it, in any pattern a node holds. (The real server's judgement of // the wildcard forms is the live test's.) for _, refused := range []string{ "$JS.API.STREAM.INFO.OBJ_declaration-files", "$JS.API.STREAM.MSG.GET.OBJ_declaration-files", "$JS.API.DIRECT.GET.OBJ_declaration-files", "$JS.API.DIRECT.GET.OBJ_declaration-files.$O.declaration-files.M.abc.def", "$JS.API.CONSUMER.CREATE.OBJ_declaration-files.x.$O.declaration-files.M.YWJj", "$JS.API.CONSUMER.CREATE.OBJ_declaration-files.x.$O.declaration-files.M.YWJj.more", "$JS.API.CONSUMER.CREATE.OBJ_declaration-files", "$O.declaration-files.M.abc", "$O.declaration-files.C.abc", } { if MayPublish(node, refused) { t.Errorf("a node-engine may publish %s, which lists or writes the bucket", refused) } } for _, kept := range []string{ "$JS.API.DIRECT.GET.OBJ_declaration-files.$O.declaration-files.M.YWJj", "$JS.API.CONSUMER.CREATE.OBJ_declaration-files.h4sh.$O.declaration-files.C.NUID", } { if !MayPublish(node, kept) { t.Errorf("a node-engine may not publish %s, which reads one object by its name", kept) } } controller, err := PermissionsFor(Principal{Kind: KindController, PasswordHash: "x"}) if err != nil { t.Fatal(err) } if !MayPublish(controller, "$O.declaration-files.M.abc") || !MayPublish(controller, "$O.declaration-files.C.nuid") { t.Error("the controller may not write the bucket") } for _, p := range []Principal{ {Kind: KindModule, Module: "mesh-vault", PasswordHash: "x"}, {Kind: KindNodeTools, Node: "alpha", PasswordHash: "x"}, {Kind: KindPerson, Module: "jochen", Invokes: []string{"*"}, PasswordHash: "x"}, } { perms, err := PermissionsFor(p) if err != nil { t.Fatal(err) } for _, s := range append(append([]string(nil), perms.Publish...), perms.Subscribe...) { if strings.Contains(s, "declaration-files") { t.Errorf("%s holds %s, and no account but the controller's and the node-engines' has any access", p.Username(), s) } } } }