5c7dd252db
Initialize a DB, drop EMCLI_ADMIN_KEY, attempt every admin command with only EMCLI_KEY: each is refused and the DB is byte-for-byte unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
57 lines
1.4 KiB
Go
57 lines
1.4 KiB
Go
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, _ := store.Open(db)
|
|
ak, _ := crypto.AdminKeyFromEnv()
|
|
gk, _ := crypto.AgentKeyFromEnv()
|
|
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", "list"},
|
|
{"config", "set", "audit_retention_days", "30"},
|
|
{"audit"},
|
|
}
|
|
for _, args := range adminAttempts {
|
|
code, out, errOut := run(t, args...)
|
|
if code == 0 {
|
|
t.Fatalf("admin command %v must be refused with only EMCLI_KEY (out=%q err=%q)", args, out, errOut)
|
|
}
|
|
}
|
|
if !bytes.Equal(before, dbBytes(t, db)) {
|
|
t.Fatal("DB changed despite all admin commands being refused")
|
|
}
|
|
}
|