feat(aa): continue refractoring the aa structure.

This commit is contained in:
Alexandre Pujol 2024-04-19 22:43:02 +01:00
parent 8ef858ad35
commit c97886d960
Failed to generate hash of commit
22 changed files with 160 additions and 182 deletions

View file

@ -35,6 +35,7 @@ type Preamble struct {
Includes []*Include
Aliases []*Alias
Variables []*Variable
Comments []*RuleBase
}
func NewAppArmorProfile() *AppArmorProfileFile {

View file

@ -58,7 +58,7 @@ func TestAppArmorProfile_String(t *testing.T) {
Attributes: map[string]string{"security.tagged": "allowed"},
Flags: []string{"complain", "attach_disconnected"},
},
Rules: []ApparmorRule{
Rules: []Rule{
&Include{IsMagic: true, Path: "abstractions/base"},
&Include{IsMagic: true, Path: "abstractions/nameservice-strict"},
rlimit1,
@ -135,7 +135,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: capability1Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{capability1},
Rules: []Rule{capability1},
}},
},
},
@ -144,7 +144,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: network1Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{network1},
Rules: []Rule{network1},
}},
},
},
@ -153,7 +153,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: mount2Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{mount2},
Rules: []Rule{mount2},
}},
},
},
@ -162,7 +162,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: signal1Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{signal1},
Rules: []Rule{signal1},
}},
},
},
@ -171,7 +171,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: ptrace2Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{ptrace2},
Rules: []Rule{ptrace2},
}},
},
},
@ -180,7 +180,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: unix1Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{unix1},
Rules: []Rule{unix1},
}},
},
},
@ -189,7 +189,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: dbus2Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{dbus2},
Rules: []Rule{dbus2},
}},
},
},
@ -198,7 +198,7 @@ func TestAppArmorProfile_AddRule(t *testing.T) {
log: file2Log,
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{file2},
Rules: []Rule{file2},
}},
},
},
@ -224,7 +224,7 @@ func TestAppArmorProfile_Sort(t *testing.T) {
name: "all",
origin: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{
Rules: []Rule{
file2, network1, includeLocal1, dbus2, signal1, ptrace1,
capability2, file1, dbus1, unix2, signal2, mount2,
},
@ -232,7 +232,7 @@ func TestAppArmorProfile_Sort(t *testing.T) {
},
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{
Rules: []Rule{
capability2, network1, mount2, signal1, signal2, ptrace1,
unix2, dbus2, dbus1, file1, file2, includeLocal1,
},
@ -261,12 +261,12 @@ func TestAppArmorProfile_MergeRules(t *testing.T) {
name: "all",
origin: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{capability1, capability1, network1, network1, file1, file1},
Rules: []Rule{capability1, capability1, network1, network1, file1, file1},
}},
},
want: &AppArmorProfileFile{
Profiles: []*Profile{{
Rules: []ApparmorRule{capability1, network1, file1},
Rules: []Rule{capability1, network1, file1},
}},
},
},

View file

@ -5,14 +5,14 @@
package aa
type Capability struct {
Rule
RuleBase
Qualifier
Name string
}
func newCapabilityFromLog(log map[string]string) *Capability {
func newCapabilityFromLog(log map[string]string) Rule {
return &Capability{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Name: log["capname"],
}

View file

@ -5,16 +5,16 @@
package aa
type ChangeProfile struct {
Rule
RuleBase
Qualifier
ExecMode string
Exec string
ProfileName string
}
func newChangeProfileFromLog(log map[string]string) *ChangeProfile {
func newChangeProfileFromLog(log map[string]string) Rule {
return &ChangeProfile{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
ExecMode: log["mode"],
Exec: log["exec"],

View file

@ -71,13 +71,13 @@ var (
"flags": "rw, rbind",
}
mount1 = &Mount{
Rule: Rule{Comment: "failed perms check"},
RuleBase: RuleBase{Comment: "failed perms check"},
MountConditions: MountConditions{FsType: "overlay"},
Source: "overlay",
MountPoint: "/var/lib/docker/overlay2/opaque-bug-check1209538631/merged/",
}
mount2 = &Mount{
Rule: Rule{Comment: "failed perms check"},
RuleBase: RuleBase{Comment: "failed perms check"},
MountConditions: MountConditions{Options: []string{"rw", "rbind"}},
Source: "/oldroot/dev/tty",
MountPoint: "/newroot/dev/tty",
@ -205,9 +205,9 @@ var (
PeerLabel: "dbus-daemon",
}
unix2 = &Unix{
Rule: Rule{FileInherit: true},
Access: "receive",
Type: "stream",
RuleBase: RuleBase{FileInherit: true},
Access: "receive",
Type: "stream",
}
// Dbus
@ -285,9 +285,9 @@ var (
}
file1 = &File{Path: "/usr/share/poppler/cMap/Identity-H", Access: "r"}
file2 = &File{
Rule: Rule{NoNewPrivs: true},
Owner: true,
Path: "@{PROC}/4163/cgroup",
Access: "r",
RuleBase: RuleBase{NoNewPrivs: true},
Owner: true,
Path: "@{PROC}/4163/cgroup",
Access: "r",
}
)

View file

@ -5,7 +5,7 @@
package aa
type Dbus struct {
Rule
RuleBase
Qualifier
Access string
Bus string
@ -17,7 +17,7 @@ type Dbus struct {
PeerLabel string
}
func newDbusFromLog(log map[string]string) *Dbus {
func newDbusFromLog(log map[string]string) Rule {
name := ""
peerName := ""
if log["mask"] == "bind" {
@ -26,7 +26,7 @@ func newDbusFromLog(log map[string]string) *Dbus {
peerName = log["name"]
}
return &Dbus{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: log["mask"],
Bus: log["bus"],

View file

@ -5,7 +5,7 @@
package aa
type File struct {
Rule
RuleBase
Qualifier
Owner bool
Path string
@ -13,7 +13,7 @@ type File struct {
Target string
}
func newFileFromLog(log map[string]string) *File {
func newFileFromLog(log map[string]string) Rule {
owner := false
fsuid, hasFsUID := log["fsuid"]
ouid, hasOuUID := log["ouid"]
@ -22,7 +22,7 @@ func newFileFromLog(log map[string]string) *File {
owner = true
}
return &File{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Owner: owner,
Path: log["name"],

View file

@ -5,15 +5,15 @@
package aa
type IOUring struct {
Rule
RuleBase
Qualifier
Access string
Label string
}
func newIOUringFromLog(log map[string]string) *IOUring {
func newIOUringFromLog(log map[string]string) Rule {
return &IOUring{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: toAccess(log["requested"]),
Label: log["label"],

View file

@ -37,16 +37,16 @@ func (m MountConditions) Equals(other MountConditions) bool {
}
type Mount struct {
Rule
RuleBase
Qualifier
MountConditions
Source string
MountPoint string
}
func newMountFromLog(log map[string]string) *Mount {
func newMountFromLog(log map[string]string) Rule {
return &Mount{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
MountConditions: newMountConditionsFromLog(log),
Source: log["srcname"],
@ -76,15 +76,15 @@ func (r *Mount) Equals(other any) bool {
}
type Umount struct {
Rule
RuleBase
Qualifier
MountConditions
MountPoint string
}
func newUmountFromLog(log map[string]string) *Umount {
func newUmountFromLog(log map[string]string) Rule {
return &Umount{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
MountConditions: newMountConditionsFromLog(log),
MountPoint: log["name"],
@ -110,15 +110,15 @@ func (r *Umount) Equals(other any) bool {
}
type Remount struct {
Rule
RuleBase
Qualifier
MountConditions
MountPoint string
}
func newRemountFromLog(log map[string]string) *Remount {
func newRemountFromLog(log map[string]string) Rule {
return &Remount{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
MountConditions: newMountConditionsFromLog(log),
MountPoint: log["name"],

View file

@ -9,7 +9,7 @@ import (
)
type Mqueue struct {
Rule
RuleBase
Qualifier
Access string
Type string
@ -17,7 +17,7 @@ type Mqueue struct {
Name string
}
func newMqueueFromLog(log map[string]string) *Mqueue {
func newMqueueFromLog(log map[string]string) Rule {
mqueueType := "posix"
if strings.Contains(log["class"], "posix") {
mqueueType = "posix"
@ -25,7 +25,7 @@ func newMqueueFromLog(log map[string]string) *Mqueue {
mqueueType = "sysv"
}
return &Mqueue{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: toAccess(log["requested"]),
Type: mqueueType,

View file

@ -34,7 +34,7 @@ func (r AddressExpr) Equals(other AddressExpr) bool {
}
type Network struct {
Rule
RuleBase
Qualifier
AddressExpr
Domain string
@ -42,9 +42,9 @@ type Network struct {
Protocol string
}
func newNetworkFromLog(log map[string]string) *Network {
func newNetworkFromLog(log map[string]string) Rule {
return &Network{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
AddressExpr: newAddressExprFromLog(log),
Domain: log["family"],

View file

@ -5,16 +5,16 @@
package aa
type PivotRoot struct {
Rule
RuleBase
Qualifier
OldRoot string
NewRoot string
TargetProfile string
}
func newPivotRootFromLog(log map[string]string) *PivotRoot {
func newPivotRootFromLog(log map[string]string) Rule {
return &PivotRoot{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
OldRoot: log["srcname"],
NewRoot: log["name"],

View file

@ -9,7 +9,7 @@ import (
)
type Abi struct {
Rule
RuleBase
Path string
IsMagic bool
}
@ -28,7 +28,7 @@ func (r *Abi) Equals(other any) bool {
}
type Alias struct {
Rule
RuleBase
Path string
RewrittenPath string
}
@ -47,7 +47,7 @@ func (r Alias) Equals(other any) bool {
}
type Include struct {
Rule
RuleBase
IfExists bool
Path string
IsMagic bool
@ -70,18 +70,20 @@ func (r *Include) Equals(other any) bool {
}
type Variable struct {
Rule
RuleBase
Name string
Values []string
}
func (r *Variable) Less(other Variable) bool {
if r.Name != other.Name {
return r.Name < other.Name
func (r *Variable) Less(other any) bool {
o, _ := other.(*Variable)
if r.Name != o.Name {
return r.Name < o.Name
}
return len(r.Values) < len(other.Values)
return len(r.Values) < len(o.Values)
}
func (r *Variable) Equals(other Variable) bool {
return r.Name == other.Name && slices.Equal(r.Values, other.Values)
func (r *Variable) Equals(other any) bool {
o, _ := other.(*Variable)
return r.Name == o.Name && slices.Equal(r.Values, o.Values)
}

View file

@ -12,7 +12,7 @@ import (
// Profile represents a single AppArmor profile.
type Profile struct {
Rule
RuleBase
Header
Rules Rules
}
@ -25,17 +25,17 @@ type Header struct {
Flags []string
}
func (r *Profile) Less(other any) bool {
func (p *Profile) Less(other any) bool {
o, _ := other.(*Profile)
if r.Name != o.Name {
return r.Name < o.Name
if p.Name != o.Name {
return p.Name < o.Name
}
return len(r.Attachments) < len(o.Attachments)
return len(p.Attachments) < len(o.Attachments)
}
func (r *Profile) Equals(other any) bool {
func (p *Profile) Equals(other any) bool {
o, _ := other.(*Profile)
return r.Name == o.Name && slices.Equal(r.Attachments, o.Attachments) &&
maps.Equal(r.Attributes, o.Attributes) &&
slices.Equal(r.Flags, o.Flags)
return p.Name == o.Name && slices.Equal(p.Attachments, o.Attachments) &&
maps.Equal(p.Attributes, o.Attributes) &&
slices.Equal(p.Flags, o.Flags)
}

View file

@ -5,15 +5,15 @@
package aa
type Ptrace struct {
Rule
RuleBase
Qualifier
Access string
Peer string
}
func newPtraceFromLog(log map[string]string) *Ptrace {
func newPtraceFromLog(log map[string]string) Rule {
return &Ptrace{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: toAccess(log["requested_mask"]),
Peer: log["peer"],

View file

@ -5,18 +5,18 @@
package aa
type Rlimit struct {
Rule
RuleBase
Key string
Op string
Value string
}
func newRlimitFromLog(log map[string]string) *Rlimit {
func newRlimitFromLog(log map[string]string) Rule {
return &Rlimit{
Rule: newRuleFromLog(log),
Key: log["key"],
Op: log["op"],
Value: log["value"],
RuleBase: newRuleFromLog(log),
Key: log["key"],
Op: log["op"],
Value: log["value"],
}
}

View file

@ -5,19 +5,18 @@
package aa
import (
"fmt"
"strings"
)
// ApparmorRule generic interface
type ApparmorRule interface {
// Rule generic interface for all AppArmor rules
type Rule interface {
Less(other any) bool
Equals(other any) bool
}
type Rules []ApparmorRule
type Rules []Rule
type Rule struct {
type RuleBase struct {
Comment string
NoNewPrivs bool
FileInherit bool
@ -26,7 +25,7 @@ type Rule struct {
Optional bool
}
func newRuleFromLog(log map[string]string) Rule {
func newRuleFromLog(log map[string]string) RuleBase {
fileInherit := false
if log["operation"] == "file_inherit" {
fileInherit = true
@ -54,7 +53,7 @@ func newRuleFromLog(log map[string]string) Rule {
default:
}
return Rule{
return RuleBase{
Comment: msg,
NoNewPrivs: noNewPrivs,
FileInherit: fileInherit,
@ -62,11 +61,11 @@ func newRuleFromLog(log map[string]string) Rule {
}
}
func (r Rule) Less(other any) bool {
func (r RuleBase) Less(other any) bool {
return false
}
func (r Rule) Equals(other any) bool {
func (r RuleBase) Equals(other any) bool {
return false
}
@ -95,7 +94,7 @@ func (r Qualifier) Equals(other Qualifier) bool {
}
type All struct {
Rule
RuleBase
}
func (r *All) Less(other any) bool {

View file

@ -12,105 +12,81 @@ import (
func TestRule_FromLog(t *testing.T) {
tests := []struct {
name string
fromLog func(map[string]string) ApparmorRule
fromLog func(map[string]string) Rule
log map[string]string
want ApparmorRule
want Rule
}{
{
name: "capbability",
fromLog: func(m map[string]string) ApparmorRule {
return newCapabilityFromLog(m)
},
log: capability1Log,
want: capability1,
name: "capbability",
fromLog: newCapabilityFromLog,
log: capability1Log,
want: capability1,
},
{
name: "network",
fromLog: func(m map[string]string) ApparmorRule {
return newNetworkFromLog(m)
},
log: network1Log,
want: network1,
name: "network",
fromLog: newNetworkFromLog,
log: network1Log,
want: network1,
},
{
name: "mount",
fromLog: func(m map[string]string) ApparmorRule {
return newMountFromLog(m)
},
log: mount1Log,
want: mount1,
name: "mount",
fromLog: newMountFromLog,
log: mount1Log,
want: mount1,
},
{
name: "umount",
fromLog: func(m map[string]string) ApparmorRule {
return newUmountFromLog(m)
},
log: umount1Log,
want: umount1,
name: "umount",
fromLog: newUmountFromLog,
log: umount1Log,
want: umount1,
},
{
name: "pivotroot",
fromLog: func(m map[string]string) ApparmorRule {
return newPivotRootFromLog(m)
},
log: pivotroot1Log,
want: pivotroot1,
name: "pivotroot",
fromLog: newPivotRootFromLog,
log: pivotroot1Log,
want: pivotroot1,
},
{
name: "changeprofile",
fromLog: func(m map[string]string) ApparmorRule {
return newChangeProfileFromLog(m)
},
log: changeprofile1Log,
want: changeprofile1,
name: "changeprofile",
fromLog: newChangeProfileFromLog,
log: changeprofile1Log,
want: changeprofile1,
},
{
name: "signal",
fromLog: func(m map[string]string) ApparmorRule {
return newSignalFromLog(m)
},
log: signal1Log,
want: signal1,
name: "signal",
fromLog: newSignalFromLog,
log: signal1Log,
want: signal1,
},
{
name: "ptrace/xdg-document-portal",
fromLog: func(m map[string]string) ApparmorRule {
return newPtraceFromLog(m)
},
log: ptrace1Log,
want: ptrace1,
name: "ptrace/xdg-document-portal",
fromLog: newPtraceFromLog,
log: ptrace1Log,
want: ptrace1,
},
{
name: "ptrace/snap-update-ns.firefox",
fromLog: func(m map[string]string) ApparmorRule {
return newPtraceFromLog(m)
},
log: ptrace2Log,
want: ptrace2,
name: "ptrace/snap-update-ns.firefox",
fromLog: newPtraceFromLog,
log: ptrace2Log,
want: ptrace2,
},
{
name: "unix",
fromLog: func(m map[string]string) ApparmorRule {
return newUnixFromLog(m)
},
log: unix1Log,
want: unix1,
name: "unix",
fromLog: newUnixFromLog,
log: unix1Log,
want: unix1,
},
{
name: "dbus",
fromLog: func(m map[string]string) ApparmorRule {
return newDbusFromLog(m)
},
log: dbus1Log,
want: dbus1,
name: "dbus",
fromLog: newDbusFromLog,
log: dbus1Log,
want: dbus1,
},
{
name: "file",
fromLog: func(m map[string]string) ApparmorRule {
return newFileFromLog(m)
},
log: file1Log,
want: file1,
name: "file",
fromLog: newFileFromLog,
log: file1Log,
want: file1,
},
}
for _, tt := range tests {
@ -125,8 +101,8 @@ func TestRule_FromLog(t *testing.T) {
func TestRule_Less(t *testing.T) {
tests := []struct {
name string
rule ApparmorRule
other ApparmorRule
rule Rule
other Rule
want bool
}{
{
@ -299,8 +275,8 @@ func TestRule_Less(t *testing.T) {
func TestRule_Equals(t *testing.T) {
tests := []struct {
name string
rule ApparmorRule
other ApparmorRule
rule Rule
other Rule
want bool
}{
{

View file

@ -5,16 +5,16 @@
package aa
type Signal struct {
Rule
RuleBase
Qualifier
Access string
Set string
Peer string
}
func newSignalFromLog(log map[string]string) *Signal {
func newSignalFromLog(log map[string]string) Rule {
return &Signal{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: toAccess(log["requested_mask"]),
Set: log["signal"],

View file

@ -5,7 +5,7 @@
package aa
type Unix struct {
Rule
RuleBase
Qualifier
Access string
Type string
@ -18,9 +18,9 @@ type Unix struct {
PeerAddr string
}
func newUnixFromLog(log map[string]string) *Unix {
func newUnixFromLog(log map[string]string) Rule {
return &Unix{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Access: toAccess(log["requested_mask"]),
Type: log["sock_type"],

View file

@ -5,14 +5,14 @@
package aa
type Userns struct {
Rule
RuleBase
Qualifier
Create bool
}
func newUsernsFromLog(log map[string]string) *Userns {
func newUsernsFromLog(log map[string]string) Rule {
return &Userns{
Rule: newRuleFromLog(log),
RuleBase: newRuleFromLog(log),
Qualifier: newQualifierFromLog(log),
Create: true,
}

View file

@ -303,13 +303,13 @@ func TestAppArmorLogs_ParseToProfiles(t *testing.T) {
Header: aa.Header{Name: "kmod"},
Rules: aa.Rules{
&aa.Unix{
Rule: aa.Rule{FileInherit: true},
RuleBase: aa.RuleBase{FileInherit: true},
Access: "send receive",
Type: "stream",
Protocol: "0",
},
&aa.Unix{
Rule: aa.Rule{FileInherit: true},
RuleBase: aa.RuleBase{FileInherit: true},
Access: "send receive",
Type: "stream",
Protocol: "0",