diff --git a/pkg/prebuild/build.go b/pkg/prebuild/build.go index 780126b2..d52eab94 100644 --- a/pkg/prebuild/build.go +++ b/pkg/prebuild/build.go @@ -14,9 +14,18 @@ import ( ) // Build the profiles with the following build tasks -var Builds = []BuildFunc{ - BuildUserspace, -} +var ( + Builds = []BuildFunc{ + BuildUserspace, + } + BuildMsg = map[string]string{ + "BuildComplain": "Set complain flag on all profiles", + "BuildEnforce": "All profiles have been enforced", + "BuildUserspace": "Bypass userspace tools restriction", + "BuildABI3": "Build all profiles for abi 3.0 compatibility", + "BuildFullSystemPolicy": "Build all profiles for full system policy mode", + } +) var ( regAttachments = regexp.MustCompile(`(profile .* @{exec_path})`) diff --git a/pkg/prebuild/prebuild.go b/pkg/prebuild/prebuild.go index d9e82d2d..179fff7a 100644 --- a/pkg/prebuild/prebuild.go +++ b/pkg/prebuild/prebuild.go @@ -5,7 +5,12 @@ package prebuild import ( + "reflect" + "runtime" + "strings" + "github.com/arduino/go-paths-helper" + "github.com/roddhjav/apparmor.d/pkg/logging" ) var ( @@ -24,11 +29,35 @@ func init() { Distribution = getSupportedDistribution() } +func getFctName(i any) string { + tmp := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() + res := strings.Split(tmp, ".") + return res[len(res)-1] +} + +func printPrepareMessage(name string, msg []string) { + logging.Success("%v", PrepareMsg[name]) + logging.Indent = " " + for _, line := range msg { + logging.Bullet("%s", line) + } + logging.Indent = "" +} + +func printBuildMessage() { + for _, fct := range Builds { + name := getFctName(fct) + logging.Success("%v", BuildMsg[name]) + } +} + func Prepare() error { for _, fct := range Prepares { - if err := fct(); err != nil { + msg, err := fct() + if err != nil { return err } + printPrepareMessage(getFctName(fct), msg) } return nil } @@ -48,5 +77,6 @@ func Build() error { panic(err) } } + printBuildMessage() return nil } diff --git a/pkg/prebuild/prepare.go b/pkg/prebuild/prepare.go index 52dd45a5..eb08bbeb 100644 --- a/pkg/prebuild/prepare.go +++ b/pkg/prebuild/prepare.go @@ -15,35 +15,47 @@ import ( ) // Prepare the build directory with the following tasks -var Prepares = []PrepareFunc{ - Synchronise, - Ignore, - Merge, - Configure, - SetFlags, -} +var ( + Prepares = []PrepareFunc{ + Synchronise, + Ignore, + Merge, + Configure, + SetFlags, + } + PrepareMsg = map[string]string{ + "Synchronise": "Initialize a new clean apparmor.d build directory", + "Ignore": "Ignore profiles and files from:", + "Merge": "Merge all profiles", + "Configure": "Set distribution specificities", + "SetFlags": "Set flags on some profiles", + "SetDefaultSystemd": "Set systemd unit drop in files to ensure some service start after apparmor", + "SetFullSystemPolicy": "Configure AppArmor for full system policy", + } +) -type PrepareFunc func() error +type PrepareFunc func() ([]string, error) // Initialize a new clean apparmor.d build directory -func Synchronise() error { +func Synchronise() ([]string, error) { + res := []string{} dirs := paths.PathList{RootApparmord, Root.Join("root"), Root.Join("systemd")} for _, dir := range dirs { if err := dir.RemoveAll(); err != nil { - return err + return res, err } } for _, name := range []string{"apparmor.d", "root"} { if err := copyTo(paths.New(name), Root.Join(name)); err != nil { - return err + return res, err } } - logging.Success("Initialize a new clean apparmor.d build directory") - return nil + return res, nil } // Ignore profiles and files as defined in dists/ignore/ -func Ignore() error { +func Ignore() ([]string, error) { + res := []string{} for _, name := range []string{"main.ignore", Distribution + ".ignore"} { path := DistDir.Join("ignore", name) if !path.Exist() { @@ -58,27 +70,28 @@ func Ignore() error { if profile.NotExist() { files, err := RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(line)) if err != nil { - return err + return res, err } for _, path := range files { if err := path.RemoveAll(); err != nil { - return err + return res, err } } } else { if err := profile.RemoveAll(); err != nil { - return err + return res, err } } } - logging.Success("Ignore profiles/files in %s", path) + res = append(res, path.String()) } - return nil + return res, nil } // Merge all profiles in a new apparmor.d directory -func Merge() error { - var dirToMerge = []string{ +func Merge() ([]string, error) { + res := []string{} + dirToMerge := []string{ "groups/*/*", "groups", "profiles-*-*/*", "profiles-*", } @@ -88,50 +101,51 @@ func Merge() error { dirMoved, dirRemoved := dirToMerge[idx], dirToMerge[idx+1] files, err := filepath.Glob(RootApparmord.Join(dirMoved).String()) if err != nil { - return err + return res, err } for _, file := range files { err := os.Rename(file, RootApparmord.Join(filepath.Base(file)).String()) if err != nil { - return err + return res, err } } files, err = filepath.Glob(RootApparmord.Join(dirRemoved).String()) if err != nil { - return err + return []string{}, err } for _, file := range files { if err := paths.New(file).RemoveAll(); err != nil { - return err + return res, err } } idx = idx + 2 } - logging.Success("Merge all profiles") - return nil + return res, nil } // Set the distribution specificities -func Configure() (err error) { +func Configure() ([]string, error) { + res := []string{} switch Distribution { case "arch", "opensuse": case "debian", "ubuntu", "whonix": // Copy Ubuntu specific profiles if err := copyTo(DistDir.Join("ubuntu"), RootApparmord); err != nil { - return err + return res, err } default: - return fmt.Errorf("%s is not a supported distribution", Distribution) + return []string{}, fmt.Errorf("%s is not a supported distribution", Distribution) } - return err + return res, nil } // Set flags on some profiles according to manifest defined in `dists/flags/` -func SetFlags() error { +func SetFlags() ([]string, error) { + res := []string{} for _, name := range []string{"main.flags", Distribution + ".flags"} { path := FlagDir.Join(name) if !path.Exist() { @@ -155,51 +169,47 @@ func SetFlags() error { flags := " flags=(" + manifest[1] + ") {" content, err := file.ReadFile() if err != nil { - return err + return res, err } // Remove all flags definition, then set manifest' flags - res := regFlags.ReplaceAllLiteralString(string(content), "") - res = regProfileHeader.ReplaceAllLiteralString(res, flags) - if err := file.WriteFile([]byte(res)); err != nil { - return err + out := regFlags.ReplaceAllLiteralString(string(content), "") + out = regProfileHeader.ReplaceAllLiteralString(out, flags) + if err := file.WriteFile([]byte(out)); err != nil { + return res, err } } } - logging.Success("Set profile flags from %s", path) + res = append(res, path.String()) } - return nil + return res, nil } // Set systemd unit drop in files to ensure some service start after apparmor -func SetDefaultSystemd() error { - return copyTo(paths.New("systemd/default/"), Root.Join("systemd")) +func SetDefaultSystemd() ([]string, error) { + return []string{}, copyTo(paths.New("systemd/default/"), Root.Join("systemd")) } // Set AppArmor for (experimental) full system policy. // See https://apparmor.pujol.io/development/structure/#full-system-policy -func SetFullSystemPolicy() error { +func SetFullSystemPolicy() ([]string, error) { + res := []string{} // Install full system policy profiles if err := copyTo(paths.New("apparmor.d/groups/_full/"), Root.Join("apparmor.d")); err != nil { - return err + return res, err } // Set systemd profile name path := RootApparmord.Join("tunables/multiarch.d/system") content, err := path.ReadFile() if err != nil { - return err + return res, err } - res := strings.Replace(string(content), "@{systemd}=unconfined", "@{systemd}=systemd", -1) - if err := path.WriteFile([]byte(res)); err != nil { - return err + out := strings.Replace(string(content), "@{systemd}=unconfined", "@{systemd}=systemd", -1) + if err := path.WriteFile([]byte(out)); err != nil { + return res, err } // Set systemd unit drop-in files - if err := copyTo(paths.New("systemd/full/"), Root.Join("systemd")); err != nil { - return err - } - - logging.Success("Configure AppArmor for full system policy") - return nil + return res, copyTo(paths.New("systemd/full/"), Root.Join("systemd")) }