github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/internal/adapters/terraform/google/gke/adapt.go (about) 1 package gke 2 3 import ( 4 "github.com/aquasecurity/defsec/pkg/providers/google/gke" 5 "github.com/aquasecurity/defsec/pkg/terraform" 6 defsecTypes "github.com/aquasecurity/defsec/pkg/types" 7 "github.com/google/uuid" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 func Adapt(modules terraform.Modules) gke.GKE { 12 return gke.GKE{ 13 Clusters: (&adapter{ 14 modules: modules, 15 clusterMap: make(map[string]gke.Cluster), 16 }).adaptClusters(), 17 } 18 } 19 20 type adapter struct { 21 modules terraform.Modules 22 clusterMap map[string]gke.Cluster 23 } 24 25 func (a *adapter) adaptClusters() []gke.Cluster { 26 for _, module := range a.modules { 27 for _, resource := range module.GetResourcesByType("google_container_cluster") { 28 a.adaptCluster(resource, module) 29 } 30 } 31 32 a.adaptNodePools() 33 34 for id, cluster := range a.clusterMap { 35 if len(cluster.NodePools) > 0 { 36 cluster.NodeConfig = cluster.NodePools[0].NodeConfig 37 a.clusterMap[id] = cluster 38 } 39 } 40 41 var clusters []gke.Cluster 42 for _, cluster := range a.clusterMap { 43 clusters = append(clusters, cluster) 44 } 45 return clusters 46 } 47 48 func (a *adapter) adaptCluster(resource *terraform.Block, module *terraform.Module) { 49 50 cluster := gke.Cluster{ 51 Metadata: resource.GetMetadata(), 52 NodePools: nil, 53 IPAllocationPolicy: gke.IPAllocationPolicy{ 54 Metadata: resource.GetMetadata(), 55 Enabled: defsecTypes.BoolDefault(false, resource.GetMetadata()), 56 }, 57 MasterAuthorizedNetworks: gke.MasterAuthorizedNetworks{ 58 Metadata: resource.GetMetadata(), 59 Enabled: defsecTypes.BoolDefault(false, resource.GetMetadata()), 60 CIDRs: []defsecTypes.StringValue{}, 61 }, 62 NetworkPolicy: gke.NetworkPolicy{ 63 Metadata: resource.GetMetadata(), 64 Enabled: defsecTypes.BoolDefault(false, resource.GetMetadata()), 65 }, 66 DatapathProvider: resource.GetAttribute("datapath_provider"). 67 AsStringValueOrDefault("DATAPATH_PROVIDER_UNSPECIFIED", resource), 68 PrivateCluster: gke.PrivateCluster{ 69 Metadata: resource.GetMetadata(), 70 EnablePrivateNodes: defsecTypes.BoolDefault(false, resource.GetMetadata()), 71 }, 72 LoggingService: defsecTypes.StringDefault("logging.googleapis.com/kubernetes", resource.GetMetadata()), 73 MonitoringService: defsecTypes.StringDefault("monitoring.googleapis.com/kubernetes", resource.GetMetadata()), 74 MasterAuth: gke.MasterAuth{ 75 Metadata: resource.GetMetadata(), 76 ClientCertificate: gke.ClientCertificate{ 77 Metadata: resource.GetMetadata(), 78 IssueCertificate: defsecTypes.BoolDefault(false, resource.GetMetadata()), 79 }, 80 Username: defsecTypes.StringDefault("", resource.GetMetadata()), 81 Password: defsecTypes.StringDefault("", resource.GetMetadata()), 82 }, 83 NodeConfig: gke.NodeConfig{ 84 Metadata: resource.GetMetadata(), 85 ImageType: defsecTypes.StringDefault("", resource.GetMetadata()), 86 WorkloadMetadataConfig: gke.WorkloadMetadataConfig{ 87 Metadata: resource.GetMetadata(), 88 NodeMetadata: defsecTypes.StringDefault("", resource.GetMetadata()), 89 }, 90 ServiceAccount: defsecTypes.StringDefault("", resource.GetMetadata()), 91 EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()), 92 }, 93 EnableShieldedNodes: defsecTypes.BoolDefault(true, resource.GetMetadata()), 94 EnableLegacyABAC: defsecTypes.BoolDefault(false, resource.GetMetadata()), 95 ResourceLabels: defsecTypes.MapDefault(make(map[string]string), resource.GetMetadata()), 96 RemoveDefaultNodePool: defsecTypes.BoolDefault(false, resource.GetMetadata()), 97 EnableAutpilot: defsecTypes.BoolDefault(false, resource.GetMetadata()), 98 } 99 100 if allocBlock := resource.GetBlock("ip_allocation_policy"); allocBlock.IsNotNil() { 101 cluster.IPAllocationPolicy.Metadata = allocBlock.GetMetadata() 102 cluster.IPAllocationPolicy.Enabled = defsecTypes.Bool(true, allocBlock.GetMetadata()) 103 } 104 105 if blocks := resource.GetBlocks("master_authorized_networks_config"); len(blocks) > 0 { 106 cluster.MasterAuthorizedNetworks = adaptMasterAuthNetworksAsBlocks(resource, blocks) 107 } 108 109 if policyBlock := resource.GetBlock("network_policy"); policyBlock.IsNotNil() { 110 enabledAttr := policyBlock.GetAttribute("enabled") 111 cluster.NetworkPolicy.Metadata = policyBlock.GetMetadata() 112 cluster.NetworkPolicy.Enabled = enabledAttr.AsBoolValueOrDefault(false, policyBlock) 113 } 114 115 if privBlock := resource.GetBlock("private_cluster_config"); privBlock.IsNotNil() { 116 privateNodesEnabledAttr := privBlock.GetAttribute("enable_private_nodes") 117 cluster.PrivateCluster.Metadata = privBlock.GetMetadata() 118 cluster.PrivateCluster.EnablePrivateNodes = privateNodesEnabledAttr.AsBoolValueOrDefault(false, privBlock) 119 } 120 121 loggingAttr := resource.GetAttribute("logging_service") 122 cluster.LoggingService = loggingAttr.AsStringValueOrDefault("logging.googleapis.com/kubernetes", resource) 123 monitoringServiceAttr := resource.GetAttribute("monitoring_service") 124 cluster.MonitoringService = monitoringServiceAttr.AsStringValueOrDefault("monitoring.googleapis.com/kubernetes", resource) 125 126 if masterBlock := resource.GetBlock("master_auth"); masterBlock.IsNotNil() { 127 cluster.MasterAuth = adaptMasterAuth(masterBlock) 128 } 129 130 if configBlock := resource.GetBlock("node_config"); configBlock.IsNotNil() { 131 if configBlock.GetBlock("metadata").IsNotNil() { 132 cluster.NodeConfig.Metadata = configBlock.GetBlock("metadata").GetMetadata() 133 } 134 cluster.NodeConfig = adaptNodeConfig(configBlock) 135 } 136 137 cluster.EnableShieldedNodes = resource.GetAttribute("enable_shielded_nodes").AsBoolValueOrDefault(true, resource) 138 139 enableLegacyABACAttr := resource.GetAttribute("enable_legacy_abac") 140 cluster.EnableLegacyABAC = enableLegacyABACAttr.AsBoolValueOrDefault(false, resource) 141 142 cluster.EnableAutpilot = resource.GetAttribute("enable_autopilot").AsBoolValueOrDefault(false, resource) 143 144 resourceLabelsAttr := resource.GetAttribute("resource_labels") 145 if resourceLabelsAttr.IsNotNil() { 146 cluster.ResourceLabels = resourceLabelsAttr.AsMapValue() 147 } 148 149 cluster.RemoveDefaultNodePool = resource.GetAttribute("remove_default_node_pool").AsBoolValueOrDefault(false, resource) 150 151 a.clusterMap[resource.ID()] = cluster 152 } 153 154 func (a *adapter) adaptNodePools() { 155 for _, nodePoolBlock := range a.modules.GetResourcesByType("google_container_node_pool") { 156 a.adaptNodePool(nodePoolBlock) 157 } 158 } 159 160 func (a *adapter) adaptNodePool(resource *terraform.Block) { 161 nodeConfig := gke.NodeConfig{ 162 Metadata: resource.GetMetadata(), 163 ImageType: defsecTypes.StringDefault("", resource.GetMetadata()), 164 WorkloadMetadataConfig: gke.WorkloadMetadataConfig{ 165 Metadata: resource.GetMetadata(), 166 NodeMetadata: defsecTypes.StringDefault("", resource.GetMetadata()), 167 }, 168 ServiceAccount: defsecTypes.StringDefault("", resource.GetMetadata()), 169 EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()), 170 } 171 172 management := gke.Management{ 173 Metadata: resource.GetMetadata(), 174 EnableAutoRepair: defsecTypes.BoolDefault(false, resource.GetMetadata()), 175 EnableAutoUpgrade: defsecTypes.BoolDefault(false, resource.GetMetadata()), 176 } 177 178 if resource.HasChild("management") { 179 management.Metadata = resource.GetBlock("management").GetMetadata() 180 181 autoRepairAttr := resource.GetBlock("management").GetAttribute("auto_repair") 182 management.EnableAutoRepair = autoRepairAttr.AsBoolValueOrDefault(false, resource.GetBlock("management")) 183 184 autoUpgradeAttr := resource.GetBlock("management").GetAttribute("auto_upgrade") 185 management.EnableAutoUpgrade = autoUpgradeAttr.AsBoolValueOrDefault(false, resource.GetBlock("management")) 186 } 187 188 if resource.HasChild("node_config") { 189 nodeConfig = adaptNodeConfig(resource.GetBlock("node_config")) 190 } 191 192 nodePool := gke.NodePool{ 193 Metadata: resource.GetMetadata(), 194 Management: management, 195 NodeConfig: nodeConfig, 196 } 197 198 clusterAttr := resource.GetAttribute("cluster") 199 if referencedCluster, err := a.modules.GetReferencedBlock(clusterAttr, resource); err == nil { 200 if referencedCluster.TypeLabel() == "google_container_cluster" { 201 if cluster, ok := a.clusterMap[referencedCluster.ID()]; ok { 202 cluster.NodePools = append(cluster.NodePools, nodePool) 203 a.clusterMap[referencedCluster.ID()] = cluster 204 return 205 } 206 } 207 } 208 209 // we didn't find a cluster to put the nodepool in, so create a placeholder 210 a.clusterMap[uuid.NewString()] = gke.Cluster{ 211 Metadata: defsecTypes.NewUnmanagedMetadata(), 212 NodePools: []gke.NodePool{nodePool}, 213 IPAllocationPolicy: gke.IPAllocationPolicy{ 214 Metadata: defsecTypes.NewUnmanagedMetadata(), 215 Enabled: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 216 }, 217 MasterAuthorizedNetworks: gke.MasterAuthorizedNetworks{ 218 Metadata: defsecTypes.NewUnmanagedMetadata(), 219 Enabled: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 220 CIDRs: nil, 221 }, 222 NetworkPolicy: gke.NetworkPolicy{ 223 Metadata: defsecTypes.NewUnmanagedMetadata(), 224 Enabled: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 225 }, 226 PrivateCluster: gke.PrivateCluster{ 227 Metadata: defsecTypes.NewUnmanagedMetadata(), 228 EnablePrivateNodes: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 229 }, 230 LoggingService: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 231 MonitoringService: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 232 MasterAuth: gke.MasterAuth{ 233 Metadata: defsecTypes.NewUnmanagedMetadata(), 234 ClientCertificate: gke.ClientCertificate{ 235 Metadata: defsecTypes.NewUnmanagedMetadata(), 236 IssueCertificate: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 237 }, 238 Username: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 239 Password: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 240 }, 241 NodeConfig: gke.NodeConfig{ 242 Metadata: defsecTypes.NewUnmanagedMetadata(), 243 ImageType: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 244 WorkloadMetadataConfig: gke.WorkloadMetadataConfig{ 245 Metadata: defsecTypes.NewUnmanagedMetadata(), 246 NodeMetadata: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 247 }, 248 ServiceAccount: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 249 EnableLegacyEndpoints: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 250 }, 251 EnableShieldedNodes: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 252 EnableLegacyABAC: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 253 ResourceLabels: defsecTypes.MapDefault(nil, defsecTypes.NewUnmanagedMetadata()), 254 RemoveDefaultNodePool: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 255 EnableAutpilot: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 256 } 257 } 258 259 func adaptNodeConfig(resource *terraform.Block) gke.NodeConfig { 260 261 config := gke.NodeConfig{ 262 Metadata: resource.GetMetadata(), 263 ImageType: resource.GetAttribute("image_type").AsStringValueOrDefault("", resource), 264 WorkloadMetadataConfig: gke.WorkloadMetadataConfig{ 265 Metadata: resource.GetMetadata(), 266 NodeMetadata: defsecTypes.StringDefault("UNSPECIFIED", resource.GetMetadata()), 267 }, 268 ServiceAccount: resource.GetAttribute("service_account").AsStringValueOrDefault("", resource), 269 EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()), 270 } 271 272 if metadata := resource.GetAttribute("metadata"); metadata.IsNotNil() { 273 legacyMetadata := metadata.MapValue("disable-legacy-endpoints") 274 if legacyMetadata.IsWhollyKnown() && legacyMetadata.Type() == cty.Bool { 275 config.EnableLegacyEndpoints = defsecTypes.Bool(legacyMetadata.False(), metadata.GetMetadata()) 276 } 277 } 278 279 workloadBlock := resource.GetBlock("workload_metadata_config") 280 if workloadBlock.IsNotNil() { 281 config.WorkloadMetadataConfig.Metadata = workloadBlock.GetMetadata() 282 modeAttr := workloadBlock.GetAttribute("node_metadata") 283 if modeAttr.IsNil() { 284 modeAttr = workloadBlock.GetAttribute("mode") // try newest version 285 } 286 config.WorkloadMetadataConfig.NodeMetadata = modeAttr.AsStringValueOrDefault("UNSPECIFIED", workloadBlock) 287 } 288 289 return config 290 } 291 292 func adaptMasterAuth(resource *terraform.Block) gke.MasterAuth { 293 clientCert := gke.ClientCertificate{ 294 Metadata: resource.GetMetadata(), 295 IssueCertificate: defsecTypes.BoolDefault(false, resource.GetMetadata()), 296 } 297 298 if resource.HasChild("client_certificate_config") { 299 clientCertAttr := resource.GetBlock("client_certificate_config").GetAttribute("issue_client_certificate") 300 clientCert.IssueCertificate = clientCertAttr.AsBoolValueOrDefault(false, resource.GetBlock("client_certificate_config")) 301 clientCert.Metadata = resource.GetBlock("client_certificate_config").GetMetadata() 302 } 303 304 username := resource.GetAttribute("username").AsStringValueOrDefault("", resource) 305 password := resource.GetAttribute("password").AsStringValueOrDefault("", resource) 306 307 return gke.MasterAuth{ 308 Metadata: resource.GetMetadata(), 309 ClientCertificate: clientCert, 310 Username: username, 311 Password: password, 312 } 313 } 314 315 func adaptMasterAuthNetworksAsBlocks(parent *terraform.Block, blocks terraform.Blocks) gke.MasterAuthorizedNetworks { 316 var cidrs []defsecTypes.StringValue 317 for _, block := range blocks { 318 for _, cidrBlock := range block.GetBlocks("cidr_blocks") { 319 if cidrAttr := cidrBlock.GetAttribute("cidr_block"); cidrAttr.IsNotNil() { 320 cidrs = append(cidrs, cidrAttr.AsStringValues()...) 321 } 322 } 323 } 324 enabled := defsecTypes.Bool(true, blocks[0].GetMetadata()) 325 return gke.MasterAuthorizedNetworks{ 326 Metadata: blocks[0].GetMetadata(), 327 Enabled: enabled, 328 CIDRs: cidrs, 329 } 330 }