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  }