mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2025-01-18 00:48:10 +01:00
feat(aa-log): add a new apparmor profile struct
Also rewrite variables resolution to this new struct.
This commit is contained in:
parent
b2d093e125
commit
a8470dfa38
5 changed files with 379 additions and 156 deletions
|
@ -2,104 +2,19 @@
|
|||
// Copyright (C) 2023 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
// Warning: this is purposely not using a Yacc parser. Its only aim is to
|
||||
// extract variables and attachments for apparmor.d profile
|
||||
|
||||
package aa
|
||||
// AppArmorProfiles represents a full set of apparmor profiles
|
||||
type AppArmorProfiles map[string]*AppArmorProfile
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
var (
|
||||
regVariablesDef = regexp.MustCompile(`@{(.*)}\s*[+=]+\s*(.*)`)
|
||||
regVariablesRef = regexp.MustCompile(`@{([^{}]+)}`)
|
||||
|
||||
// Tunables
|
||||
Tunables = map[string][]string{
|
||||
"bin": {"/{usr/,}{s,}bin"},
|
||||
"lib": {"/{usr/,}lib{,exec,32,64}"},
|
||||
"multiarch": {"*-linux-gnu*"},
|
||||
"user_share_dirs": {"/home/*/.local/share"},
|
||||
"etc_ro": {"/{usr/,}etc/"},
|
||||
}
|
||||
)
|
||||
|
||||
// ApparmorProfile represents a full apparmor profile.
|
||||
// Warning: close to the BNF grammar of apparmor profile but not exactly the same (yet):
|
||||
// - Some rules are not supported yet (subprofile, hat...)
|
||||
// - The structure is simplified as it only aims at writting profile, not parsing it.
|
||||
type AppArmorProfile struct {
|
||||
Variables map[string][]string
|
||||
Attachments []string
|
||||
Preamble
|
||||
Profile
|
||||
}
|
||||
|
||||
func NewAppArmorProfile() *AppArmorProfile {
|
||||
variables := make(map[string][]string)
|
||||
maps.Copy(variables, Tunables)
|
||||
return &AppArmorProfile{
|
||||
Variables: variables,
|
||||
Attachments: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// ParseVariables extract all variables from the profile
|
||||
func (p *AppArmorProfile) ParseVariables(content string) {
|
||||
matches := regVariablesDef.FindAllStringSubmatch(content, -1)
|
||||
for _, match := range matches {
|
||||
if len(match) > 2 {
|
||||
key := match[1]
|
||||
values := match[2]
|
||||
if _, ok := p.Variables[key]; ok {
|
||||
p.Variables[key] = append(p.Variables[key], strings.Split(values, " ")...)
|
||||
} else {
|
||||
p.Variables[key] = strings.Split(values, " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolve recursively resolves all variables references
|
||||
func (p *AppArmorProfile) resolve(str string) []string {
|
||||
if strings.Contains(str, "@{") {
|
||||
vars := []string{}
|
||||
match := regVariablesRef.FindStringSubmatch(str)
|
||||
if len(match) > 1 {
|
||||
variable := match[0]
|
||||
varname := match[1]
|
||||
for _, value := range p.Variables[varname] {
|
||||
newVar := strings.ReplaceAll(str, variable, value)
|
||||
vars = append(vars, p.resolve(newVar)...)
|
||||
}
|
||||
} else {
|
||||
vars = append(vars, str)
|
||||
}
|
||||
return vars
|
||||
}
|
||||
return []string{str}
|
||||
}
|
||||
|
||||
// ResolveAttachments resolve profile attachments defined in exec_path
|
||||
func (p *AppArmorProfile) ResolveAttachments() {
|
||||
for _, exec := range p.Variables["exec_path"] {
|
||||
p.Attachments = append(p.Attachments, p.resolve(exec)...)
|
||||
}
|
||||
}
|
||||
|
||||
// NestAttachments return a nested attachment string
|
||||
func (p *AppArmorProfile) NestAttachments() string {
|
||||
if len(p.Attachments) == 0 {
|
||||
return ""
|
||||
} else if len(p.Attachments) == 1 {
|
||||
return p.Attachments[0]
|
||||
} else {
|
||||
res := []string{}
|
||||
for _, attachment := range p.Attachments {
|
||||
if strings.HasPrefix(attachment, "/") {
|
||||
res = append(res, attachment[1:])
|
||||
} else {
|
||||
res = append(res, attachment)
|
||||
}
|
||||
}
|
||||
return "/{" + strings.Join(res, ",") + "}"
|
||||
}
|
||||
return &AppArmorProfile{}
|
||||
}
|
||||
|
|
202
pkg/aa/rules.go
Normal file
202
pkg/aa/rules.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2021-2023 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package aa
|
||||
|
||||
// Preamble section of a profile
|
||||
type Preamble struct {
|
||||
Abi []Abi
|
||||
PreambleIncludes []Include
|
||||
Aliases []Alias
|
||||
Variables []Variable
|
||||
}
|
||||
|
||||
// Profile section of a profile
|
||||
type Profile struct {
|
||||
Name string
|
||||
Attachments []string
|
||||
Attributes []string
|
||||
Flags []string
|
||||
Rules
|
||||
}
|
||||
|
||||
type Rules struct {
|
||||
Includes []Include
|
||||
Rlimit []Rlimit
|
||||
Userns Userns
|
||||
Capability []Capability
|
||||
Network []Network
|
||||
Mount []Mount
|
||||
Umount []Umount
|
||||
Remount []Remount
|
||||
PivotRoot []PivotRoot
|
||||
ChangeProfile []ChangeProfile
|
||||
Unix []Unix
|
||||
Ptrace []Ptrace
|
||||
Signal []Signal
|
||||
Dbus []Dbus
|
||||
File []File
|
||||
}
|
||||
|
||||
|
||||
// Qualifier to apply extra settings to a rule
|
||||
type Qualifier struct {
|
||||
Audit bool
|
||||
AccessType string
|
||||
Owner bool
|
||||
NoNewPrivs bool
|
||||
FileInherit bool
|
||||
}
|
||||
|
||||
// Preamble rules
|
||||
|
||||
type Abi struct {
|
||||
AbsPath string
|
||||
MagicPath string
|
||||
}
|
||||
|
||||
type Alias struct {
|
||||
Path string
|
||||
RewrittenPath string
|
||||
}
|
||||
|
||||
type Include struct {
|
||||
IfExists bool
|
||||
AbsPath string
|
||||
MagicPath string
|
||||
}
|
||||
|
||||
type Variable struct {
|
||||
Name string
|
||||
Values []string
|
||||
}
|
||||
|
||||
// Profile rules
|
||||
|
||||
type Rlimit struct {
|
||||
Key string
|
||||
Op string
|
||||
Value string
|
||||
}
|
||||
|
||||
type Userns struct {
|
||||
Qualifier
|
||||
Create bool
|
||||
}
|
||||
|
||||
type Capability struct {
|
||||
Qualifier
|
||||
Name string
|
||||
}
|
||||
|
||||
type AddressExpr struct {
|
||||
Source string
|
||||
Destination string
|
||||
Port string
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Qualifier
|
||||
Domain string
|
||||
Type string
|
||||
Protocol string
|
||||
AddressExpr
|
||||
}
|
||||
|
||||
type MountConditions struct {
|
||||
Fs string
|
||||
Op string
|
||||
FsType string
|
||||
Options []string
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
Qualifier
|
||||
MountConditions
|
||||
Source string
|
||||
MountPoint string
|
||||
}
|
||||
|
||||
type Umount struct {
|
||||
Qualifier
|
||||
MountConditions
|
||||
MountPoint string
|
||||
}
|
||||
|
||||
type Remount struct {
|
||||
Qualifier
|
||||
MountConditions
|
||||
MountPoint string
|
||||
}
|
||||
|
||||
type PivotRoot struct {
|
||||
Qualifier
|
||||
OldRoot string
|
||||
NewRoot string
|
||||
TargetProfile string
|
||||
}
|
||||
|
||||
type ChangeProfile struct {
|
||||
ExecMode string
|
||||
Exec string
|
||||
ProfileName string
|
||||
}
|
||||
|
||||
type IOUring struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Label string
|
||||
}
|
||||
|
||||
type Signal struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Set string
|
||||
Peer string
|
||||
}
|
||||
|
||||
type Ptrace struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Peer string
|
||||
}
|
||||
|
||||
type Unix struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Type string
|
||||
Protocol string
|
||||
Address string
|
||||
Label string
|
||||
Attr string
|
||||
Opt string
|
||||
Peer string
|
||||
PeerAddr string
|
||||
}
|
||||
|
||||
type Mqueue struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Type string
|
||||
Label string
|
||||
}
|
||||
|
||||
type Dbus struct {
|
||||
Qualifier
|
||||
Access string
|
||||
Bus string
|
||||
Name string
|
||||
Path string
|
||||
Interface string
|
||||
Member string
|
||||
Label string
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Qualifier
|
||||
Path string
|
||||
Access string
|
||||
Target string
|
||||
}
|
||||
|
117
pkg/aa/variables.go
Normal file
117
pkg/aa/variables.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2021-2023 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
// Warning: this is purposely not using a Yacc parser. Its only aim is to
|
||||
// extract variables and attachments for apparmor.d profile
|
||||
|
||||
package aa
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/arduino/go-paths-helper"
|
||||
)
|
||||
|
||||
var (
|
||||
regVariablesDef = regexp.MustCompile(`@{(.*)}\s*[+=]+\s*(.*)`)
|
||||
regVariablesRef = regexp.MustCompile(`@{([^{}]+)}`)
|
||||
)
|
||||
|
||||
// Default Apparmor magic directory: /etc/apparmor.d/.
|
||||
var MagicRoot = paths.New("/etc/apparmor.d")
|
||||
|
||||
// DefaultTunables return a minimal working profile to build the profile
|
||||
// It should not be used when loading file from /etc/apparmor.d
|
||||
func DefaultTunables() *AppArmorProfile {
|
||||
return &AppArmorProfile{
|
||||
Preamble: Preamble{
|
||||
Variables: []Variable{
|
||||
{"bin", []string{"/{usr/,}{s,}bin"}},
|
||||
{"lib", []string{"/{usr/,}lib{,exec,32,64}"}},
|
||||
{"multiarch", []string{"*-linux-gnu*"}},
|
||||
{"user_share_dirs", []string{"/home/*/.local/share"}},
|
||||
{"etc_ro", []string{"/{usr/,}etc/"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ParseVariables extract all variables from the profile
|
||||
func (p *AppArmorProfile) ParseVariables(content string) {
|
||||
matches := regVariablesDef.FindAllStringSubmatch(content, -1)
|
||||
for _, match := range matches {
|
||||
if len(match) > 2 {
|
||||
key := match[1]
|
||||
values := strings.Split(match[2], " ")
|
||||
found := false
|
||||
for idx, variable := range p.Variables {
|
||||
if variable.Name == key {
|
||||
p.Variables[idx].Values = append(p.Variables[idx].Values, values...)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
variable := Variable{Name: key, Values: values}
|
||||
p.Variables = append(p.Variables, variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolve recursively resolves all variables references
|
||||
func (p *AppArmorProfile) resolve(str string) []string {
|
||||
if strings.Contains(str, "@{") {
|
||||
vars := []string{}
|
||||
match := regVariablesRef.FindStringSubmatch(str)
|
||||
if len(match) > 1 {
|
||||
variable := match[0]
|
||||
varname := match[1]
|
||||
for _, vrbl := range p.Variables {
|
||||
if vrbl.Name == varname {
|
||||
for _, value := range vrbl.Values {
|
||||
newVar := strings.ReplaceAll(str, variable, value)
|
||||
vars = append(vars, p.resolve(newVar)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vars = append(vars, str)
|
||||
}
|
||||
return vars
|
||||
}
|
||||
return []string{str}
|
||||
}
|
||||
|
||||
// ResolveAttachments resolve profile attachments defined in exec_path
|
||||
func (p *AppArmorProfile) ResolveAttachments() {
|
||||
for _, variable := range p.Variables {
|
||||
if variable.Name == "exec_path" {
|
||||
for _, value := range variable.Values {
|
||||
p.Attachments = append(p.Attachments, p.resolve(value)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NestAttachments return a nested attachment string
|
||||
func (p *AppArmorProfile) NestAttachments() string {
|
||||
if len(p.Attachments) == 0 {
|
||||
return ""
|
||||
} else if len(p.Attachments) == 1 {
|
||||
return p.Attachments[0]
|
||||
} else {
|
||||
res := []string{}
|
||||
for _, attachment := range p.Attachments {
|
||||
if strings.HasPrefix(attachment, "/") {
|
||||
res = append(res, attachment[1:])
|
||||
} else {
|
||||
res = append(res, attachment)
|
||||
}
|
||||
}
|
||||
return "/{" + strings.Join(res, ",") + "}"
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestNewAppArmorProfile(t *testing.T) {
|
||||
func TestDefaultTunables(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want *AppArmorProfile
|
||||
|
@ -17,20 +17,21 @@ func TestNewAppArmorProfile(t *testing.T) {
|
|||
{
|
||||
name: "aa",
|
||||
want: &AppArmorProfile{
|
||||
Variables: map[string][]string{
|
||||
"bin": {"/{usr/,}{s,}bin"},
|
||||
"lib": {"/{usr/,}lib{,exec,32,64}"},
|
||||
"multiarch": {"*-linux-gnu*"},
|
||||
"user_share_dirs": {"/home/*/.local/share"},
|
||||
"etc_ro": {"/{usr/,}etc/"},
|
||||
Preamble: Preamble{
|
||||
Variables: []Variable{
|
||||
{"bin", []string{"/{usr/,}{s,}bin"}},
|
||||
{"lib", []string{"/{usr/,}lib{,exec,32,64}"}},
|
||||
{"multiarch", []string{"*-linux-gnu*"}},
|
||||
{"user_share_dirs", []string{"/home/*/.local/share"}},
|
||||
{"etc_ro", []string{"/{usr/,}etc/"}},
|
||||
},
|
||||
},
|
||||
Attachments: []string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := NewAppArmorProfile(); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := DefaultTunables(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("NewAppArmorProfile() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
@ -41,7 +42,7 @@ func TestAppArmorProfile_ParseVariables(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
want map[string][]string
|
||||
want []Variable
|
||||
}{
|
||||
{
|
||||
name: "firefox",
|
||||
|
@ -51,12 +52,12 @@ func TestAppArmorProfile_ParseVariables(t *testing.T) {
|
|||
@{firefox_cache_dirs} = @{user_cache_dirs}/mozilla/
|
||||
@{exec_path} = /{usr/,}bin/@{firefox_name} @{firefox_lib_dirs}/@{firefox_name}
|
||||
`,
|
||||
want: map[string][]string{
|
||||
"firefox_name": {"firefox{,-esr,-bin}"},
|
||||
"firefox_config_dirs": {"@{HOME}/.mozilla/"},
|
||||
"firefox_lib_dirs": {"/{usr/,}lib{,32,64}/@{firefox_name}", "/opt/@{firefox_name}"},
|
||||
"firefox_cache_dirs": {"@{user_cache_dirs}/mozilla/"},
|
||||
"exec_path": {"/{usr/,}bin/@{firefox_name}", "@{firefox_lib_dirs}/@{firefox_name}"},
|
||||
want: []Variable{
|
||||
{"firefox_name", []string{"firefox{,-esr,-bin}"}},
|
||||
{"firefox_lib_dirs", []string{"/{usr/,}lib{,32,64}/@{firefox_name}", "/opt/@{firefox_name}"}},
|
||||
{"firefox_config_dirs", []string{"@{HOME}/.mozilla/"}},
|
||||
{"firefox_cache_dirs", []string{"@{user_cache_dirs}/mozilla/"}},
|
||||
{"exec_path", []string{"/{usr/,}bin/@{firefox_name}", "@{firefox_lib_dirs}/@{firefox_name}"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -65,23 +66,19 @@ func TestAppArmorProfile_ParseVariables(t *testing.T) {
|
|||
@{exec_path} += /{usr/,}bin/Xorg{,.bin}
|
||||
@{exec_path} += /{usr/,}lib/Xorg{,.wrap}
|
||||
@{exec_path} += /{usr/,}lib/xorg/Xorg{,.wrap}`,
|
||||
want: map[string][]string{
|
||||
"exec_path": {
|
||||
want: []Variable{
|
||||
{"exec_path", []string{
|
||||
"/{usr/,}bin/X",
|
||||
"/{usr/,}bin/Xorg{,.bin}",
|
||||
"/{usr/,}lib/Xorg{,.wrap}",
|
||||
"/{usr/,}lib/xorg/Xorg{,.wrap}",
|
||||
"/{usr/,}lib/xorg/Xorg{,.wrap}"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &AppArmorProfile{
|
||||
Variables: map[string][]string{},
|
||||
Attachments: []string{},
|
||||
}
|
||||
|
||||
p := NewAppArmorProfile()
|
||||
p.ParseVariables(tt.content)
|
||||
if !reflect.DeepEqual(p.Variables, tt.want) {
|
||||
t.Errorf("AppArmorProfile.ParseVariables() = %v, want %v", p.Variables, tt.want)
|
||||
|
@ -93,23 +90,18 @@ func TestAppArmorProfile_ParseVariables(t *testing.T) {
|
|||
func TestAppArmorProfile_resolve(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
variables map[string][]string
|
||||
input string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
variables: Tunables,
|
||||
input: "@{}",
|
||||
want: []string{"@{}"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &AppArmorProfile{
|
||||
Variables: tt.variables,
|
||||
Attachments: []string{},
|
||||
}
|
||||
p := DefaultTunables()
|
||||
if got := p.resolve(tt.input); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppArmorProfile.resolve() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
@ -120,15 +112,15 @@ func TestAppArmorProfile_resolve(t *testing.T) {
|
|||
func TestAppArmorProfile_ResolveAttachments(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
variables map[string][]string
|
||||
variables []Variable
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "firefox",
|
||||
variables: map[string][]string{
|
||||
"firefox_name": {"firefox{,-esr,-bin}"},
|
||||
"firefox_lib_dirs": {"/{usr/,}/lib{,32,64}/@{firefox_name}", "/opt/@{firefox_name}"},
|
||||
"exec_path": {"/{usr/,}bin/@{firefox_name}", "@{firefox_lib_dirs}/@{firefox_name}"},
|
||||
variables: []Variable{
|
||||
{"firefox_name", []string{"firefox{,-esr,-bin}"}},
|
||||
{"firefox_lib_dirs", []string{"/{usr/,}/lib{,32,64}/@{firefox_name}", "/opt/@{firefox_name}"}},
|
||||
{"exec_path", []string{"/{usr/,}bin/@{firefox_name}", "@{firefox_lib_dirs}/@{firefox_name}"}},
|
||||
},
|
||||
want: []string{
|
||||
"/{usr/,}bin/firefox{,-esr,-bin}",
|
||||
|
@ -138,10 +130,10 @@ func TestAppArmorProfile_ResolveAttachments(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "chromium",
|
||||
variables: map[string][]string{
|
||||
"chromium_name": {"chromium"},
|
||||
"chromium_lib_dirs": {"/{usr/,}lib/@{chromium_name}"},
|
||||
"exec_path": {"@{chromium_lib_dirs}/@{chromium_name}"},
|
||||
variables: []Variable{
|
||||
{"chromium_name", []string{"chromium"}},
|
||||
{"chromium_lib_dirs", []string{"/{usr/,}lib/@{chromium_name}"}},
|
||||
{"exec_path", []string{"@{chromium_lib_dirs}/@{chromium_name}"}},
|
||||
},
|
||||
want: []string{
|
||||
"/{usr/,}lib/chromium/chromium",
|
||||
|
@ -149,9 +141,9 @@ func TestAppArmorProfile_ResolveAttachments(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "geoclue",
|
||||
variables: map[string][]string{
|
||||
"libexec": {"/{usr/,}libexec"},
|
||||
"exec_path": {"@{libexec}/geoclue", "@{libexec}/geoclue-2.0/demos/agent"},
|
||||
variables: []Variable{
|
||||
{"libexec", []string{"/{usr/,}libexec"}},
|
||||
{"exec_path", []string{"@{libexec}/geoclue", "@{libexec}/geoclue-2.0/demos/agent"}},
|
||||
},
|
||||
want: []string{
|
||||
"/{usr/,}libexec/geoclue",
|
||||
|
@ -160,11 +152,11 @@ func TestAppArmorProfile_ResolveAttachments(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "opera",
|
||||
variables: map[string][]string{
|
||||
"multiarch": {"*-linux-gnu*"},
|
||||
"chromium_name": {"opera{,-beta,-developer}"},
|
||||
"chromium_lib_dirs": {"/{usr/,}lib/@{multiarch}/@{chromium_name}"},
|
||||
"exec_path": {"@{chromium_lib_dirs}/@{chromium_name}"},
|
||||
variables: []Variable{
|
||||
{"multiarch", []string{"*-linux-gnu*"}},
|
||||
{"chromium_name", []string{"opera{,-beta,-developer}"}},
|
||||
{"chromium_lib_dirs", []string{"/{usr/,}lib/@{multiarch}/@{chromium_name}"}},
|
||||
{"exec_path", []string{"@{chromium_lib_dirs}/@{chromium_name}"}},
|
||||
},
|
||||
want: []string{
|
||||
"/{usr/,}lib/*-linux-gnu*/opera{,-beta,-developer}/opera{,-beta,-developer}",
|
||||
|
@ -173,10 +165,8 @@ func TestAppArmorProfile_ResolveAttachments(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &AppArmorProfile{
|
||||
Variables: tt.variables,
|
||||
Attachments: []string{},
|
||||
}
|
||||
p := NewAppArmorProfile()
|
||||
p.Variables = tt.variables
|
||||
p.ResolveAttachments()
|
||||
if !reflect.DeepEqual(p.Attachments, tt.want) {
|
||||
t.Errorf("AppArmorProfile.ResolveAttachments() = %v, want %v", p.Attachments, tt.want)
|
||||
|
@ -226,13 +216,12 @@ func TestAppArmorProfile_NestAttachments(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &AppArmorProfile{
|
||||
Variables: map[string][]string{},
|
||||
Attachments: tt.Attachments,
|
||||
}
|
||||
p := NewAppArmorProfile()
|
||||
p.Attachments = tt.Attachments
|
||||
if got := p.NestAttachments(); got != tt.want {
|
||||
t.Errorf("AppArmorProfile.NestAttachments() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ func BuildComplain(profile string) string {
|
|||
|
||||
// Bypass userspace tools restriction
|
||||
func BuildUserspace(profile string) string {
|
||||
p := aa.NewAppArmorProfile()
|
||||
p := aa.DefaultTunables()
|
||||
p.ParseVariables(profile)
|
||||
p.ResolveAttachments()
|
||||
att := p.NestAttachments()
|
||||
|
|
Loading…
Reference in a new issue