mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2025-02-20 08:55:34 +01:00
feat(build): rewrite the dbus directive fot the new format.
This commit is contained in:
parent
b32ee4a5a9
commit
99e386705f
3 changed files with 325 additions and 0 deletions
|
@ -61,3 +61,32 @@ func TestNewOption(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
file *paths.Path
|
||||
profile string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
file: nil,
|
||||
profile: ` `,
|
||||
want: ` `,
|
||||
},
|
||||
{
|
||||
name: "present",
|
||||
file: nil,
|
||||
profile: ` #aa:dbus own bus=system name=org.freedesktop.systemd1`,
|
||||
want: dbusOwnSystemd1,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Run(tt.file, tt.profile); got != tt.want {
|
||||
t.Errorf("Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
154
pkg/prebuild/directive/dbus.go
Normal file
154
pkg/prebuild/directive/dbus.go
Normal file
|
@ -0,0 +1,154 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
// Dbus directive
|
||||
//
|
||||
// Example of supported directive:
|
||||
// #aa:dbus own bus=session name=org.freedesktop.FileManager1
|
||||
// #aa:dbus talk name=org.freedesktop.login1 label=systemd-logind
|
||||
//
|
||||
// See https://apparmor.pujol.io/development/dbus/#dbus-directive
|
||||
//
|
||||
|
||||
package directive
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/roddhjav/apparmor.d/pkg/aa"
|
||||
)
|
||||
|
||||
var defaultInterfaces = []string{
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"org.freedesktop.DBus.ObjectManager",
|
||||
}
|
||||
|
||||
type Dbus struct {
|
||||
DirectiveBase
|
||||
}
|
||||
|
||||
func init() {
|
||||
Directives["dbus"] = &Dbus{
|
||||
DirectiveBase: DirectiveBase{
|
||||
message: "Dbus directive applied",
|
||||
usage: `#aa:dbus own bus=(system | session) name=<interface>
|
||||
#aa:dbus talk bus=(system | session) name=<interface> label=<profile_name>`,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setInterfaces(rules map[string]string) []string {
|
||||
interfaces := []string{rules["name"]}
|
||||
if _, present := rules["interface"]; present {
|
||||
interfaces = append(interfaces, rules["interface"])
|
||||
}
|
||||
interfaces = append(interfaces, defaultInterfaces...)
|
||||
return interfaces
|
||||
}
|
||||
|
||||
func (d Dbus) Apply(opt *Option, profile string) string {
|
||||
var p *aa.AppArmorProfile
|
||||
var action string
|
||||
if _, ok := opt.Args["own"]; ok {
|
||||
action = "own"
|
||||
} else if _, ok := opt.Args["talk"]; ok {
|
||||
action = "talk"
|
||||
} else {
|
||||
panic(fmt.Sprintf("Unknown dbus action: %s in %s", opt.Name, opt.File))
|
||||
}
|
||||
|
||||
d.sanityCheck(action, opt)
|
||||
switch action {
|
||||
case "own":
|
||||
p = d.own(opt.Args)
|
||||
case "talk":
|
||||
p = d.talk(opt.Args)
|
||||
}
|
||||
|
||||
generatedDbus := p.String()
|
||||
lenDbus := len(generatedDbus)
|
||||
generatedDbus = generatedDbus[:lenDbus-1]
|
||||
profile = strings.Replace(profile, opt.Raw, generatedDbus, -1)
|
||||
return profile
|
||||
}
|
||||
|
||||
func (d Dbus) sanityCheck(action string, opt *Option) {
|
||||
if _, present := opt.Args["name"]; !present {
|
||||
panic(fmt.Sprintf("Missing name for 'dbus: %s' in %s", action, opt.File))
|
||||
}
|
||||
if _, present := opt.Args["bus"]; !present {
|
||||
panic(fmt.Sprintf("Missing bus for '%s' in %s", opt.Args["name"], opt.File))
|
||||
}
|
||||
if _, present := opt.Args["label"]; !present && action == "talk" {
|
||||
panic(fmt.Sprintf("Missing label for '%s' in %s", opt.Args["name"], opt.File))
|
||||
}
|
||||
|
||||
// Set default values
|
||||
if _, present := opt.Args["path"]; !present {
|
||||
opt.Args["path"] = "/" + strings.Replace(opt.Args["name"], ".", "/", -1) + "{,/**}"
|
||||
}
|
||||
opt.Args["name"] += "{,.*}"
|
||||
}
|
||||
|
||||
func (d Dbus) own(rules map[string]string) *aa.AppArmorProfile {
|
||||
interfaces := setInterfaces(rules)
|
||||
p := &aa.AppArmorProfile{}
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "bind", Bus: rules["bus"], Name: rules["name"],
|
||||
})
|
||||
for _, iface := range interfaces {
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "receive",
|
||||
Bus: rules["bus"],
|
||||
Path: rules["path"],
|
||||
Interface: iface,
|
||||
Name: `":1.@{int}"`,
|
||||
})
|
||||
}
|
||||
for _, iface := range interfaces {
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "send",
|
||||
Bus: rules["bus"],
|
||||
Path: rules["path"],
|
||||
Interface: iface,
|
||||
Name: `"{:1.@{int},org.freedesktop.DBus}"`,
|
||||
})
|
||||
}
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "receive",
|
||||
Bus: rules["bus"],
|
||||
Path: rules["path"],
|
||||
Interface: "org.freedesktop.DBus.Introspectable",
|
||||
Member: "Introspect",
|
||||
Name: `":1.@{int}"`,
|
||||
})
|
||||
return p
|
||||
}
|
||||
|
||||
func (d Dbus) talk(rules map[string]string) *aa.AppArmorProfile {
|
||||
interfaces := setInterfaces(rules)
|
||||
p := &aa.AppArmorProfile{}
|
||||
for _, iface := range interfaces {
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "send",
|
||||
Bus: rules["bus"],
|
||||
Path: rules["path"],
|
||||
Interface: iface,
|
||||
Name: `"{:1.@{int},` + rules["name"] + `}"`,
|
||||
Label: rules["label"],
|
||||
})
|
||||
}
|
||||
for _, iface := range interfaces {
|
||||
p.Rules = append(p.Rules, &aa.Dbus{
|
||||
Access: "receive",
|
||||
Bus: rules["bus"],
|
||||
Path: rules["path"],
|
||||
Interface: iface,
|
||||
Name: `"{:1.@{int},` + rules["name"] + `}"`,
|
||||
Label: rules["label"],
|
||||
})
|
||||
}
|
||||
return p
|
||||
}
|
142
pkg/prebuild/directive/dbus_test.go
Normal file
142
pkg/prebuild/directive/dbus_test.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
// apparmor.d - Full set of apparmor profiles
|
||||
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
package directive
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
const dbusOwnSystemd1 = ` dbus bind bus=system name=org.freedesktop.systemd1{,.*},
|
||||
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.systemd1{,.*}
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus send bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.systemd1{,.*}
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus send bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus send bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
|
||||
interface=org.freedesktop.DBus.Introspectable
|
||||
member=Introspect
|
||||
peer=(name=":1.@{int}"),`
|
||||
|
||||
func TestDbus_Apply(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
opt *Option
|
||||
profile string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "own",
|
||||
opt: &Option{
|
||||
Name: "dbus",
|
||||
Args: map[string]string{
|
||||
"bus": "system",
|
||||
"name": "org.freedesktop.systemd1",
|
||||
"own": "",
|
||||
},
|
||||
File: nil,
|
||||
Raw: " #aa:dbus own bus=system name=org.freedesktop.systemd1",
|
||||
},
|
||||
profile: " #aa:dbus own bus=system name=org.freedesktop.systemd1",
|
||||
want: dbusOwnSystemd1,
|
||||
},
|
||||
{
|
||||
name: "own-interface",
|
||||
opt: &Option{
|
||||
Name: "dbus",
|
||||
Args: map[string]string{
|
||||
"bus": "session",
|
||||
"name": "com.rastersoft.dingextension",
|
||||
"interface": "org.gtk.Actions",
|
||||
"own": "",
|
||||
},
|
||||
File: nil,
|
||||
Raw: " #aa:dbus own bus=session name=com.rastersoft.dingextension interface=org.gtk.Actions",
|
||||
},
|
||||
profile: " #aa:dbus own bus=session name=com.rastersoft.dingextension interface=org.gtk.Actions",
|
||||
want: ` dbus bind bus=session name=com.rastersoft.dingextension{,.*},
|
||||
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=com.rastersoft.dingextension{,.*}
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.gtk.Actions
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name=":1.@{int}"),
|
||||
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=com.rastersoft.dingextension{,.*}
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.gtk.Actions
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
|
||||
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
|
||||
interface=org.freedesktop.DBus.Introspectable
|
||||
member=Introspect
|
||||
peer=(name=":1.@{int}"),`,
|
||||
},
|
||||
{
|
||||
name: "talk",
|
||||
opt: &Option{
|
||||
Name: "dbus",
|
||||
Args: map[string]string{
|
||||
"bus": "system",
|
||||
"name": "org.freedesktop.Accounts",
|
||||
"label": "accounts-daemon",
|
||||
"talk": "",
|
||||
},
|
||||
File: nil,
|
||||
Raw: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon",
|
||||
},
|
||||
profile: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon",
|
||||
want: ` dbus send bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.Accounts{,.*}
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
|
||||
dbus send bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
|
||||
dbus send bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
|
||||
dbus receive bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.Accounts{,.*}
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
|
||||
dbus receive bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.DBus.Properties
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
|
||||
dbus receive bus=system path=/org/freedesktop/Accounts{,/**}
|
||||
interface=org.freedesktop.DBus.ObjectManager
|
||||
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Directives["dbus"].Apply(tt.opt, tt.profile); got != tt.want {
|
||||
t.Errorf("Dbus.Apply() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue