github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/terraform/azure/storage/adapt.go (about) 1 package storage 2 3 import ( 4 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 5 6 "github.com/khulnasoft-lab/defsec/pkg/providers/azure/storage" 7 "github.com/khulnasoft-lab/defsec/pkg/terraform" 8 ) 9 10 func Adapt(modules terraform.Modules) storage.Storage { 11 accounts, containers, networkRules := adaptAccounts(modules) 12 13 orphanAccount := storage.Account{ 14 Metadata: defsecTypes.NewUnmanagedMetadata(), 15 NetworkRules: adaptOrphanNetworkRules(modules, networkRules), 16 EnforceHTTPS: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 17 Containers: adaptOrphanContainers(modules, containers), 18 QueueProperties: storage.QueueProperties{ 19 Metadata: defsecTypes.NewUnmanagedMetadata(), 20 EnableLogging: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 21 }, 22 MinimumTLSVersion: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 23 } 24 25 accounts = append(accounts, orphanAccount) 26 27 return storage.Storage{ 28 Accounts: accounts, 29 } 30 } 31 32 func adaptOrphanContainers(modules terraform.Modules, containers []string) (orphans []storage.Container) { 33 accountedFor := make(map[string]bool) 34 for _, container := range containers { 35 accountedFor[container] = true 36 } 37 for _, module := range modules { 38 for _, containerResource := range module.GetResourcesByType("azurerm_storage_container") { 39 if _, ok := accountedFor[containerResource.ID()]; ok { 40 continue 41 } 42 orphans = append(orphans, adaptContainer(containerResource)) 43 } 44 } 45 46 return orphans 47 } 48 49 func adaptOrphanNetworkRules(modules terraform.Modules, networkRules []string) (orphans []storage.NetworkRule) { 50 accountedFor := make(map[string]bool) 51 for _, networkRule := range networkRules { 52 accountedFor[networkRule] = true 53 } 54 55 for _, module := range modules { 56 for _, networkRuleResource := range module.GetResourcesByType("azurerm_storage_account_network_rules") { 57 if _, ok := accountedFor[networkRuleResource.ID()]; ok { 58 continue 59 } 60 61 orphans = append(orphans, adaptNetworkRule(networkRuleResource)) 62 } 63 } 64 65 return orphans 66 } 67 68 func adaptAccounts(modules terraform.Modules) ([]storage.Account, []string, []string) { 69 var accounts []storage.Account 70 var accountedForContainers []string 71 var accountedForNetworkRules []string 72 73 for _, module := range modules { 74 for _, resource := range module.GetResourcesByType("azurerm_storage_account") { 75 account := adaptAccount(resource) 76 containerResource := module.GetReferencingResources(resource, "azurerm_storage_container", "storage_account_name") 77 for _, containerBlock := range containerResource { 78 accountedForContainers = append(accountedForContainers, containerBlock.ID()) 79 account.Containers = append(account.Containers, adaptContainer(containerBlock)) 80 } 81 networkRulesResource := module.GetReferencingResources(resource, "azurerm_storage_account_network_rules", "storage_account_name") 82 for _, networkRuleBlock := range networkRulesResource { 83 accountedForNetworkRules = append(accountedForNetworkRules, networkRuleBlock.ID()) 84 account.NetworkRules = append(account.NetworkRules, adaptNetworkRule(networkRuleBlock)) 85 } 86 for _, queueBlock := range module.GetReferencingResources(resource, "azurerm_storage_queue", "storage_account_name") { 87 queue := storage.Queue{ 88 Metadata: queueBlock.GetMetadata(), 89 Name: queueBlock.GetAttribute("name").AsStringValueOrDefault("", queueBlock), 90 } 91 account.Queues = append(account.Queues, queue) 92 } 93 accounts = append(accounts, account) 94 } 95 } 96 97 return accounts, accountedForContainers, accountedForNetworkRules 98 } 99 100 func adaptAccount(resource *terraform.Block) storage.Account { 101 account := storage.Account{ 102 Metadata: resource.GetMetadata(), 103 NetworkRules: nil, 104 EnforceHTTPS: defsecTypes.BoolDefault(true, resource.GetMetadata()), 105 Containers: nil, 106 QueueProperties: storage.QueueProperties{ 107 Metadata: resource.GetMetadata(), 108 EnableLogging: defsecTypes.BoolDefault(false, resource.GetMetadata()), 109 }, 110 MinimumTLSVersion: defsecTypes.StringDefault("TLS1_2", resource.GetMetadata()), 111 } 112 113 networkRulesBlocks := resource.GetBlocks("network_rules") 114 for _, networkBlock := range networkRulesBlocks { 115 account.NetworkRules = append(account.NetworkRules, adaptNetworkRule(networkBlock)) 116 } 117 118 httpsOnlyAttr := resource.GetAttribute("enable_https_traffic_only") 119 account.EnforceHTTPS = httpsOnlyAttr.AsBoolValueOrDefault(true, resource) 120 121 queuePropertiesBlock := resource.GetBlock("queue_properties") 122 if queuePropertiesBlock.IsNotNil() { 123 account.QueueProperties.Metadata = queuePropertiesBlock.GetMetadata() 124 loggingBlock := queuePropertiesBlock.GetBlock("logging") 125 if loggingBlock.IsNotNil() { 126 account.QueueProperties.EnableLogging = defsecTypes.Bool(true, loggingBlock.GetMetadata()) 127 } 128 } 129 130 minTLSVersionAttr := resource.GetAttribute("min_tls_version") 131 account.MinimumTLSVersion = minTLSVersionAttr.AsStringValueOrDefault("TLS1_0", resource) 132 return account 133 } 134 135 func adaptContainer(resource *terraform.Block) storage.Container { 136 accessTypeAttr := resource.GetAttribute("container_access_type") 137 publicAccess := defsecTypes.StringDefault(storage.PublicAccessOff, resource.GetMetadata()) 138 139 if accessTypeAttr.Equals("blob") { 140 publicAccess = defsecTypes.String(storage.PublicAccessBlob, accessTypeAttr.GetMetadata()) 141 } else if accessTypeAttr.Equals("container") { 142 publicAccess = defsecTypes.String(storage.PublicAccessContainer, accessTypeAttr.GetMetadata()) 143 } 144 145 return storage.Container{ 146 Metadata: resource.GetMetadata(), 147 PublicAccess: publicAccess, 148 } 149 } 150 151 func adaptNetworkRule(resource *terraform.Block) storage.NetworkRule { 152 var allowByDefault defsecTypes.BoolValue 153 var bypass []defsecTypes.StringValue 154 155 defaultActionAttr := resource.GetAttribute("default_action") 156 157 if defaultActionAttr.IsNotNil() { 158 allowByDefault = defsecTypes.Bool(defaultActionAttr.Equals("Allow", terraform.IgnoreCase), defaultActionAttr.GetMetadata()) 159 } else { 160 allowByDefault = defsecTypes.BoolDefault(false, resource.GetMetadata()) 161 } 162 163 if resource.HasChild("bypass") { 164 bypassAttr := resource.GetAttribute("bypass") 165 bypass = bypassAttr.AsStringValues() 166 } 167 168 return storage.NetworkRule{ 169 Metadata: resource.GetMetadata(), 170 Bypass: bypass, 171 AllowByDefault: allowByDefault, 172 } 173 }