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  }