diff --git a/cmd/secubox/internal/profile/profile.go b/cmd/secubox/internal/profile/profile.go new file mode 100644 index 00000000..84e01021 --- /dev/null +++ b/cmd/secubox/internal/profile/profile.go @@ -0,0 +1,74 @@ +// cmd/secubox/internal/profile/profile.go +package profile + +import ( + "fmt" + "os" + + "gopkg.in/yaml.v3" +) + +// Profile represents a SecuBox image profile configuration +type Profile struct { + Name string `yaml:"name"` + Inherits string `yaml:"inherits,omitempty"` + Description string `yaml:"description"` + Constraints Constraints `yaml:"constraints,omitempty"` + Packages Packages `yaml:"packages,omitempty"` + Kernel Kernel `yaml:"kernel,omitempty"` + Services Services `yaml:"services,omitempty"` + Sysctl map[string]interface{} `yaml:"sysctl,omitempty"` + Features Features `yaml:"features,omitempty"` +} + +// Constraints defines hardware requirements for the profile +type Constraints struct { + MinRAM string `yaml:"min_ram,omitempty"` + MaxRAM string `yaml:"max_ram,omitempty"` +} + +// Packages defines required and excluded packages +type Packages struct { + Required []string `yaml:"required,omitempty"` + Excluded []string `yaml:"excluded,omitempty"` +} + +// Kernel defines kernel version and module configuration +type Kernel struct { + Version string `yaml:"version,omitempty"` + Modules KernelModules `yaml:"modules,omitempty"` +} + +// KernelModules defines modules to enable or blacklist +type KernelModules struct { + Enable []string `yaml:"enable,omitempty"` + Blacklist []string `yaml:"blacklist,omitempty"` +} + +// Services defines systemd services to enable or disable +type Services struct { + Enable []string `yaml:"enable,omitempty"` + Disable []string `yaml:"disable,omitempty"` +} + +// Features defines optional feature flags +type Features struct { + DPI interface{} `yaml:"dpi,omitempty"` + LXC bool `yaml:"lxc,omitempty"` + Swap string `yaml:"swap,omitempty"` +} + +// Load reads and parses a profile YAML file +func Load(path string) (*Profile, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read profile %s: %w", path, err) + } + + var p Profile + if err := yaml.Unmarshal(data, &p); err != nil { + return nil, fmt.Errorf("parse profile %s: %w", path, err) + } + + return &p, nil +} diff --git a/cmd/secubox/internal/profile/profile_test.go b/cmd/secubox/internal/profile/profile_test.go new file mode 100644 index 00000000..4f2ae149 --- /dev/null +++ b/cmd/secubox/internal/profile/profile_test.go @@ -0,0 +1,36 @@ +package profile + +import ( + "os" + "path/filepath" + "testing" +) + +func TestLoadProfile(t *testing.T) { + dir := t.TempDir() + content := ` +name: test-profile +description: Test profile +packages: + required: + - secubox-core + - secubox-hub +` + path := filepath.Join(dir, "test.yaml") + if err := os.WriteFile(path, []byte(content), 0644); err != nil { + t.Fatal(err) + } + + p, err := Load(path) + if err != nil { + t.Fatalf("Load() error = %v", err) + } + + if p.Name != "test-profile" { + t.Errorf("Name = %q, want %q", p.Name, "test-profile") + } + + if len(p.Packages.Required) != 2 { + t.Errorf("Packages.Required = %d, want 2", len(p.Packages.Required)) + } +} diff --git a/profiles/base.yaml b/profiles/base.yaml new file mode 100644 index 00000000..91aba059 --- /dev/null +++ b/profiles/base.yaml @@ -0,0 +1,35 @@ +# profiles/base.yaml +version: "2.8.0" +name: base +description: Common SecuBox foundation + +packages: + required: + - secubox-core + - secubox-hub + - secubox-portal + - secubox-system + - secubox-hardening + +kernel: + version: "6.6" + modules: + enable: + - wireguard + - nf_tables + - nft_nat + - nft_ct + - nft_log + blacklist: [] + +services: + enable: + - secubox-hub + - nginx + - nftables + +sysctl: + net.ipv4.ip_forward: 1 + net.ipv4.conf.all.rp_filter: 1 + kernel.randomize_va_space: 2 + kernel.kptr_restrict: 2