package security_test import ( "os" "path/filepath" "testing" shellsecurity "github.com/enmanuel/agents/shell/security" ) // writeFile is a helper that creates a file in dir with the given content. func writeFile(t *testing.T, dir, name, content string) { t.Helper() if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0o644); err != nil { t.Fatalf("writeFile %s: %v", name, err) } } // --- Test 3.1: directorio inexistente → policy vacía, sin error --- func TestLoad_NonExistentDir(t *testing.T) { policy, err := shellsecurity.Load("/tmp/does-not-exist-security-xyz") if err != nil { t.Fatalf("expected no error, got: %v", err) } if len(policy.UserGroups) != 0 || len(policy.AgentGroups) != 0 || len(policy.Policies) != 0 { t.Errorf("expected empty policy, got: %+v", policy) } } // --- Test 3.2: directorio vacío (sin YAML) → policy vacía, sin error --- func TestLoad_EmptyDir(t *testing.T) { dir := t.TempDir() policy, err := shellsecurity.Load(dir) if err != nil { t.Fatalf("expected no error, got: %v", err) } if len(policy.UserGroups) != 0 || len(policy.AgentGroups) != 0 || len(policy.Policies) != 0 { t.Errorf("expected empty policy, got: %+v", policy) } } // --- Test 3.3: los 3 YAML válidos → policy con todos los campos --- func TestLoad_AllFiles(t *testing.T) { dir := t.TempDir() writeFile(t, dir, "user-groups.yaml", ` groups: admins: members: ["@admin:example.com"] everyone: members: ["*"] `) writeFile(t, dir, "agent-groups.yaml", ` groups: assistants: agents: - assistant-bot all: agents: ["*"] `) writeFile(t, dir, "permissions.yaml", ` policies: - agent_group: all permissions: - user_group: admins actions: ["*"] - user_group: everyone actions: ["ask"] `) policy, err := shellsecurity.Load(dir) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(policy.UserGroups) != 2 { t.Errorf("expected 2 user groups, got %d", len(policy.UserGroups)) } if len(policy.AgentGroups) != 2 { t.Errorf("expected 2 agent groups, got %d", len(policy.AgentGroups)) } if len(policy.Policies) != 1 { t.Errorf("expected 1 policy, got %d", len(policy.Policies)) } if len(policy.Policies[0].Permissions) != 2 { t.Errorf("expected 2 permissions, got %d", len(policy.Policies[0].Permissions)) } } // --- Test 3.4: solo user-groups.yaml → user groups poblados, resto vacío --- func TestLoad_OnlyUserGroups(t *testing.T) { dir := t.TempDir() writeFile(t, dir, "user-groups.yaml", ` groups: admins: members: ["@admin:example.com"] `) policy, err := shellsecurity.Load(dir) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(policy.UserGroups) != 1 { t.Errorf("expected 1 user group, got %d", len(policy.UserGroups)) } if policy.UserGroups[0].Name != "admins" { t.Errorf("expected group name 'admins', got %q", policy.UserGroups[0].Name) } if len(policy.AgentGroups) != 0 { t.Errorf("expected no agent groups, got %d", len(policy.AgentGroups)) } if len(policy.Policies) != 0 { t.Errorf("expected no policies, got %d", len(policy.Policies)) } } // --- Test 3.5: YAML malformado → error con nombre de archivo en el mensaje --- func TestLoad_MalformedYAML(t *testing.T) { dir := t.TempDir() writeFile(t, dir, "user-groups.yaml", `this: is: not: valid: yaml: [`) _, err := shellsecurity.Load(dir) if err == nil { t.Fatal("expected error for malformed YAML, got nil") } if got := err.Error(); len(got) == 0 { t.Fatal("error message is empty") } // Must mention the filename if !containsString(err.Error(), "user-groups.yaml") { t.Errorf("error message should contain filename, got: %s", err.Error()) } } // --- Test 3.6: "*" como string literal en members y agents --- func TestLoad_WildcardStrings(t *testing.T) { dir := t.TempDir() writeFile(t, dir, "user-groups.yaml", ` groups: everyone: members: ["*"] `) writeFile(t, dir, "agent-groups.yaml", ` groups: all: agents: ["*"] `) policy, err := shellsecurity.Load(dir) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(policy.UserGroups) != 1 { t.Fatalf("expected 1 user group, got %d", len(policy.UserGroups)) } if len(policy.UserGroups[0].Members) != 1 || policy.UserGroups[0].Members[0] != "*" { t.Errorf("expected members=[\"*\"], got %v", policy.UserGroups[0].Members) } if len(policy.AgentGroups) != 1 { t.Fatalf("expected 1 agent group, got %d", len(policy.AgentGroups)) } if len(policy.AgentGroups[0].Agents) != 1 || policy.AgentGroups[0].Agents[0] != "*" { t.Errorf("expected agents=[\"*\"], got %v", policy.AgentGroups[0].Agents) } } func containsString(s, sub string) bool { return len(s) >= len(sub) && (s == sub || len(s) > 0 && containsSubstr(s, sub)) } func containsSubstr(s, sub string) bool { for i := 0; i <= len(s)-len(sub); i++ { if s[i:i+len(sub)] == sub { return true } } return false }