github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/internal/adapters/terraform/aws/rds/adapt.go (about) 1 package rds 2 3 import ( 4 "github.com/aquasecurity/defsec/pkg/providers/aws/rds" 5 "github.com/aquasecurity/defsec/pkg/terraform" 6 defsecTypes "github.com/aquasecurity/defsec/pkg/types" 7 ) 8 9 func Adapt(modules terraform.Modules) rds.RDS { 10 return rds.RDS{ 11 Instances: getInstances(modules), 12 Clusters: getClusters(modules), 13 Classic: getClassic(modules), 14 Snapshots: getSnapshots(modules), 15 ParameterGroups: getParameterGroups(modules), 16 } 17 } 18 19 func getInstances(modules terraform.Modules) (instances []rds.Instance) { 20 for _, resource := range modules.GetResourcesByType("aws_db_instance") { 21 instances = append(instances, adaptInstance(resource, modules)) 22 } 23 24 return instances 25 } 26 27 func getParameterGroups(modules terraform.Modules) (parametergroups []rds.ParameterGroups) { 28 for _, resource := range modules.GetResourcesByType("aws_db_parameter_group") { 29 parametergroups = append(parametergroups, adaptDBParameterGroups(resource, modules)) 30 } 31 32 return parametergroups 33 } 34 35 func getSnapshots(modules terraform.Modules) (snapshots []rds.Snapshots) { 36 for _, resource := range modules.GetResourcesByType("aws_db_snapshot") { 37 snapshots = append(snapshots, adaptDBSnapshots(resource, modules)) 38 } 39 40 return snapshots 41 } 42 43 func getClusters(modules terraform.Modules) (clusters []rds.Cluster) { 44 45 rdsInstanceMaps := modules.GetChildResourceIDMapByType("aws_rds_cluster_instance") 46 for _, resource := range modules.GetResourcesByType("aws_rds_cluster") { 47 cluster, instanceIDs := adaptCluster(resource, modules) 48 for _, id := range instanceIDs { 49 rdsInstanceMaps.Resolve(id) 50 } 51 clusters = append(clusters, cluster) 52 } 53 54 orphanResources := modules.GetResourceByIDs(rdsInstanceMaps.Orphans()...) 55 56 if len(orphanResources) > 0 { 57 orphanage := rds.Cluster{ 58 Metadata: defsecTypes.NewUnmanagedMetadata(), 59 BackupRetentionPeriodDays: defsecTypes.IntDefault(1, defsecTypes.NewUnmanagedMetadata()), 60 ReplicationSourceARN: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 61 PerformanceInsights: rds.PerformanceInsights{ 62 Metadata: defsecTypes.NewUnmanagedMetadata(), 63 Enabled: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 64 KMSKeyID: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 65 }, 66 Instances: nil, 67 Encryption: rds.Encryption{ 68 Metadata: defsecTypes.NewUnmanagedMetadata(), 69 EncryptStorage: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 70 KMSKeyID: defsecTypes.StringDefault("", defsecTypes.NewUnmanagedMetadata()), 71 }, 72 PublicAccess: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 73 Engine: defsecTypes.StringUnresolvable(defsecTypes.NewUnmanagedMetadata()), 74 LatestRestorableTime: defsecTypes.TimeUnresolvable(defsecTypes.NewUnmanagedMetadata()), 75 DeletionProtection: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 76 } 77 for _, orphan := range orphanResources { 78 orphanage.Instances = append(orphanage.Instances, adaptClusterInstance(orphan, modules)) 79 } 80 clusters = append(clusters, orphanage) 81 } 82 83 return clusters 84 } 85 86 func getClassic(modules terraform.Modules) rds.Classic { 87 classic := rds.Classic{ 88 DBSecurityGroups: nil, 89 } 90 for _, resource := range modules.GetResourcesByType("aws_db_security_group", "aws_redshift_security_group", "aws_elasticache_security_group") { 91 classic.DBSecurityGroups = append(classic.DBSecurityGroups, adaptClassicDBSecurityGroup(resource)) 92 } 93 return classic 94 } 95 96 func adaptClusterInstance(resource *terraform.Block, modules terraform.Modules) rds.ClusterInstance { 97 clusterIdAttr := resource.GetAttribute("cluster_identifier") 98 clusterId := clusterIdAttr.AsStringValueOrDefault("", resource) 99 100 if clusterIdAttr.IsResourceBlockReference("aws_rds_cluster") { 101 if referenced, err := modules.GetReferencedBlock(clusterIdAttr, resource); err == nil { 102 clusterId = defsecTypes.String(referenced.FullName(), referenced.GetMetadata()) 103 } 104 } 105 106 return rds.ClusterInstance{ 107 ClusterIdentifier: clusterId, 108 Instance: adaptInstance(resource, modules), 109 } 110 } 111 112 func adaptClassicDBSecurityGroup(resource *terraform.Block) rds.DBSecurityGroup { 113 return rds.DBSecurityGroup{ 114 Metadata: resource.GetMetadata(), 115 } 116 } 117 118 func adaptInstance(resource *terraform.Block, modules terraform.Modules) rds.Instance { 119 120 var ReadReplicaDBInstanceIdentifiers []defsecTypes.StringValue 121 rrdiAttr := resource.GetAttribute("replicate_source_db") 122 for _, rrdi := range rrdiAttr.AsStringValues() { 123 ReadReplicaDBInstanceIdentifiers = append(ReadReplicaDBInstanceIdentifiers, rrdi) 124 } 125 126 var TagList []rds.TagList 127 tagres := resource.GetBlocks("tags") 128 for _, tagres := range tagres { 129 130 TagList = append(TagList, rds.TagList{ 131 Metadata: tagres.GetMetadata(), 132 }) 133 } 134 135 var EnabledCloudwatchLogsExports []defsecTypes.StringValue 136 ecweAttr := resource.GetAttribute("enabled_cloudwatch_logs_exports") 137 for _, ecwe := range ecweAttr.AsStringValues() { 138 EnabledCloudwatchLogsExports = append(EnabledCloudwatchLogsExports, ecwe) 139 } 140 141 replicaSource := resource.GetAttribute("replicate_source_db") 142 replicaSourceValue := "" 143 if replicaSource.IsNotNil() { 144 if referenced, err := modules.GetReferencedBlock(replicaSource, resource); err == nil { 145 replicaSourceValue = referenced.ID() 146 } 147 } 148 return rds.Instance{ 149 Metadata: resource.GetMetadata(), 150 BackupRetentionPeriodDays: resource.GetAttribute("backup_retention_period").AsIntValueOrDefault(0, resource), 151 ReplicationSourceARN: defsecTypes.StringExplicit(replicaSourceValue, resource.GetMetadata()), 152 PerformanceInsights: adaptPerformanceInsights(resource), 153 Encryption: adaptEncryption(resource), 154 PublicAccess: resource.GetAttribute("publicly_accessible").AsBoolValueOrDefault(false, resource), 155 Engine: resource.GetAttribute("engine").AsStringValueOrDefault(rds.EngineAurora, resource), 156 IAMAuthEnabled: resource.GetAttribute("iam_database_authentication_enabled").AsBoolValueOrDefault(false, resource), 157 DeletionProtection: resource.GetAttribute("deletion_protection").AsBoolValueOrDefault(false, resource), 158 DBInstanceArn: resource.GetAttribute("arn").AsStringValueOrDefault("", resource), 159 StorageEncrypted: resource.GetAttribute("storage_encrypted").AsBoolValueOrDefault(true, resource), 160 DBInstanceIdentifier: resource.GetAttribute("identifier").AsStringValueOrDefault("", resource), 161 EngineVersion: resource.GetAttribute("engine_version").AsStringValueOrDefault("", resource), 162 AutoMinorVersionUpgrade: resource.GetAttribute("auto_minor_version_upgrade").AsBoolValueOrDefault(false, resource), 163 MultiAZ: resource.GetAttribute("multi_az").AsBoolValueOrDefault(false, resource), 164 PubliclyAccessible: resource.GetAttribute("publicly_accessible").AsBoolValueOrDefault(false, resource), 165 LatestRestorableTime: defsecTypes.TimeUnresolvable(resource.GetMetadata()), 166 ReadReplicaDBInstanceIdentifiers: ReadReplicaDBInstanceIdentifiers, 167 TagList: TagList, 168 EnabledCloudwatchLogsExports: EnabledCloudwatchLogsExports, 169 } 170 } 171 172 func adaptDBParameterGroups(resource *terraform.Block, modules terraform.Modules) rds.ParameterGroups { 173 174 var Parameters []rds.Parameters 175 paramres := resource.GetBlocks("parameter") 176 for _, paramres := range paramres { 177 178 Parameters = append(Parameters, rds.Parameters{ 179 Metadata: paramres.GetMetadata(), 180 ParameterName: defsecTypes.StringDefault("", paramres.GetMetadata()), 181 ParameterValue: defsecTypes.StringDefault("", paramres.GetMetadata()), 182 }) 183 } 184 185 return rds.ParameterGroups{ 186 Metadata: resource.GetMetadata(), 187 DBParameterGroupName: resource.GetAttribute("name").AsStringValueOrDefault("", resource), 188 DBParameterGroupFamily: resource.GetAttribute("family").AsStringValueOrDefault("", resource), 189 Parameters: Parameters, 190 } 191 } 192 193 func adaptDBSnapshots(resource *terraform.Block, modules terraform.Modules) rds.Snapshots { 194 195 return rds.Snapshots{ 196 Metadata: resource.GetMetadata(), 197 DBSnapshotIdentifier: resource.GetAttribute("db_snapshot_identifier").AsStringValueOrDefault("", resource), 198 DBSnapshotArn: resource.GetAttribute("db_snapshot_arn").AsStringValueOrDefault("", resource), 199 Encrypted: resource.GetAttribute("encrypted").AsBoolValueOrDefault(true, resource), 200 KmsKeyId: resource.GetAttribute("kms_key_id").AsStringValueOrDefault("", resource), 201 SnapshotAttributes: nil, 202 } 203 } 204 205 func adaptCluster(resource *terraform.Block, modules terraform.Modules) (rds.Cluster, []string) { 206 207 clusterInstances, ids := getClusterInstances(resource, modules) 208 209 var public bool 210 for _, instance := range clusterInstances { 211 if instance.PublicAccess.IsTrue() { 212 public = true 213 break 214 } 215 } 216 217 return rds.Cluster{ 218 Metadata: resource.GetMetadata(), 219 BackupRetentionPeriodDays: resource.GetAttribute("backup_retention_period").AsIntValueOrDefault(1, resource), 220 ReplicationSourceARN: resource.GetAttribute("replication_source_identifier").AsStringValueOrDefault("", resource), 221 PerformanceInsights: adaptPerformanceInsights(resource), 222 Instances: clusterInstances, 223 Encryption: adaptEncryption(resource), 224 PublicAccess: defsecTypes.Bool(public, resource.GetMetadata()), 225 Engine: resource.GetAttribute("engine").AsStringValueOrDefault(rds.EngineAurora, resource), 226 LatestRestorableTime: defsecTypes.TimeUnresolvable(resource.GetMetadata()), 227 AvailabilityZones: resource.GetAttribute("availability_zones").AsStringValueSliceOrEmpty(), 228 DeletionProtection: resource.GetAttribute("deletion_protection").AsBoolValueOrDefault(false, resource), 229 }, ids 230 } 231 232 func getClusterInstances(resource *terraform.Block, modules terraform.Modules) (clusterInstances []rds.ClusterInstance, instanceIDs []string) { 233 clusterInstanceResources := modules.GetReferencingResources(resource, "aws_rds_cluster_instance", "cluster_identifier") 234 235 for _, ciResource := range clusterInstanceResources { 236 instanceIDs = append(instanceIDs, ciResource.ID()) 237 clusterInstances = append(clusterInstances, adaptClusterInstance(ciResource, modules)) 238 } 239 return clusterInstances, instanceIDs 240 } 241 242 func adaptPerformanceInsights(resource *terraform.Block) rds.PerformanceInsights { 243 return rds.PerformanceInsights{ 244 Metadata: resource.GetMetadata(), 245 Enabled: resource.GetAttribute("performance_insights_enabled").AsBoolValueOrDefault(false, resource), 246 KMSKeyID: resource.GetAttribute("performance_insights_kms_key_id").AsStringValueOrDefault("", resource), 247 } 248 } 249 250 func adaptEncryption(resource *terraform.Block) rds.Encryption { 251 return rds.Encryption{ 252 Metadata: resource.GetMetadata(), 253 EncryptStorage: resource.GetAttribute("storage_encrypted").AsBoolValueOrDefault(false, resource), 254 KMSKeyID: resource.GetAttribute("kms_key_id").AsStringValueOrDefault("", resource), 255 } 256 }