Remove apparmor profile generation from libcontainer
The creation of the profile should be handled outside of libcontainer so that it can be customized and packaged. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
00f6b56903
commit
1865c0aac6
|
@ -12,6 +12,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsEnabled returns true if apparmor is enabled for the host.
|
||||||
func IsEnabled() bool {
|
func IsEnabled() bool {
|
||||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
|
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
|
||||||
if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
|
if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
|
||||||
|
@ -22,13 +23,14 @@ func IsEnabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyProfile will apply the profile with the specified name to the process after
|
||||||
|
// the next exec.
|
||||||
func ApplyProfile(name string) error {
|
func ApplyProfile(name string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cName := C.CString(name)
|
cName := C.CString(name)
|
||||||
defer C.free(unsafe.Pointer(cName))
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
|
||||||
if _, err := C.aa_change_onexec(cName); err != nil {
|
if _, err := C.aa_change_onexec(cName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package apparmor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
type data struct {
|
|
||||||
Name string
|
|
||||||
Imports []string
|
|
||||||
InnerImports []string
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseTemplate = `
|
|
||||||
{{range $value := .Imports}}
|
|
||||||
{{$value}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
|
|
||||||
{{range $value := .InnerImports}}
|
|
||||||
{{$value}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
network,
|
|
||||||
capability,
|
|
||||||
file,
|
|
||||||
umount,
|
|
||||||
|
|
||||||
deny @{PROC}/sys/fs/** wklx,
|
|
||||||
deny @{PROC}/sysrq-trigger rwklx,
|
|
||||||
deny @{PROC}/mem rwklx,
|
|
||||||
deny @{PROC}/kmem rwklx,
|
|
||||||
deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
|
|
||||||
deny @{PROC}/sys/kernel/*/** wklx,
|
|
||||||
|
|
||||||
deny mount,
|
|
||||||
|
|
||||||
deny /sys/[^f]*/** wklx,
|
|
||||||
deny /sys/f[^s]*/** wklx,
|
|
||||||
deny /sys/fs/[^c]*/** wklx,
|
|
||||||
deny /sys/fs/c[^g]*/** wklx,
|
|
||||||
deny /sys/fs/cg[^r]*/** wklx,
|
|
||||||
deny /sys/firmware/efi/efivars/** rwklx,
|
|
||||||
deny /sys/kernel/security/** rwklx,
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
func generateProfile(out io.Writer) error {
|
|
||||||
compiled, err := template.New("apparmor_profile").Parse(baseTemplate)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data := &data{
|
|
||||||
Name: "docker-default",
|
|
||||||
}
|
|
||||||
if tunablesExists() {
|
|
||||||
data.Imports = append(data.Imports, "#include <tunables/global>")
|
|
||||||
} else {
|
|
||||||
data.Imports = append(data.Imports, "@{PROC}=/proc/")
|
|
||||||
}
|
|
||||||
if abstractionsExists() {
|
|
||||||
data.InnerImports = append(data.InnerImports, "#include <abstractions/base>")
|
|
||||||
}
|
|
||||||
if err := compiled.Execute(out, data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the tunables/global exist
|
|
||||||
func tunablesExists() bool {
|
|
||||||
_, err := os.Stat("/etc/apparmor.d/tunables/global")
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if abstractions/base exist
|
|
||||||
func abstractionsExists() bool {
|
|
||||||
_, err := os.Stat("/etc/apparmor.d/abstractions/base")
|
|
||||||
return err == nil
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package apparmor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
DefaultProfilePath = "/etc/apparmor.d/docker"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InstallDefaultProfile() error {
|
|
||||||
if !IsEnabled() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure /etc/apparmor.d exists
|
|
||||||
if err := os.MkdirAll(path.Dir(DefaultProfilePath), 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.OpenFile(DefaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := generateProfile(f); err != nil {
|
|
||||||
f.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
|
|
||||||
cmd := exec.Command("/sbin/apparmor_parser", "-r", "-W", "docker")
|
|
||||||
// to use the parser directly we have to make sure we are in the correct
|
|
||||||
// dir with the profile
|
|
||||||
cmd.Dir = "/etc/apparmor.d"
|
|
||||||
|
|
||||||
output, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error loading docker apparmor profile: %s (%s)", err, output)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in New Issue