Files
moby/daemon/apparmor_profile_linux.go
Aleksa Sarai 7bdd547617 daemon: add ability for custom AppArmor profiles
This is a long-requested feature, and it solves several usability
problems with the default AppArmor profile:

1. The profile is completely opaque because we don't write to
  /etc/apparmor.d anymore -- this leads to lots of headaches when
  trying to run certain semi-privileged programs inside containers.
  It's much nicer to be able to have a starting point for a custom
  AppArmor profile.

2. Changes to AppArmor have broken backwards compatibility in the past
  (leading to containers not working properly) -- the poster-child for
  this problem was signal mediation. In order to fix this problem,
  distributions had to patch Docker when it would've been much nicer
  to provide a hotfix in the form of a custom configuration they could
  apply to their hosts.

It also bridges the feature gap between the default seccomp profile
(which has been configurable for a very long time). This patch also
fixes a few minor bugs in the AppArmor profile implementation (notably,
Docker would not forcefully load its built-in profile at start time --
meaning a Docker update wouldn't actually update the profile).

This feature should probably be ported to other container runtimes
(containerd, podman/cri-o, etc) so that we can continue with the effort
to merge all of the disparate AppArmor profile implementations. Ideally
they would all use the same template variables too.

Signed-off-by: Aleksa Sarai <asarai@suse.de>

---

The above was reapplied from the original commit on top of the current
daemon code.

The daemon already force-loads the default AppArmor profile at startup,
so this change wires the configured template into that existing reload
path instead of introducing the reload behavior itself.

The built-in profile now lives in github.com/moby/profiles/apparmor, so
the custom template data follows the current profile variables.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-08-24 13:13:35 +02:00

30 lines
709 B
Go

//go:build linux
package daemon
import (
"fmt"
"os"
"text/template"
"github.com/moby/moby/v2/daemon/config"
)
func (daemon *Daemon) setupAppArmorProfile(cfg *config.Config) error {
if cfg.AppArmorProfile == "" {
return nil
}
daemon.appArmorProfilePath = cfg.AppArmorProfile
b, err := os.ReadFile(daemon.appArmorProfilePath)
if err != nil {
return fmt.Errorf("opening AppArmor profile (%s) failed: %v", daemon.appArmorProfilePath, err)
}
tmpl, err := template.New("apparmor_profile").Option("missingkey=error").Parse(string(b))
if err != nil {
return fmt.Errorf("parsing AppArmor profile (%s) failed: %v", daemon.appArmorProfilePath, err)
}
daemon.appArmorProfile = tmpl
return nil
}