116 lines
4.1 KiB
Go
116 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"agent-system-backend/internal/store"
|
|
)
|
|
|
|
func TestLegacyUserCredentialCommandsStopBeforeOpeningStorage(t *testing.T) {
|
|
data := t.TempDir()
|
|
for _, args := range [][]string{
|
|
{"reset-password", "--data", data, "--owner", "victim", "--password", "attacker-password"},
|
|
{"issue-login-key", "--data", data, "--owner", "victim", "--purpose", "recover", "--revoke-all-credentials"},
|
|
} {
|
|
if code := runUser(args); code != 2 {
|
|
t.Fatalf("legacy command did not reject before storage: %v code=%d", args[0], code)
|
|
}
|
|
}
|
|
out := filepath.Join(data, "delivery.json")
|
|
if code := runUser([]string{"create", "--data", data, "--owner", "victim", "--password", "attacker-password", "--out", out}); code != 2 {
|
|
t.Fatalf("password-bearing local create accepted: %d", code)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(data, "agent-system.db")); !os.IsNotExist(err) {
|
|
t.Fatalf("rejected commands opened/created a database: %v", err)
|
|
}
|
|
if _, err := os.Stat(out); !os.IsNotExist(err) {
|
|
t.Fatalf("rejected commands wrote a delivery file: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUserCLIRejectsAdministratorAppointmentBeforeOpeningStorage(t *testing.T) {
|
|
data := t.TempDir()
|
|
out := filepath.Join(data, "delivery.json")
|
|
for _, args := range [][]string{
|
|
{"create", "--data", data, "--owner", "mallory", "--admin", "--out", out},
|
|
{"create", "--data", data, "--owner", "mallory", "--role", "admin", "--out", out},
|
|
{"bootstrap-admin", "--data", data, "--owner", "mallory", "--out", out},
|
|
} {
|
|
if code := runUser(args); code != 2 {
|
|
t.Fatalf("administrator appointment accepted: %v code=%d", args, code)
|
|
}
|
|
}
|
|
if _, err := os.Stat(filepath.Join(data, "agent-system.db")); !os.IsNotExist(err) {
|
|
t.Fatalf("rejected commands opened/created a database: %v", err)
|
|
}
|
|
if _, err := os.Stat(out); !os.IsNotExist(err) {
|
|
t.Fatalf("rejected commands wrote a delivery file: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUserCLIAdministratorAppointmentLeavesExistingStoreUnchanged(t *testing.T) {
|
|
dir, s := cliStore(t)
|
|
if _, err := s.BootstrapSuperAdmin("root", mustHash(t, "Root-Password-1")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, args := range [][]string{
|
|
{"create", "--data", dir, "--owner", "mallory", "--admin", "--out-file", filepath.Join(t.TempDir(), "a")},
|
|
{"create", "--data", dir, "--owner", "mallory", "--role", "admin", "--out-file", filepath.Join(t.TempDir(), "b")},
|
|
{"bootstrap-admin", "--data", dir, "--owner", "mallory", "--out-file", filepath.Join(t.TempDir(), "c")},
|
|
} {
|
|
rc, output := accountCLI(t, args...)
|
|
if rc != 2 || !strings.Contains(output, "super administrator") {
|
|
t.Fatalf("%v: rc=%d output=%q", args, rc, output)
|
|
}
|
|
}
|
|
if _, err := s.GetUser("mallory"); err == nil {
|
|
t.Fatal("rejected CLI appointment created an account")
|
|
}
|
|
rc, _ := accountCLI(t, "create", "--data", dir, "--owner", "ada")
|
|
if rc != 0 {
|
|
t.Fatalf("ordinary local create failed: %d", rc)
|
|
}
|
|
if ada, err := s.GetAccountByOwner("ada"); err != nil || ada.IsAdmin || ada.IsSuperAdmin {
|
|
t.Fatalf("ordinary local create: %+v %v", ada, err)
|
|
}
|
|
}
|
|
|
|
func mustHash(t *testing.T, password string) string {
|
|
t.Helper()
|
|
hash, err := store.HashPassword(password)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return hash
|
|
}
|
|
|
|
func TestCredentialDeliveryCreatesExclusive0600File(t *testing.T) {
|
|
dir := t.TempDir()
|
|
out := filepath.Join(dir, "credential.json")
|
|
if err := os.WriteFile(out, []byte("old"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := deliverCredential(out, "activation", "alice", "secret", nil); err == nil {
|
|
t.Fatal("existing permissive file was overwritten")
|
|
}
|
|
bytes, err := os.ReadFile(out)
|
|
if err != nil || string(bytes) != "old" {
|
|
t.Fatalf("existing file changed: %q %v", bytes, err)
|
|
}
|
|
out = filepath.Join(dir, "new.json")
|
|
if err := deliverCredential(out, "activation", "alice", "secret", nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
info, err := os.Stat(out)
|
|
if err != nil || info.Mode().Perm() != 0o600 {
|
|
t.Fatalf("delivery mode: %v %v", info, err)
|
|
}
|
|
bytes, err = os.ReadFile(out)
|
|
if err != nil || !strings.Contains(string(bytes), `"secret": "secret"`) {
|
|
t.Fatalf("delivery payload: %v", err)
|
|
}
|
|
}
|