go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/kubelet.go (about) 1 // copyright: 2019, Dominik Richter and Christoph Hartmann 2 // author: Dominik Richter 3 // author: Christoph Hartmann 4 5 package resources 6 7 import ( 8 "errors" 9 "fmt" 10 "strings" 11 12 "github.com/spf13/afero" 13 kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1" 14 15 "sigs.k8s.io/yaml" 16 17 "go.mondoo.com/cnquery/llx" 18 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 19 "go.mondoo.com/cnquery/providers-sdk/v1/util/convert" 20 "go.mondoo.com/cnquery/providers/os/connection/shared" 21 "go.mondoo.com/cnquery/types" 22 ) 23 24 const defaultKubeletConfig = "/var/lib/kubelet/config.yaml" 25 26 func initKubelet(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 27 if len(args) > 0 { 28 return args, nil, nil 29 } 30 31 p, err := getKubeletProcess(runtime) 32 if err != nil { 33 return nil, nil, err 34 } 35 args["process"] = llx.ResourceData(p, "process") 36 37 kubeletFlagsData := p.GetFlags() 38 if kubeletFlagsData.Error != nil { 39 return nil, nil, err 40 } 41 kubeletFlags := kubeletFlagsData.Data 42 43 // Check kubelet for "--config" flag and set path to config file accordingly 44 configFilePath := defaultKubeletConfig 45 if kubeletConfigFilePath, ok := kubeletFlags["config"]; ok { 46 path, ok := kubeletConfigFilePath.(string) 47 if !ok { 48 return nil, nil, errors.New("wrong type for value of '--config' flag, it must be a string") 49 } 50 configFilePath = path 51 } 52 53 provider, ok := runtime.Connection.(shared.Connection) 54 if !ok { 55 return nil, nil, fmt.Errorf("error getting operating system provider") 56 } 57 // AKS has no kubelet config file 58 configFileExists, err := afero.Exists(provider.FileSystem(), configFilePath) 59 if err != nil { 60 return nil, nil, fmt.Errorf("error when checking whether config file exists: %v", err) 61 } 62 63 if configFileExists { 64 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 65 "path": llx.StringData(configFilePath), 66 }) 67 if err != nil { 68 return nil, nil, err 69 } 70 mqlFile, ok := f.(*mqlFile) 71 if !ok { 72 return nil, nil, err 73 } 74 args["configFile"] = llx.ResourceData(mqlFile, "file") 75 } else { 76 args["configFile"] = llx.NilData 77 } 78 79 // I cannot re-use "mqlFile" here, as it is not read at this point in time 80 configuration, err := createConfiguration(kubeletFlags, configFilePath, provider, configFileExists) 81 if err != nil { 82 return nil, nil, err 83 } 84 args["configuration"] = llx.MapData(configuration, types.String) 85 86 return args, nil, nil 87 } 88 89 // createConfiguration applies the kubelet defaults to the config and then 90 // merges the kubelet flags and the kubelet config file into a single map 91 // This map is representing the running state of the kubelet config 92 func createConfiguration(kubeletFlags map[string]interface{}, configFilePath string, provider shared.Connection, configFileExists bool) (map[string]interface{}, error) { 93 kubeletConfig := kubeletconfigv1beta1.KubeletConfiguration{} 94 SetDefaults_KubeletConfiguration(&kubeletConfig) 95 96 // AKS has no kubelet config file 97 if configFileExists { 98 configFileContent, err := afero.ReadFile(provider.FileSystem(), configFilePath) 99 if err != nil { 100 return nil, fmt.Errorf("error when getting file content: %v", err) 101 } 102 err = yaml.Unmarshal([]byte(configFileContent), &kubeletConfig) 103 if err != nil { 104 return nil, fmt.Errorf("error when converting file content into KubeletConfiguration: %v", err) 105 } 106 } 107 108 options, err := convert.JsonToDict(kubeletConfig) 109 if err != nil { 110 return nil, fmt.Errorf("error when converting KubeletConfig into dict: %v", err) 111 } 112 113 err = mergeFlagsIntoConfig(options, kubeletFlags) 114 if err != nil { 115 return nil, fmt.Errorf("error applying precedence to KubeletConfig: %v", err) 116 } 117 118 err = mergeDeprecatedFlagsIntoConfig(options, kubeletFlags) 119 if err != nil { 120 return nil, fmt.Errorf("error applying precedence for deprecated flags to KubeletConfig: %v", err) 121 } 122 123 return options, nil 124 } 125 126 func getKubeletProcess(runtime *plugin.Runtime) (*mqlProcess, error) { 127 obj, err := CreateResource(runtime, "processes", nil) 128 if err != nil { 129 return nil, err 130 } 131 processes := obj.(*mqlProcesses) 132 133 data := processes.GetList() 134 if data.Error != nil { 135 return nil, data.Error 136 } 137 for _, process := range data.Data { 138 mqlProcess := process.(*mqlProcess) 139 exec := mqlProcess.Executable 140 if exec.Error != nil { 141 continue 142 } 143 if strings.HasSuffix(exec.Data, "kubelet") { 144 return mqlProcess, nil 145 } 146 } 147 return nil, errors.New("no kubelet process found") 148 }