go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/discovery/k8s/asset_data.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package k8s 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/rs/zerolog/log" 11 "go.mondoo.com/cnquery/motor/asset" 12 "go.mondoo.com/cnquery/motor/platform" 13 "go.mondoo.com/cnquery/motor/providers" 14 "go.mondoo.com/cnquery/motor/providers/k8s" 15 "google.golang.org/protobuf/proto" 16 "k8s.io/apimachinery/pkg/api/meta" 17 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 18 "k8s.io/apimachinery/pkg/runtime" 19 ) 20 21 func createPlatformData(objectKind, runtime string) (*platform.Platform, error) { 22 platformData := &platform.Platform{ 23 Family: []string{"k8s"}, 24 Kind: providers.Kind_KIND_K8S_OBJECT, 25 Runtime: runtime, 26 } 27 // We need this at two places (discovery and tranport) 28 // Here it is needed for the discovery and this is what ends up in the database 29 switch objectKind { 30 case "Node": 31 platformData.Name = "k8s-node" 32 platformData.Title = "Kubernetes Node" 33 case "Pod": 34 platformData.Family = append(platformData.Family, "k8s-workload") 35 platformData.Name = "k8s-pod" 36 platformData.Title = "Kubernetes Pod" 37 case "CronJob": 38 platformData.Family = append(platformData.Family, "k8s-workload") 39 platformData.Name = "k8s-cronjob" 40 platformData.Title = "Kubernetes CronJob" 41 case "StatefulSet": 42 platformData.Family = append(platformData.Family, "k8s-workload") 43 platformData.Name = "k8s-statefulset" 44 platformData.Title = "Kubernetes StatefulSet" 45 case "Deployment": 46 platformData.Family = append(platformData.Family, "k8s-workload") 47 platformData.Name = "k8s-deployment" 48 platformData.Title = "Kubernetes Deployment" 49 case "Job": 50 platformData.Family = append(platformData.Family, "k8s-workload") 51 platformData.Name = "k8s-job" 52 platformData.Title = "Kubernetes Job" 53 case "ReplicaSet": 54 platformData.Family = append(platformData.Family, "k8s-workload") 55 platformData.Name = "k8s-replicaset" 56 platformData.Title = "Kubernetes ReplicaSet" 57 case "DaemonSet": 58 platformData.Family = append(platformData.Family, "k8s-workload") 59 platformData.Name = "k8s-daemonset" 60 platformData.Title = "Kubernetes DaemonSet" 61 case "AdmissionReview": 62 platformData.Family = append(platformData.Family, "k8s-admission") 63 platformData.Name = "k8s-admission" 64 platformData.Title = "Kubernetes Admission Review" 65 case "Ingress": 66 platformData.Family = append(platformData.Family, "k8s-ingress") 67 platformData.Name = "k8s-ingress" 68 platformData.Title = "Kubernetes Ingress" 69 case "Namespace": 70 platformData.Family = append(platformData.Family, "k8s-namespace") 71 platformData.Name = "k8s-namespace" 72 platformData.Title = "Kubernetes Namespace" 73 default: 74 return nil, fmt.Errorf("could not determine object kind %s", objectKind) 75 } 76 return platformData, nil 77 } 78 79 func createAssetFromObject(object runtime.Object, runtime string, connection *providers.Config, clusterIdentifier string) (*asset.Asset, error) { 80 objMeta, err := meta.Accessor(object) 81 if err != nil { 82 log.Error().Err(err).Msg("could not access object attributes") 83 return nil, err 84 } 85 objType, err := meta.TypeAccessor(object) 86 if err != nil { 87 log.Error().Err(err).Msg("could not access object attributes") 88 return nil, err 89 } 90 91 objectKind := objType.GetKind() 92 platformData, err := createPlatformData(objectKind, runtime) 93 if err != nil { 94 return nil, err 95 } 96 platformData.Version = objType.GetAPIVersion() 97 platformData.Build = objMeta.GetResourceVersion() 98 platformData.Labels = map[string]string{ 99 "uid": string(objMeta.GetUID()), 100 } 101 102 assetLabels := objMeta.GetLabels() 103 if assetLabels == nil { 104 assetLabels = map[string]string{} 105 } 106 ns := objMeta.GetNamespace() 107 var name string 108 if ns != "" { 109 name = ns + "/" + objMeta.GetName() 110 platformData.Labels["namespace"] = ns 111 } else { 112 name = objMeta.GetName() 113 } 114 115 addMondooAssetLabels(assetLabels, objMeta, objType, clusterIdentifier) 116 117 newConnection := proto.Clone(connection).(*providers.Config) 118 newConnection.Options = map[string]string{} 119 for k, v := range connection.Options { 120 newConnection.Options[k] = v 121 } 122 newConnection.Options["object-kind"] = strings.ToLower(objectKind) 123 124 asset := &asset.Asset{ 125 PlatformIds: []string{k8s.NewPlatformWorkloadId(clusterIdentifier, strings.ToLower(objectKind), objMeta.GetNamespace(), objMeta.GetName(), string(objMeta.GetUID()))}, 126 Name: name, 127 Platform: platformData, 128 Connections: []*providers.Config{newConnection}, 129 State: asset.State_STATE_ONLINE, 130 Labels: assetLabels, 131 } 132 133 return asset, nil 134 } 135 136 func addMondooAssetLabels(assetLabels map[string]string, objMeta v1.Object, objType meta.Type, clusterIdentifier string) { 137 ns := objMeta.GetNamespace() 138 if ns != "" { 139 assetLabels["k8s.mondoo.com/namespace"] = ns 140 } 141 assetLabels["k8s.mondoo.com/name"] = objMeta.GetName() 142 if string(objMeta.GetUID()) != "" { 143 // objects discovered from manifest do not necessarily have a UID 144 assetLabels["k8s.mondoo.com/uid"] = string(objMeta.GetUID()) 145 } 146 assetLabels["k8s.mondoo.com/kind"] = objType.GetKind() 147 assetLabels["k8s.mondoo.com/apiVersion"] = objType.GetAPIVersion() 148 if objMeta.GetResourceVersion() != "" { 149 // objects discovered from manifest do not necessarily have a resource version 150 assetLabels["k8s.mondoo.com/resource-version"] = objMeta.GetResourceVersion() 151 } 152 assetLabels["k8s.mondoo.com/cluster-id"] = clusterIdentifier 153 154 owners := objMeta.GetOwnerReferences() 155 if len(owners) > 0 { 156 owner := owners[0] 157 assetLabels["k8s.mondoo.com/owner-kind"] = owner.Kind 158 assetLabels["k8s.mondoo.com/owner-name"] = owner.Name 159 assetLabels["k8s.mondoo.com/owner-uid"] = string(owner.UID) 160 } 161 }