diff --git a/providers/aws/resources/shared.go b/providers/aws/resources/aws.go similarity index 97% rename from providers/aws/resources/shared.go rename to providers/aws/resources/aws.go index fcbffb0a74..e73071ba89 100644 --- a/providers/aws/resources/shared.go +++ b/providers/aws/resources/aws.go @@ -8,6 +8,7 @@ import ( "crypto/x509" "encoding/pem" "errors" + "fmt" "io" "strings" @@ -45,6 +46,10 @@ const ( apiStageArnPattern = "arn:aws:apigateway:%s:%s::/apis/%s/stages/%s" ) +func NewSecurityGroupArn(region, accountID, sgID string) string { + return fmt.Sprintf(securityGroupArnPattern, region, accountID, sgID) +} + func (a *mqlAws) regions() ([]interface{}, error) { conn := a.MqlRuntime.Connection.(*connection.AwsConnection) res := []interface{}{} diff --git a/providers/aws/resources/aws.lr b/providers/aws/resources/aws.lr index 1be96ab6bb..509750766e 100644 --- a/providers/aws/resources/aws.lr +++ b/providers/aws/resources/aws.lr @@ -2325,7 +2325,7 @@ private aws.elasticache.cluster @defaults("cacheClusterId region nodeType engine // Region where the cluster exists region string // A list of VPC security groups associated with the cluster - securityGroups []aws.ec2.securitygroup + securityGroups() []aws.ec2.securitygroup // The number of days for which ElastiCache retains automatic cluster snapshots before deleting them snapshotRetentionLimit int // Whether in-transit encryption is enabled @@ -2351,7 +2351,7 @@ private aws.elasticache.serverlessCache @defaults("name description status engin // ID of the Amazon Web Services Key Management Service (KMS) key kmsKeyId string // A list of VPC security groups associated with the cluster - securityGroups []aws.ec2.securitygroup + securityGroups() []aws.ec2.securitygroup // The number of days for which ElastiCache retains automatic cluster snapshots before deleting them snapshotRetentionLimit int // Time that a cache snapshot will be created diff --git a/providers/aws/resources/aws.lr.go b/providers/aws/resources/aws.lr.go index a4ffdcf12e..9a699dcc85 100644 --- a/providers/aws/resources/aws.lr.go +++ b/providers/aws/resources/aws.lr.go @@ -22724,7 +22724,7 @@ func (c *mqlAwsElasticache) GetServerlessCaches() *plugin.TValue[[]interface{}] type mqlAwsElasticacheCluster struct { MqlRuntime *plugin.Runtime __id string - // optional: if you define mqlAwsElasticacheClusterInternal it will be used here + mqlAwsElasticacheClusterInternal Arn plugin.TValue[string] AtRestEncryptionEnabled plugin.TValue[bool] AuthTokenEnabled plugin.TValue[bool] @@ -22879,7 +22879,19 @@ func (c *mqlAwsElasticacheCluster) GetRegion() *plugin.TValue[string] { } func (c *mqlAwsElasticacheCluster) GetSecurityGroups() *plugin.TValue[[]interface{}] { - return &c.SecurityGroups + return plugin.GetOrCompute[[]interface{}](&c.SecurityGroups, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("aws.elasticache.cluster", c.__id, "securityGroups") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.securityGroups() + }) } func (c *mqlAwsElasticacheCluster) GetSnapshotRetentionLimit() *plugin.TValue[int64] { @@ -22898,7 +22910,7 @@ func (c *mqlAwsElasticacheCluster) GetTransitEncryptionMode() *plugin.TValue[str type mqlAwsElasticacheServerlessCache struct { MqlRuntime *plugin.Runtime __id string - // optional: if you define mqlAwsElasticacheServerlessCacheInternal it will be used here + mqlAwsElasticacheServerlessCacheInternal Arn plugin.TValue[string] Name plugin.TValue[string] Description plugin.TValue[string] @@ -22975,7 +22987,19 @@ func (c *mqlAwsElasticacheServerlessCache) GetKmsKeyId() *plugin.TValue[string] } func (c *mqlAwsElasticacheServerlessCache) GetSecurityGroups() *plugin.TValue[[]interface{}] { - return &c.SecurityGroups + return plugin.GetOrCompute[[]interface{}](&c.SecurityGroups, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("aws.elasticache.serverlessCache", c.__id, "securityGroups") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.securityGroups() + }) } func (c *mqlAwsElasticacheServerlessCache) GetSnapshotRetentionLimit() *plugin.TValue[int64] { diff --git a/providers/aws/resources/aws_elasticache.go b/providers/aws/resources/aws_elasticache.go index 02f2fdd325..5215a41dc1 100644 --- a/providers/aws/resources/aws_elasticache.go +++ b/providers/aws/resources/aws_elasticache.go @@ -5,7 +5,6 @@ package resources import ( "context" - "fmt" "github.com/aws/aws-sdk-go-v2/service/elasticache" elasticache_types "github.com/aws/aws-sdk-go-v2/service/elasticache/types" "github.com/rs/zerolog/log" @@ -17,6 +16,30 @@ import ( "go.mondoo.com/cnquery/v11/types" ) +type securityGroupIdHandler struct { + securityGroupArns []string +} + +func (sgh *securityGroupIdHandler) setSecurityGroupArns(ids []string) { + sgh.securityGroupArns = ids +} + +func (sgh *securityGroupIdHandler) newSecurityGroupResources(runtime *plugin.Runtime) ([]interface{}, error) { + sgs := []interface{}{} + for i := range sgh.securityGroupArns { + sgArn := sgh.securityGroupArns[i] + mqlSg, err := NewResource(runtime, "aws.ec2.securitygroup", + map[string]*llx.RawData{ + "arn": llx.StringData(sgArn), + }) + if err != nil { + return nil, err + } + sgs = append(sgs, mqlSg) + } + return sgs, nil +} + func (a *mqlAwsElasticache) id() (string, error) { return "aws.elasticache", nil } @@ -156,6 +179,10 @@ func (a *mqlAwsElasticache) getCacheClusters(conn *connection.AwsConnection) []* return tasks } +type mqlAwsElasticacheClusterInternal struct { + securityGroupIdHandler +} + func newMqlAwsElasticacheCluster(runtime *plugin.Runtime, region string, accountID string, cluster elasticache_types.CacheCluster) (*mqlAwsElasticacheCluster, error) { cacheNodes := []interface{}{} for i := range cluster.CacheNodes { @@ -174,20 +201,17 @@ func newMqlAwsElasticacheCluster(runtime *plugin.Runtime, region string, account notificationConfiguration = convert.ToString(cluster.NotificationConfiguration.TopicArn) } - sgs := []interface{}{} + sgs := []string{} for i := range cluster.SecurityGroups { sg := cluster.SecurityGroups[i] - mqlSg, err := NewResource(runtime, "aws.ec2.securitygroup", - map[string]*llx.RawData{ - "arn": llx.StringData(fmt.Sprintf(securityGroupArnPattern, region, accountID, convert.ToString(sg.SecurityGroupId))), - }) - if err != nil { - return nil, err + if sg.SecurityGroupId == nil { + log.Debug().Msgf("elasticache>newMqlAwsElasticacheCluster>missing security group id for cluster %s", *cluster.CacheClusterId) + continue } - sgs = append(sgs, mqlSg) + sgs = append(sgs, NewSecurityGroupArn(region, accountID, convert.ToString(sg.SecurityGroupId))) } - mqlCluster, err := CreateResource(runtime, "aws.elasticache.cluster", + resource, err := CreateResource(runtime, "aws.elasticache.cluster", map[string]*llx.RawData{ "__id": llx.StringDataPtr(cluster.ARN), "arn": llx.StringDataPtr(cluster.ARN), @@ -213,7 +237,6 @@ func newMqlAwsElasticacheCluster(runtime *plugin.Runtime, region string, account "numCacheNodes": llx.IntDataDefault(cluster.NumCacheNodes, 0), "preferredAvailabilityZone": llx.StringDataPtr(cluster.PreferredAvailabilityZone), "region": llx.StringData(region), - "securityGroups": llx.ArrayData(sgs, types.Resource("aws.ec2.securitygroup")), "snapshotRetentionLimit": llx.IntDataDefault(cluster.SnapshotRetentionLimit, 0), "transitEncryptionEnabled": llx.BoolDataPtr(cluster.TransitEncryptionEnabled), "transitEncryptionMode": llx.StringData(string(cluster.TransitEncryptionMode)), @@ -221,7 +244,14 @@ func newMqlAwsElasticacheCluster(runtime *plugin.Runtime, region string, account if err != nil { return nil, err } - return mqlCluster.(*mqlAwsElasticacheCluster), nil + + mqlCluster := resource.(*mqlAwsElasticacheCluster) + mqlCluster.setSecurityGroupArns(sgs) + return mqlCluster, nil +} + +func (a *mqlAwsElasticacheCluster) securityGroups() ([]interface{}, error) { + return a.newSecurityGroupResources(a.MqlRuntime) } func (a *mqlAwsElasticache) serverlessCaches() ([]interface{}, error) { @@ -295,21 +325,18 @@ func (a *mqlAwsElasticache) getServerlessCaches(conn *connection.AwsConnection) return tasks } +type mqlAwsElasticacheServerlessCacheInternal struct { + securityGroupIdHandler +} + func newMqlAwsElasticacheServerlessCache(runtime *plugin.Runtime, region string, accountID string, cache elasticache_types.ServerlessCache) (*mqlAwsElasticacheServerlessCache, error) { - sgs := []interface{}{} + sgArgs := []string{} for i := range cache.SecurityGroupIds { sgId := cache.SecurityGroupIds[i] - mqlSg, err := NewResource(runtime, "aws.ec2.securitygroup", - map[string]*llx.RawData{ - "arn": llx.StringData(fmt.Sprintf(securityGroupArnPattern, region, accountID, sgId)), - }) - if err != nil { - return nil, err - } - sgs = append(sgs, mqlSg) + sgArgs = append(sgArgs, NewSecurityGroupArn(region, accountID, sgId)) } - mqlCache, err := CreateResource(runtime, "aws.elasticache.serverlessCache", + resource, err := CreateResource(runtime, "aws.elasticache.serverlessCache", map[string]*llx.RawData{ "__id": llx.StringDataPtr(cache.ARN), "arn": llx.StringDataPtr(cache.ARN), @@ -320,7 +347,6 @@ func newMqlAwsElasticacheServerlessCache(runtime *plugin.Runtime, region string, "majorEngineVersion": llx.StringDataPtr(cache.MajorEngineVersion), "kmsKeyId": llx.StringDataPtr(cache.KmsKeyId), "region": llx.StringData(region), - "securityGroups": llx.ArrayData(sgs, types.Resource("aws.ec2.securitygroup")), "snapshotRetentionLimit": llx.IntDataDefault(cache.SnapshotRetentionLimit, 0), "dailySnapshotTime": llx.StringDataPtr(cache.DailySnapshotTime), "createdAt": llx.TimeDataPtr(cache.CreateTime), @@ -329,5 +355,12 @@ func newMqlAwsElasticacheServerlessCache(runtime *plugin.Runtime, region string, if err != nil { return nil, err } - return mqlCache.(*mqlAwsElasticacheServerlessCache), nil + + mqlCache := resource.(*mqlAwsElasticacheServerlessCache) + mqlCache.setSecurityGroupArns(sgArgs) + return mqlCache, nil +} + +func (a *mqlAwsElasticacheServerlessCache) securityGroups() ([]interface{}, error) { + return a.newSecurityGroupResources(a.MqlRuntime) }