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  }