mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2024-12-25 22:46:47 +01:00
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.
This commit is contained in:
parent
d6b7bef89e
commit
59ac54e2fc
39 changed files with 473 additions and 440 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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**
|
||||
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <abi/3.0>,
|
||||
profile test {
|
||||
# userns,
|
||||
# mqueue r type=posix /,
|
||||
}`,
|
||||
want: `
|
||||
abi <abi/4.0>,
|
||||
profile test {
|
||||
userns,
|
||||
mqueue r type=posix /,
|
||||
}`,
|
||||
want: `
|
||||
abi <abi/3.0>,
|
||||
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)
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
181
pkg/prebuild/cli/cli.go
Normal file
181
pkg/prebuild/cli/cli.go
Normal file
|
@ -0,0 +1,181 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2023-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2023-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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)
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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")}
|
||||
|
|
@ -2,11 +2,9 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package cfg
|
||||
package prebuild
|
||||
|
||||
import (
|
||||
"reflect"
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package cfg
|
||||
package prebuild
|
||||
|
||||
import (
|
||||
"os"
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package cfg
|
||||
package prebuild
|
||||
|
||||
import (
|
||||
"reflect"
|
|
@ -1,117 +0,0 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2023-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// 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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
|
|
Loading…
Reference in a new issue