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

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