github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/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 12 "github.com/docker/docker/pkg/aaparser" 13 "github.com/docker/docker/utils/templates" 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 // Imports defines the apparmor functions to import, before defining the profile. 28 Imports []string 29 // InnerImports defines the apparmor functions to import in the profile. 30 InnerImports []string 31 // Version is the {major, minor, patch} version of apparmor_parser as a single number. 32 Version int 33 } 34 35 // generateDefault creates an apparmor profile from ProfileData. 36 func (p *profileData) generateDefault(out io.Writer) error { 37 compiled, err := templates.NewParse("apparmor_profile", baseTemplate) 38 if err != nil { 39 return err 40 } 41 42 if macroExists("tunables/global") { 43 p.Imports = append(p.Imports, "#include <tunables/global>") 44 } else { 45 p.Imports = append(p.Imports, "@{PROC}=/proc/") 46 } 47 48 if macroExists("abstractions/base") { 49 p.InnerImports = append(p.InnerImports, "#include <abstractions/base>") 50 } 51 52 ver, err := aaparser.GetVersion() 53 if err != nil { 54 return err 55 } 56 p.Version = ver 57 58 if err := compiled.Execute(out, p); err != nil { 59 return err 60 } 61 return nil 62 } 63 64 // macrosExists checks if the passed macro exists. 65 func macroExists(m string) bool { 66 _, err := os.Stat(path.Join(profileDirectory, m)) 67 return err == nil 68 } 69 70 // InstallDefault generates a default profile and installs it in the 71 // ProfileDirectory with `apparmor_parser`. 72 func InstallDefault(name string) error { 73 // Make sure the path where they want to save the profile exists 74 if err := os.MkdirAll(profileDirectory, 0755); err != nil { 75 return err 76 } 77 78 p := profileData{ 79 Name: name, 80 } 81 82 f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) 83 if err != nil { 84 return err 85 } 86 if err := p.generateDefault(f); err != nil { 87 f.Close() 88 return err 89 } 90 f.Close() 91 92 if err := aaparser.LoadProfile(defaultProfilePath); err != nil { 93 return err 94 } 95 96 return nil 97 } 98 99 // IsLoaded checks if a passed profile has been loaded into the kernel. 100 func IsLoaded(name string) error { 101 file, err := os.Open("/sys/kernel/security/apparmor/profiles") 102 if err != nil { 103 return err 104 } 105 r := bufio.NewReader(file) 106 for { 107 p, err := r.ReadString('\n') 108 if err != nil { 109 return err 110 } 111 if strings.HasPrefix(p, name+" ") { 112 return nil 113 } 114 } 115 }