The generic command verb ran node account and node agent-account, so an agent could name itself the operator account and have the next send grant it root (hq ADR 0266 review). Refuse every node subcommand but list and show through any verb; refuse the operator account as the agent account in both directions and well-known service accounts as an agent account; and count a verdict heard more than 15 minutes ago as not judged, so stopping the node-engine cannot freeze a healthy one. Re-pin mesh-host to its review head.
94 lines
3.4 KiB
Go
94 lines
3.4 KiB
Go
package inventory
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// The agent account (novox/hq ADR 0266): recorded and read back with every node, its home derived when
|
|
// not stated, cleared by an empty name — and refused when it is root, the operator's own account, or no
|
|
// login at all, because each of those would say agents have an account of their own while they do not.
|
|
func TestAgentAccountIsRecordedAndRefusedWhereItWouldNotConfine(t *testing.T) {
|
|
inv := ForTest(t)
|
|
ctx := context.Background()
|
|
if _, err := inv.AddNode(ctx, "anchor"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.SetAccount(ctx, "anchor", "operator", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
n, err := inv.NodeByName(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n.AgentAccount != "" || n.AgentHome() != "" {
|
|
t.Fatalf("a node that names none has agent account %q, home %q", n.AgentAccount, n.AgentHome())
|
|
}
|
|
|
|
if err := inv.SetAgentAccount(ctx, "anchor", "agent", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
n, _ = inv.NodeByName(ctx, "anchor")
|
|
if n.AgentAccount != "agent" || n.AgentHome() != "/home/agent" {
|
|
t.Fatalf("agent account %q, home %q; want agent, /home/agent", n.AgentAccount, n.AgentHome())
|
|
}
|
|
all, err := inv.Nodes(ctx)
|
|
if err != nil || len(all) != 1 || all[0].AgentAccount != "agent" {
|
|
t.Fatalf("the listing does not carry the agent account: %+v %v", all, err)
|
|
}
|
|
|
|
if err := inv.SetAgentAccount(ctx, "anchor", "agent", "/srv/agent"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n, _ = inv.NodeByName(ctx, "anchor"); n.AgentHome() != "/srv/agent" {
|
|
t.Fatalf("the stated home is %q", n.AgentHome())
|
|
}
|
|
|
|
for _, c := range []struct{ account, home, says string }{
|
|
{"root", "", "may not run as root"},
|
|
{"operator", "", "operator account"},
|
|
{"Agent", "", "not a login name"},
|
|
{"9agent", "", "not a login name"},
|
|
{"agent", "relative", "absolute"},
|
|
{"postgres", "", "service account"},
|
|
{"systemd-network", "", "service account"},
|
|
{"showcase", "", "service account"},
|
|
{"", "/home/x", "without an agent account"},
|
|
} {
|
|
err := inv.SetAgentAccount(ctx, "anchor", c.account, c.home)
|
|
if err == nil || !strings.Contains(err.Error(), c.says) {
|
|
t.Errorf("%q %q: %v; want a refusal saying %q", c.account, c.home, err, c.says)
|
|
}
|
|
}
|
|
if n, _ = inv.NodeByName(ctx, "anchor"); n.AgentAccount != "agent" {
|
|
t.Fatalf("a refusal changed the record: %q", n.AgentAccount)
|
|
}
|
|
|
|
// The other direction: the operator account may not be named as the agent account either.
|
|
if err := inv.SetAccount(ctx, "anchor", "agent", ""); err == nil || !strings.Contains(err.Error(), "agent account") {
|
|
t.Fatalf("the operator account named as the agent account: %v; want a refusal", err)
|
|
}
|
|
if n, _ = inv.NodeByName(ctx, "anchor"); n.Account != "operator" {
|
|
t.Fatalf("a refusal changed the operator account: %q", n.Account)
|
|
}
|
|
|
|
if err := inv.SetAgentAccount(ctx, "anchor", "", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.SetAccount(ctx, "anchor", "agent", ""); err != nil {
|
|
t.Fatalf("with the agent account cleared, the name is free: %v", err)
|
|
}
|
|
if err := inv.SetAccount(ctx, "anchor", "operator", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n, _ = inv.NodeByName(ctx, "anchor"); n.AgentAccount != "" || n.AgentAccountHome != "" {
|
|
t.Fatalf("clearing left %q %q", n.AgentAccount, n.AgentAccountHome)
|
|
}
|
|
if err := inv.SetAgentAccount(ctx, "nowhere", "agent", ""); !errors.Is(err, ErrNoSuchNode) {
|
|
t.Fatalf("an unknown node: %v", err)
|
|
}
|
|
}
|