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 }