mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2024-11-15 07:54:17 +01:00
test(aa-log): add unit tests for profile rules.
This commit is contained in:
parent
43981517b2
commit
a5b6373b02
268
pkg/aa/data_test.go
Normal file
268
pkg/aa/data_test.go
Normal file
@ -0,0 +1,268 @@
|
||||
// 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
|
||||
|
||||
var (
|
||||
// Capability
|
||||
capability1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "cap",
|
||||
"operation": "capable",
|
||||
"capname": "net_admin",
|
||||
"capability": "12",
|
||||
"profile": "pkexec",
|
||||
"comm": "pkexec",
|
||||
}
|
||||
capability1 = &Capability{
|
||||
Qualifier: Qualifier{},
|
||||
Name: "net_admin",
|
||||
}
|
||||
capability2 = &Capability{
|
||||
Qualifier: Qualifier{},
|
||||
Name: "sys_ptrace",
|
||||
}
|
||||
|
||||
// Network
|
||||
network1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "net",
|
||||
"operation": "create",
|
||||
"family": "netlink",
|
||||
"profile": "sddm-greeter",
|
||||
"sock_type": "raw",
|
||||
"protocol": "15",
|
||||
"requested_mask": "create",
|
||||
"denied_mask": "create",
|
||||
"comm": "sddm-greeter",
|
||||
}
|
||||
network1 = &Network{
|
||||
Qualifier: Qualifier{},
|
||||
Domain: "netlink",
|
||||
Type: "raw",
|
||||
Protocol: "15",
|
||||
AddressExpr: AddressExpr{},
|
||||
}
|
||||
network2 = &Network{
|
||||
Qualifier: Qualifier{},
|
||||
Domain: "inet",
|
||||
Type: "dgram",
|
||||
Protocol: "",
|
||||
AddressExpr: AddressExpr{},
|
||||
}
|
||||
|
||||
// Mount
|
||||
mount1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "mount",
|
||||
"operation": "mount",
|
||||
"info": "failed perms check",
|
||||
"error": "-13",
|
||||
"profile": "dockerd",
|
||||
"name": "/var/lib/docker/overlay2/opaque-bug-check1209538631/merged/",
|
||||
"comm": "dockerd",
|
||||
"fstype": "overlay",
|
||||
"srcname": "overlay",
|
||||
}
|
||||
mount2Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "mount",
|
||||
"operation": "mount",
|
||||
"info": "failed perms check",
|
||||
"error": "-13",
|
||||
"profile": "dockerd",
|
||||
"name": "/var/lib/docker/overlay2/metacopy-check906831159/merged/",
|
||||
"comm": "dockerd",
|
||||
"fstype": "overlay",
|
||||
"srcname": "overlay",
|
||||
}
|
||||
mount1 = &Mount{
|
||||
Qualifier: Qualifier{},
|
||||
MountConditions: MountConditions{
|
||||
Fs: "",
|
||||
Op: "",
|
||||
FsType: "overlay",
|
||||
Options: []string{},
|
||||
},
|
||||
Source: "overlay",
|
||||
MountPoint: "/var/lib/docker/overlay2/opaque-bug-check1209538631/merged/",
|
||||
}
|
||||
mount2 = &Mount{
|
||||
Qualifier: Qualifier{},
|
||||
MountConditions: MountConditions{
|
||||
Fs: "",
|
||||
Op: "",
|
||||
FsType: "overlay",
|
||||
Options: []string{},
|
||||
},
|
||||
Source: "overlay",
|
||||
MountPoint: "/var/lib/docker/overlay2/metacopy-check906831159/merged/",
|
||||
}
|
||||
|
||||
// Signal
|
||||
signal1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "signal",
|
||||
"profile": "firefox",
|
||||
"operation": "signal",
|
||||
"comm": "49504320492F4F20506172656E74",
|
||||
"requested_mask": "receive",
|
||||
"denied_mask": "receive",
|
||||
"signal": "kill",
|
||||
"peer": "firefox//&firejail-default",
|
||||
}
|
||||
signal1 = &Signal{
|
||||
Qualifier: Qualifier{},
|
||||
Access: "receive",
|
||||
Set: "kill",
|
||||
Peer: "firefox//&firejail-default",
|
||||
}
|
||||
signal2 = &Signal{
|
||||
Qualifier: Qualifier{},
|
||||
Access: "receive",
|
||||
Set: "up",
|
||||
Peer: "firefox//&firejail-default",
|
||||
}
|
||||
|
||||
// Ptrace
|
||||
ptrace1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "ptrace",
|
||||
"profile": "xdg-document-portal",
|
||||
"operation": "ptrace",
|
||||
"comm": "pool-/usr/lib/x",
|
||||
"requested_mask": "read",
|
||||
"denied_mask": "read",
|
||||
"peer": "nautilus",
|
||||
}
|
||||
ptrace2Log = map[string]string{
|
||||
"apparmor": "DENIED",
|
||||
"class": "ptrace",
|
||||
"operation": "ptrace",
|
||||
"comm": "systemd-journal",
|
||||
"requested_mask": "readby",
|
||||
"denied_mask": "readby",
|
||||
"peer": "systemd-journald",
|
||||
}
|
||||
ptrace1 = &Ptrace{
|
||||
Qualifier: Qualifier{},
|
||||
Access: "read",
|
||||
Peer: "nautilus",
|
||||
}
|
||||
ptrace2 = &Ptrace{
|
||||
Qualifier: Qualifier{},
|
||||
Access: "readby",
|
||||
Peer: "systemd-journald",
|
||||
}
|
||||
|
||||
// Unix
|
||||
unix1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"class": "net",
|
||||
"family": "unix",
|
||||
"operation": "file_perm",
|
||||
"profile": "gsettings",
|
||||
"comm": "dbus-daemon",
|
||||
"requested_mask": "send receive",
|
||||
"addr": "none",
|
||||
"peer_addr": "@/tmp/dbus-AaKMpxzC4k",
|
||||
"peer": "dbus-daemon",
|
||||
"denied_mask": "send receive",
|
||||
"sock_type": "stream",
|
||||
"protocol": "0",
|
||||
}
|
||||
unix1 = &Unix{
|
||||
Access: "send receive",
|
||||
Type: "stream",
|
||||
Protocol: "0",
|
||||
Address: "none",
|
||||
Peer: "dbus-daemon",
|
||||
PeerAddr: "@/tmp/dbus-AaKMpxzC4k",
|
||||
}
|
||||
unix2 = &Unix{
|
||||
Qualifier: Qualifier{FileInherit: true},
|
||||
Access: "receive",
|
||||
Type: "stream",
|
||||
}
|
||||
|
||||
// Dbus
|
||||
dbus1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"operation": "dbus_method_call",
|
||||
"bus": "session",
|
||||
"path": "/org/gtk/vfs/metadata",
|
||||
"interface": "org.gtk.vfs.Metadata",
|
||||
"member": "Remove",
|
||||
"name": ":1.15",
|
||||
"mask": "receive",
|
||||
"label": "gvfsd-metadata",
|
||||
"peer_pid": "3888",
|
||||
"peer_label": "tracker-extract",
|
||||
}
|
||||
dbus2Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"operation": "dbus_bind",
|
||||
"bus": "session",
|
||||
"name": "org.gnome.evolution.dataserver.Sources5",
|
||||
"mask": "bind",
|
||||
"pid": "3442",
|
||||
"label": "evolution-source-registry",
|
||||
}
|
||||
dbus1 = &Dbus{
|
||||
Access: "receive",
|
||||
Bus: "session",
|
||||
Name: ":1.15",
|
||||
Path: "/org/gtk/vfs/metadata",
|
||||
Interface: "org.gtk.vfs.Metadata",
|
||||
Member: "Remove",
|
||||
Label: "tracker-extract",
|
||||
}
|
||||
dbus2 = &Dbus{
|
||||
Access: "bind",
|
||||
Bus: "session",
|
||||
Name: "org.gnome.evolution.dataserver.Sources5",
|
||||
}
|
||||
|
||||
// File
|
||||
file1Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"operation": "open",
|
||||
"class": "file",
|
||||
"profile": "cupsd",
|
||||
"name": "/usr/share/poppler/cMap/Identity-H",
|
||||
"comm": "gs",
|
||||
"requested_mask": "r",
|
||||
"denied_mask": "r",
|
||||
"fsuid": "209",
|
||||
"FSUID": "cups",
|
||||
"ouid": "0",
|
||||
"OUID": "root",
|
||||
}
|
||||
file2Log = map[string]string{
|
||||
"apparmor": "ALLOWED",
|
||||
"operation": "open",
|
||||
"class": "file",
|
||||
"profile": "gsd-print-notifications",
|
||||
"name": "/proc/4163/cgroup",
|
||||
"comm": "gsd-print-notif",
|
||||
"requested_mask": "r",
|
||||
"denied_mask": "r",
|
||||
"fsuid": "1000",
|
||||
"FSUID": "user",
|
||||
"ouid": "1000",
|
||||
"OUID": "user",
|
||||
"error": "-1",
|
||||
}
|
||||
file1 = &File{
|
||||
Path: "/usr/share/poppler/cMap/Identity-H",
|
||||
Access: "r",
|
||||
Target: "",
|
||||
}
|
||||
file2 = &File{
|
||||
Qualifier: Qualifier{Owner: true, NoNewPrivs: true},
|
||||
Path: "/proc/4163/cgroup",
|
||||
Access: "r",
|
||||
Target: "",
|
||||
}
|
||||
)
|
@ -25,7 +25,160 @@ func TestAppArmorProfile_String(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.p.String(); got != tt.want {
|
||||
t.Errorf("AppArmorProfile.String() = %v, want %v", got, tt.want)
|
||||
t.Errorf("AppArmorProfile.String() = |%v|, want |%v|", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppArmorProfile_AddRule(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
log map[string]string
|
||||
want *AppArmorProfile
|
||||
}{
|
||||
{
|
||||
name: "capability",
|
||||
log: capability1Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{capability1},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "network",
|
||||
log: network1Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{network1},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mount",
|
||||
log: mount2Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Flags: []string{"attach_disconnected"},
|
||||
Rules: []ApparmorRule{mount2},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "signal",
|
||||
log: signal1Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{signal1},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ptrace",
|
||||
log: ptrace2Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{ptrace2},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unix",
|
||||
log: unix1Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{unix1},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dbus",
|
||||
log: dbus2Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{dbus2},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
log: file2Log,
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{file2},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := NewAppArmorProfile()
|
||||
got.AddRule(tt.log)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppArmorProfile.AddRule() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppArmorProfile_Sort(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
origin *AppArmorProfile
|
||||
want *AppArmorProfile
|
||||
}{
|
||||
{
|
||||
name: "all",
|
||||
origin: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{file2, network1, dbus2, signal1, ptrace1, capability2, file1, dbus1, unix2, signal2, mount2},
|
||||
},
|
||||
},
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{capability2, network1, mount2, signal1, signal2, ptrace1, unix2, dbus2, dbus1, file2, file1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.origin
|
||||
got.Sort()
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppArmorProfile.Sort() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppArmorProfile_MergeRules(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
origin *AppArmorProfile
|
||||
want *AppArmorProfile
|
||||
}{
|
||||
{
|
||||
name: "all",
|
||||
origin: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{capability1, capability1, network1, network1, file1, file1},
|
||||
},
|
||||
},
|
||||
want: &AppArmorProfile{
|
||||
Profile: Profile{
|
||||
Rules: []ApparmorRule{capability1, network1, file1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.origin
|
||||
got.MergeRules()
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppArmorProfile.MergeRules() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
225
pkg/aa/rules_test.go
Normal file
225
pkg/aa/rules_test.go
Normal file
@ -0,0 +1,225 @@
|
||||
// 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
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRule_FromLog(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fromLog func(map[string]string, bool, bool) ApparmorRule
|
||||
log map[string]string
|
||||
want ApparmorRule
|
||||
}{
|
||||
{
|
||||
name: "capbability",
|
||||
fromLog: CapabilityFromLog,
|
||||
log: capability1Log,
|
||||
want: capability1,
|
||||
},
|
||||
{
|
||||
name: "network",
|
||||
fromLog: NetworkFromLog,
|
||||
log: network1Log,
|
||||
want: network1,
|
||||
},
|
||||
{
|
||||
name: "mount",
|
||||
fromLog: MountFromLog,
|
||||
log: mount1Log,
|
||||
want: mount1,
|
||||
},
|
||||
{
|
||||
name: "signal",
|
||||
fromLog: SignalFromLog,
|
||||
log: signal1Log,
|
||||
want: signal1,
|
||||
},
|
||||
{
|
||||
name: "ptrace/xdg-document-portal",
|
||||
fromLog: PtraceFromLog,
|
||||
log: ptrace1Log,
|
||||
want: ptrace1,
|
||||
},
|
||||
{
|
||||
name: "ptrace/snap-update-ns.firefox",
|
||||
fromLog: PtraceFromLog,
|
||||
log: ptrace2Log,
|
||||
want: ptrace2,
|
||||
},
|
||||
{
|
||||
name: "unix",
|
||||
fromLog: UnixFromLog,
|
||||
log: unix1Log,
|
||||
want: unix1,
|
||||
},
|
||||
{
|
||||
name: "dbus",
|
||||
fromLog: DbusFromLog,
|
||||
log: dbus1Log,
|
||||
want: dbus1,
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
fromLog: FileFromLog,
|
||||
log: file1Log,
|
||||
want: file1,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.fromLog(tt.log, false, false); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("RuleFromLog() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRule_Less(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rule ApparmorRule
|
||||
other ApparmorRule
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "capability",
|
||||
rule: capability1,
|
||||
other: capability2,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "network",
|
||||
rule: network1,
|
||||
other: network2,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "mount",
|
||||
rule: mount1,
|
||||
other: mount2,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "signal",
|
||||
rule: signal1,
|
||||
other: signal2,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "ptrace/less",
|
||||
rule: ptrace1,
|
||||
other: ptrace2,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "ptrace/more",
|
||||
rule: ptrace2,
|
||||
other: ptrace1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "unix",
|
||||
rule: unix1,
|
||||
other: unix1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "dbus",
|
||||
rule: dbus1,
|
||||
other: dbus1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
rule: file1,
|
||||
other: file2,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := tt.rule
|
||||
if got := r.Less(tt.other); got != tt.want {
|
||||
t.Errorf("Rule.Less() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRule_Equals(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rule ApparmorRule
|
||||
other ApparmorRule
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "capability/equal",
|
||||
rule: capability1,
|
||||
other: capability1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "network/equal",
|
||||
rule: network1,
|
||||
other: network1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "mount",
|
||||
rule: mount1,
|
||||
other: mount1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "signal1/equal",
|
||||
rule: signal1,
|
||||
other: signal1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "ptrace/equal",
|
||||
rule: ptrace1,
|
||||
other: ptrace1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "ptrace/not_equal",
|
||||
rule: ptrace1,
|
||||
other: ptrace2,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "unix",
|
||||
rule: unix1,
|
||||
other: unix1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "dbus",
|
||||
rule: dbus1,
|
||||
other: dbus2,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
rule: file2,
|
||||
other: file2,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := tt.rule
|
||||
if got := r.Equals(tt.other); got != tt.want {
|
||||
t.Errorf("Rule.Equals() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user