github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/aaparser/aaparser.go (about) 1 // Package aaparser is a convenience package interacting with `apparmor_parser`. 2 package aaparser // import "github.com/demonoid81/moby/pkg/aaparser" 3 4 import ( 5 "fmt" 6 "os/exec" 7 "strconv" 8 "strings" 9 ) 10 11 const ( 12 binary = "apparmor_parser" 13 ) 14 15 // GetVersion returns the major and minor version of apparmor_parser. 16 func GetVersion() (int, error) { 17 output, err := cmd("", "--version") 18 if err != nil { 19 return -1, err 20 } 21 22 return parseVersion(output) 23 } 24 25 // LoadProfile runs `apparmor_parser -Kr` on a specified apparmor profile to 26 // replace the profile. The `-K` is necessary to make sure that apparmor_parser 27 // doesn't try to write to a read-only filesystem. 28 func LoadProfile(profilePath string) error { 29 _, err := cmd("", "-Kr", profilePath) 30 return err 31 } 32 33 // cmd runs `apparmor_parser` with the passed arguments. 34 func cmd(dir string, arg ...string) (string, error) { 35 c := exec.Command(binary, arg...) 36 c.Dir = dir 37 38 output, err := c.CombinedOutput() 39 if err != nil { 40 return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), output, err) 41 } 42 43 return string(output), nil 44 } 45 46 // parseVersion takes the output from `apparmor_parser --version` and returns 47 // a representation of the {major, minor, patch} version as a single number of 48 // the form MMmmPPP {major, minor, patch}. 49 func parseVersion(output string) (int, error) { 50 // output is in the form of the following: 51 // AppArmor parser version 2.9.1 52 // Copyright (C) 1999-2008 Novell Inc. 53 // Copyright 2009-2012 Canonical Ltd. 54 55 lines := strings.SplitN(output, "\n", 2) 56 words := strings.Split(lines[0], " ") 57 version := words[len(words)-1] 58 59 // split by major minor version 60 v := strings.Split(version, ".") 61 if len(v) == 0 || len(v) > 3 { 62 return -1, fmt.Errorf("parsing version failed for output: `%s`", output) 63 } 64 65 // Default the versions to 0. 66 var majorVersion, minorVersion, patchLevel int 67 68 majorVersion, err := strconv.Atoi(v[0]) 69 if err != nil { 70 return -1, err 71 } 72 73 if len(v) > 1 { 74 minorVersion, err = strconv.Atoi(v[1]) 75 if err != nil { 76 return -1, err 77 } 78 } 79 if len(v) > 2 { 80 patchLevel, err = strconv.Atoi(v[2]) 81 if err != nil { 82 return -1, err 83 } 84 } 85 86 // major*10^5 + minor*10^3 + patch*10^0 87 numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel 88 return numericVersion, nil 89 }