feat(prebuild): add err reporting to builder & directive tasks.

This commit is contained in:
Alexandre Pujol 2024-05-25 22:30:20 +01:00
parent 865ce4c66b
commit 02e3334949
No known key found for this signature in database
GPG key ID: C5469996F0DF68EC
19 changed files with 108 additions and 53 deletions

View file

@ -30,6 +30,6 @@ func init() {
}) })
} }
func (b ABI3) Apply(profile string) string { func (b ABI3) Apply(profile string) (string, error) {
return regAbi4To3.Replace(profile) return regAbi4To3.Replace(profile), nil
} }

View file

@ -30,13 +30,13 @@ func init() {
}) })
} }
func (b Complain) Apply(profile string) string { func (b Complain) Apply(profile string) (string, error) {
flags := []string{} flags := []string{}
matches := regFlags.FindStringSubmatch(profile) matches := regFlags.FindStringSubmatch(profile)
if len(matches) != 0 { if len(matches) != 0 {
flags = strings.Split(matches[1], ",") flags = strings.Split(matches[1], ",")
if slices.Contains(flags, "complain") { if slices.Contains(flags, "complain") {
return profile return profile, nil
} }
} }
flags = append(flags, "complain") flags = append(flags, "complain")
@ -44,5 +44,5 @@ func (b Complain) Apply(profile string) string {
// Remove all flags definition, then set manifest' flags // Remove all flags definition, then set manifest' flags
profile = regFlags.ReplaceAllLiteralString(profile, "") profile = regFlags.ReplaceAllLiteralString(profile, "")
return regProfileHeader.ReplaceAllLiteralString(profile, strFlags) return regProfileHeader.ReplaceAllLiteralString(profile, strFlags), nil
} }

View file

@ -21,7 +21,7 @@ var (
// Main directive interface // Main directive interface
type Builder interface { type Builder interface {
cfg.BaseInterface cfg.BaseInterface
Apply(profile string) string Apply(profile string) (string, error)
} }
func Register(names ...string) { func Register(names ...string) {

View file

@ -15,6 +15,7 @@ func TestBuilder_Apply(t *testing.T) {
b Builder b Builder
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "abi3", name: "abi3",
@ -237,7 +238,12 @@ func TestBuilder_Apply(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := tt.b.Apply(tt.profile); got != tt.want { got, err := tt.b.Apply(tt.profile)
if (err != nil) != tt.wantErr {
t.Errorf("Builder.Apply() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Builder.Apply() = %v, want %v", got, tt.want) t.Errorf("Builder.Apply() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -31,6 +31,6 @@ func init() {
}) })
} }
func (b Dev) Apply(profile string) string { func (b Dev) Apply(profile string) (string, error) {
return regDev.Replace(profile) return regDev.Replace(profile), nil
} }

View file

@ -24,16 +24,16 @@ func init() {
}) })
} }
func (b Enforce) Apply(profile string) string { func (b Enforce) Apply(profile string) (string, error) {
matches := regFlags.FindStringSubmatch(profile) matches := regFlags.FindStringSubmatch(profile)
if len(matches) == 0 { if len(matches) == 0 {
return profile return profile, nil
} }
flags := strings.Split(matches[1], ",") flags := strings.Split(matches[1], ",")
idx := slices.Index(flags, "complain") idx := slices.Index(flags, "complain")
if idx == -1 { if idx == -1 {
return profile return profile, nil
} }
flags = slices.Delete(flags, idx, idx+1) flags = slices.Delete(flags, idx, idx+1)
strFlags := "{" strFlags := "{"
@ -43,5 +43,5 @@ func (b Enforce) Apply(profile string) string {
// Remove all flags definition, then set new flags // Remove all flags definition, then set new flags
profile = regFlags.ReplaceAllLiteralString(profile, "") profile = regFlags.ReplaceAllLiteralString(profile, "")
return regProfileHeader.ReplaceAllLiteralString(profile, strFlags) return regProfileHeader.ReplaceAllLiteralString(profile, strFlags), nil
} }

View file

@ -28,6 +28,6 @@ func init() {
}) })
} }
func (b FullSystemPolicy) Apply(profile string) string { func (b FullSystemPolicy) Apply(profile string) (string, error) {
return regFullSystemPolicy.Replace(profile) return regFullSystemPolicy.Replace(profile), nil
} }

View file

@ -29,7 +29,7 @@ func init() {
}) })
} }
func (b Userspace) Apply(profile string) string { func (b Userspace) Apply(profile string) (string, error) {
p := aa.DefaultTunables() p := aa.DefaultTunables()
p.ParseVariables(profile) p.ParseVariables(profile)
p.ResolveAttachments() p.ResolveAttachments()
@ -37,7 +37,7 @@ func (b Userspace) Apply(profile string) string {
matches := regAttachments.FindAllString(profile, -1) matches := regAttachments.FindAllString(profile, -1)
if len(matches) > 0 { if len(matches) > 0 {
strheader := strings.Replace(matches[0], "@{exec_path}", att, -1) strheader := strings.Replace(matches[0], "@{exec_path}", att, -1)
return regAttachments.ReplaceAllLiteralString(profile, strheader) return regAttachments.ReplaceAllLiteralString(profile, strheader), nil
} }
return profile return profile, nil
} }

View file

@ -26,7 +26,7 @@ var (
// Main directive interface // Main directive interface
type Directive interface { type Directive interface {
cfg.BaseInterface cfg.BaseInterface
Apply(opt *Option, profile string) string Apply(opt *Option, profile string) (string, error)
} }
// Directive options // Directive options
@ -65,14 +65,18 @@ func RegisterDirective(d Directive) {
Directives[d.Name()] = d Directives[d.Name()] = d
} }
func Run(file *paths.Path, profile string) string { func Run(file *paths.Path, profile string) (string, error) {
var err error
for _, match := range regDirective.FindAllStringSubmatch(profile, -1) { for _, match := range regDirective.FindAllStringSubmatch(profile, -1) {
opt := NewOption(file, match) opt := NewOption(file, match)
drtv, ok := Directives[opt.Name] drtv, ok := Directives[opt.Name]
if !ok { if !ok {
panic(fmt.Sprintf("Unknown directive: %s", opt.Name)) return "", fmt.Errorf("Unknown directive: %s", opt.Name)
} }
profile = drtv.Apply(opt, profile) profile, err = drtv.Apply(opt, profile)
if err != nil {
return "", err
} }
return profile }
return profile, nil
} }

View file

@ -70,6 +70,7 @@ func TestRun(t *testing.T) {
file *paths.Path file *paths.Path
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "none", name: "none",
@ -86,7 +87,12 @@ func TestRun(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := Run(tt.file, tt.profile); got != tt.want { got, err := Run(tt.file, tt.profile)
if (err != nil) != tt.wantErr {
t.Errorf("Run() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Run() = %v, want %v", got, tt.want) t.Errorf("Run() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -50,10 +50,13 @@ func setInterfaces(rules map[string]string) []string {
return interfaces return interfaces
} }
func (d Dbus) Apply(opt *Option, profile string) string { func (d Dbus) Apply(opt *Option, profile string) (string, error) {
var r aa.Rules var r aa.Rules
action := d.sanityCheck(opt) action, err := d.sanityCheck(opt)
if err != nil {
return "", err
}
switch action { switch action {
case "own": case "own":
r = d.own(opt.ArgMap) r = d.own(opt.ArgMap)
@ -68,26 +71,26 @@ func (d Dbus) Apply(opt *Option, profile string) string {
lenDbus := len(generatedDbus) lenDbus := len(generatedDbus)
generatedDbus = generatedDbus[:lenDbus-1] generatedDbus = generatedDbus[:lenDbus-1]
profile = strings.Replace(profile, opt.Raw, generatedDbus, -1) profile = strings.Replace(profile, opt.Raw, generatedDbus, -1)
return profile return profile, nil
} }
func (d Dbus) sanityCheck(opt *Option) string { func (d Dbus) sanityCheck(opt *Option) (string, error) {
if len(opt.ArgList) < 1 { if len(opt.ArgList) < 1 {
panic(fmt.Sprintf("Unknown dbus action: %s in %s", opt.Name, opt.File)) return "", fmt.Errorf("Unknown dbus action: %s in %s", opt.Name, opt.File)
} }
action := opt.ArgList[0] action := opt.ArgList[0]
if action != "own" && action != "talk" { if action != "own" && action != "talk" {
panic(fmt.Sprintf("Unknown dbus action: %s in %s", opt.Name, opt.File)) return "", fmt.Errorf("Unknown dbus action: %s in %s", opt.Name, opt.File)
} }
if _, present := opt.ArgMap["name"]; !present { if _, present := opt.ArgMap["name"]; !present {
panic(fmt.Sprintf("Missing name for 'dbus: %s' in %s", action, opt.File)) return "", fmt.Errorf("Missing name for 'dbus: %s' in %s", action, opt.File)
} }
if _, present := opt.ArgMap["bus"]; !present { if _, present := opt.ArgMap["bus"]; !present {
panic(fmt.Sprintf("Missing bus for '%s' in %s", opt.ArgMap["name"], opt.File)) return "", fmt.Errorf("Missing bus for '%s' in %s", opt.ArgMap["name"], opt.File)
} }
if _, present := opt.ArgMap["label"]; !present && action == "talk" { if _, present := opt.ArgMap["label"]; !present && action == "talk" {
panic(fmt.Sprintf("Missing label for '%s' in %s", opt.ArgMap["name"], opt.File)) return "", fmt.Errorf("Missing label for '%s' in %s", opt.ArgMap["name"], opt.File)
} }
// Set default values // Set default values
@ -95,7 +98,7 @@ func (d Dbus) sanityCheck(opt *Option) string {
opt.ArgMap["path"] = "/" + strings.Replace(opt.ArgMap["name"], ".", "/", -1) + "{,/**}" opt.ArgMap["path"] = "/" + strings.Replace(opt.ArgMap["name"], ".", "/", -1) + "{,/**}"
} }
opt.ArgMap["name"] += "{,.*}" opt.ArgMap["name"] += "{,.*}"
return action return action, nil
} }
func (d Dbus) own(rules map[string]string) aa.Rules { func (d Dbus) own(rules map[string]string) aa.Rules {

View file

@ -38,6 +38,7 @@ func TestDbus_Apply(t *testing.T) {
opt *Option opt *Option
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "own", name: "own",
@ -137,7 +138,12 @@ func TestDbus_Apply(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := Directives["dbus"].Apply(tt.opt, tt.profile); got != tt.want { got, err := Directives["dbus"].Apply(tt.opt, tt.profile)
if (err != nil) != tt.wantErr {
t.Errorf("Dbus.Apply() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Dbus.Apply() = %v, want %v", got, tt.want) t.Errorf("Dbus.Apply() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -27,7 +27,7 @@ func init() {
}) })
} }
func (d Exec) Apply(opt *Option, profileRaw string) string { func (d Exec) Apply(opt *Option, profileRaw string) (string, error) {
transition := "Px" transition := "Px"
transitions := []string{"P", "U", "p", "u", "PU", "pu"} transitions := []string{"P", "U", "p", "u", "PU", "pu"}
t := opt.ArgList[0] t := opt.ArgList[0]
@ -60,5 +60,5 @@ func (d Exec) Apply(opt *Option, profileRaw string) string {
rules.Sort() rules.Sort()
new := rules.String() new := rules.String()
new = new[:len(new)-1] new = new[:len(new)-1]
return strings.Replace(profileRaw, opt.Raw, new, -1) return strings.Replace(profileRaw, opt.Raw, new, -1), nil
} }

View file

@ -18,6 +18,7 @@ func TestExec_Apply(t *testing.T) {
opt *Option opt *Option
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "exec", name: "exec",
@ -51,7 +52,12 @@ func TestExec_Apply(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cfg.RootApparmord = tt.rootApparmord cfg.RootApparmord = tt.rootApparmord
if got := Directives["exec"].Apply(tt.opt, tt.profile); got != tt.want { 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)
return
}
if got != tt.want {
t.Errorf("Exec.Apply() = |%v|, want |%v|", got, tt.want) t.Errorf("Exec.Apply() = |%v|, want |%v|", got, tt.want)
} }
}) })

View file

@ -41,12 +41,12 @@ func filterRuleForUs(opt *Option) bool {
return slices.Contains(opt.ArgList, cfg.Distribution) || slices.Contains(opt.ArgList, cfg.Family) return slices.Contains(opt.ArgList, cfg.Distribution) || slices.Contains(opt.ArgList, cfg.Family)
} }
func filter(only bool, opt *Option, profile string) string { func filter(only bool, opt *Option, profile string) (string, error) {
if only && filterRuleForUs(opt) { if only && filterRuleForUs(opt) {
return profile return profile, nil
} }
if !only && !filterRuleForUs(opt) { if !only && !filterRuleForUs(opt) {
return profile return profile, nil
} }
inline := true inline := true
@ -64,13 +64,13 @@ func filter(only bool, opt *Option, profile string) string {
regRemoveParagraph := regexp.MustCompile(`(?s)` + opt.Raw + `\n.*?\n\n`) regRemoveParagraph := regexp.MustCompile(`(?s)` + opt.Raw + `\n.*?\n\n`)
profile = regRemoveParagraph.ReplaceAllString(profile, "") profile = regRemoveParagraph.ReplaceAllString(profile, "")
} }
return profile return profile, nil
} }
func (d FilterOnly) Apply(opt *Option, profile string) string { func (d FilterOnly) Apply(opt *Option, profile string) (string, error) {
return filter(true, opt, profile) return filter(true, opt, profile)
} }
func (d FilterExclude) Apply(opt *Option, profile string) string { func (d FilterExclude) Apply(opt *Option, profile string) (string, error) {
return filter(false, opt, profile) return filter(false, opt, profile)
} }

View file

@ -18,6 +18,7 @@ func TestFilterOnly_Apply(t *testing.T) {
opt *Option opt *Option
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "inline", name: "inline",
@ -79,7 +80,12 @@ func TestFilterOnly_Apply(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cfg.Distribution = tt.dist cfg.Distribution = tt.dist
cfg.Family = tt.family cfg.Family = tt.family
if got := Directives["only"].Apply(tt.opt, tt.profile); got != tt.want { 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)
return
}
if got != tt.want {
t.Errorf("FilterOnly.Apply() = %v, want %v", got, tt.want) t.Errorf("FilterOnly.Apply() = %v, want %v", got, tt.want)
} }
}) })
@ -94,6 +100,7 @@ func TestFilterExclude_Apply(t *testing.T) {
opt *Option opt *Option
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "inline", name: "inline",
@ -128,7 +135,12 @@ func TestFilterExclude_Apply(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cfg.Distribution = tt.dist cfg.Distribution = tt.dist
cfg.Family = tt.family cfg.Family = tt.family
if got := Directives["exclude"].Apply(tt.opt, tt.profile); got != tt.want { 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)
return
}
if got != tt.want {
t.Errorf("FilterExclude.Apply() = %v, want %v", got, tt.want) t.Errorf("FilterExclude.Apply() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -38,13 +38,13 @@ func init() {
}) })
} }
func (s Stack) Apply(opt *Option, profile string) string { func (s Stack) Apply(opt *Option, profile string) (string, error) {
res := "" res := ""
for name := range opt.ArgMap { for name := range opt.ArgMap {
stackedProfile := util.MustReadFile(cfg.RootApparmord.Join(name)) stackedProfile := util.MustReadFile(cfg.RootApparmord.Join(name))
m := regRules.FindStringSubmatch(stackedProfile) m := regRules.FindStringSubmatch(stackedProfile)
if len(m) < 2 { if len(m) < 2 {
panic(fmt.Sprintf("No profile found in %s", name)) return "", fmt.Errorf("No profile found in %s", name)
} }
stackedRules := m[1] stackedRules := m[1]
stackedRules = regCleanStakedRules.Replace(stackedRules) stackedRules = regCleanStakedRules.Replace(stackedRules)
@ -54,9 +54,9 @@ func (s Stack) Apply(opt *Option, profile string) string {
// Insert the stacked profile at the end of the current profile, remove the stack directive // Insert the stacked profile at the end of the current profile, remove the stack directive
m := regEndOfRules.FindStringSubmatch(profile) m := regEndOfRules.FindStringSubmatch(profile)
if len(m) <= 1 { if len(m) <= 1 {
panic(fmt.Sprintf("No end of rules found in %s", opt.File)) return "", fmt.Errorf("No end of rules found in %s", opt.File)
} }
profile = strings.Replace(profile, m[0], res+m[0], -1) profile = strings.Replace(profile, m[0], res+m[0], -1)
profile = strings.Replace(profile, opt.Raw, "", -1) profile = strings.Replace(profile, opt.Raw, "", -1)
return profile return profile, nil
} }

View file

@ -18,6 +18,7 @@ func TestStack_Apply(t *testing.T) {
opt *Option opt *Option
profile string profile string
want string want string
wantErr bool
}{ }{
{ {
name: "stack", name: "stack",
@ -68,7 +69,12 @@ profile parent @{exec_path} {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cfg.RootApparmord = tt.rootApparmord cfg.RootApparmord = tt.rootApparmord
if got := Directives["stack"].Apply(tt.opt, tt.profile); got != tt.want { 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)
return
}
if got != tt.want {
t.Errorf("Stack.Apply() = %v, want %v", got, tt.want) t.Errorf("Stack.Apply() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -84,9 +84,15 @@ func Build() error {
return err return err
} }
for _, b := range builder.Builds { for _, b := range builder.Builds {
profile = b.Apply(profile) profile, err = b.Apply(profile)
if err != nil {
return err
}
}
profile, err = directive.Run(file, profile)
if err != nil {
return err
} }
profile = directive.Run(file, profile)
if err := file.WriteFile([]byte(profile)); err != nil { if err := file.WriteFile([]byte(profile)); err != nil {
return err return err
} }