feat: import agents_and_robots platform as unibots (Matrix-out, unibus transport)
Reemplaza el scaffold del echobot por la plataforma completa de bots traida desde ~/DataProyects/Github/agents_and_robots tras la operacion Matrix-out: los bots ya no hablan por Matrix sino por el bus unibus (modelo todo-rooms + E2E via shell/transportunibus sobre github.com/enmanuel/unibus/pkg/client). - go.mod: replace de unibus -> ../unibus y de fn-registry -> ../../../.. (paths relativos reajustados a la nueva ubicacion dentro de fn_registry). - app.md: bump a 0.2.0, descripcion + arquitectura + comandos + gotchas reales. - modulo Go conservado como github.com/enmanuel/agents (sin reescribir imports). agents_and_robots queda archivado como museo de la era Matrix.
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
// Package security provides the impure loader for security policy YAML files.
|
||||
// It reads security/ directory files and returns a pure security.SecurityPolicy.
|
||||
package security
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/enmanuel/agents/pkg/security"
|
||||
)
|
||||
|
||||
// --- YAML intermediate types (private, only for parsing) ---
|
||||
|
||||
type yamlUserGroups struct {
|
||||
Groups map[string]struct {
|
||||
Members []string `yaml:"members"`
|
||||
} `yaml:"groups"`
|
||||
}
|
||||
|
||||
type yamlAgentGroups struct {
|
||||
Groups map[string]struct {
|
||||
Agents []string `yaml:"agents"`
|
||||
} `yaml:"groups"`
|
||||
}
|
||||
|
||||
type yamlPermissions struct {
|
||||
Policies []struct {
|
||||
AgentGroup string `yaml:"agent_group"`
|
||||
Permissions []struct {
|
||||
UserGroup string `yaml:"user_group"`
|
||||
Actions []string `yaml:"actions"`
|
||||
} `yaml:"permissions"`
|
||||
} `yaml:"policies"`
|
||||
}
|
||||
|
||||
// Load reads the security YAML files from dir and returns a SecurityPolicy.
|
||||
// If dir does not exist or is empty, returns an empty policy without error.
|
||||
// If an individual file is missing, that section is left empty.
|
||||
// If a YAML file is malformed, returns an error naming the file.
|
||||
func Load(dir string) (security.SecurityPolicy, error) {
|
||||
if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
|
||||
return security.SecurityPolicy{}, nil
|
||||
}
|
||||
|
||||
userGroups, err := loadUserGroups(filepath.Join(dir, "user-groups.yaml"))
|
||||
if err != nil {
|
||||
return security.SecurityPolicy{}, err
|
||||
}
|
||||
|
||||
agentGroups, err := loadAgentGroups(filepath.Join(dir, "agent-groups.yaml"))
|
||||
if err != nil {
|
||||
return security.SecurityPolicy{}, err
|
||||
}
|
||||
|
||||
policies, err := loadPermissions(filepath.Join(dir, "permissions.yaml"))
|
||||
if err != nil {
|
||||
return security.SecurityPolicy{}, err
|
||||
}
|
||||
|
||||
return security.SecurityPolicy{
|
||||
UserGroups: userGroups,
|
||||
AgentGroups: agentGroups,
|
||||
Policies: policies,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadUserGroups(path string) ([]security.UserGroup, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("security: reading %s: %w", path, err)
|
||||
}
|
||||
|
||||
var raw yamlUserGroups
|
||||
if err := yaml.Unmarshal(data, &raw); err != nil {
|
||||
return nil, fmt.Errorf("security: parsing %s: %w", path, err)
|
||||
}
|
||||
|
||||
groups := make([]security.UserGroup, 0, len(raw.Groups))
|
||||
for name, g := range raw.Groups {
|
||||
groups = append(groups, security.UserGroup{
|
||||
Name: name,
|
||||
Members: g.Members,
|
||||
})
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func loadAgentGroups(path string) ([]security.AgentGroup, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("security: reading %s: %w", path, err)
|
||||
}
|
||||
|
||||
var raw yamlAgentGroups
|
||||
if err := yaml.Unmarshal(data, &raw); err != nil {
|
||||
return nil, fmt.Errorf("security: parsing %s: %w", path, err)
|
||||
}
|
||||
|
||||
groups := make([]security.AgentGroup, 0, len(raw.Groups))
|
||||
for name, g := range raw.Groups {
|
||||
groups = append(groups, security.AgentGroup{
|
||||
Name: name,
|
||||
Agents: g.Agents,
|
||||
})
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func loadPermissions(path string) ([]security.AgentPolicy, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("security: reading %s: %w", path, err)
|
||||
}
|
||||
|
||||
var raw yamlPermissions
|
||||
if err := yaml.Unmarshal(data, &raw); err != nil {
|
||||
return nil, fmt.Errorf("security: parsing %s: %w", path, err)
|
||||
}
|
||||
|
||||
policies := make([]security.AgentPolicy, 0, len(raw.Policies))
|
||||
for _, p := range raw.Policies {
|
||||
perms := make([]security.Permission, 0, len(p.Permissions))
|
||||
for _, perm := range p.Permissions {
|
||||
perms = append(perms, security.Permission{
|
||||
UserGroup: perm.UserGroup,
|
||||
Actions: perm.Actions,
|
||||
})
|
||||
}
|
||||
policies = append(policies, security.AgentPolicy{
|
||||
AgentGroup: p.AgentGroup,
|
||||
Permissions: perms,
|
||||
})
|
||||
}
|
||||
return policies, nil
|
||||
}
|
||||
Reference in New Issue
Block a user