github.com/ncdc/docker@v0.10.1-0.20160129113957-6c6729ef5b74/profiles/apparmor/apparmor.go (about) 1 // +build linux 2 3 package apparmor 4 5 import ( 6 "bufio" 7 "io" 8 "os" 9 "path" 10 "strings" 11 "text/template" 12 13 "github.com/docker/docker/pkg/aaparser" 14 ) 15 16 var ( 17 // profileDirectory is the file store for apparmor profiles and macros. 18 profileDirectory = "/etc/apparmor.d" 19 // defaultProfilePath is the default path for the apparmor profile to be saved. 20 defaultProfilePath = path.Join(profileDirectory, "docker") 21 ) 22 23 // profileData holds information about the given profile for generation. 24 type profileData struct { 25 // Name is profile name. 26 Name string 27 // ExecPath is the path to the docker binary. 28 ExecPath string 29 // Imports defines the apparmor functions to import, before defining the profile. 30 Imports []string 31 // InnerImports defines the apparmor functions to import in the profile. 32 InnerImports []string 33 // MajorVersion is the apparmor_parser major version. 34 MajorVersion int 35 // MinorVersion is the apparmor_parser minor version. 36 MinorVersion int 37 } 38 39 // generateDefault creates an apparmor profile from ProfileData. 40 func (p *profileData) generateDefault(out io.Writer) error { 41 compiled, err := template.New("apparmor_profile").Parse(baseTemplate) 42 if err != nil { 43 return err 44 } 45 if macroExists("tunables/global") { 46 p.Imports = append(p.Imports, "#include <tunables/global>") 47 } else { 48 p.Imports = append(p.Imports, "@{PROC}=/proc/") 49 } 50 if macroExists("abstractions/base") { 51 p.InnerImports = append(p.InnerImports, "#include <abstractions/base>") 52 } 53 if err := compiled.Execute(out, p); err != nil { 54 return err 55 } 56 return nil 57 } 58 59 // macrosExists checks if the passed macro exists. 60 func macroExists(m string) bool { 61 _, err := os.Stat(path.Join(profileDirectory, m)) 62 return err == nil 63 } 64 65 // InstallDefault generates a default profile and installs it in the 66 // ProfileDirectory with `apparmor_parser`. 67 func InstallDefault(name string) error { 68 // Make sure the path where they want to save the profile exists 69 if err := os.MkdirAll(profileDirectory, 0755); err != nil { 70 return err 71 } 72 73 p := profileData{ 74 Name: name, 75 } 76 77 f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) 78 if err != nil { 79 return err 80 } 81 if err := p.generateDefault(f); err != nil { 82 f.Close() 83 return err 84 } 85 f.Close() 86 87 if err := aaparser.LoadProfile(defaultProfilePath); err != nil { 88 return err 89 } 90 91 return nil 92 } 93 94 // IsLoaded checks if a passed profile as been loaded into the kernel. 95 func IsLoaded(name string) error { 96 file, err := os.Open("/sys/kernel/security/apparmor/profiles") 97 if err != nil { 98 return err 99 } 100 r := bufio.NewReader(file) 101 for { 102 p, err := r.ReadString('\n') 103 if err != nil { 104 return err 105 } 106 if strings.HasPrefix(p, name+" ") { 107 return nil 108 } 109 } 110 }