github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/cloudformation/aws/s3/bucket.go (about) 1 package s3 2 3 import ( 4 "regexp" 5 "strings" 6 7 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 8 9 "github.com/khulnasoft-lab/defsec/pkg/providers/aws/s3" 10 "github.com/khulnasoft-lab/defsec/pkg/scanners/cloudformation/parser" 11 ) 12 13 var aclConvertRegex = regexp.MustCompile(`[A-Z][^A-Z]*`) 14 15 func getBuckets(cfFile parser.FileContext) []s3.Bucket { 16 var buckets []s3.Bucket 17 bucketResources := cfFile.GetResourcesByType("AWS::S3::Bucket") 18 19 for _, r := range bucketResources { 20 s3b := s3.Bucket{ 21 Metadata: r.Metadata(), 22 Name: r.GetStringProperty("BucketName"), 23 PublicAccessBlock: getPublicAccessBlock(r), 24 Encryption: getEncryption(r, cfFile), 25 Versioning: s3.Versioning{ 26 Metadata: r.Metadata(), 27 Enabled: hasVersioning(r), 28 MFADelete: defsecTypes.BoolUnresolvable(r.Metadata()), 29 }, 30 Logging: getLogging(r), 31 ACL: convertAclValue(r.GetStringProperty("AccessControl", "private")), 32 LifecycleConfiguration: getLifecycle(r), 33 AccelerateConfigurationStatus: r.GetStringProperty("AccelerateConfiguration.AccelerationStatus"), 34 Website: getWebsite(r), 35 BucketLocation: defsecTypes.String("", r.Metadata()), 36 Objects: nil, 37 } 38 39 buckets = append(buckets, s3b) 40 } 41 return buckets 42 } 43 44 func getPublicAccessBlock(r *parser.Resource) *s3.PublicAccessBlock { 45 if block := r.GetProperty("PublicAccessBlockConfiguration"); block.IsNil() { 46 return nil 47 } 48 49 return &s3.PublicAccessBlock{ 50 Metadata: r.Metadata(), 51 BlockPublicACLs: r.GetBoolProperty("PublicAccessBlockConfiguration.BlockPublicAcls"), 52 BlockPublicPolicy: r.GetBoolProperty("PublicAccessBlockConfiguration.BlockPublicPolicy"), 53 IgnorePublicACLs: r.GetBoolProperty("PublicAccessBlockConfiguration.IgnorePublicAcls"), 54 RestrictPublicBuckets: r.GetBoolProperty("PublicAccessBlockConfiguration.RestrictPublicBuckets"), 55 } 56 } 57 58 func convertAclValue(aclValue defsecTypes.StringValue) defsecTypes.StringValue { 59 matches := aclConvertRegex.FindAllString(aclValue.Value(), -1) 60 61 return defsecTypes.String(strings.ToLower(strings.Join(matches, "-")), aclValue.GetMetadata()) 62 } 63 64 func getLogging(r *parser.Resource) s3.Logging { 65 66 logging := s3.Logging{ 67 Metadata: r.Metadata(), 68 Enabled: defsecTypes.BoolDefault(false, r.Metadata()), 69 TargetBucket: defsecTypes.StringDefault("", r.Metadata()), 70 } 71 72 if config := r.GetProperty("LoggingConfiguration"); config.IsNotNil() { 73 logging.TargetBucket = config.GetStringProperty("DestinationBucketName") 74 if logging.TargetBucket.IsNotEmpty() || !logging.TargetBucket.GetMetadata().IsResolvable() { 75 logging.Enabled = defsecTypes.Bool(true, config.Metadata()) 76 } 77 } 78 return logging 79 } 80 81 func hasVersioning(r *parser.Resource) defsecTypes.BoolValue { 82 versioningProp := r.GetProperty("VersioningConfiguration.Status") 83 84 if versioningProp.IsNil() { 85 return defsecTypes.BoolDefault(false, r.Metadata()) 86 } 87 88 versioningEnabled := false 89 if versioningProp.EqualTo("Enabled") { 90 versioningEnabled = true 91 92 } 93 return defsecTypes.Bool(versioningEnabled, versioningProp.Metadata()) 94 } 95 96 func getEncryption(r *parser.Resource, _ parser.FileContext) s3.Encryption { 97 98 encryption := s3.Encryption{ 99 Metadata: r.Metadata(), 100 Enabled: defsecTypes.BoolDefault(false, r.Metadata()), 101 Algorithm: defsecTypes.StringDefault("", r.Metadata()), 102 KMSKeyId: defsecTypes.StringDefault("", r.Metadata()), 103 } 104 105 if encryptProps := r.GetProperty("BucketEncryption.ServerSideEncryptionConfiguration"); encryptProps.IsNotNil() { 106 for _, rule := range encryptProps.AsList() { 107 if algo := rule.GetProperty("ServerSideEncryptionByDefault.SSEAlgorithm"); algo.EqualTo("AES256") { 108 encryption.Enabled = defsecTypes.Bool(true, algo.Metadata()) 109 } else if kmsKeyProp := rule.GetProperty("ServerSideEncryptionByDefault.KMSMasterKeyID"); !kmsKeyProp.IsEmpty() && kmsKeyProp.IsString() { 110 encryption.KMSKeyId = kmsKeyProp.AsStringValue() 111 } 112 if encryption.Enabled.IsFalse() { 113 encryption.Enabled = rule.GetBoolProperty("BucketKeyEnabled", false) 114 } 115 } 116 } 117 118 return encryption 119 } 120 121 func getLifecycle(resource *parser.Resource) []s3.Rules { 122 LifecycleProp := resource.GetProperty("LifecycleConfiguration") 123 RuleProp := LifecycleProp.GetProperty("Rules") 124 125 var rule []s3.Rules 126 127 if RuleProp.IsNil() || RuleProp.IsNotList() { 128 return rule 129 } 130 131 for _, r := range RuleProp.AsList() { 132 rule = append(rule, s3.Rules{ 133 Metadata: r.Metadata(), 134 Status: r.GetStringProperty("Status"), 135 }) 136 } 137 return rule 138 } 139 140 func getWebsite(r *parser.Resource) *s3.Website { 141 if block := r.GetProperty("WebsiteConfiguration"); block.IsNil() { 142 return nil 143 } else { 144 return &s3.Website{ 145 Metadata: block.Metadata(), 146 } 147 } 148 }