github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/internal/adapters/terraform/google/compute/networks.go (about)

     1  package compute
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
     8  
     9  	"github.com/aquasecurity/defsec/pkg/providers/google/compute"
    10  	"github.com/aquasecurity/defsec/pkg/terraform"
    11  )
    12  
    13  const (
    14  	defaultSubnetPurpose = "PRIVATE_RFC_1918"
    15  )
    16  
    17  func adaptNetworks(modules terraform.Modules) (networks []compute.Network) {
    18  
    19  	networkMap := make(map[string]compute.Network)
    20  
    21  	for _, networkBlock := range modules.GetResourcesByType("google_compute_network") {
    22  		network := compute.Network{
    23  			Metadata:    networkBlock.GetMetadata(),
    24  			Firewall:    nil,
    25  			Subnetworks: nil,
    26  		}
    27  		networkMap[networkBlock.ID()] = network
    28  	}
    29  
    30  	for _, subnetworkBlock := range modules.GetResourcesByType("google_compute_subnetwork") {
    31  
    32  		subnetwork := compute.SubNetwork{
    33  			Metadata:       subnetworkBlock.GetMetadata(),
    34  			Name:           subnetworkBlock.GetAttribute("name").AsStringValueOrDefault("", subnetworkBlock),
    35  			Purpose:        subnetworkBlock.GetAttribute("purpose").AsStringValueOrDefault(defaultSubnetPurpose, subnetworkBlock),
    36  			EnableFlowLogs: defsecTypes.BoolDefault(false, subnetworkBlock.GetMetadata()),
    37  		}
    38  
    39  		// logging
    40  		if logConfigBlock := subnetworkBlock.GetBlock("log_config"); logConfigBlock.IsNotNil() {
    41  			subnetwork.EnableFlowLogs = defsecTypes.BoolExplicit(true, logConfigBlock.GetMetadata())
    42  		}
    43  
    44  		nwAttr := subnetworkBlock.GetAttribute("network")
    45  		if nwAttr.IsNotNil() {
    46  			if nwblock, err := modules.GetReferencedBlock(nwAttr, subnetworkBlock); err == nil {
    47  				if network, ok := networkMap[nwblock.ID()]; ok {
    48  					network.Subnetworks = append(network.Subnetworks, subnetwork)
    49  					networkMap[nwblock.ID()] = network
    50  					continue
    51  				}
    52  			}
    53  		}
    54  
    55  		placeholder := compute.Network{
    56  			Metadata:    defsecTypes.NewUnmanagedMetadata(),
    57  			Firewall:    nil,
    58  			Subnetworks: nil,
    59  		}
    60  		placeholder.Subnetworks = append(placeholder.Subnetworks, subnetwork)
    61  		networks = append(networks, placeholder)
    62  	}
    63  
    64  	for _, firewallBlock := range modules.GetResourcesByType("google_compute_firewall") {
    65  
    66  		firewall := compute.Firewall{
    67  			Metadata:     firewallBlock.GetMetadata(),
    68  			Name:         firewallBlock.GetAttribute("name").AsStringValueOrDefault("", firewallBlock),
    69  			IngressRules: nil,
    70  			EgressRules:  nil,
    71  			SourceTags:   firewallBlock.GetAttribute("source_tags").AsStringValueSliceOrEmpty(),
    72  			TargetTags:   firewallBlock.GetAttribute("target_tags").AsStringValueSliceOrEmpty(),
    73  		}
    74  
    75  		for _, allowBlock := range firewallBlock.GetBlocks("allow") {
    76  			adaptFirewallRule(&firewall, firewallBlock, allowBlock, true)
    77  		}
    78  		for _, denyBlock := range firewallBlock.GetBlocks("deny") {
    79  			adaptFirewallRule(&firewall, firewallBlock, denyBlock, false)
    80  		}
    81  
    82  		nwAttr := firewallBlock.GetAttribute("network")
    83  		if nwAttr.IsNotNil() {
    84  			if nwblock, err := modules.GetReferencedBlock(nwAttr, firewallBlock); err == nil {
    85  				if network, ok := networkMap[nwblock.ID()]; ok {
    86  					network.Firewall = &firewall
    87  					networkMap[nwblock.ID()] = network
    88  					continue
    89  				}
    90  			}
    91  		}
    92  
    93  		placeholder := compute.Network{
    94  			Metadata:    defsecTypes.NewUnmanagedMetadata(),
    95  			Firewall:    nil,
    96  			Subnetworks: nil,
    97  		}
    98  		placeholder.Firewall = &firewall
    99  		networks = append(networks, placeholder)
   100  	}
   101  
   102  	for _, nw := range networkMap {
   103  		networks = append(networks, nw)
   104  	}
   105  
   106  	return networks
   107  }
   108  
   109  func expandRange(ports string, attr *terraform.Attribute) []defsecTypes.IntValue {
   110  	ports = strings.ReplaceAll(ports, " ", "")
   111  	if !strings.Contains(ports, "-") {
   112  		i, err := strconv.Atoi(ports)
   113  		if err != nil {
   114  			return nil
   115  		}
   116  		return []defsecTypes.IntValue{
   117  			defsecTypes.Int(i, attr.GetMetadata()),
   118  		}
   119  	}
   120  	parts := strings.Split(ports, "-")
   121  	if len(parts) != 2 {
   122  		return nil
   123  	}
   124  	start, err := strconv.Atoi(parts[0])
   125  	if err != nil {
   126  		return nil
   127  	}
   128  	end, err := strconv.Atoi(parts[1])
   129  	if err != nil {
   130  		return nil
   131  	}
   132  	var output []defsecTypes.IntValue
   133  	for i := start; i <= end; i++ {
   134  		output = append(output, defsecTypes.Int(i, attr.GetMetadata()))
   135  	}
   136  	return output
   137  }
   138  
   139  func adaptFirewallRule(firewall *compute.Firewall, firewallBlock, ruleBlock *terraform.Block, allow bool) {
   140  	protocolAttr := ruleBlock.GetAttribute("protocol")
   141  	portsAttr := ruleBlock.GetAttribute("ports")
   142  
   143  	var ports []defsecTypes.IntValue
   144  	rawPorts := portsAttr.AsStringValues()
   145  	for _, portStr := range rawPorts {
   146  		ports = append(ports, expandRange(portStr.Value(), portsAttr)...)
   147  	}
   148  
   149  	// ingress by default
   150  	isEgress := firewallBlock.GetAttribute("direction").Equals("EGRESS", terraform.IgnoreCase)
   151  
   152  	rule := compute.FirewallRule{
   153  		Metadata: firewallBlock.GetMetadata(),
   154  		Enforced: defsecTypes.BoolDefault(true, firewallBlock.GetMetadata()),
   155  		IsAllow:  defsecTypes.Bool(allow, ruleBlock.GetMetadata()),
   156  		Protocol: protocolAttr.AsStringValueOrDefault("tcp", ruleBlock),
   157  		Ports:    ports,
   158  	}
   159  
   160  	disabledAttr := firewallBlock.GetAttribute("disabled")
   161  	switch {
   162  	case disabledAttr.IsNil():
   163  		rule.Enforced = defsecTypes.BoolDefault(true, firewallBlock.GetMetadata())
   164  	case disabledAttr.IsTrue():
   165  		rule.Enforced = defsecTypes.Bool(false, disabledAttr.GetMetadata())
   166  	default:
   167  		rule.Enforced = defsecTypes.Bool(true, disabledAttr.GetMetadata())
   168  	}
   169  
   170  	if isEgress {
   171  		var destinations []defsecTypes.StringValue
   172  		if destinationAttr := firewallBlock.GetAttribute("destination_ranges"); destinationAttr.IsNotNil() {
   173  			destinations = append(destinations, destinationAttr.AsStringValues()...)
   174  		}
   175  		if len(destinations) == 0 {
   176  			destinations = append(destinations, defsecTypes.StringDefault("0.0.0.0/0", firewallBlock.GetMetadata()))
   177  		}
   178  		firewall.EgressRules = append(firewall.EgressRules, compute.EgressRule{
   179  			Metadata:          firewallBlock.GetMetadata(),
   180  			FirewallRule:      rule,
   181  			DestinationRanges: destinations,
   182  		})
   183  	} else {
   184  		var sources []defsecTypes.StringValue
   185  		if sourceAttr := firewallBlock.GetAttribute("source_ranges"); sourceAttr.IsNotNil() {
   186  			sources = append(sources, sourceAttr.AsStringValues()...)
   187  		}
   188  		if len(sources) == 0 {
   189  			sources = append(sources, defsecTypes.StringDefault("0.0.0.0/0", firewallBlock.GetMetadata()))
   190  		}
   191  		firewall.IngressRules = append(firewall.IngressRules, compute.IngressRule{
   192  			Metadata:     firewallBlock.GetMetadata(),
   193  			FirewallRule: rule,
   194  			SourceRanges: sources,
   195  		})
   196  	}
   197  
   198  }