package cli import ( "bytes" "os" "path/filepath" "testing" "git.dcglab.co.uk/steve/emcli/internal/crypto" "git.dcglab.co.uk/steve/emcli/internal/store" ) func dbBytes(t *testing.T, path string) []byte { t.Helper() b, err := os.ReadFile(path) if err != nil { t.Fatalf("read db: %v", err) } return b } // A forced agent holding ONLY EMCLI_KEY must not be able to run any admin // command, and the DB must be unchanged after it tries. func TestAgentKeyCannotRunAdminCommands(t *testing.T) { db := filepath.Join(t.TempDir(), "emcli.db") t.Setenv("EMCLI_ADMIN_KEY", b64Key()) t.Setenv("EMCLI_KEY", b64AgentKey()) t.Setenv("EMCLI_DB", db) st, err := store.Open(db) if err != nil { t.Fatalf("store.Open: %v", err) } ak, err := crypto.AdminKeyFromEnv() if err != nil { t.Fatalf("AdminKeyFromEnv: %v", err) } gk, err := crypto.AgentKeyFromEnv() if err != nil { t.Fatalf("AgentKeyFromEnv: %v", err) } if err := st.InitKeys(ak, gk); err != nil { t.Fatalf("InitKeys: %v", err) } st.Close() // Simulate the agent's environment: admin key absent. t.Setenv("EMCLI_ADMIN_KEY", "") before := dbBytes(t, db) adminAttempts := [][]string{ {"account", "add", "--name", "x", "--imap-host", "h", "--username", "u@x.com"}, {"config", "set", "audit_retention_days", "30"}, {"audit"}, } for _, args := range adminAttempts { code, out, errOut := run(t, args...) if code == 0 { t.Errorf("admin command %v must be refused with only EMCLI_KEY (out=%q err=%q)", args, out, errOut) continue } } if !bytes.Equal(before, dbBytes(t, db)) { t.Fatal("DB changed despite all admin commands being refused") } }