2023-08-18 00:36:46 +02:00
|
|
|
// apparmor.d - Full set of apparmor profiles
|
2024-02-07 00:16:21 +01:00
|
|
|
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
2023-08-18 00:36:46 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
|
|
|
|
package aa
|
|
|
|
|
|
|
|
import (
|
2023-09-25 01:28:28 +02:00
|
|
|
"reflect"
|
2023-08-18 00:36:46 +02:00
|
|
|
"testing"
|
2023-09-25 01:28:28 +02:00
|
|
|
|
|
|
|
"github.com/arduino/go-paths-helper"
|
2024-04-23 22:38:52 +02:00
|
|
|
"github.com/roddhjav/apparmor.d/pkg/util"
|
2023-08-18 00:36:46 +02:00
|
|
|
)
|
|
|
|
|
2024-04-23 22:38:52 +02:00
|
|
|
var (
|
|
|
|
testData = paths.New("../../").Join("tests")
|
|
|
|
intData = paths.New("../../").Join("apparmor.d")
|
|
|
|
)
|
2023-09-25 01:28:28 +02:00
|
|
|
|
2024-04-23 22:35:23 +02:00
|
|
|
func TestAppArmorProfileFile_String(t *testing.T) {
|
2023-08-18 00:36:46 +02:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-04-16 22:51:56 +02:00
|
|
|
f *AppArmorProfileFile
|
2023-08-18 00:36:46 +02:00
|
|
|
want string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "empty",
|
2024-04-16 22:51:56 +02:00
|
|
|
f: &AppArmorProfileFile{},
|
2024-02-24 18:01:03 +01:00
|
|
|
want: ``,
|
2023-08-18 00:36:46 +02:00
|
|
|
},
|
2023-09-25 01:28:28 +02:00
|
|
|
{
|
|
|
|
name: "foo",
|
2024-04-16 22:51:56 +02:00
|
|
|
f: &AppArmorProfileFile{
|
2023-09-25 01:28:28 +02:00
|
|
|
Preamble: Preamble{
|
2024-04-15 00:58:34 +02:00
|
|
|
Abi: []*Abi{{IsMagic: true, Path: "abi/4.0"}},
|
|
|
|
Includes: []*Include{{IsMagic: true, Path: "tunables/global"}},
|
|
|
|
Aliases: []*Alias{{Path: "/mnt/usr", RewrittenPath: "/usr"}},
|
|
|
|
Variables: []*Variable{{
|
2024-04-23 22:18:44 +02:00
|
|
|
Name: "exec_path", Define: true,
|
2023-10-01 20:04:43 +02:00
|
|
|
Values: []string{"@{bin}/foo", "@{lib}/foo"},
|
|
|
|
}},
|
2024-04-23 22:38:52 +02:00
|
|
|
Comments: []*RuleBase{{Comment: "Simple test profile for the AppArmorProfileFile.String() method", IsLineRule: true}},
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
|
|
|
Header: Header{
|
|
|
|
Name: "foo",
|
|
|
|
Attachments: []string{"@{exec_path}"},
|
|
|
|
Attributes: map[string]string{"security.tagged": "allowed"},
|
|
|
|
Flags: []string{"complain", "attach_disconnected"},
|
|
|
|
},
|
2024-04-19 23:43:02 +02:00
|
|
|
Rules: []Rule{
|
2023-10-01 20:04:43 +02:00
|
|
|
&Include{IsMagic: true, Path: "abstractions/base"},
|
|
|
|
&Include{IsMagic: true, Path: "abstractions/nameservice-strict"},
|
|
|
|
rlimit1,
|
2024-04-23 22:17:25 +02:00
|
|
|
&Capability{Names: []string{"dac_read_search"}},
|
|
|
|
&Capability{Names: []string{"dac_override"}},
|
2023-10-01 20:04:43 +02:00
|
|
|
&Network{Domain: "inet", Type: "stream"},
|
|
|
|
&Network{Domain: "inet6", Type: "stream"},
|
2023-09-25 01:28:28 +02:00
|
|
|
&Mount{
|
2024-04-23 22:38:52 +02:00
|
|
|
RuleBase: RuleBase{Comment: "failed perms check"},
|
2023-09-25 01:28:28 +02:00
|
|
|
MountConditions: MountConditions{
|
|
|
|
FsType: "fuse.portal",
|
|
|
|
Options: []string{"rw", "rbind"},
|
|
|
|
},
|
2024-04-23 22:38:52 +02:00
|
|
|
Source: "@{run}/user/@{uid}/",
|
2023-09-25 01:28:28 +02:00
|
|
|
MountPoint: "/",
|
|
|
|
},
|
|
|
|
&Umount{
|
|
|
|
MountConditions: MountConditions{},
|
|
|
|
MountPoint: "@{run}/user/@{uid}/",
|
|
|
|
},
|
|
|
|
&Signal{
|
2024-04-23 22:17:25 +02:00
|
|
|
Access: []string{"receive"},
|
|
|
|
Set: []string{"term"},
|
2023-09-25 01:28:28 +02:00
|
|
|
Peer: "at-spi-bus-launcher",
|
|
|
|
},
|
2024-04-23 22:17:25 +02:00
|
|
|
&Ptrace{Access: []string{"read"}, Peer: "nautilus"},
|
2023-09-25 01:28:28 +02:00
|
|
|
&Unix{
|
2024-04-23 22:17:25 +02:00
|
|
|
Access: []string{"send", "receive"},
|
2024-04-15 00:58:34 +02:00
|
|
|
Type: "stream",
|
|
|
|
Address: "@/tmp/.ICE-unix/1995",
|
|
|
|
PeerLabel: "gnome-shell",
|
|
|
|
PeerAddr: "none",
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
|
|
|
&Dbus{
|
2024-04-23 22:17:25 +02:00
|
|
|
Access: []string{"bind"},
|
2023-09-25 01:28:28 +02:00
|
|
|
Bus: "session",
|
|
|
|
Name: "org.gnome.*",
|
|
|
|
},
|
|
|
|
&Dbus{
|
2024-04-23 22:17:25 +02:00
|
|
|
Access: []string{"receive"},
|
2023-09-25 01:28:28 +02:00
|
|
|
Bus: "system",
|
|
|
|
Path: "/org/freedesktop/DBus",
|
|
|
|
Interface: "org.freedesktop.DBus",
|
|
|
|
Member: "AddMatch",
|
2024-04-15 00:58:34 +02:00
|
|
|
PeerName: ":1.3",
|
|
|
|
PeerLabel: "power-profiles-daemon",
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
2024-04-23 22:17:25 +02:00
|
|
|
&File{Path: "/opt/intel/oneapi/compiler/*/linux/lib/*.so./*", Access: []string{"r", "m"}},
|
|
|
|
&File{Path: "@{PROC}/@{pid}/task/@{tid}/comm", Access: []string{"r", "w"}},
|
|
|
|
&File{Path: "@{sys}/devices/@{pci}/class", Access: []string{"r"}},
|
2023-09-30 14:55:56 +02:00
|
|
|
includeLocal1,
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
2024-04-23 22:38:52 +02:00
|
|
|
want: util.MustReadFile(testData.Join("string.aa")),
|
2023-09-25 01:28:28 +02:00
|
|
|
},
|
2023-08-18 00:36:46 +02:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2024-04-16 22:51:56 +02:00
|
|
|
if got := tt.f.String(); got != tt.want {
|
2023-09-25 01:22:41 +02:00
|
|
|
t.Errorf("AppArmorProfile.String() = |%v|, want |%v|", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-23 22:35:23 +02:00
|
|
|
func TestAppArmorProfileFile_Sort(t *testing.T) {
|
2023-09-25 01:22:41 +02:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-04-16 22:51:56 +02:00
|
|
|
origin *AppArmorProfileFile
|
|
|
|
want *AppArmorProfileFile
|
2023-09-25 01:22:41 +02:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "all",
|
2024-04-16 22:51:56 +02:00
|
|
|
origin: &AppArmorProfileFile{
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
2024-04-19 23:43:02 +02:00
|
|
|
Rules: []Rule{
|
2023-09-30 14:55:56 +02:00
|
|
|
file2, network1, includeLocal1, dbus2, signal1, ptrace1,
|
|
|
|
capability2, file1, dbus1, unix2, signal2, mount2,
|
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-09-25 01:22:41 +02:00
|
|
|
},
|
2024-04-16 22:51:56 +02:00
|
|
|
want: &AppArmorProfileFile{
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
2024-04-19 23:43:02 +02:00
|
|
|
Rules: []Rule{
|
2023-09-30 14:55:56 +02:00
|
|
|
capability2, network1, mount2, signal1, signal2, ptrace1,
|
|
|
|
unix2, dbus2, dbus1, file1, file2, includeLocal1,
|
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-09-25 01:22:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-23 22:35:23 +02:00
|
|
|
func TestAppArmorProfileFile_MergeRules(t *testing.T) {
|
2023-09-25 01:22:41 +02:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-04-16 22:51:56 +02:00
|
|
|
origin *AppArmorProfileFile
|
|
|
|
want *AppArmorProfileFile
|
2023-09-25 01:22:41 +02:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "all",
|
2024-04-16 22:51:56 +02:00
|
|
|
origin: &AppArmorProfileFile{
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
2024-04-19 23:43:02 +02:00
|
|
|
Rules: []Rule{capability1, capability1, network1, network1, file1, file1},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-09-25 01:22:41 +02:00
|
|
|
},
|
2024-04-16 22:51:56 +02:00
|
|
|
want: &AppArmorProfileFile{
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
2024-04-19 23:43:02 +02:00
|
|
|
Rules: []Rule{capability1, network1, file1},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-09-25 01:22:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
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)
|
2023-08-18 00:36:46 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-10-01 20:03:12 +02:00
|
|
|
|
2024-04-23 22:35:23 +02:00
|
|
|
func TestAppArmorProfileFile_Integration(t *testing.T) {
|
2023-10-01 20:03:12 +02:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-04-16 22:51:56 +02:00
|
|
|
f *AppArmorProfileFile
|
2023-10-01 20:03:12 +02:00
|
|
|
want string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "aa-status",
|
2024-04-16 22:51:56 +02:00
|
|
|
f: &AppArmorProfileFile{
|
2023-10-01 20:03:12 +02:00
|
|
|
Preamble: Preamble{
|
2024-04-15 00:58:34 +02:00
|
|
|
Abi: []*Abi{{IsMagic: true, Path: "abi/3.0"}},
|
|
|
|
Includes: []*Include{{IsMagic: true, Path: "tunables/global"}},
|
|
|
|
Variables: []*Variable{{
|
2024-04-23 22:38:52 +02:00
|
|
|
Name: "exec_path", Define: true,
|
2023-10-01 20:03:12 +02:00
|
|
|
Values: []string{"@{bin}/aa-status", "@{bin}/apparmor_status"},
|
|
|
|
}},
|
2024-04-23 22:38:52 +02:00
|
|
|
Comments: []*RuleBase{
|
|
|
|
{Comment: "apparmor.d - Full set of apparmor profiles", IsLineRule: true},
|
|
|
|
{Comment: "Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>", IsLineRule: true},
|
|
|
|
{Comment: "SPDX-License-Identifier: GPL-2.0-only", IsLineRule: true},
|
|
|
|
},
|
2023-10-01 20:03:12 +02:00
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
Profiles: []*Profile{{
|
|
|
|
Header: Header{
|
|
|
|
Name: "aa-status",
|
|
|
|
Attachments: []string{"@{exec_path}"},
|
|
|
|
},
|
2023-10-01 20:03:12 +02:00
|
|
|
Rules: Rules{
|
|
|
|
&Include{IfExists: true, IsMagic: true, Path: "local/aa-status"},
|
2024-04-23 22:17:25 +02:00
|
|
|
&Capability{Names: []string{"dac_read_search"}},
|
|
|
|
&File{Path: "@{exec_path}", Access: []string{"m", "r"}},
|
|
|
|
&File{Path: "@{PROC}/@{pids}/attr/apparmor/current", Access: []string{"r"}},
|
|
|
|
&File{Path: "@{PROC}/", Access: []string{"r"}},
|
|
|
|
&File{Path: "@{sys}/module/apparmor/parameters/enabled", Access: []string{"r"}},
|
|
|
|
&File{Path: "@{sys}/kernel/security/apparmor/profiles", Access: []string{"r"}},
|
|
|
|
&File{Path: "@{PROC}/@{pids}/attr/current", Access: []string{"r"}},
|
2023-10-01 20:03:12 +02:00
|
|
|
&Include{IsMagic: true, Path: "abstractions/consoles"},
|
2024-04-23 22:17:25 +02:00
|
|
|
&File{Owner: true, Path: "@{PROC}/@{pid}/mounts", Access: []string{"r"}},
|
2023-10-01 20:03:12 +02:00
|
|
|
&Include{IsMagic: true, Path: "abstractions/base"},
|
2024-04-23 22:17:25 +02:00
|
|
|
&File{Path: "/dev/tty@{int}", Access: []string{"r", "w"}},
|
|
|
|
&Capability{Names: []string{"sys_ptrace"}},
|
|
|
|
&Ptrace{Access: []string{"read"}},
|
2023-10-01 20:03:12 +02:00
|
|
|
},
|
2024-04-15 15:09:04 +02:00
|
|
|
}},
|
2023-10-01 20:03:12 +02:00
|
|
|
},
|
2024-04-23 22:38:52 +02:00
|
|
|
want: util.MustReadFile(intData.Join("profiles-a-f/aa-status")),
|
2023-10-01 20:03:12 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2024-04-16 22:51:56 +02:00
|
|
|
tt.f.Sort()
|
|
|
|
tt.f.MergeRules()
|
|
|
|
tt.f.Format()
|
2024-04-23 22:38:52 +02:00
|
|
|
if got := tt.f.String(); got != tt.want {
|
|
|
|
t.Errorf("AppArmorProfile = |%v|, want |%v|", got, tt.want)
|
2023-10-01 20:03:12 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|