// apparmor.d - Full set of apparmor profiles // Copyright (C) 2021-2024 Alexandre Pujol // 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 }