github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/terraform/google/gke/adapt.go (about)

     1  package gke
     2  
     3  import (
     4  	"github.com/google/uuid"
     5  	"github.com/khulnasoft-lab/defsec/pkg/providers/google/gke"
     6  	"github.com/khulnasoft-lab/defsec/pkg/terraform"
     7  	defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types"
     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  		PrivateCluster: gke.PrivateCluster{
    67  			Metadata:           resource.GetMetadata(),
    68  			EnablePrivateNodes: defsecTypes.BoolDefault(false, resource.GetMetadata()),
    69  		},
    70  		LoggingService:    defsecTypes.StringDefault("logging.googleapis.com/kubernetes", resource.GetMetadata()),
    71  		MonitoringService: defsecTypes.StringDefault("monitoring.googleapis.com/kubernetes", resource.GetMetadata()),
    72  		PodSecurityPolicy: gke.PodSecurityPolicy{
    73  			Metadata: resource.GetMetadata(),
    74  			Enabled:  defsecTypes.BoolDefault(false, resource.GetMetadata()),
    75  		},
    76  		MasterAuth: gke.MasterAuth{
    77  			Metadata: resource.GetMetadata(),
    78  			ClientCertificate: gke.ClientCertificate{
    79  				Metadata:         resource.GetMetadata(),
    80  				IssueCertificate: defsecTypes.BoolDefault(false, resource.GetMetadata()),
    81  			},
    82  			Username: defsecTypes.StringDefault("", resource.GetMetadata()),
    83  			Password: defsecTypes.StringDefault("", resource.GetMetadata()),
    84  		},
    85  		NodeConfig: gke.NodeConfig{
    86  			Metadata:  resource.GetMetadata(),
    87  			ImageType: defsecTypes.StringDefault("", resource.GetMetadata()),
    88  			WorkloadMetadataConfig: gke.WorkloadMetadataConfig{
    89  				Metadata:     resource.GetMetadata(),
    90  				NodeMetadata: defsecTypes.StringDefault("", resource.GetMetadata()),
    91  			},
    92  			ServiceAccount:        defsecTypes.StringDefault("", resource.GetMetadata()),
    93  			EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()),
    94  		},
    95  		EnableShieldedNodes:   defsecTypes.BoolDefault(true, resource.GetMetadata()),
    96  		EnableLegacyABAC:      defsecTypes.BoolDefault(false, resource.GetMetadata()),
    97  		ResourceLabels:        defsecTypes.MapDefault(make(map[string]string), resource.GetMetadata()),
    98  		RemoveDefaultNodePool: defsecTypes.BoolDefault(false, resource.GetMetadata()),
    99  	}
   100  
   101  	if allocBlock := resource.GetBlock("ip_allocation_policy"); allocBlock.IsNotNil() {
   102  		cluster.IPAllocationPolicy.Metadata = allocBlock.GetMetadata()
   103  		cluster.IPAllocationPolicy.Enabled = defsecTypes.Bool(true, allocBlock.GetMetadata())
   104  	}
   105  
   106  	if blocks := resource.GetBlocks("master_authorized_networks_config"); len(blocks) > 0 {
   107  		cluster.MasterAuthorizedNetworks = adaptMasterAuthNetworksAsBlocks(resource, blocks)
   108  	}
   109  
   110  	if policyBlock := resource.GetBlock("network_policy"); policyBlock.IsNotNil() {
   111  		enabledAttr := policyBlock.GetAttribute("enabled")
   112  		cluster.NetworkPolicy.Metadata = policyBlock.GetMetadata()
   113  		cluster.NetworkPolicy.Enabled = enabledAttr.AsBoolValueOrDefault(false, policyBlock)
   114  	}
   115  
   116  	if privBlock := resource.GetBlock("private_cluster_config"); privBlock.IsNotNil() {
   117  		privateNodesEnabledAttr := privBlock.GetAttribute("enable_private_nodes")
   118  		cluster.PrivateCluster.Metadata = privBlock.GetMetadata()
   119  		cluster.PrivateCluster.EnablePrivateNodes = privateNodesEnabledAttr.AsBoolValueOrDefault(false, privBlock)
   120  	}
   121  
   122  	loggingAttr := resource.GetAttribute("logging_service")
   123  	cluster.LoggingService = loggingAttr.AsStringValueOrDefault("logging.googleapis.com/kubernetes", resource)
   124  	monitoringServiceAttr := resource.GetAttribute("monitoring_service")
   125  	cluster.MonitoringService = monitoringServiceAttr.AsStringValueOrDefault("monitoring.googleapis.com/kubernetes", resource)
   126  
   127  	if policyBlock := resource.GetBlock("pod_security_policy_config"); policyBlock.IsNotNil() {
   128  		enabledAttr := policyBlock.GetAttribute("enabled")
   129  		cluster.PodSecurityPolicy.Metadata = policyBlock.GetMetadata()
   130  		cluster.PodSecurityPolicy.Enabled = enabledAttr.AsBoolValueOrDefault(false, policyBlock)
   131  	}
   132  
   133  	if masterBlock := resource.GetBlock("master_auth"); masterBlock.IsNotNil() {
   134  		cluster.MasterAuth = adaptMasterAuth(masterBlock)
   135  	}
   136  
   137  	if configBlock := resource.GetBlock("node_config"); configBlock.IsNotNil() {
   138  		if configBlock.GetBlock("metadata").IsNotNil() {
   139  			cluster.NodeConfig.Metadata = configBlock.GetBlock("metadata").GetMetadata()
   140  		}
   141  		cluster.NodeConfig = adaptNodeConfig(configBlock)
   142  	}
   143  
   144  	cluster.EnableShieldedNodes = resource.GetAttribute("enable_shielded_nodes").AsBoolValueOrDefault(true, resource)
   145  
   146  	enableLegacyABACAttr := resource.GetAttribute("enable_legacy_abac")
   147  	cluster.EnableLegacyABAC = enableLegacyABACAttr.AsBoolValueOrDefault(false, resource)
   148  
   149  	resourceLabelsAttr := resource.GetAttribute("resource_labels")
   150  	if resourceLabelsAttr.IsNotNil() {
   151  		resourceLabels := make(map[string]string)
   152  		_ = resourceLabelsAttr.Each(func(key, val cty.Value) {
   153  			if key.Type() == cty.String && val.Type() == cty.String {
   154  				resourceLabels[key.AsString()] = val.AsString()
   155  			}
   156  		})
   157  		cluster.ResourceLabels = defsecTypes.Map(resourceLabels, resourceLabelsAttr.GetMetadata())
   158  	}
   159  
   160  	cluster.RemoveDefaultNodePool = resource.GetAttribute("remove_default_node_pool").AsBoolValueOrDefault(false, resource)
   161  
   162  	a.clusterMap[resource.ID()] = cluster
   163  }
   164  
   165  func (a *adapter) adaptNodePools() {
   166  	for _, nodePoolBlock := range a.modules.GetResourcesByType("google_container_node_pool") {
   167  		a.adaptNodePool(nodePoolBlock)
   168  	}
   169  }
   170  
   171  func (a *adapter) adaptNodePool(resource *terraform.Block) {
   172  	nodeConfig := gke.NodeConfig{
   173  		Metadata:  resource.GetMetadata(),
   174  		ImageType: defsecTypes.StringDefault("", resource.GetMetadata()),
   175  		WorkloadMetadataConfig: gke.WorkloadMetadataConfig{
   176  			Metadata:     resource.GetMetadata(),
   177  			NodeMetadata: defsecTypes.StringDefault("", resource.GetMetadata()),
   178  		},
   179  		ServiceAccount:        defsecTypes.StringDefault("", resource.GetMetadata()),
   180  		EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()),
   181  	}
   182  
   183  	management := gke.Management{
   184  		Metadata:          resource.GetMetadata(),
   185  		EnableAutoRepair:  defsecTypes.BoolDefault(false, resource.GetMetadata()),
   186  		EnableAutoUpgrade: defsecTypes.BoolDefault(false, resource.GetMetadata()),
   187  	}
   188  
   189  	if resource.HasChild("management") {
   190  		management.Metadata = resource.GetBlock("management").GetMetadata()
   191  
   192  		autoRepairAttr := resource.GetBlock("management").GetAttribute("auto_repair")
   193  		management.EnableAutoRepair = autoRepairAttr.AsBoolValueOrDefault(false, resource.GetBlock("management"))
   194  
   195  		autoUpgradeAttr := resource.GetBlock("management").GetAttribute("auto_upgrade")
   196  		management.EnableAutoUpgrade = autoUpgradeAttr.AsBoolValueOrDefault(false, resource.GetBlock("management"))
   197  	}
   198  
   199  	if resource.HasChild("node_config") {
   200  		nodeConfig = adaptNodeConfig(resource.GetBlock("node_config"))
   201  	}
   202  
   203  	nodePool := gke.NodePool{
   204  		Metadata:   resource.GetMetadata(),
   205  		Management: management,
   206  		NodeConfig: nodeConfig,
   207  	}
   208  
   209  	clusterAttr := resource.GetAttribute("cluster")
   210  	if referencedCluster, err := a.modules.GetReferencedBlock(clusterAttr, resource); err == nil {
   211  		if referencedCluster.TypeLabel() == "google_container_cluster" {
   212  			if cluster, ok := a.clusterMap[referencedCluster.ID()]; ok {
   213  				cluster.NodePools = append(cluster.NodePools, nodePool)
   214  				a.clusterMap[referencedCluster.ID()] = cluster
   215  				return
   216  			}
   217  		}
   218  	}
   219  
   220  	// we didn't find a cluster to put the nodepool in, so create a placeholder
   221  	a.clusterMap[uuid.NewString()] = gke.Cluster{
   222  		Metadata:  defsecTypes.NewUnmanagedMetadata(),
   223  		NodePools: []gke.NodePool{nodePool},
   224  		IPAllocationPolicy: gke.IPAllocationPolicy{
   225  			Metadata: defsecTypes.NewUnmanagedMetadata(),
   226  			Enabled:  defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   227  		},
   228  		MasterAuthorizedNetworks: gke.MasterAuthorizedNetworks{
   229  			Metadata: defsecTypes.NewUnmanagedMetadata(),
   230  			Enabled:  defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   231  			CIDRs:    nil,
   232  		},
   233  		NetworkPolicy: gke.NetworkPolicy{
   234  			Metadata: defsecTypes.NewUnmanagedMetadata(),
   235  			Enabled:  defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   236  		},
   237  		PrivateCluster: gke.PrivateCluster{
   238  			Metadata:           defsecTypes.NewUnmanagedMetadata(),
   239  			EnablePrivateNodes: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   240  		},
   241  		LoggingService:    defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   242  		MonitoringService: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   243  		PodSecurityPolicy: gke.PodSecurityPolicy{
   244  			Metadata: defsecTypes.NewUnmanagedMetadata(),
   245  			Enabled:  defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   246  		},
   247  		MasterAuth: gke.MasterAuth{
   248  			Metadata: defsecTypes.NewUnmanagedMetadata(),
   249  			ClientCertificate: gke.ClientCertificate{
   250  				Metadata:         defsecTypes.NewUnmanagedMetadata(),
   251  				IssueCertificate: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   252  			},
   253  			Username: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   254  			Password: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   255  		},
   256  		NodeConfig: gke.NodeConfig{
   257  			Metadata:  defsecTypes.NewUnmanagedMetadata(),
   258  			ImageType: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   259  			WorkloadMetadataConfig: gke.WorkloadMetadataConfig{
   260  				Metadata:     defsecTypes.NewUnmanagedMetadata(),
   261  				NodeMetadata: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   262  			},
   263  			ServiceAccount:        defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
   264  			EnableLegacyEndpoints: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   265  		},
   266  		EnableShieldedNodes:   defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   267  		EnableLegacyABAC:      defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   268  		ResourceLabels:        defsecTypes.MapDefault(nil, defsecTypes.NewUnmanagedMetadata()),
   269  		RemoveDefaultNodePool: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   270  	}
   271  }
   272  
   273  func adaptNodeConfig(resource *terraform.Block) gke.NodeConfig {
   274  
   275  	config := gke.NodeConfig{
   276  		Metadata:  resource.GetMetadata(),
   277  		ImageType: resource.GetAttribute("image_type").AsStringValueOrDefault("", resource),
   278  		WorkloadMetadataConfig: gke.WorkloadMetadataConfig{
   279  			Metadata:     resource.GetMetadata(),
   280  			NodeMetadata: defsecTypes.StringDefault("UNSPECIFIED", resource.GetMetadata()),
   281  		},
   282  		ServiceAccount:        resource.GetAttribute("service_account").AsStringValueOrDefault("", resource),
   283  		EnableLegacyEndpoints: defsecTypes.BoolDefault(true, resource.GetMetadata()),
   284  	}
   285  
   286  	if metadata := resource.GetAttribute("metadata"); metadata.IsNotNil() {
   287  		legacyMetadata := metadata.MapValue("disable-legacy-endpoints")
   288  		if legacyMetadata.IsWhollyKnown() && legacyMetadata.Type() == cty.Bool {
   289  			config.EnableLegacyEndpoints = defsecTypes.Bool(legacyMetadata.False(), metadata.GetMetadata())
   290  		}
   291  	}
   292  
   293  	workloadBlock := resource.GetBlock("workload_metadata_config")
   294  	if workloadBlock.IsNotNil() {
   295  		config.WorkloadMetadataConfig.Metadata = workloadBlock.GetMetadata()
   296  		modeAttr := workloadBlock.GetAttribute("node_metadata")
   297  		if modeAttr.IsNil() {
   298  			modeAttr = workloadBlock.GetAttribute("mode") // try newest version
   299  		}
   300  		config.WorkloadMetadataConfig.NodeMetadata = modeAttr.AsStringValueOrDefault("UNSPECIFIED", workloadBlock)
   301  	}
   302  
   303  	return config
   304  }
   305  
   306  func adaptMasterAuth(resource *terraform.Block) gke.MasterAuth {
   307  	clientCert := gke.ClientCertificate{
   308  		Metadata:         resource.GetMetadata(),
   309  		IssueCertificate: defsecTypes.BoolDefault(false, resource.GetMetadata()),
   310  	}
   311  
   312  	if resource.HasChild("client_certificate_config") {
   313  		clientCertAttr := resource.GetBlock("client_certificate_config").GetAttribute("issue_client_certificate")
   314  		clientCert.IssueCertificate = clientCertAttr.AsBoolValueOrDefault(false, resource.GetBlock("client_certificate_config"))
   315  		clientCert.Metadata = resource.GetBlock("client_certificate_config").GetMetadata()
   316  	}
   317  
   318  	username := resource.GetAttribute("username").AsStringValueOrDefault("", resource)
   319  	password := resource.GetAttribute("password").AsStringValueOrDefault("", resource)
   320  
   321  	return gke.MasterAuth{
   322  		Metadata:          resource.GetMetadata(),
   323  		ClientCertificate: clientCert,
   324  		Username:          username,
   325  		Password:          password,
   326  	}
   327  }
   328  
   329  func adaptMasterAuthNetworksAsBlocks(parent *terraform.Block, blocks terraform.Blocks) gke.MasterAuthorizedNetworks {
   330  	var cidrs []defsecTypes.StringValue
   331  	for _, block := range blocks {
   332  		for _, cidrBlock := range block.GetBlocks("cidr_blocks") {
   333  			if cidrAttr := cidrBlock.GetAttribute("cidr_block"); cidrAttr.IsNotNil() {
   334  				cidrs = append(cidrs, cidrAttr.AsStringValues()...)
   335  			}
   336  		}
   337  	}
   338  	enabled := defsecTypes.Bool(true, blocks[0].GetMetadata())
   339  	return gke.MasterAuthorizedNetworks{
   340  		Metadata: blocks[0].GetMetadata(),
   341  		Enabled:  enabled,
   342  		CIDRs:    cidrs,
   343  	}
   344  }