From 59ac54e2fcb069c39242306f206f6aaeb3c665a9 Mon Sep 17 00:00:00 2001 From: Alexandre Pujol Date: Wed, 2 Oct 2024 16:22:46 +0100 Subject: [PATCH] build: reorganise build: abi4, fallback, prebuild cli - ABI4 by default, fallback to abi 3. - aa-prebuild cli that can be used by other project shipping profiles. - --file option to cli to only build one dev profile. - add abi version filter to only & exclude directives. --- cmd/prebuild/main.go | 120 +++++------- cmd/prebuild/main_test.go | 61 ++---- docs/development/directives.md | 1 + pkg/prebuild/builder/abi.go | 14 +- pkg/prebuild/builder/complain.go | 6 +- pkg/prebuild/builder/core.go | 4 +- pkg/prebuild/builder/core_test.go | 16 +- pkg/prebuild/builder/dev.go | 6 +- pkg/prebuild/builder/enforce.go | 6 +- pkg/prebuild/builder/fsp.go | 6 +- pkg/prebuild/builder/userspace.go | 10 +- pkg/prebuild/cli/cli.go | 181 ++++++++++++++++++ .../{prebuild_test.go => cli/cli_test.go} | 29 ++- pkg/prebuild/{cfg => }/core.go | 12 +- pkg/prebuild/{cfg => }/core_test.go | 5 +- pkg/prebuild/directive/core.go | 14 +- pkg/prebuild/directive/dbus.go | 6 +- pkg/prebuild/directive/exec.go | 8 +- pkg/prebuild/directive/exec_test.go | 4 +- pkg/prebuild/directive/filter.go | 17 +- pkg/prebuild/directive/filter_test.go | 10 +- pkg/prebuild/directive/stack.go | 8 +- pkg/prebuild/directive/stack_test.go | 4 +- pkg/prebuild/{cfg => }/directories.go | 10 +- pkg/prebuild/{cfg => }/files.go | 35 +--- pkg/prebuild/{cfg => }/files_test.go | 2 +- pkg/prebuild/{cfg => }/os.go | 2 +- pkg/prebuild/{cfg => }/os_test.go | 2 +- pkg/prebuild/prebuild.go | 117 ----------- pkg/prebuild/prepare/configure.go | 71 +++++-- pkg/prebuild/prepare/core.go | 4 +- pkg/prebuild/prepare/core_test.go | 14 +- pkg/prebuild/prepare/flags.go | 14 +- pkg/prebuild/prepare/fsp.go | 14 +- pkg/prebuild/prepare/ignore.go | 16 +- pkg/prebuild/prepare/merge.go | 12 +- pkg/prebuild/prepare/synchronise.go | 30 ++- pkg/prebuild/prepare/systemd.go | 14 +- tests/cmd/main.go | 8 +- 39 files changed, 473 insertions(+), 440 deletions(-) create mode 100644 pkg/prebuild/cli/cli.go rename pkg/prebuild/{prebuild_test.go => cli/cli_test.go} (79%) rename pkg/prebuild/{cfg => }/core.go (73%) rename pkg/prebuild/{cfg => }/core_test.go (90%) rename pkg/prebuild/{cfg => }/directories.go (83%) rename pkg/prebuild/{cfg => }/files.go (63%) rename pkg/prebuild/{cfg => }/files_test.go (99%) rename pkg/prebuild/{cfg => }/os.go (99%) rename pkg/prebuild/{cfg => }/os_test.go (99%) delete mode 100644 pkg/prebuild/prebuild.go diff --git a/cmd/prebuild/main.go b/cmd/prebuild/main.go index d909cc81..6b2b2422 100644 --- a/cmd/prebuild/main.go +++ b/cmd/prebuild/main.go @@ -5,92 +5,66 @@ package main import ( - "flag" - "fmt" - "os" + "slices" - "github.com/roddhjav/apparmor.d/pkg/logging" "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" - "github.com/roddhjav/apparmor.d/pkg/prebuild/directive" + "github.com/roddhjav/apparmor.d/pkg/prebuild/cli" "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" ) -const usage = `prebuild [-h] [--full] [--complain | --enforce] - - Prebuild apparmor.d profiles for a given distribution and apply - internal built-in directives. - -Options: - -h, --help Show this help message and exit. - -f, --full Set AppArmor for full system policy. - -c, --complain Set complain flag on all profiles. - -e, --enforce Set enforce flag on all profiles. - --abi4 Convert the profiles to Apparmor abi/4.0. - -` - -var ( - help bool - full bool - complain bool - enforce bool - abi4 bool -) - func init() { - flag.BoolVar(&help, "h", false, "Show this help message and exit.") - flag.BoolVar(&help, "help", false, "Show this help message and exit.") - flag.BoolVar(&full, "f", false, "Set AppArmor for full system policy.") - flag.BoolVar(&full, "full", false, "Set AppArmor for full system policy.") - flag.BoolVar(&complain, "c", false, "Set complain flag on all profiles.") - flag.BoolVar(&complain, "complain", false, "Set complain flag on all profiles.") - flag.BoolVar(&enforce, "e", false, "Set enforce flag on all profiles.") - flag.BoolVar(&enforce, "enforce", false, "Set enforce flag on all profiles.") - flag.BoolVar(&abi4, "abi4", false, "Convert the profiles to Apparmor abi/4.0.") -} + // Define the tasks applied by default + prepare.Register( + "synchronise", + "ignore", + "merge", + "configure", + "setflags", + "systemd-default", + ) -func aaPrebuild() error { - logging.Step("Building apparmor.d profiles for %s.", cfg.Distribution) + // Build tasks applied by default + builder.Register( + "userspace", // Resolve variable in the userspace profile + "dev", // Temporary fix for #74, #80 & #235 + ) - if full { - prepare.Register("fsp") - builder.Register("fsp") - } else { - prepare.Register("systemd-early") + // Compatibility with AppArmor 3 + switch prebuild.Distribution { + case "arch": + prebuild.ABI = 3 + + case "ubuntu": + if !slices.Contains([]string{"noble"}, prebuild.Release["VERSION_CODENAME"]) { + prebuild.ABI = 3 + } + + case "debian": + prebuild.ABI = 3 + + case "whonix": + prebuild.ABI = 3 + + // Hide rewrittem Whonix profiles + prebuild.Hide += `/etc/apparmor.d/abstractions/base.d/kicksecure + /etc/apparmor.d/home.tor-browser.firefox + /etc/apparmor.d/tunables/homsanitycheck + /etc/apparmor.d/usr.bin.url_e.d/anondist + /etc/apparmor.d/tunables/home.d/live-mode + /etc/apparmor.d/tunables/home.d/qubes-whonix-anondist + /etc/apparmor.d/usr.bin.hexchat + /etc/apparmor.d/usr.bin.sdwdate + /etc/apparmor.d/usr.bin.systemcheck + /etc/apparmor.d/usr.bin.timeto_unixtime + /etc/apparmor.d/whonix-firewall + ` } - - if complain { - builder.Register("complain") - } else if enforce { - builder.Register("enforce") - } - - if abi4 { + if prebuild.ABI == 3 { builder.Register("abi3") } - - if err := prebuild.Prepare(); err != nil { - return err - } - return prebuild.Build() } func main() { - flag.Usage = func() { - fmt.Printf("%s%s\n%s\n%s", usage, - cfg.Help("Prepare", prepare.Tasks), - cfg.Help("Build", builder.Builders), - cfg.Usage("Directives", directive.Directives), - ) - } - flag.Parse() - if help { - flag.Usage() - os.Exit(0) - } - if err := aaPrebuild(); err != nil { - logging.Fatal("%s", err.Error()) - } + cli.Prebuild() } diff --git a/cmd/prebuild/main_test.go b/cmd/prebuild/main_test.go index 8e80c3ab..d3c28f02 100644 --- a/cmd/prebuild/main_test.go +++ b/cmd/prebuild/main_test.go @@ -9,9 +9,7 @@ import ( "os/exec" "testing" - "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" - "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func chdirGitRoot() { @@ -26,64 +24,33 @@ func chdirGitRoot() { } } -func Test_AAPrebuild(t *testing.T) { +func Test_main(t *testing.T) { tests := []struct { - name string - wantErr bool - full bool - complain bool - dist string + name string + dist string }{ { - name: "Build for Archlinux", - wantErr: false, - full: false, - complain: true, - dist: "arch", + name: "Build for Archlinux", + dist: "arch", }, { - name: "Build for Ubuntu", - wantErr: false, - full: true, - complain: false, - dist: "ubuntu", + name: "Build for Ubuntu", + dist: "ubuntu", }, { - name: "Build for Debian", - wantErr: false, - full: true, - complain: false, - dist: "debian", + name: "Build for Debian", + dist: "debian", }, { - name: "Build for OpenSUSE Tumbleweed", - wantErr: false, - full: true, - complain: true, - dist: "opensuse", + name: "Build for OpenSUSE Tumbleweed", + dist: "opensuse", }, - // { - // name: "Build for Fedora", - // wantErr: true, - // full: false, - // complain: false, - // dist: "fedora", - // }, } chdirGitRoot() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfg.Distribution = tt.dist - if tt.full { - prepare.Register("fsp") - builder.Register("fsp") - } - if tt.complain { - builder.Register("complain") - } - if err := aaPrebuild(); (err != nil) != tt.wantErr { - t.Errorf("aaPrebuild() error = %v, wantErr %v", err, tt.wantErr) - } + prebuild.Distribution = tt.dist + main() }) } } diff --git a/docs/development/directives.md b/docs/development/directives.md index 7263b491..8897f951 100644 --- a/docs/development/directives.md +++ b/docs/development/directives.md @@ -40,6 +40,7 @@ The `only` and `exclude` directives can be used to filter individual rule or rul - A supported target distribution: `arch`, `debian`, `ubuntu`, `opensuse`, `whonix`. - A supported distribution family: `apt`, `pacman`, `zypper`. + - A supported ABI: `abi3`, `abi4`. **Example** diff --git a/pkg/prebuild/builder/abi.go b/pkg/prebuild/builder/abi.go index 72b3943d..4e74a541 100644 --- a/pkg/prebuild/builder/abi.go +++ b/pkg/prebuild/builder/abi.go @@ -5,25 +5,25 @@ package builder import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) var ( - regAbi4To3 = util.ToRegexRepl([]string{ // Currently Abi3 -> Abi4 - `abi/3.0`, `abi/4.0`, - `# userns,`, `userns,`, - `# mqueue`, `mqueue`, + regAbi4To3 = util.ToRegexRepl([]string{ + `abi/4.0`, `abi/3.0`, + `userns,`, `# userns,`, + `mqueue`, `# mqueue`, }) ) type ABI3 struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&ABI3{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "abi3", Msg: "Convert all profiles from abi 4.0 to abi 3.0", }, diff --git a/pkg/prebuild/builder/complain.go b/pkg/prebuild/builder/complain.go index 68dcc9f4..dbd9b347 100644 --- a/pkg/prebuild/builder/complain.go +++ b/pkg/prebuild/builder/complain.go @@ -9,7 +9,7 @@ import ( "slices" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) var ( @@ -18,12 +18,12 @@ var ( ) type Complain struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&Complain{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "complain", Msg: "Set complain flag on all profiles", }, diff --git a/pkg/prebuild/builder/core.go b/pkg/prebuild/builder/core.go index 64046721..b45075e1 100644 --- a/pkg/prebuild/builder/core.go +++ b/pkg/prebuild/builder/core.go @@ -8,7 +8,7 @@ import ( "fmt" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) var ( @@ -21,7 +21,7 @@ var ( // Main directive interface type Builder interface { - cfg.BaseInterface + prebuild.BaseInterface Apply(opt *Option, profile string) (string, error) } diff --git a/pkg/prebuild/builder/core_test.go b/pkg/prebuild/builder/core_test.go index 597832b9..5a1a39da 100644 --- a/pkg/prebuild/builder/core_test.go +++ b/pkg/prebuild/builder/core_test.go @@ -8,7 +8,7 @@ import ( "slices" "testing" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func TestBuilder_Apply(t *testing.T) { @@ -23,17 +23,17 @@ func TestBuilder_Apply(t *testing.T) { name: "abi3", b: Builders["abi3"], profile: ` - abi , - profile test { - # userns, - # mqueue r type=posix /, - }`, - want: ` abi , profile test { userns, mqueue r type=posix /, }`, + want: ` + abi , + profile test { + # userns, + # mqueue r type=posix /, + }`, }, { name: "complain-1", @@ -234,7 +234,7 @@ func TestBuilder_Apply(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - opt := &Option{File: cfg.RootApparmord.Join(tt.name)} + opt := &Option{File: prebuild.RootApparmord.Join(tt.name)} got, err := tt.b.Apply(opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Builder.Apply() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/prebuild/builder/dev.go b/pkg/prebuild/builder/dev.go index f8ebdff0..19fbe409 100644 --- a/pkg/prebuild/builder/dev.go +++ b/pkg/prebuild/builder/dev.go @@ -5,7 +5,7 @@ package builder import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -19,12 +19,12 @@ var ( ) type Dev struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&Dev{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "dev", Msg: "Apply test development changes", }, diff --git a/pkg/prebuild/builder/enforce.go b/pkg/prebuild/builder/enforce.go index d453da51..a7ce90a7 100644 --- a/pkg/prebuild/builder/enforce.go +++ b/pkg/prebuild/builder/enforce.go @@ -8,16 +8,16 @@ import ( "slices" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) type Enforce struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&Enforce{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "enforce", Msg: "All profiles have been enforced", }, diff --git a/pkg/prebuild/builder/fsp.go b/pkg/prebuild/builder/fsp.go index 003f7952..ed2285de 100644 --- a/pkg/prebuild/builder/fsp.go +++ b/pkg/prebuild/builder/fsp.go @@ -5,7 +5,7 @@ package builder import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -16,12 +16,12 @@ var ( ) type FullSystemPolicy struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&FullSystemPolicy{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "fsp", Msg: "Prevent unconfined transitions in profile rules", }, diff --git a/pkg/prebuild/builder/userspace.go b/pkg/prebuild/builder/userspace.go index 8a7df0bc..be5886cb 100644 --- a/pkg/prebuild/builder/userspace.go +++ b/pkg/prebuild/builder/userspace.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) const tokATTACHMENT = "@{exec_path}" @@ -20,12 +20,12 @@ var ( ) type Userspace struct { - cfg.Base + prebuild.Base } func init() { RegisterBuilder(&Userspace{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "userspace", Msg: "Bypass userspace tools restriction", }, @@ -33,10 +33,10 @@ func init() { } func (b Userspace) Apply(opt *Option, profile string) (string, error) { - if ok, _ := opt.File.IsInsideDir(cfg.RootApparmord.Join("abstractions")); ok { + if ok, _ := opt.File.IsInsideDir(prebuild.RootApparmord.Join("abstractions")); ok { return profile, nil } - if ok, _ := opt.File.IsInsideDir(cfg.RootApparmord.Join("tunables")); ok { + if ok, _ := opt.File.IsInsideDir(prebuild.RootApparmord.Join("tunables")); ok { return profile, nil } diff --git a/pkg/prebuild/cli/cli.go b/pkg/prebuild/cli/cli.go new file mode 100644 index 00000000..6fd0a36f --- /dev/null +++ b/pkg/prebuild/cli/cli.go @@ -0,0 +1,181 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023-2024 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package cli + +import ( + "flag" + "fmt" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/logging" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" + "github.com/roddhjav/apparmor.d/pkg/prebuild/directive" + "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +const ( + nilABI uint = 0 + usage = `aa-prebuild [-h] [--complain | --enforce] [--full] [--abi 3|4] + + Prebuild apparmor.d profiles for a given distribution and apply + internal built-in directives. + +Options: + -h, --help Show this help message and exit. + -c, --complain Set complain flag on all profiles. + -e, --enforce Set enforce flag on all profiles. + -a, --abi ABI Target apparmor ABI. + -f, --full Set AppArmor for full system policy. + -F, --file Only prebuild a given file. +` +) + +var ( + help bool + complain bool + enforce bool + full bool + abi uint + file string +) + +func init() { + flag.BoolVar(&help, "h", false, "Show this help message and exit.") + flag.BoolVar(&help, "help", false, "Show this help message and exit.") + flag.BoolVar(&full, "f", false, "Set AppArmor for full system policy.") + flag.BoolVar(&full, "full", false, "Set AppArmor for full system policy.") + flag.BoolVar(&complain, "c", false, "Set complain flag on all profiles.") + flag.BoolVar(&complain, "complain", false, "Set complain flag on all profiles.") + flag.BoolVar(&enforce, "e", false, "Set enforce flag on all profiles.") + flag.BoolVar(&enforce, "enforce", false, "Set enforce flag on all profiles.") + flag.UintVar(&abi, "a", nilABI, "Target apparmor ABI.") + flag.UintVar(&abi, "abi", nilABI, "Target apparmor ABI.") + flag.StringVar(&file, "F", "", "Only prebuild a given file.") + flag.StringVar(&file, "file", "", "Only prebuild a given file.") +} + +func Prebuild() { + flag.Usage = func() { + fmt.Printf("%s%s\n%s\n%s", usage, + prebuild.Help("Prepare", prepare.Tasks), + prebuild.Help("Build", builder.Builders), + directive.Usage(), + ) + } + flag.Parse() + if help { + flag.Usage() + return + } + logging.Step("Building apparmor.d profiles for %s.", prebuild.Distribution) + + if full { + prepare.Register("fsp") + builder.Register("fsp") + } else { + prepare.Register("systemd-early") + } + + if complain { + builder.Register("complain") + } else if enforce { + builder.Register("enforce") + } + + switch abi { + case 3: + prebuild.ABI = 3 + builder.Register("abi3") + case 4: + prebuild.ABI = 4 + for i, b := range builder.Builds { + if b.Name() == "abi3" { + builder.Builds = append(builder.Builds[:i], builder.Builds[i+1:]...) + break + } + } + case nilABI: + default: + logging.Fatal("ABI %d not supported", abi) + } + + if file != "" { + sync, _ := prepare.Tasks["synchronise"].(*prepare.Synchronise) + sync.Path = file + configure, _ := prepare.Tasks["configure"].(*prepare.Configure) + configure.OneFile = true + } + + if err := Prepare(); err != nil { + logging.Fatal("%s", err.Error()) + } + if err := Build(); err != nil { + logging.Fatal("%s", err.Error()) + } +} + +func Prepare() error { + for _, task := range prepare.Prepares { + msg, err := task.Apply() + if err != nil { + return err + } + if file != "" && task.Name() == "setflags" { + continue + } + logging.Success("%s", task.Message()) + logging.Indent = " " + for _, line := range msg { + if strings.Contains(line, "not found") { + logging.Warning("%s", line) + } else { + logging.Bullet("%s", line) + } + } + logging.Indent = "" + } + return nil +} + +func Build() error { + files, _ := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories()) + for _, file := range files { + if !file.Exist() { + continue + } + profile, err := util.ReadFile(file) + if err != nil { + return err + } + profile, err = builder.Run(file, profile) + if err != nil { + return err + } + profile, err = directive.Run(file, profile) + if err != nil { + return err + } + if err := file.WriteFile([]byte(profile)); err != nil { + return err + } + } + + logging.Success("Build tasks:") + logging.Indent = " " + for _, task := range builder.Builds { + logging.Bullet("%s", task.Message()) + } + logging.Indent = "" + logging.Success("Directives processed:") + logging.Indent = " " + for _, dir := range directive.Directives { + logging.Bullet("%s%s", directive.Keyword, dir.Name()) + } + logging.Indent = "" + return nil +} diff --git a/pkg/prebuild/prebuild_test.go b/pkg/prebuild/cli/cli_test.go similarity index 79% rename from pkg/prebuild/prebuild_test.go rename to pkg/prebuild/cli/cli_test.go index db709c31..782d8175 100644 --- a/pkg/prebuild/prebuild_test.go +++ b/pkg/prebuild/cli/cli_test.go @@ -2,7 +2,7 @@ // Copyright (C) 2023-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prebuild +package cli import ( "os" @@ -10,15 +10,15 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" ) func setTestBuildDirectories(name string) { testRoot := paths.New("/tmp/tests") - cfg.Root = testRoot.Join(name) - cfg.RootApparmord = cfg.Root.Join("apparmor.d") + prebuild.Root = testRoot.Join(name) + prebuild.RootApparmord = prebuild.Root.Join("apparmor.d") } func chdirGitRoot() { @@ -33,7 +33,7 @@ func chdirGitRoot() { } } -func Test_PreBuild(t *testing.T) { +func Test_Prebuild(t *testing.T) { tests := []struct { name string wantErr bool @@ -79,17 +79,26 @@ func Test_PreBuild(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { setTestBuildDirectories(tt.name) - cfg.Distribution = tt.dist - if tt.full { + prebuild.Distribution = tt.dist + prepare.Prepares = []prepare.Task{} + prepare.Register( + "synchronise", "ignore", "merge", + "configure", "setflags", "systemd-default", + ) + + if full { prepare.Register("fsp") builder.Register("fsp") + } else { + prepare.Register("systemd-early") } - if tt.complain { + + if complain { builder.Register("complain") - } - if tt.enforce { + } else if enforce { builder.Register("enforce") } + if err := Prepare(); (err != nil) != tt.wantErr { t.Errorf("Prepare() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/prebuild/cfg/core.go b/pkg/prebuild/core.go similarity index 73% rename from pkg/prebuild/cfg/core.go rename to pkg/prebuild/core.go index 56b91ed6..8c2410d1 100644 --- a/pkg/prebuild/cfg/core.go +++ b/pkg/prebuild/core.go @@ -2,7 +2,7 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import "fmt" @@ -37,13 +37,3 @@ func Help[T BaseInterface](name string, tasks map[string]T) string { } return res } - -func Usage[T BaseInterface](name string, tasks map[string]T) string { - res := fmt.Sprintf("%s\n", name) - for _, t := range tasks { - for _, h := range t.Usage() { - res += fmt.Sprintf(" #aa:%s %s\n", t.Name(), h) - } - } - return res -} diff --git a/pkg/prebuild/cfg/core_test.go b/pkg/prebuild/core_test.go similarity index 90% rename from pkg/prebuild/cfg/core_test.go rename to pkg/prebuild/core_test.go index 7cde166a..5abf0a9c 100644 --- a/pkg/prebuild/cfg/core_test.go +++ b/pkg/prebuild/core_test.go @@ -2,7 +2,7 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import ( "slices" @@ -57,9 +57,6 @@ func TestHelp(t *testing.T) { if got := Help(tt.name, tt.tasks); !strings.Contains(got, tt.want) { t.Errorf("Help() = %v, want %v", got, tt.want) } - if got := Usage(tt.name, tt.tasks); !strings.Contains(got, tt.want) { - t.Errorf("Usage() = %v, want %v", got, tt.want) - } }) } } diff --git a/pkg/prebuild/directive/core.go b/pkg/prebuild/directive/core.go index 0e791730..2568cb09 100644 --- a/pkg/prebuild/directive/core.go +++ b/pkg/prebuild/directive/core.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) var ( @@ -25,10 +25,20 @@ var ( // Main directive interface type Directive interface { - cfg.BaseInterface + prebuild.BaseInterface Apply(opt *Option, profile string) (string, error) } +func Usage() string { + res := fmt.Sprintf("Directive:\n") + for _, d := range Directives { + for _, h := range d.Usage() { + res += fmt.Sprintf(" %s%s %s\n", Keyword, d.Name(), h) + } + } + return res +} + // Directive options type Option struct { Name string diff --git a/pkg/prebuild/directive/dbus.go b/pkg/prebuild/directive/dbus.go index 98f5cd61..a1135d67 100644 --- a/pkg/prebuild/directive/dbus.go +++ b/pkg/prebuild/directive/dbus.go @@ -18,7 +18,7 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) var defaultInterfaces = []string{ @@ -27,12 +27,12 @@ var defaultInterfaces = []string{ } type Dbus struct { - cfg.Base + prebuild.Base } func init() { RegisterDirective(&Dbus{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "dbus", Msg: "Dbus directive applied", Help: []string{ diff --git a/pkg/prebuild/directive/exec.go b/pkg/prebuild/directive/exec.go index 64c97e9c..c856b726 100644 --- a/pkg/prebuild/directive/exec.go +++ b/pkg/prebuild/directive/exec.go @@ -12,17 +12,17 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) type Exec struct { - cfg.Base + prebuild.Base } func init() { RegisterDirective(&Exec{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "exec", Msg: "Exec directive applied", Help: []string{"[P|U|p|u|PU|pu|] profiles..."}, @@ -44,7 +44,7 @@ func (d Exec) Apply(opt *Option, profileRaw string) (string, error) { rules := aa.Rules{} for name := range opt.ArgMap { - profiletoTransition := util.MustReadFile(cfg.RootApparmord.Join(name)) + profiletoTransition := util.MustReadFile(prebuild.RootApparmord.Join(name)) dstProfile := aa.DefaultTunables() if _, err := dstProfile.Parse(profiletoTransition); err != nil { return "", err diff --git a/pkg/prebuild/directive/exec_test.go b/pkg/prebuild/directive/exec_test.go index c6d4e32a..5581d7f2 100644 --- a/pkg/prebuild/directive/exec_test.go +++ b/pkg/prebuild/directive/exec_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func TestExec_Apply(t *testing.T) { @@ -51,7 +51,7 @@ func TestExec_Apply(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfg.RootApparmord = tt.rootApparmord + prebuild.RootApparmord = tt.rootApparmord got, err := Directives["exec"].Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Exec.Apply() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/prebuild/directive/filter.go b/pkg/prebuild/directive/filter.go index 1aa2e1c7..2fe46e6f 100644 --- a/pkg/prebuild/directive/filter.go +++ b/pkg/prebuild/directive/filter.go @@ -5,31 +5,32 @@ package directive import ( + "fmt" "regexp" "slices" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) type FilterOnly struct { - cfg.Base + prebuild.Base } type FilterExclude struct { - cfg.Base + prebuild.Base } func init() { RegisterDirective(&FilterOnly{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "only", Msg: "Only directive applied", Help: []string{"filters..."}, }, }) RegisterDirective(&FilterExclude{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "exclude", Msg: "Exclude directive applied", Help: []string{"filters..."}, @@ -38,7 +39,11 @@ func init() { } func filterRuleForUs(opt *Option) bool { - return slices.Contains(opt.ArgList, cfg.Distribution) || slices.Contains(opt.ArgList, cfg.Family) + abiStr := fmt.Sprintf("abi%d", prebuild.ABI) + if slices.Contains(opt.ArgList, abiStr) { + return true + } + return slices.Contains(opt.ArgList, prebuild.Distribution) || slices.Contains(opt.ArgList, prebuild.Family) } func filter(only bool, opt *Option, profile string) (string, error) { diff --git a/pkg/prebuild/directive/filter_test.go b/pkg/prebuild/directive/filter_test.go index 465ba50a..ebbd5ef5 100644 --- a/pkg/prebuild/directive/filter_test.go +++ b/pkg/prebuild/directive/filter_test.go @@ -7,7 +7,7 @@ package directive import ( "testing" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func TestFilterOnly_Apply(t *testing.T) { @@ -78,8 +78,8 @@ func TestFilterOnly_Apply(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfg.Distribution = tt.dist - cfg.Family = tt.family + prebuild.Distribution = tt.dist + prebuild.Family = tt.family got, err := Directives["only"].Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("FilterOnly.Apply() error = %v, wantErr %v", err, tt.wantErr) @@ -133,8 +133,8 @@ func TestFilterExclude_Apply(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfg.Distribution = tt.dist - cfg.Family = tt.family + prebuild.Distribution = tt.dist + prebuild.Family = tt.family got, err := Directives["exclude"].Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("FilterExclude.Apply() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/prebuild/directive/stack.go b/pkg/prebuild/directive/stack.go index c673a170..70740536 100644 --- a/pkg/prebuild/directive/stack.go +++ b/pkg/prebuild/directive/stack.go @@ -10,7 +10,7 @@ import ( "slices" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -25,12 +25,12 @@ var ( ) type Stack struct { - cfg.Base + prebuild.Base } func init() { RegisterDirective(&Stack{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "stack", Msg: "Stack directive applied", Help: []string{"[X] profiles..."}, @@ -55,7 +55,7 @@ func (s Stack) Apply(opt *Option, profile string) (string, error) { res := "" for name := range opt.ArgMap { - stackedProfile := util.MustReadFile(cfg.RootApparmord.Join(name)) + stackedProfile := util.MustReadFile(prebuild.RootApparmord.Join(name)) m := regRules.FindStringSubmatch(stackedProfile) if len(m) < 2 { return "", fmt.Errorf("No profile found in %s", name) diff --git a/pkg/prebuild/directive/stack_test.go b/pkg/prebuild/directive/stack_test.go index ef603aae..8f99d6f7 100644 --- a/pkg/prebuild/directive/stack_test.go +++ b/pkg/prebuild/directive/stack_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func TestStack_Apply(t *testing.T) { @@ -68,7 +68,7 @@ profile parent @{exec_path} { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfg.RootApparmord = tt.rootApparmord + prebuild.RootApparmord = tt.rootApparmord got, err := Directives["stack"].Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Stack.Apply() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/prebuild/cfg/directories.go b/pkg/prebuild/directories.go similarity index 83% rename from pkg/prebuild/cfg/directories.go rename to pkg/prebuild/directories.go index 282aa1ad..6fbde10b 100644 --- a/pkg/prebuild/cfg/directories.go +++ b/pkg/prebuild/directories.go @@ -2,11 +2,14 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import "github.com/roddhjav/apparmor.d/pkg/paths" var ( + // AppArmor ABI version + ABI uint = 0 + // Root is the root directory for the build Root *paths.Path = paths.New(".build") @@ -28,11 +31,6 @@ var ( // DebianDir is the directory where the debian specific files are stored DebianDir *paths.Path = paths.New("debian") - // AppArmor 4.0 contains several profiles that allow userns and are otherwise - // unconfined. Overwriter disables upstream profile in favor of (better) apparmor.d - // counterpart - Overwrite Overwriter = false - // DebianHide is the path to the debian/apparmor.d.hide file DebianHide = DebianHider{path: DebianDir.Join("apparmor.d.hide")} diff --git a/pkg/prebuild/cfg/files.go b/pkg/prebuild/files.go similarity index 63% rename from pkg/prebuild/cfg/files.go rename to pkg/prebuild/files.go index 6f81d25b..d275c916 100644 --- a/pkg/prebuild/cfg/files.go +++ b/pkg/prebuild/files.go @@ -2,11 +2,9 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import ( - "fmt" - "os" "strings" "github.com/roddhjav/apparmor.d/pkg/paths" @@ -54,37 +52,6 @@ func (i Ignorer) Read(name string) []string { return util.MustReadFileAsLines(path) } -type Overwriter bool - -// Overwrite upstream profile: disable upstream & rename ours -func (o Overwriter) Apply() error { - const ext = ".apparmor.d" - disableDir := RootApparmord.Join("disable") - if err := disableDir.Mkdir(); err != nil { - return err - } - - path := DistDir.Join("overwrite") - if !path.Exist() { - return fmt.Errorf("%s not found", path) - } - for _, name := range util.MustReadFileAsLines(path) { - origin := RootApparmord.Join(name) - dest := RootApparmord.Join(name + ext) - if err := origin.Rename(dest); err != nil { - return err - } - originRel, err := origin.RelFrom(dest) - if err != nil { - return err - } - if err := os.Symlink(originRel.String(), disableDir.Join(name).String()); err != nil { - return err - } - } - return nil -} - type DebianHider struct { path *paths.Path } diff --git a/pkg/prebuild/cfg/files_test.go b/pkg/prebuild/files_test.go similarity index 99% rename from pkg/prebuild/cfg/files_test.go rename to pkg/prebuild/files_test.go index b4ce13a1..24d621fd 100644 --- a/pkg/prebuild/cfg/files_test.go +++ b/pkg/prebuild/files_test.go @@ -2,7 +2,7 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import ( "reflect" diff --git a/pkg/prebuild/cfg/os.go b/pkg/prebuild/os.go similarity index 99% rename from pkg/prebuild/cfg/os.go rename to pkg/prebuild/os.go index b742a398..352f4e18 100644 --- a/pkg/prebuild/cfg/os.go +++ b/pkg/prebuild/os.go @@ -2,7 +2,7 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import ( "os" diff --git a/pkg/prebuild/cfg/os_test.go b/pkg/prebuild/os_test.go similarity index 99% rename from pkg/prebuild/cfg/os_test.go rename to pkg/prebuild/os_test.go index 44aef107..8f9bd338 100644 --- a/pkg/prebuild/cfg/os_test.go +++ b/pkg/prebuild/os_test.go @@ -2,7 +2,7 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package cfg +package prebuild import ( "reflect" diff --git a/pkg/prebuild/prebuild.go b/pkg/prebuild/prebuild.go deleted file mode 100644 index 30bf5c2e..00000000 --- a/pkg/prebuild/prebuild.go +++ /dev/null @@ -1,117 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2023-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prebuild - -import ( - "strings" - - "github.com/roddhjav/apparmor.d/pkg/logging" - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" - "github.com/roddhjav/apparmor.d/pkg/prebuild/directive" - "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" - "github.com/roddhjav/apparmor.d/pkg/util" -) - -func init() { - // Define the tasks applied by default - prepare.Register( - "synchronise", - "ignore", - "merge", - "configure", - "setflags", - "systemd-default", - ) - - // Build tasks applied by default - builder.Register("userspace") - builder.Register("dev") - - switch cfg.Distribution { - case "opensuse": - builder.Register("abi3") - cfg.Overwrite = true - - case "ubuntu": - if cfg.Release["VERSION_CODENAME"] == "noble" { - builder.Register("abi3") - cfg.Overwrite = true - } - - case "whonix": - cfg.Hide += `/etc/apparmor.d/abstractions/base.d/kicksecure -/etc/apparmor.d/home.tor-browser.firefox -/etc/apparmor.d/tunables/homsanitycheck -/etc/apparmor.d/usr.bin.url_e.d/anondist -/etc/apparmor.d/tunables/home.d/live-mode -/etc/apparmor.d/tunables/home.d/qubes-whonix-anondist -/etc/apparmor.d/usr.bin.hexchat -/etc/apparmor.d/usr.bin.sdwdate -/etc/apparmor.d/usr.bin.systemcheck -/etc/apparmor.d/usr.bin.timeto_unixtime -/etc/apparmor.d/whonix-firewall -` - } -} - -func Prepare() error { - for _, task := range prepare.Prepares { - msg, err := task.Apply() - if err != nil { - return err - } - logging.Success("%s", task.Message()) - logging.Indent = " " - for _, line := range msg { - if strings.Contains(line, "not found") { - logging.Warning("%s", line) - } else { - logging.Bullet("%s", line) - } - } - logging.Indent = "" - } - return nil -} - -func Build() error { - files, _ := cfg.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories()) - for _, file := range files { - if !file.Exist() { - continue - } - profile, err := util.ReadFile(file) - if err != nil { - return err - } - profile, err = builder.Run(file, profile) - if err != nil { - return err - } - profile, err = directive.Run(file, profile) - if err != nil { - return err - } - if err := file.WriteFile([]byte(profile)); err != nil { - return err - } - } - - logging.Success("Build tasks:") - logging.Indent = " " - for _, task := range builder.Builds { - logging.Bullet("%s", task.Message()) - } - logging.Indent = "" - logging.Success("Directives processed:") - logging.Indent = " " - for _, dir := range directive.Directives { - logging.Bullet("%s%s", directive.Keyword, dir.Name()) - } - logging.Indent = "" - return nil -} diff --git a/pkg/prebuild/prepare/configure.go b/pkg/prebuild/prepare/configure.go index df4daaeb..6be35d3d 100644 --- a/pkg/prebuild/prepare/configure.go +++ b/pkg/prebuild/prepare/configure.go @@ -6,62 +6,95 @@ package prepare import ( "fmt" + "os" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) type Configure struct { - cfg.Base + prebuild.Base + OneFile bool } func init() { RegisterTask(&Configure{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "configure", Msg: "Set distribution specificities", }, + OneFile: false, }) } func (p Configure) Apply() ([]string, error) { res := []string{} - switch cfg.Distribution { - case "arch", "opensuse": - if cfg.Overwrite { - if err := cfg.Overwrite.Apply(); err != nil { - return res, err - } + + if prebuild.ABI == 4 { + if err := OverwriteUpstreamProfile(p.OneFile); err != nil { + return res, err } + } + switch prebuild.Distribution { + case "arch", "opensuse": case "ubuntu": - if err := cfg.DebianHide.Init(); err != nil { + if err := prebuild.DebianHide.Init(); err != nil { return res, err } - if cfg.Overwrite { - if err := cfg.Overwrite.Apply(); err != nil { - return res, err - } - } else { - if err := util.CopyTo(cfg.DistDir.Join("ubuntu"), cfg.RootApparmord); err != nil { + if prebuild.ABI == 3 { + if err := util.CopyTo(prebuild.DistDir.Join("ubuntu"), prebuild.RootApparmord); err != nil { return res, err } } case "debian", "whonix": - if err := cfg.DebianHide.Init(); err != nil { + if err := prebuild.DebianHide.Init(); err != nil { return res, err } // Copy Debian specific abstractions - if err := util.CopyTo(cfg.DistDir.Join("ubuntu"), cfg.RootApparmord); err != nil { + if err := util.CopyTo(prebuild.DistDir.Join("ubuntu"), prebuild.RootApparmord); err != nil { return res, err } default: - return []string{}, fmt.Errorf("%s is not a supported distribution", cfg.Distribution) + return []string{}, fmt.Errorf("%s is not a supported distribution", prebuild.Distribution) } return res, nil } + +// Overwrite upstream profile: disable upstream & rename ours +func OverwriteUpstreamProfile(oneFile bool) error { + const ext = ".apparmor.d" + disableDir := prebuild.RootApparmord.Join("disable") + if err := disableDir.Mkdir(); err != nil { + return err + } + + path := prebuild.DistDir.Join("overwrite") + if !path.Exist() { + return fmt.Errorf("%s not found", path) + } + for _, name := range util.MustReadFileAsLines(path) { + origin := prebuild.RootApparmord.Join(name) + dest := prebuild.RootApparmord.Join(name + ext) + if !dest.Exist() && oneFile { + continue + } + if err := origin.Rename(dest); err != nil { + + return err + } + originRel, err := origin.RelFrom(dest) + if err != nil { + return err + } + if err := os.Symlink(originRel.String(), disableDir.Join(name).String()); err != nil { + return err + } + } + return nil +} diff --git a/pkg/prebuild/prepare/core.go b/pkg/prebuild/prepare/core.go index 3daf19d8..d96e2104 100644 --- a/pkg/prebuild/prepare/core.go +++ b/pkg/prebuild/prepare/core.go @@ -7,7 +7,7 @@ package prepare import ( "fmt" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) var ( @@ -20,7 +20,7 @@ var ( // Main directive interface type Task interface { - cfg.BaseInterface + prebuild.BaseInterface Apply() ([]string, error) } diff --git a/pkg/prebuild/prepare/core_test.go b/pkg/prebuild/prepare/core_test.go index 34071ff3..3c35e3e8 100644 --- a/pkg/prebuild/prepare/core_test.go +++ b/pkg/prebuild/prepare/core_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func chdirGitRoot() { @@ -39,7 +39,7 @@ func TestTask_Apply(t *testing.T) { name: "synchronise", task: Tasks["synchronise"], wantErr: false, - wantFiles: paths.PathList{cfg.RootApparmord.Join("/groups/_full/systemd")}, + wantFiles: paths.PathList{prebuild.RootApparmord.Join("/groups/_full/systemd")}, }, { name: "ignore", @@ -51,7 +51,7 @@ func TestTask_Apply(t *testing.T) { name: "merge", task: Tasks["merge"], wantErr: false, - wantFiles: paths.PathList{cfg.RootApparmord.Join("aa-log")}, + wantFiles: paths.PathList{prebuild.RootApparmord.Join("aa-log")}, }, { name: "configure", @@ -68,23 +68,23 @@ func TestTask_Apply(t *testing.T) { name: "systemd-default", task: Tasks["systemd-default"], wantErr: false, - wantFiles: paths.PathList{cfg.Root.Join("systemd/system/dbus.service")}, + wantFiles: paths.PathList{prebuild.Root.Join("systemd/system/dbus.service")}, }, { name: "systemd-early", task: Tasks["systemd-early"], wantErr: false, - wantFiles: paths.PathList{cfg.Root.Join("systemd/system/pcscd.service")}, + wantFiles: paths.PathList{prebuild.Root.Join("systemd/system/pcscd.service")}, }, { name: "fsp", task: Tasks["fsp"], wantErr: false, - wantFiles: paths.PathList{cfg.RootApparmord.Join("systemd")}, + wantFiles: paths.PathList{prebuild.RootApparmord.Join("systemd")}, }, } chdirGitRoot() - _ = cfg.Root.RemoveAll() + _ = prebuild.Root.RemoveAll() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := tt.task.Apply() diff --git a/pkg/prebuild/prepare/flags.go b/pkg/prebuild/prepare/flags.go index 4ef41ef5..23998d4d 100644 --- a/pkg/prebuild/prepare/flags.go +++ b/pkg/prebuild/prepare/flags.go @@ -9,7 +9,7 @@ import ( "regexp" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -19,12 +19,12 @@ var ( ) type SetFlags struct { - cfg.Base + prebuild.Base } func init() { RegisterTask(&SetFlags{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "setflags", Msg: "Set flags on some profiles", }, @@ -33,9 +33,9 @@ func init() { func (p SetFlags) Apply() ([]string, error) { res := []string{} - for _, name := range []string{"main", cfg.Distribution} { - for profile, flags := range cfg.Flags.Read(name) { - file := cfg.RootApparmord.Join(profile) + for _, name := range []string{"main", prebuild.Distribution} { + for profile, flags := range prebuild.Flags.Read(name) { + file := prebuild.RootApparmord.Join(profile) if !file.Exist() { res = append(res, fmt.Sprintf("Profile %s not found, ignoring", profile)) continue @@ -57,7 +57,7 @@ func (p SetFlags) Apply() ([]string, error) { } } } - res = append(res, cfg.FlagDir.Join(name+".flags").String()) + res = append(res, prebuild.FlagDir.Join(name+".flags").String()) } return res, nil } diff --git a/pkg/prebuild/prepare/fsp.go b/pkg/prebuild/prepare/fsp.go index ac3e0504..af57ed9d 100644 --- a/pkg/prebuild/prepare/fsp.go +++ b/pkg/prebuild/prepare/fsp.go @@ -8,17 +8,17 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) type FullSystemPolicy struct { - cfg.Base + prebuild.Base } func init() { RegisterTask(&FullSystemPolicy{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "fsp", Msg: "Configure AppArmor for full system policy", }, @@ -29,12 +29,12 @@ func (p FullSystemPolicy) Apply() ([]string, error) { res := []string{} // Install full system policy profiles - if err := util.CopyTo(paths.New("apparmor.d/groups/_full/"), cfg.Root.Join("apparmor.d")); err != nil { + if err := util.CopyTo(paths.New("apparmor.d/groups/_full/"), prebuild.Root.Join("apparmor.d")); err != nil { return res, err } // Set systemd profile name - path := cfg.RootApparmord.Join("tunables/multiarch.d/system") + path := prebuild.RootApparmord.Join("tunables/multiarch.d/system") out, err := util.ReadFile(path) if err != nil { return res, err @@ -46,7 +46,7 @@ func (p FullSystemPolicy) Apply() ([]string, error) { } // Fix conflicting x modifiers in abstractions - FIXME: Temporary solution - path = cfg.RootApparmord.Join("abstractions/gstreamer") + path = prebuild.RootApparmord.Join("abstractions/gstreamer") out, err = util.ReadFile(path) if err != nil { return res, err @@ -58,5 +58,5 @@ func (p FullSystemPolicy) Apply() ([]string, error) { } // Set systemd unit drop-in files - return res, util.CopyTo(cfg.SystemdDir.Join("full"), cfg.Root.Join("systemd")) + return res, util.CopyTo(prebuild.SystemdDir.Join("full"), prebuild.Root.Join("systemd")) } diff --git a/pkg/prebuild/prepare/ignore.go b/pkg/prebuild/prepare/ignore.go index 92a1498a..2aece517 100644 --- a/pkg/prebuild/prepare/ignore.go +++ b/pkg/prebuild/prepare/ignore.go @@ -6,16 +6,16 @@ package prepare import ( "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) type Ignore struct { - cfg.Base + prebuild.Base } func init() { RegisterTask(&Ignore{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "ignore", Msg: "Ignore profiles and files from:", }, @@ -24,11 +24,11 @@ func init() { func (p Ignore) Apply() ([]string, error) { res := []string{} - for _, name := range []string{"main", cfg.Distribution} { - for _, ignore := range cfg.Ignore.Read(name) { - profile := cfg.Root.Join(ignore) + for _, name := range []string{"main", prebuild.Distribution} { + for _, ignore := range prebuild.Ignore.Read(name) { + profile := prebuild.Root.Join(ignore) if profile.NotExist() { - files, err := cfg.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(ignore)) + files, err := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(ignore)) if err != nil { return res, err } @@ -43,7 +43,7 @@ func (p Ignore) Apply() ([]string, error) { } } } - res = append(res, cfg.IgnoreDir.Join(name+".ignore").String()) + res = append(res, prebuild.IgnoreDir.Join(name+".ignore").String()) } return res, nil } diff --git a/pkg/prebuild/prepare/merge.go b/pkg/prebuild/prepare/merge.go index 86a2cead..75945b81 100644 --- a/pkg/prebuild/prepare/merge.go +++ b/pkg/prebuild/prepare/merge.go @@ -9,16 +9,16 @@ import ( "path/filepath" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" ) type Merge struct { - cfg.Base + prebuild.Base } func init() { RegisterTask(&Merge{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "merge", Msg: "Merge all profiles into a unified apparmor.d directory", }, @@ -35,18 +35,18 @@ func (p Merge) Apply() ([]string, error) { idx := 0 for idx < len(dirToMerge)-1 { dirMoved, dirRemoved := dirToMerge[idx], dirToMerge[idx+1] - files, err := filepath.Glob(cfg.RootApparmord.Join(dirMoved).String()) + files, err := filepath.Glob(prebuild.RootApparmord.Join(dirMoved).String()) if err != nil { return res, err } for _, file := range files { - err := os.Rename(file, cfg.RootApparmord.Join(filepath.Base(file)).String()) + err := os.Rename(file, prebuild.RootApparmord.Join(filepath.Base(file)).String()) if err != nil { return res, err } } - files, err = filepath.Glob(cfg.RootApparmord.Join(dirRemoved).String()) + files, err = filepath.Glob(prebuild.RootApparmord.Join(dirRemoved).String()) if err != nil { return []string{}, err } diff --git a/pkg/prebuild/prepare/synchronise.go b/pkg/prebuild/prepare/synchronise.go index e2b5dacd..741c015c 100644 --- a/pkg/prebuild/prepare/synchronise.go +++ b/pkg/prebuild/prepare/synchronise.go @@ -6,35 +6,53 @@ package prepare import ( "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) type Synchronise struct { - cfg.Base + prebuild.Base + Path string } func init() { RegisterTask(&Synchronise{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "synchronise", Msg: "Initialize a new clean apparmor.d build directory", }, + Path: "", }) } func (p Synchronise) Apply() ([]string, error) { res := []string{} - dirs := paths.PathList{cfg.RootApparmord, cfg.Root.Join("root"), cfg.Root.Join("systemd")} + dirs := paths.PathList{prebuild.RootApparmord, prebuild.Root.Join("root"), prebuild.Root.Join("systemd")} for _, dir := range dirs { if err := dir.RemoveAll(); err != nil { return res, err } } - for _, name := range []string{"apparmor.d", "root"} { - if err := util.CopyTo(paths.New(name), cfg.Root.Join(name)); err != nil { + if p.Path == "" { + for _, name := range []string{"apparmor.d", "root"} { + if err := util.CopyTo(paths.New(name), prebuild.Root.Join(name)); err != nil { + return res, err + } + } + } else { + file := paths.New(p.Path) + destination, err := file.RelFrom(paths.New("apparmor.d")) + if err != nil { return res, err } + destination = prebuild.RootApparmord.JoinPath(destination) + if err := destination.Parent().MkdirAll(); err != nil { + return res, err + } + if err := file.CopyTo(destination); err != nil { + return res, err + } + res = append(res, destination.String()) } return res, nil } diff --git a/pkg/prebuild/prepare/systemd.go b/pkg/prebuild/prepare/systemd.go index 5681783c..cee95285 100644 --- a/pkg/prebuild/prepare/systemd.go +++ b/pkg/prebuild/prepare/systemd.go @@ -5,27 +5,27 @@ package prepare import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/util" ) type SystemdDefault struct { - cfg.Base + prebuild.Base } type SystemdEarly struct { - cfg.Base + prebuild.Base } func init() { RegisterTask(&SystemdDefault{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "systemd-default", Msg: "Configure systemd unit drop in files to a profile for some units", }, }) RegisterTask(&SystemdEarly{ - Base: cfg.Base{ + Base: prebuild.Base{ Keyword: "systemd-early", Msg: "Configure systemd unit drop in files to ensure some service start after apparmor", }, @@ -33,9 +33,9 @@ func init() { } func (p SystemdDefault) Apply() ([]string, error) { - return []string{}, util.CopyTo(cfg.SystemdDir.Join("default"), cfg.Root.Join("systemd")) + return []string{}, util.CopyTo(prebuild.SystemdDir.Join("default"), prebuild.Root.Join("systemd")) } func (p SystemdEarly) Apply() ([]string, error) { - return []string{}, util.CopyTo(cfg.SystemdDir.Join("early"), cfg.Root.Join("systemd")) + return []string{}, util.CopyTo(prebuild.SystemdDir.Join("early"), prebuild.Root.Join("systemd")) } diff --git a/tests/cmd/main.go b/tests/cmd/main.go index 057994f8..b549aab3 100644 --- a/tests/cmd/main.go +++ b/tests/cmd/main.go @@ -14,7 +14,7 @@ import ( "github.com/roddhjav/apparmor.d/pkg/aa" "github.com/roddhjav/apparmor.d/pkg/logging" "github.com/roddhjav/apparmor.d/pkg/paths" - bcfg "github.com/roddhjav/apparmor.d/pkg/prebuild/cfg" + "github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/tests/integration" ) @@ -28,8 +28,8 @@ Options: -r, --run Run a predefined list of tests. -l, --list List the configured tests. -f, --file FILE Set a tests file. Default: tests/tests.yml - -d, --deps Install tests dependencies. - -D, --dryrun Do not do the action, list it. + -d, --deps Install tests dependencies. + -D, --dryrun Do not do the action, list it. ` @@ -123,7 +123,7 @@ func testDeps(dryRun bool) error { } deps := tSuite.GetDependencies() - switch bcfg.Distribution { + switch prebuild.Distribution { case "arch": arg := []string{"pacman", "-Sy", "--noconfirm"} arg = append(arg, deps...)