github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/terraform/aws/s3/bucket.go (about) 1 package s3 2 3 import ( 4 "github.com/khulnasoft-lab/defsec/pkg/providers/aws/s3" 5 "github.com/khulnasoft-lab/defsec/pkg/terraform" 6 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 7 ) 8 9 type adapter struct { 10 modules terraform.Modules 11 bucketMap map[string]*s3.Bucket 12 } 13 14 func (a *adapter) adaptBuckets() []s3.Bucket { 15 for _, block := range a.modules.GetResourcesByType("aws_s3_bucket") { 16 bucket := &s3.Bucket{ 17 Metadata: block.GetMetadata(), 18 Name: block.GetAttribute("bucket").AsStringValueOrDefault("", block), 19 PublicAccessBlock: nil, 20 BucketPolicies: nil, 21 Encryption: getEncryption(block, a), 22 Versioning: getVersioning(block, a), 23 Logging: getLogging(block, a), 24 ACL: getBucketAcl(block, a), 25 AccelerateConfigurationStatus: getaccelerateStatus(block, a), 26 BucketLocation: block.GetAttribute("region").AsStringValueOrDefault("", block), 27 LifecycleConfiguration: getLifecycle(block, a), 28 Website: getWebsite(block, a), 29 Objects: getObject(block, a), 30 } 31 a.bucketMap[block.ID()] = bucket 32 } 33 34 a.adaptBucketPolicies() 35 a.adaptPublicAccessBlocks() 36 37 var buckets []s3.Bucket 38 for _, bucket := range a.bucketMap { 39 buckets = append(buckets, *bucket) 40 } 41 42 return buckets 43 } 44 45 func getEncryption(block *terraform.Block, a *adapter) s3.Encryption { 46 if block.HasChild("server_side_encryption_configuration") { 47 return s3.Encryption{ 48 Metadata: block.GetMetadata(), 49 Enabled: isEncrypted(block.GetBlock("server_side_encryption_configuration")), 50 Algorithm: block.GetNestedAttribute("server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm").AsStringValueOrDefault("", block), 51 KMSKeyId: block.GetNestedAttribute("server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.kms_master_key_id").AsStringValueOrDefault("", block), 52 } 53 } 54 if val, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_server_side_encryption_configuration", func(resource *terraform.Block) s3.Encryption { 55 return s3.Encryption{ 56 Metadata: resource.GetMetadata(), 57 Enabled: isEncrypted(resource), 58 Algorithm: resource.GetNestedAttribute("rule.apply_server_side_encryption_by_default.sse_algorithm").AsStringValueOrDefault("", block), 59 KMSKeyId: resource.GetNestedAttribute("rule.apply_server_side_encryption_by_default.kms_master_key_id").AsStringValueOrDefault("", block), 60 } 61 }); ok { 62 return val 63 } 64 return s3.Encryption{ 65 Metadata: block.GetMetadata(), 66 Enabled: defsecTypes.BoolDefault(false, block.GetMetadata()), 67 KMSKeyId: defsecTypes.StringDefault("", block.GetMetadata()), 68 Algorithm: defsecTypes.StringDefault("", block.GetMetadata()), 69 } 70 } 71 72 func getVersioning(block *terraform.Block, a *adapter) s3.Versioning { 73 versioning := s3.Versioning{ 74 Metadata: block.GetMetadata(), 75 Enabled: defsecTypes.BoolDefault(false, block.GetMetadata()), 76 MFADelete: defsecTypes.BoolDefault(false, block.GetMetadata()), 77 } 78 if lockBlock := block.GetBlock("object_lock_configuration"); lockBlock != nil { 79 if enabled := isObjeckLockEnabled(lockBlock); enabled != nil { 80 versioning.Enabled = *enabled 81 } 82 } 83 if vBlock := block.GetBlock("versioning"); vBlock != nil { 84 versioning.Enabled = vBlock.GetAttribute("enabled").AsBoolValueOrDefault(true, vBlock) 85 versioning.MFADelete = vBlock.GetAttribute("mfa_delete").AsBoolValueOrDefault(false, vBlock) 86 } 87 88 if enabled, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_object_lock_configuration", func(resource *terraform.Block) *defsecTypes.BoolValue { 89 if block.GetAttribute("object_lock_enabled").IsTrue() { 90 return isObjeckLockEnabled(resource) 91 } 92 return nil 93 }); ok && enabled != nil { 94 versioning.Enabled = *enabled 95 } 96 97 if val, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_versioning", getVersioningFromResource); ok { 98 return val 99 } 100 return versioning 101 } 102 103 func isObjeckLockEnabled(resource *terraform.Block) *defsecTypes.BoolValue { 104 var val defsecTypes.BoolValue 105 attr := resource.GetAttribute("object_lock_enabled") 106 switch { 107 case attr.IsNil(): // enabled by default 108 val = defsecTypes.BoolDefault(true, resource.GetMetadata()) 109 case attr.Equals("Enabled"): 110 val = defsecTypes.Bool(true, attr.GetMetadata()) 111 } 112 return &val 113 } 114 115 // from aws_s3_bucket_versioning 116 func getVersioningFromResource(block *terraform.Block) s3.Versioning { 117 versioning := s3.Versioning{ 118 Metadata: block.GetMetadata(), 119 Enabled: defsecTypes.BoolDefault(false, block.GetMetadata()), 120 MFADelete: defsecTypes.BoolDefault(false, block.GetMetadata()), 121 } 122 if config := block.GetBlock("versioning_configuration"); config != nil { 123 if status := config.GetAttribute("status"); status.IsNotNil() { 124 versioning.Enabled = defsecTypes.Bool(status.Equals("Enabled", terraform.IgnoreCase), status.GetMetadata()) 125 } 126 if mfa := config.GetAttribute("mfa_delete"); mfa.IsNotNil() { 127 versioning.MFADelete = defsecTypes.Bool(mfa.Equals("Enabled", terraform.IgnoreCase), mfa.GetMetadata()) 128 } 129 } 130 return versioning 131 } 132 133 func getLogging(block *terraform.Block, a *adapter) s3.Logging { 134 if loggingBlock := block.GetBlock("logging"); loggingBlock.IsNotNil() { 135 targetBucket := loggingBlock.GetAttribute("target_bucket").AsStringValueOrDefault("", loggingBlock) 136 if referencedBlock, err := a.modules.GetReferencedBlock(loggingBlock.GetAttribute("target_bucket"), loggingBlock); err == nil { 137 targetBucket = defsecTypes.String(referencedBlock.FullName(), loggingBlock.GetAttribute("target_bucket").GetMetadata()) 138 } 139 return s3.Logging{ 140 Metadata: loggingBlock.GetMetadata(), 141 Enabled: defsecTypes.Bool(true, loggingBlock.GetMetadata()), 142 TargetBucket: targetBucket, 143 } 144 } 145 146 if val, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_logging", func(resource *terraform.Block) s3.Logging { 147 targetBucket := resource.GetAttribute("target-bucket").AsStringValueOrDefault("", resource) 148 if referencedBlock, err := a.modules.GetReferencedBlock(resource.GetAttribute("target_bucket"), resource); err == nil { 149 targetBucket = defsecTypes.String(referencedBlock.FullName(), resource.GetAttribute("target_bucket").GetMetadata()) 150 } 151 return s3.Logging{ 152 Metadata: resource.GetMetadata(), 153 Enabled: hasLogging(resource), 154 TargetBucket: targetBucket, 155 } 156 }); ok { 157 return val 158 } 159 160 return s3.Logging{ 161 Metadata: block.GetMetadata(), 162 Enabled: defsecTypes.Bool(false, block.GetMetadata()), 163 TargetBucket: defsecTypes.StringDefault("", block.GetMetadata()), 164 } 165 } 166 167 func getBucketAcl(block *terraform.Block, a *adapter) defsecTypes.StringValue { 168 aclAttr := block.GetAttribute("acl") 169 if aclAttr.IsString() { 170 return aclAttr.AsStringValueOrDefault("private", block) 171 } 172 173 if val, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_acl", func(resource *terraform.Block) defsecTypes.StringValue { 174 return resource.GetAttribute("acl").AsStringValueOrDefault("private", resource) 175 }); ok { 176 return val 177 } 178 return defsecTypes.StringDefault("private", block.GetMetadata()) 179 } 180 181 func isEncrypted(encryptionBlock *terraform.Block) defsecTypes.BoolValue { 182 ruleBlock := encryptionBlock.GetBlock("rule") 183 if ruleBlock.IsNil() { 184 return defsecTypes.BoolDefault(false, encryptionBlock.GetMetadata()) 185 } 186 defaultBlock := ruleBlock.GetBlock("apply_server_side_encryption_by_default") 187 if defaultBlock.IsNil() { 188 return defsecTypes.BoolDefault(false, ruleBlock.GetMetadata()) 189 } 190 sseAlgorithm := defaultBlock.GetAttribute("sse_algorithm") 191 if sseAlgorithm.IsNil() { 192 return defsecTypes.BoolDefault(false, defaultBlock.GetMetadata()) 193 } 194 return defsecTypes.Bool( 195 true, 196 sseAlgorithm.GetMetadata(), 197 ) 198 } 199 200 func hasLogging(b *terraform.Block) defsecTypes.BoolValue { 201 if loggingBlock := b.GetBlock("logging"); loggingBlock.IsNotNil() { 202 if targetAttr := loggingBlock.GetAttribute("target_bucket"); targetAttr.IsNotNil() && targetAttr.IsNotEmpty() { 203 return defsecTypes.Bool(true, targetAttr.GetMetadata()) 204 } 205 return defsecTypes.BoolDefault(false, loggingBlock.GetMetadata()) 206 } 207 if targetBucket := b.GetAttribute("target_bucket"); targetBucket.IsNotNil() { 208 return defsecTypes.Bool(true, targetBucket.GetMetadata()) 209 } 210 return defsecTypes.BoolDefault(false, b.GetMetadata()) 211 } 212 213 func getLifecycle(b *terraform.Block, a *adapter) []s3.Rules { 214 215 var rules []s3.Rules 216 for _, r := range a.modules.GetReferencingResources(b, "aws_s3_bucket_lifecycle_configuration", "bucket") { 217 ruleblock := r.GetBlocks("rule") 218 for _, rule := range ruleblock { 219 rules = append(rules, s3.Rules{ 220 Metadata: rule.GetMetadata(), 221 Status: rule.GetAttribute("status").AsStringValueOrDefault("Enabled", rule), 222 }) 223 } 224 } 225 return rules 226 } 227 228 func getWebsite(b *terraform.Block, a *adapter) (website *s3.Website) { 229 for _, r := range a.modules.GetReferencingResources(b, "aws_s3_bucket_website_configuration", "bucket") { 230 website = &s3.Website{ 231 Metadata: r.GetMetadata(), 232 } 233 } 234 return website 235 } 236 237 func getObject(b *terraform.Block, a *adapter) []s3.Contents { 238 var object []s3.Contents 239 for _, r := range a.modules.GetReferencingResources(b, "aws_s3_object", "bucket") { 240 object = append(object, s3.Contents{ 241 Metadata: r.GetMetadata(), 242 }) 243 } 244 return object 245 } 246 247 func getaccelerateStatus(b *terraform.Block, a *adapter) defsecTypes.StringValue { 248 var status defsecTypes.StringValue 249 for _, r := range a.modules.GetReferencingResources(b, " aws_s3_bucket_accelerate_configuration", "bucket") { 250 status = r.GetAttribute("status").AsStringValueOrDefault("Enabled", r) 251 } 252 return status 253 } 254 255 func applyForBucketRelatedResource[T any](a *adapter, block *terraform.Block, resType string, fn func(resource *terraform.Block) T) (T, bool) { 256 for _, resource := range a.modules.GetResourcesByType(resType) { 257 bucketAttr := resource.GetAttribute("bucket") 258 if bucketAttr.IsNotNil() { 259 if bucketAttr.IsString() { 260 actualBucketName := block.GetAttribute("bucket").AsStringValueOrDefault("", block).Value() 261 if bucketAttr.Equals(block.ID()) || bucketAttr.Equals(actualBucketName) { 262 return fn(resource), true 263 } 264 } 265 if referencedBlock, err := a.modules.GetReferencedBlock(bucketAttr, resource); err == nil { 266 if referencedBlock.ID() == block.ID() { 267 return fn(resource), true 268 } 269 } 270 } 271 272 } 273 var res T 274 return res, false 275 }