github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/terraform/azure/network/adapt.go (about) 1 package network 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/terraform" 10 11 "github.com/khulnasoft-lab/defsec/pkg/providers/azure/network" 12 13 "github.com/google/uuid" 14 ) 15 16 func Adapt(modules terraform.Modules) network.Network { 17 return network.Network{ 18 SecurityGroups: (&adapter{ 19 modules: modules, 20 groups: make(map[string]network.SecurityGroup), 21 }).adaptSecurityGroups(), 22 NetworkWatcherFlowLogs: adaptWatcherLogs(modules), 23 } 24 } 25 26 type adapter struct { 27 modules terraform.Modules 28 groups map[string]network.SecurityGroup 29 } 30 31 func (a *adapter) adaptSecurityGroups() []network.SecurityGroup { 32 33 for _, module := range a.modules { 34 for _, resource := range module.GetResourcesByType("azurerm_network_security_group") { 35 a.adaptSecurityGroup(resource) 36 } 37 } 38 39 for _, ruleBlock := range a.modules.GetResourcesByType("azurerm_network_security_rule") { 40 rule := a.adaptSGRule(ruleBlock) 41 42 groupAttr := ruleBlock.GetAttribute("network_security_group_name") 43 if groupAttr.IsNotNil() { 44 if referencedBlock, err := a.modules.GetReferencedBlock(groupAttr, ruleBlock); err == nil { 45 if group, ok := a.groups[referencedBlock.ID()]; ok { 46 group.Rules = append(group.Rules, rule) 47 a.groups[referencedBlock.ID()] = group 48 continue 49 } 50 } 51 52 } 53 54 a.groups[uuid.NewString()] = network.SecurityGroup{ 55 Metadata: defsecTypes.NewUnmanagedMetadata(), 56 Rules: []network.SecurityGroupRule{rule}, 57 } 58 } 59 60 var securityGroups []network.SecurityGroup 61 for _, group := range a.groups { 62 securityGroups = append(securityGroups, group) 63 } 64 65 return securityGroups 66 } 67 68 func adaptWatcherLogs(modules terraform.Modules) []network.NetworkWatcherFlowLog { 69 var watcherLogs []network.NetworkWatcherFlowLog 70 71 for _, module := range modules { 72 for _, resource := range module.GetResourcesByType("azurerm_network_watcher_flow_log") { 73 watcherLogs = append(watcherLogs, adaptWatcherLog(resource)) 74 } 75 } 76 return watcherLogs 77 } 78 79 func (a *adapter) adaptSecurityGroup(resource *terraform.Block) { 80 var rules []network.SecurityGroupRule 81 for _, ruleBlock := range resource.GetBlocks("security_rule") { 82 rules = append(rules, a.adaptSGRule(ruleBlock)) 83 } 84 a.groups[resource.ID()] = network.SecurityGroup{ 85 Metadata: resource.GetMetadata(), 86 Rules: rules, 87 } 88 } 89 90 func (a *adapter) adaptSGRule(ruleBlock *terraform.Block) network.SecurityGroupRule { 91 92 rule := network.SecurityGroupRule{ 93 Metadata: ruleBlock.GetMetadata(), 94 Outbound: defsecTypes.BoolDefault(false, ruleBlock.GetMetadata()), 95 Allow: defsecTypes.BoolDefault(true, ruleBlock.GetMetadata()), 96 SourceAddresses: nil, 97 SourcePorts: nil, 98 DestinationAddresses: nil, 99 DestinationPorts: nil, 100 Protocol: ruleBlock.GetAttribute("protocol").AsStringValueOrDefault("", ruleBlock), 101 } 102 103 accessAttr := ruleBlock.GetAttribute("access") 104 if accessAttr.Equals("Allow") { 105 rule.Allow = defsecTypes.Bool(true, accessAttr.GetMetadata()) 106 } else if accessAttr.Equals("Deny") { 107 rule.Allow = defsecTypes.Bool(false, accessAttr.GetMetadata()) 108 } 109 110 directionAttr := ruleBlock.GetAttribute("direction") 111 if directionAttr.Equals("Inbound") { 112 rule.Outbound = defsecTypes.Bool(false, directionAttr.GetMetadata()) 113 } else if directionAttr.Equals("Outbound") { 114 rule.Outbound = defsecTypes.Bool(true, directionAttr.GetMetadata()) 115 } 116 117 a.adaptSource(ruleBlock, &rule) 118 a.adaptDestination(ruleBlock, &rule) 119 120 return rule 121 } 122 123 func (a *adapter) adaptSource(ruleBlock *terraform.Block, rule *network.SecurityGroupRule) { 124 if sourceAddressAttr := ruleBlock.GetAttribute("source_address_prefix"); sourceAddressAttr.IsString() { 125 rule.SourceAddresses = append(rule.SourceAddresses, sourceAddressAttr.AsStringValueOrDefault("", ruleBlock)) 126 } else if sourceAddressPrefixesAttr := ruleBlock.GetAttribute("source_address_prefixes"); sourceAddressPrefixesAttr.IsNotNil() { 127 rule.SourceAddresses = append(rule.SourceAddresses, sourceAddressPrefixesAttr.AsStringValues()...) 128 } 129 130 if sourcePortRangesAttr := ruleBlock.GetAttribute("source_port_ranges"); sourcePortRangesAttr.IsNotNil() { 131 ports := sourcePortRangesAttr.AsStringValues() 132 for _, value := range ports { 133 rule.SourcePorts = append(rule.SourcePorts, expandRange(value.Value(), value.GetMetadata())) 134 } 135 } else if sourcePortRangeAttr := ruleBlock.GetAttribute("source_port_range"); sourcePortRangeAttr.IsString() { 136 rule.SourcePorts = append(rule.SourcePorts, expandRange(sourcePortRangeAttr.Value().AsString(), sourcePortRangeAttr.GetMetadata())) 137 } else if sourcePortRangeAttr := ruleBlock.GetAttribute("source_port_range"); sourcePortRangeAttr.IsNumber() { 138 f := sourcePortRangeAttr.AsNumber() 139 rule.SourcePorts = append(rule.SourcePorts, network.PortRange{ 140 Metadata: sourcePortRangeAttr.GetMetadata(), 141 Start: int(f), 142 End: int(f), 143 }) 144 } 145 } 146 147 func (a *adapter) adaptDestination(ruleBlock *terraform.Block, rule *network.SecurityGroupRule) { 148 if destAddressAttr := ruleBlock.GetAttribute("destination_address_prefix"); destAddressAttr.IsString() { 149 rule.DestinationAddresses = append(rule.DestinationAddresses, destAddressAttr.AsStringValueOrDefault("", ruleBlock)) 150 } else if destAddressPrefixesAttr := ruleBlock.GetAttribute("destination_address_prefixes"); destAddressPrefixesAttr.IsNotNil() { 151 rule.DestinationAddresses = append(rule.DestinationAddresses, destAddressPrefixesAttr.AsStringValues()...) 152 } 153 154 if destPortRangesAttr := ruleBlock.GetAttribute("destination_port_ranges"); destPortRangesAttr.IsNotNil() { 155 ports := destPortRangesAttr.AsStringValues() 156 for _, value := range ports { 157 rule.DestinationPorts = append(rule.DestinationPorts, expandRange(value.Value(), destPortRangesAttr.GetMetadata())) 158 } 159 } else if destPortRangeAttr := ruleBlock.GetAttribute("destination_port_range"); destPortRangeAttr.IsString() { 160 rule.DestinationPorts = append(rule.DestinationPorts, expandRange(destPortRangeAttr.Value().AsString(), destPortRangeAttr.GetMetadata())) 161 } else if destPortRangeAttr := ruleBlock.GetAttribute("destination_port_range"); destPortRangeAttr.IsNumber() { 162 f := destPortRangeAttr.AsNumber() 163 rule.DestinationPorts = append(rule.DestinationPorts, network.PortRange{ 164 Metadata: destPortRangeAttr.GetMetadata(), 165 Start: int(f), 166 End: int(f), 167 }) 168 } 169 } 170 171 func expandRange(r string, m defsecTypes.Metadata) network.PortRange { 172 start := 0 173 end := 65535 174 switch { 175 case r == "*": 176 case strings.Contains(r, "-"): 177 if parts := strings.Split(r, "-"); len(parts) == 2 { 178 if p1, err := strconv.ParseInt(parts[0], 10, 32); err == nil { 179 start = int(p1) 180 } 181 if p2, err := strconv.ParseInt(parts[1], 10, 32); err == nil { 182 end = int(p2) 183 } 184 } 185 default: 186 if val, err := strconv.ParseInt(r, 10, 32); err == nil { 187 start = int(val) 188 end = int(val) 189 } 190 } 191 192 return network.PortRange{ 193 Metadata: m, 194 Start: start, 195 End: end, 196 } 197 } 198 199 func adaptWatcherLog(resource *terraform.Block) network.NetworkWatcherFlowLog { 200 flowLog := network.NetworkWatcherFlowLog{ 201 Metadata: resource.GetMetadata(), 202 RetentionPolicy: network.RetentionPolicy{ 203 Metadata: resource.GetMetadata(), 204 Enabled: defsecTypes.BoolDefault(false, resource.GetMetadata()), 205 Days: defsecTypes.IntDefault(0, resource.GetMetadata()), 206 }, 207 } 208 209 if retentionPolicyBlock := resource.GetBlock("retention_policy"); retentionPolicyBlock.IsNotNil() { 210 flowLog.RetentionPolicy.Metadata = retentionPolicyBlock.GetMetadata() 211 212 enabledAttr := retentionPolicyBlock.GetAttribute("enabled") 213 flowLog.RetentionPolicy.Enabled = enabledAttr.AsBoolValueOrDefault(false, retentionPolicyBlock) 214 215 daysAttr := retentionPolicyBlock.GetAttribute("days") 216 flowLog.RetentionPolicy.Days = daysAttr.AsIntValueOrDefault(0, retentionPolicyBlock) 217 } 218 219 return flowLog 220 }