apparmor.d/pkg/aa/resolve.go

72 lines
1.7 KiB
Go
Raw Normal View History

2024-05-05 15:09:00 +02:00
// apparmor.d - Full set of apparmor profiles
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
// SPDX-License-Identifier: GPL-2.0-only
package aa
import (
"fmt"
"regexp"
"strings"
)
var (
regVariableReference = regexp.MustCompile(`@{([^{}]+)}`)
)
// Resolve resolves all variables and includes in the profile and merge the rules in the profile
func (f *AppArmorProfileFile) Resolve() error {
// Resolve variables
for _, variable := range f.Preamble.GetVariables() {
newValues := []string{}
for _, value := range variable.Values {
vars := f.resolveVariable(value)
if len(vars) == 0 {
return fmt.Errorf("Variable not defined in: %s", value)
}
newValues = append(newValues, vars...)
}
variable.Values = newValues
}
// Resolve variables in attachements
for _, profile := range f.Profiles {
attachments := []string{}
for _, att := range profile.Attachments {
vars := f.resolveVariable(att)
if len(vars) == 0 {
return fmt.Errorf("Variable not defined in: %s", att)
}
attachments = append(attachments, vars...)
}
profile.Attachments = attachments
}
return nil
}
func (f *AppArmorProfileFile) resolveVariable(input string) []string {
if !strings.Contains(input, tokVARIABLE) {
return []string{input}
}
vars := []string{}
match := regVariableReference.FindStringSubmatch(input)
if len(match) > 1 {
variable := match[0]
varname := match[1]
for _, vrbl := range f.Preamble.GetVariables() {
if vrbl.Name == varname {
for _, v := range vrbl.Values {
newVar := strings.ReplaceAll(input, variable, v)
res := f.resolveVariable(newVar)
vars = append(vars, res...)
}
}
}
} else {
vars = append(vars, input)
}
return vars
}