From e67a66ff9405da48591da5a04db0c833aca6000c Mon Sep 17 00:00:00 2001 From: Alexandre Pujol Date: Mon, 25 Mar 2024 23:38:07 +0000 Subject: [PATCH] refractor(build): remove old builder/prepare. --- pkg/prebuild/build.go | 115 ------------------ pkg/prebuild/prepare.go | 250 ---------------------------------------- pkg/prebuild/tools.go | 83 ------------- 3 files changed, 448 deletions(-) delete mode 100644 pkg/prebuild/build.go delete mode 100644 pkg/prebuild/prepare.go delete mode 100644 pkg/prebuild/tools.go diff --git a/pkg/prebuild/build.go b/pkg/prebuild/build.go deleted file mode 100644 index b6820e7f..00000000 --- a/pkg/prebuild/build.go +++ /dev/null @@ -1,115 +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 ( - "regexp" - "strings" - - "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/util" - "golang.org/x/exp/slices" -) - -// Build the profiles with the following build tasks -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})`) - regFlags = regexp.MustCompile(`flags=\(([^)]+)\)`) - regProfileHeader = regexp.MustCompile(` {`) - regFullSystemPolicy = util.ToRegexRepl([]string{ - `r(PU|U)x,`, `rPx,`, - }) - regAbi4To3 = util.ToRegexRepl([]string{ // Currently Abi3 -> Abi4 - `abi/3.0`, `abi/4.0`, - `# userns,`, `userns,`, - `# mqueue`, `mqueue`, - }) -) - -type BuildFunc func(string) string - -// Set complain flag on all profiles -func BuildComplain(profile string) string { - flags := []string{} - matches := regFlags.FindStringSubmatch(profile) - if len(matches) != 0 { - flags = strings.Split(matches[1], ",") - if slices.Contains(flags, "complain") { - return profile - } - } - flags = append(flags, "complain") - strFlags := " flags=(" + strings.Join(flags, ",") + ") {" - - // Remove all flags definition, then set manifest' flags - profile = regFlags.ReplaceAllLiteralString(profile, "") - return regProfileHeader.ReplaceAllLiteralString(profile, strFlags) -} - -// Set all profiles in enforce mode -func BuildEnforce(profile string) string { - matches := regFlags.FindStringSubmatch(profile) - if len(matches) == 0 { - return profile - } - - flags := strings.Split(matches[1], ",") - idx := slices.Index(flags, "complain") - if idx == -1 { - return profile - } - flags = slices.Delete(flags, idx, idx+1) - strFlags := "{" - if len(flags) >= 1 { - strFlags = " flags=(" + strings.Join(flags, ",") + ") {" - } - - // Remove all flags definition, then set new flags - profile = regFlags.ReplaceAllLiteralString(profile, "") - return regProfileHeader.ReplaceAllLiteralString(profile, strFlags) -} - -// Bypass userspace tools restriction -func BuildUserspace(profile string) string { - p := aa.DefaultTunables() - p.ParseVariables(profile) - p.ResolveAttachments() - att := p.NestAttachments() - matches := regAttachments.FindAllString(profile, -1) - if len(matches) > 0 { - strheader := strings.Replace(matches[0], "@{exec_path}", att, -1) - return regAttachments.ReplaceAllLiteralString(profile, strheader) - } - return profile -} - -// Convert all profiles to abi 3.0 compatibility -func BuildABI3(profile string) string { - for _, abi4t3 := range regAbi4To3 { - profile = abi4t3.Regex.ReplaceAllLiteralString(profile, abi4t3.Repl) - } - return profile -} - -// Prevent unconfined transitions in profile rules -func BuildFullSystemPolicy(profile string) string { - for _, full := range regFullSystemPolicy { - profile = full.Regex.ReplaceAllString(profile, full.Repl) - } - return profile -} diff --git a/pkg/prebuild/prepare.go b/pkg/prebuild/prepare.go deleted file mode 100644 index 665b29d1..00000000 --- a/pkg/prebuild/prepare.go +++ /dev/null @@ -1,250 +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 ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/arduino/go-paths-helper" - "github.com/roddhjav/apparmor.d/pkg/logging" - oss "github.com/roddhjav/apparmor.d/pkg/os" - "github.com/roddhjav/apparmor.d/pkg/util" -) - -// Prepare the build directory with the following tasks -var ( - Prepares = []PrepareFunc{ - Synchronise, - Ignore, - Merge, - Configure, - SetFlags, - SetProfileSystemd, - } - 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", - "SetProfileSystemd": "Use the systemd unit file to set a profile for a given unit", - "SetEarlySystemd": "Set systemd unit drop in files to ensure some service start after apparmor", - "SetFullSystemPolicy": "Configure AppArmor for full system policy", - } -) - -type PrepareFunc func() ([]string, error) - -// Initialize a new clean apparmor.d build directory -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 res, err - } - } - for _, name := range []string{"apparmor.d", "root"} { - if err := copyTo(paths.New(name), Root.Join(name)); err != nil { - return res, err - } - } - return res, nil -} - -// Ignore profiles and files as defined in dists/ignore/ -func Ignore() ([]string, error) { - res := []string{} - for _, name := range []string{"main.ignore", oss.Distribution + ".ignore"} { - path := DistDir.Join("ignore", name) - if !path.Exist() { - continue - } - lines, _ := path.ReadFileAsLines() - for _, line := range lines { - if strings.HasPrefix(line, "#") || line == "" { - continue - } - profile := Root.Join(line) - if profile.NotExist() { - files, err := RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(line)) - if err != nil { - return res, err - } - for _, path := range files { - if err := path.RemoveAll(); err != nil { - return res, err - } - } - } else { - if err := profile.RemoveAll(); err != nil { - return res, err - } - } - } - res = append(res, path.String()) - } - return res, nil -} - -// Merge all profiles in a new apparmor.d directory -func Merge() ([]string, error) { - res := []string{} - dirToMerge := []string{ - "groups/*/*", "groups", - "profiles-*-*/*", "profiles-*", - } - - idx := 0 - for idx < len(dirToMerge)-1 { - dirMoved, dirRemoved := dirToMerge[idx], dirToMerge[idx+1] - files, err := filepath.Glob(RootApparmord.Join(dirMoved).String()) - if err != nil { - return res, err - } - for _, file := range files { - err := os.Rename(file, RootApparmord.Join(filepath.Base(file)).String()) - if err != nil { - return res, err - } - } - - files, err = filepath.Glob(RootApparmord.Join(dirRemoved).String()) - if err != nil { - return []string{}, err - } - for _, file := range files { - if err := paths.New(file).RemoveAll(); err != nil { - return res, err - } - } - idx = idx + 2 - } - return res, nil -} - -// Set the distribution specificities -func Configure() ([]string, error) { - res := []string{} - switch oss.Distribution { - case "arch", "opensuse": - - case "ubuntu": - debianOverwriteClean() - if overwrite { - profiles := getOverwriteProfiles() - debianOverwrite(profiles) - } else { - if err := copyTo(DistDir.Join("ubuntu"), RootApparmord); err != nil { - return res, err - } - } - case "debian", "whonix": - debianOverwriteClean() - - // Copy Debian specific abstractions - if err := copyTo(DistDir.Join("ubuntu"), RootApparmord); err != nil { - return res, err - } - - default: - return []string{}, fmt.Errorf("%s is not a supported distribution", oss.Distribution) - - } - return res, nil -} - -// Set flags on some profiles according to manifest defined in `dists/flags/` -func SetFlags() ([]string, error) { - res := []string{} - for _, name := range []string{"main.flags", oss.Distribution + ".flags"} { - path := FlagDir.Join(name) - if !path.Exist() { - continue - } - lines, _ := path.ReadFileAsLines() - for _, line := range lines { - if strings.HasPrefix(line, "#") || line == "" { - continue - } - manifest := strings.Split(line, " ") - profile := manifest[0] - file := RootApparmord.Join(profile) - if !file.Exist() { - logging.Warning("Profile %s not found", profile) - continue - } - - // If flags is set, overwrite profile flag - if len(manifest) > 1 { - flags := " flags=(" + manifest[1] + ") {" - content, err := file.ReadFile() - if err != nil { - return res, err - } - - // Remove all flags definition, then set manifest' flags - out := regFlags.ReplaceAllLiteralString(string(content), "") - out = regProfileHeader.ReplaceAllLiteralString(out, flags) - if err := file.WriteFile([]byte(out)); err != nil { - return res, err - } - } - } - res = append(res, path.String()) - } - return res, nil -} - -// Use the systemd unit file to set a profile for a given unit -func SetProfileSystemd() ([]string, error) { - return []string{}, copyTo(paths.New("systemd/default/"), Root.Join("systemd")) -} - -// Set systemd unit drop in files to ensure some service start after apparmor -func SetEarlySystemd() ([]string, error) { - return []string{}, copyTo(paths.New("systemd/early/"), Root.Join("systemd")) -} - -// Set AppArmor for (experimental) full system policy. -// See https://apparmor.pujol.io/full-system-policy/ -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 res, err - } - - // Set systemd profile name - path := RootApparmord.Join("tunables/multiarch.d/system") - content, err := path.ReadFile() - if err != nil { - return res, err - } - out := strings.Replace(string(content), "@{systemd}=unconfined", "@{systemd}=systemd", -1) - out = strings.Replace(out, "@{systemd_user}=unconfined", "@{systemd_user}=systemd-user", -1) - if err := path.WriteFile([]byte(out)); err != nil { - return res, err - } - - // Fix conflicting x modifiers in abstractions - FIXME: Temporary solution - path = RootApparmord.Join("abstractions/gstreamer") - content, err = path.ReadFile() - if err != nil { - return res, err - } - out = string(content) - regFixConflictX := util.ToRegexRepl([]string{`.*gst-plugin-scanner.*`, ``}) - out = regFixConflictX.Replace(out) - if err := path.WriteFile([]byte(out)); err != nil { - return res, err - } - - // Set systemd unit drop-in files - return res, copyTo(paths.New("systemd/full/"), Root.Join("systemd")) -} diff --git a/pkg/prebuild/tools.go b/pkg/prebuild/tools.go deleted file mode 100644 index f8d50673..00000000 --- a/pkg/prebuild/tools.go +++ /dev/null @@ -1,83 +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/arduino/go-paths-helper" -) - -func copyTo(src *paths.Path, dst *paths.Path) error { - files, err := src.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories(), paths.FilterOutNames("README.md")) - if err != nil { - return err - } - for _, file := range files { - destination, err := file.RelFrom(src) - if err != nil { - return err - } - destination = dst.JoinPath(destination) - if err := destination.Parent().MkdirAll(); err != nil { - return err - } - if err := file.CopyTo(destination); err != nil { - return err - } - } - return nil -} - -// Overwrite upstream profile: rename our profile & hide upstream -func debianOverwrite(files []string) { - const ext = ".apparmor.d" - file, err := paths.New("debian/apparmor.d.hide").Append() - if err != nil { - panic(err) - } - for _, name := range files { - origin := RootApparmord.Join(name) - dest := RootApparmord.Join(name + ext) - if err := origin.Rename(dest); err != nil { - panic(err) - } - if _, err := file.WriteString("/etc/apparmor.d/" + name + "\n"); err != nil { - panic(err) - } - } -} - -// Clean the debian/apparmor.d.hide file -func debianOverwriteClean() { - const debianHide = `# This file is generated by "make", all edit will be lost. - -/etc/apparmor.d/usr.bin.firefox -/etc/apparmor.d/usr.sbin.cups-browsed -/etc/apparmor.d/usr.sbin.cupsd -/etc/apparmor.d/usr.sbin.rsyslogd -` - path := paths.New("debian/apparmor.d.hide") - if err := path.WriteFile([]byte(debianHide)); err != nil { - panic(err) - } -} - -// Get the list of upstream profiles to overwrite from dist/overwrite -func getOverwriteProfiles() []string { - res := []string{} - lines, err := DistDir.Join("overwrite").ReadFileAsLines() - if err != nil { - panic(err) - } - for _, line := range lines { - if strings.HasPrefix(line, "#") || line == "" { - continue - } - res = append(res, line) - } - return res -} -