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 }