github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/internal/adapters/terraform/aws/ec2/vpc.go (about)

     1  package ec2
     2  
     3  import (
     4  	"github.com/aquasecurity/defsec/pkg/providers/aws/ec2"
     5  	"github.com/aquasecurity/defsec/pkg/terraform"
     6  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
     7  )
     8  
     9  type naclAdapter struct {
    10  	naclRuleIDs terraform.ResourceIDResolutions
    11  }
    12  
    13  type sgAdapter struct {
    14  	sgRuleIDs terraform.ResourceIDResolutions
    15  }
    16  
    17  func adaptVPCs(modules terraform.Modules) []ec2.VPC {
    18  	var vpcs []ec2.VPC
    19  	for _, module := range modules {
    20  		for _, resource := range module.GetResourcesByType("aws_default_vpc") {
    21  			vpcs = append(vpcs, adaptVPC(modules, resource, true))
    22  		}
    23  		for _, resource := range module.GetResourcesByType("aws_vpc") {
    24  			vpcs = append(vpcs, adaptVPC(modules, resource, false))
    25  		}
    26  	}
    27  	return vpcs
    28  }
    29  
    30  func adaptVPC(modules terraform.Modules, block *terraform.Block, def bool) ec2.VPC {
    31  	var hasFlowLogs bool
    32  	for _, flow := range modules.GetResourcesByType("aws_flow_log") {
    33  		vpcAttr := flow.GetAttribute("vpc_id")
    34  		if vpcAttr.IsNotNil() {
    35  			if vpcAttr.IsString() {
    36  				if vpcAttr.Equals(block.ID()) {
    37  					hasFlowLogs = true
    38  					break
    39  				}
    40  			}
    41  			if referencedBlock, err := modules.GetReferencedBlock(vpcAttr, flow); err == nil {
    42  				if referencedBlock.ID() == block.ID() {
    43  					hasFlowLogs = true
    44  					break
    45  				}
    46  			}
    47  		}
    48  	}
    49  	return ec2.VPC{
    50  		Metadata:        block.GetMetadata(),
    51  		ID:              defsecTypes.StringUnresolvable(block.GetMetadata()),
    52  		IsDefault:       defsecTypes.Bool(def, block.GetMetadata()),
    53  		SecurityGroups:  nil,
    54  		FlowLogsEnabled: defsecTypes.BoolDefault(hasFlowLogs, block.GetMetadata()),
    55  	}
    56  }
    57  
    58  func (a *sgAdapter) adaptSecurityGroups(modules terraform.Modules) []ec2.SecurityGroup {
    59  	var securityGroups []ec2.SecurityGroup
    60  	for _, resource := range modules.GetResourcesByType("aws_security_group") {
    61  		securityGroups = append(securityGroups, a.adaptSecurityGroup(resource, modules))
    62  	}
    63  	orphanResources := modules.GetResourceByIDs(a.sgRuleIDs.Orphans()...)
    64  	if len(orphanResources) > 0 {
    65  		orphanage := ec2.SecurityGroup{
    66  			Metadata:     defsecTypes.NewUnmanagedMetadata(),
    67  			Description:  defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()),
    68  			IngressRules: nil,
    69  			EgressRules:  nil,
    70  			IsDefault:    defsecTypes.BoolUnresolvable(defsecTypes.NewUnmanagedMetadata()),
    71  			VPCID:        defsecTypes.StringUnresolvable(defsecTypes.NewUnmanagedMetadata()),
    72  		}
    73  		for _, sgRule := range orphanResources {
    74  			if sgRule.GetAttribute("type").Equals("ingress") {
    75  				orphanage.IngressRules = append(orphanage.IngressRules, adaptSGRule(sgRule, modules))
    76  			} else if sgRule.GetAttribute("type").Equals("egress") {
    77  				orphanage.EgressRules = append(orphanage.EgressRules, adaptSGRule(sgRule, modules))
    78  			}
    79  		}
    80  		securityGroups = append(securityGroups, orphanage)
    81  	}
    82  
    83  	return securityGroups
    84  }
    85  
    86  func (a *naclAdapter) adaptNetworkACLs(modules terraform.Modules) []ec2.NetworkACL {
    87  	var networkACLs []ec2.NetworkACL
    88  	for _, module := range modules {
    89  		for _, resource := range module.GetResourcesByType("aws_network_acl") {
    90  			networkACLs = append(networkACLs, a.adaptNetworkACL(resource, module))
    91  		}
    92  	}
    93  
    94  	orphanResources := modules.GetResourceByIDs(a.naclRuleIDs.Orphans()...)
    95  	if len(orphanResources) > 0 {
    96  		orphanage := ec2.NetworkACL{
    97  			Metadata:      defsecTypes.NewUnmanagedMetadata(),
    98  			Rules:         nil,
    99  			IsDefaultRule: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()),
   100  		}
   101  		for _, naclRule := range orphanResources {
   102  			orphanage.Rules = append(orphanage.Rules, adaptNetworkACLRule(naclRule))
   103  		}
   104  		networkACLs = append(networkACLs, orphanage)
   105  	}
   106  
   107  	return networkACLs
   108  }
   109  
   110  func (a *sgAdapter) adaptSecurityGroup(resource *terraform.Block, module terraform.Modules) ec2.SecurityGroup {
   111  	var ingressRules []ec2.SecurityGroupRule
   112  	var egressRules []ec2.SecurityGroupRule
   113  
   114  	descriptionAttr := resource.GetAttribute("description")
   115  	descriptionVal := descriptionAttr.AsStringValueOrDefault("Managed by Terraform", resource)
   116  
   117  	ingressBlocks := resource.GetBlocks("ingress")
   118  	for _, ingressBlock := range ingressBlocks {
   119  		ingressRules = append(ingressRules, adaptSGRule(ingressBlock, module))
   120  	}
   121  
   122  	egressBlocks := resource.GetBlocks("egress")
   123  	for _, egressBlock := range egressBlocks {
   124  		egressRules = append(egressRules, adaptSGRule(egressBlock, module))
   125  	}
   126  
   127  	rulesBlocks := module.GetReferencingResources(resource, "aws_security_group_rule", "security_group_id")
   128  	for _, ruleBlock := range rulesBlocks {
   129  		a.sgRuleIDs.Resolve(ruleBlock.ID())
   130  		if ruleBlock.GetAttribute("type").Equals("ingress") {
   131  			ingressRules = append(ingressRules, adaptSGRule(ruleBlock, module))
   132  		} else if ruleBlock.GetAttribute("type").Equals("egress") {
   133  			egressRules = append(egressRules, adaptSGRule(ruleBlock, module))
   134  		}
   135  	}
   136  
   137  	return ec2.SecurityGroup{
   138  		Metadata:     resource.GetMetadata(),
   139  		Description:  descriptionVal,
   140  		IngressRules: ingressRules,
   141  		EgressRules:  egressRules,
   142  		IsDefault:    defsecTypes.Bool(false, defsecTypes.NewUnmanagedMetadata()),
   143  		VPCID:        resource.GetAttribute("vpc_id").AsStringValueOrDefault("", resource),
   144  	}
   145  }
   146  
   147  func adaptSGRule(resource *terraform.Block, modules terraform.Modules) ec2.SecurityGroupRule {
   148  	ruleDescAttr := resource.GetAttribute("description")
   149  	ruleDescVal := ruleDescAttr.AsStringValueOrDefault("", resource)
   150  
   151  	var cidrs []defsecTypes.StringValue
   152  
   153  	cidrBlocks := resource.GetAttribute("cidr_blocks")
   154  	ipv6cidrBlocks := resource.GetAttribute("ipv6_cidr_blocks")
   155  	varBlocks := modules.GetBlocks().OfType("variable")
   156  
   157  	for _, vb := range varBlocks {
   158  		if cidrBlocks.IsNotNil() && cidrBlocks.ReferencesBlock(vb) {
   159  			cidrBlocks = vb.GetAttribute("default")
   160  		}
   161  		if ipv6cidrBlocks.IsNotNil() && ipv6cidrBlocks.ReferencesBlock(vb) {
   162  			ipv6cidrBlocks = vb.GetAttribute("default")
   163  		}
   164  	}
   165  
   166  	if cidrBlocks.IsNotNil() {
   167  		cidrs = cidrBlocks.AsStringValues()
   168  	}
   169  
   170  	if ipv6cidrBlocks.IsNotNil() {
   171  		cidrs = append(cidrs, ipv6cidrBlocks.AsStringValues()...)
   172  	}
   173  
   174  	return ec2.SecurityGroupRule{
   175  		Metadata:    resource.GetMetadata(),
   176  		Description: ruleDescVal,
   177  		CIDRs:       cidrs,
   178  	}
   179  }
   180  
   181  func (a *naclAdapter) adaptNetworkACL(resource *terraform.Block, module *terraform.Module) ec2.NetworkACL {
   182  	var networkRules []ec2.NetworkACLRule
   183  	rulesBlocks := module.GetReferencingResources(resource, "aws_network_acl_rule", "network_acl_id")
   184  	for _, ruleBlock := range rulesBlocks {
   185  		a.naclRuleIDs.Resolve(ruleBlock.ID())
   186  		networkRules = append(networkRules, adaptNetworkACLRule(ruleBlock))
   187  	}
   188  	return ec2.NetworkACL{
   189  		Metadata:      resource.GetMetadata(),
   190  		Rules:         networkRules,
   191  		IsDefaultRule: defsecTypes.BoolDefault(false, resource.GetMetadata()),
   192  	}
   193  }
   194  
   195  func adaptNetworkACLRule(resource *terraform.Block) ec2.NetworkACLRule {
   196  	var cidrs []defsecTypes.StringValue
   197  
   198  	typeVal := defsecTypes.StringDefault("ingress", resource.GetMetadata())
   199  
   200  	egressAtrr := resource.GetAttribute("egress")
   201  	if egressAtrr.IsTrue() {
   202  		typeVal = defsecTypes.String("egress", egressAtrr.GetMetadata())
   203  	} else if egressAtrr.IsNotNil() {
   204  		typeVal = defsecTypes.String("ingress", egressAtrr.GetMetadata())
   205  	}
   206  
   207  	actionAttr := resource.GetAttribute("rule_action")
   208  	actionVal := actionAttr.AsStringValueOrDefault("", resource)
   209  
   210  	protocolAtrr := resource.GetAttribute("protocol")
   211  	protocolVal := protocolAtrr.AsStringValueOrDefault("-1", resource)
   212  
   213  	cidrAttr := resource.GetAttribute("cidr_block")
   214  	if cidrAttr.IsNotNil() {
   215  		cidrs = append(cidrs, cidrAttr.AsStringValueOrDefault("", resource))
   216  	}
   217  	ipv4cidrAttr := resource.GetAttribute("ipv6_cidr_block")
   218  	if ipv4cidrAttr.IsNotNil() {
   219  		cidrs = append(cidrs, ipv4cidrAttr.AsStringValueOrDefault("", resource))
   220  	}
   221  
   222  	return ec2.NetworkACLRule{
   223  		Metadata: resource.GetMetadata(),
   224  		Type:     typeVal,
   225  		Action:   actionVal,
   226  		Protocol: protocolVal,
   227  		CIDRs:    cidrs,
   228  	}
   229  }