diff --git a/providers/gcp/resources/cloudrun.go b/providers/gcp/resources/cloudrun.go index 1d76f03b0e..0e943ec4d1 100644 --- a/providers/gcp/resources/cloudrun.go +++ b/providers/gcp/resources/cloudrun.go @@ -278,6 +278,7 @@ func (g *mqlGcpProjectCloudRunService) operations() ([]any, error) { } if err != nil { log.Error().Err(err).Send() + break } mqlOp, err := CreateResource(g.MqlRuntime, "gcp.project.cloudRunService.operation", map[string]*llx.RawData{ "projectId": llx.StringData(projectId), @@ -286,6 +287,7 @@ func (g *mqlGcpProjectCloudRunService) operations() ([]any, error) { }) if err != nil { log.Error().Err(err).Send() + continue } mux.Lock() operations = append(operations, mqlOp) @@ -386,7 +388,7 @@ func (g *mqlGcpProjectCloudRunService) services() ([]any, error) { "annotations": llx.MapData(convert.MapToInterfaceMap(s.Template.Annotations), types.String), "scaling": llx.DictData(scalingCfg), "vpcAccess": llx.DictData(vpcCfg), - "timeout": llx.TimeData(llx.DurationToTime((s.Template.Timeout.Seconds))), + "timeout": llx.TimeDataPtr(durationSecondsToTimePtr(s.Template.Timeout)), "serviceAccountEmail": llx.StringData(s.Template.ServiceAccount), "containers": llx.ArrayData(mqlContainers, "gcp.project.cloudRunService.container"), "volumes": llx.ArrayData(mqlVolumes(s.Template.Volumes), types.Dict), @@ -443,10 +445,10 @@ func (g *mqlGcpProjectCloudRunService) services() ([]any, error) { "generation": llx.IntData(s.Generation), "labels": llx.MapData(convert.MapToInterfaceMap(s.Labels), types.String), "annotations": llx.MapData(convert.MapToInterfaceMap(s.Annotations), types.String), - "created": llx.TimeData(s.CreateTime.AsTime()), - "updated": llx.TimeData(s.UpdateTime.AsTime()), - "deleted": llx.TimeData(s.DeleteTime.AsTime()), - "expired": llx.TimeData(s.ExpireTime.AsTime()), + "created": llx.TimeDataPtr(timestampAsTimePtr(s.CreateTime)), + "updated": llx.TimeDataPtr(timestampAsTimePtr(s.UpdateTime)), + "deleted": llx.TimeDataPtr(timestampAsTimePtr(s.DeleteTime)), + "expired": llx.TimeDataPtr(timestampAsTimePtr(s.ExpireTime)), "creator": llx.StringData(s.Creator), "lastModifier": llx.StringData(s.LastModifier), "ingress": llx.StringData(s.Ingress.String()), @@ -586,7 +588,7 @@ func (g *mqlGcpProjectCloudRunService) jobs() ([]any, error) { "id": llx.StringData(fmt.Sprintf("%s/template", templateId)), "projectId": llx.StringData(projectId), "vpcAccess": llx.DictData(vpcAccess), - "timeout": llx.TimeData(llx.DurationToTime((j.Template.Template.Timeout.Seconds))), + "timeout": llx.TimeDataPtr(durationSecondsToTimePtr(j.Template.Template.Timeout)), "serviceAccountEmail": llx.StringData(j.Template.Template.ServiceAccount), "containers": llx.ArrayData(mqlContainers, types.Resource("gcp.project.cloudRunService.container")), "volumes": llx.ArrayData(mqlVolumes(j.Template.Template.Volumes), types.Dict), @@ -638,10 +640,10 @@ func (g *mqlGcpProjectCloudRunService) jobs() ([]any, error) { "generation": llx.IntData(j.Generation), "labels": llx.MapData(convert.MapToInterfaceMap(j.Labels), types.String), "annotations": llx.MapData(convert.MapToInterfaceMap(j.Annotations), types.String), - "created": llx.TimeData(j.CreateTime.AsTime()), - "updated": llx.TimeData(j.UpdateTime.AsTime()), - "deleted": llx.TimeData(j.DeleteTime.AsTime()), - "expired": llx.TimeData(j.ExpireTime.AsTime()), + "created": llx.TimeDataPtr(timestampAsTimePtr(j.CreateTime)), + "updated": llx.TimeDataPtr(timestampAsTimePtr(j.UpdateTime)), + "deleted": llx.TimeDataPtr(timestampAsTimePtr(j.DeleteTime)), + "expired": llx.TimeDataPtr(timestampAsTimePtr(j.ExpireTime)), "creator": llx.StringData(j.Creator), "lastModifier": llx.StringData(j.LastModifier), "client": llx.StringData(j.Client), @@ -717,7 +719,7 @@ func mqlCondition(runtime *plugin.Runtime, c *runpb.Condition, parentId, suffix "type": llx.StringData(c.Type), "state": llx.StringData(c.String()), "message": llx.StringData(c.Message), - "lastTransitionTime": llx.TimeData(c.LastTransitionTime.AsTime()), + "lastTransitionTime": llx.TimeDataPtr(timestampAsTimePtr(c.LastTransitionTime)), "severity": llx.StringData(c.Severity.String()), }) } @@ -743,7 +745,7 @@ func mqlContainers(runtime *plugin.Runtime, containers []*runpb.Container, templ for _, e := range c.Env { valueSource := e.GetValueSource() var mqlValueSource map[string]any - if valueSource != nil { + if valueSource != nil && valueSource.SecretKeyRef != nil { mqlValueSource = map[string]any{ "secretKeyRef": map[string]any{ "secret": valueSource.SecretKeyRef.Secret, diff --git a/providers/gcp/resources/common.go b/providers/gcp/resources/common.go index 9a015c359a..b34e42d3de 100644 --- a/providers/gcp/resources/common.go +++ b/providers/gcp/resources/common.go @@ -15,6 +15,7 @@ import ( "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -79,6 +80,14 @@ func timestampAsTimePtr(t *timestamppb.Timestamp) *time.Time { return &tm } +func durationSecondsToTimePtr(d *durationpb.Duration) *time.Time { + if d == nil { + return nil + } + t := llx.DurationToTime(d.Seconds) + return &t +} + func boolValueToPtr(b *wrapperspb.BoolValue) *bool { if b == nil { return nil @@ -117,6 +126,9 @@ func getAssetIdentifier(runtime *plugin.Runtime) *assetIdentifier { if !ok { return nil } + if conn.Asset() == nil || len(conn.Asset().PlatformIds) == 0 { + return nil + } id := conn.Asset().PlatformIds[0] if strings.HasPrefix(id, "//platformid.api.mondoo.app/runtime/gcp/") { @@ -184,6 +196,9 @@ func getNetworkByUrl(networkUrl string, runtime *plugin.Runtime) (*mqlGcpProject params := strings.TrimPrefix(networkUrl, "https://www.googleapis.com/compute/v1/") params = strings.TrimPrefix(params, "https://compute.googleapis.com/compute/v1/") parts := strings.Split(params, "/") + if len(parts) < 5 { + return nil, errors.New("malformed network URL: " + networkUrl) + } resId := resourceId{Project: parts[1], Region: parts[2], Name: parts[4]} res, err := CreateResource(runtime, "gcp.project.computeService.network", map[string]*llx.RawData{ @@ -207,6 +222,9 @@ func getSubnetworkByUrl(subnetUrl string, runtime *plugin.Runtime) (*mqlGcpProje params := strings.TrimPrefix(subnetUrl, "https://www.googleapis.com/compute/v1/") params = strings.TrimPrefix(params, "https://compute.googleapis.com/compute/v1/") parts := strings.Split(params, "/") + if len(parts) < 6 { + return nil, errors.New("malformed subnetwork URL: " + subnetUrl) + } resId := resourceId{Project: parts[1], Region: parts[3], Name: parts[5]} // regionUrl is the full URL up to and including the region segment regionUrl := "https://www.googleapis.com/compute/v1/projects/" + resId.Project + "/regions/" + resId.Region @@ -233,5 +251,8 @@ func getDiskIdByUrl(diskUrl string) (*resourceId, error) { params := strings.TrimPrefix(diskUrl, "https://www.googleapis.com/compute/v1/") params = strings.TrimPrefix(params, "https://compute.googleapis.com/compute/v1/") parts := strings.Split(params, "/") + if len(parts) < 6 { + return nil, errors.New("malformed disk URL: " + diskUrl) + } return &resourceId{Project: parts[1], Region: parts[3], Name: parts[5]}, nil } diff --git a/providers/gcp/resources/dataproc.go b/providers/gcp/resources/dataproc.go index 95c5f9256f..c0bd8c27be 100644 --- a/providers/gcp/resources/dataproc.go +++ b/providers/gcp/resources/dataproc.go @@ -525,10 +525,16 @@ func (g *mqlGcpProjectDataprocService) clusters() ([]any, error) { SparkHistoryServerConfig mqlSparkHistoryServerConfig `json:"sparkHistoryServerConfig"` } - mqlAuxServices, err := convert.JsonToDict(mqlAuxiliaryServices{ - MetastoreConfig: mqlMetastoreConfig{DataprocMetastoreService: c.VirtualClusterConfig.AuxiliaryServicesConfig.MetastoreConfig.DataprocMetastoreService}, - SparkHistoryServerConfig: mqlSparkHistoryServerConfig{DataprocCluster: c.VirtualClusterConfig.AuxiliaryServicesConfig.SparkHistoryServerConfig.DataprocCluster}, - }) + var auxSvc mqlAuxiliaryServices + if c.VirtualClusterConfig.AuxiliaryServicesConfig != nil { + if c.VirtualClusterConfig.AuxiliaryServicesConfig.MetastoreConfig != nil { + auxSvc.MetastoreConfig = mqlMetastoreConfig{DataprocMetastoreService: c.VirtualClusterConfig.AuxiliaryServicesConfig.MetastoreConfig.DataprocMetastoreService} + } + if c.VirtualClusterConfig.AuxiliaryServicesConfig.SparkHistoryServerConfig != nil { + auxSvc.SparkHistoryServerConfig = mqlSparkHistoryServerConfig{DataprocCluster: c.VirtualClusterConfig.AuxiliaryServicesConfig.SparkHistoryServerConfig.DataprocCluster} + } + } + mqlAuxServices, err := convert.JsonToDict(auxSvc) if err != nil { log.Error().Err(err).Send() } @@ -552,20 +558,32 @@ func (g *mqlGcpProjectDataprocService) clusters() ([]any, error) { KubernetesNamespace string `json:"kubernetesNamespace"` } - npTargets := make([]mqlGkeNodePoolTarget, 0, len(c.VirtualClusterConfig.KubernetesClusterConfig.GkeClusterConfig.NodePoolTarget)) - for _, npt := range c.VirtualClusterConfig.KubernetesClusterConfig.GkeClusterConfig.NodePoolTarget { - npTargets = append(npTargets, nodePoolTargetToMql(npt)) + var k8sClusterCfg mqlKubernetesClusterConfig + if k8sCfg := c.VirtualClusterConfig.KubernetesClusterConfig; k8sCfg != nil { + if gkeCfg := k8sCfg.GkeClusterConfig; gkeCfg != nil { + npTargets := make([]mqlGkeNodePoolTarget, 0, len(gkeCfg.NodePoolTarget)) + for _, npt := range gkeCfg.NodePoolTarget { + npTargets = append(npTargets, nodePoolTargetToMql(npt)) + } + var nsTarget mqlNamespacedGkeDeploymentTarget + if gkeCfg.NamespacedGkeDeploymentTarget != nil { + nsTarget = mqlNamespacedGkeDeploymentTarget{ + ClusterNamespace: gkeCfg.NamespacedGkeDeploymentTarget.ClusterNamespace, + TargetGkeCluster: gkeCfg.NamespacedGkeDeploymentTarget.TargetGkeCluster, + } + } + k8sClusterCfg.GkeClusterConfig = mqlGkeClusterConfig{ + TargetCluster: gkeCfg.GkeClusterTarget, + NamespacedGkeDeploymentTarget: nsTarget, + NodePoolTarget: npTargets, + } + } + k8sClusterCfg.KubernetesNamespace = k8sCfg.KubernetesNamespace } mqlK8sClusterCfg, err := convert.JsonToDict(mqlKubernetesClusterConfig{ - GkeClusterConfig: mqlGkeClusterConfig{ - TargetCluster: c.VirtualClusterConfig.KubernetesClusterConfig.GkeClusterConfig.GkeClusterTarget, - NamespacedGkeDeploymentTarget: mqlNamespacedGkeDeploymentTarget{ - ClusterNamespace: c.VirtualClusterConfig.KubernetesClusterConfig.GkeClusterConfig.NamespacedGkeDeploymentTarget.ClusterNamespace, - TargetGkeCluster: c.VirtualClusterConfig.KubernetesClusterConfig.GkeClusterConfig.NamespacedGkeDeploymentTarget.TargetGkeCluster, - }, - NodePoolTarget: npTargets, - }, + GkeClusterConfig: k8sClusterCfg.GkeClusterConfig, + KubernetesNamespace: k8sClusterCfg.KubernetesNamespace, }) if err != nil { log.Error().Err(err).Send() @@ -736,35 +754,40 @@ func (g *mqlGcpProjectDataprocServiceClusterConfigInstanceDiskConfig) id() (stri } func nodePoolTargetToMql(npt *dataproc.GkeNodePoolTarget) mqlGkeNodePoolTarget { - accs := make([]mqlGkeNodePoolAccelerator, 0, len(npt.NodePoolConfig.Config.Accelerators)) - for _, acc := range npt.NodePoolConfig.Config.Accelerators { - accs = append(accs, mqlGkeNodePoolAccelerator{ - AcceleratorCount: acc.AcceleratorCount, - AcceleratorType: acc.AcceleratorType, - GpuPartitionSize: acc.GpuPartitionSize, - }) - } - - return mqlGkeNodePoolTarget{ + result := mqlGkeNodePoolTarget{ NodePool: npt.NodePool, - NodePoolConfig: mqlGkeNodePoolConfig{ - Autoscaling: mqlGkeNodePoolAutoscalingConfig{ - MaxNodeCount: npt.NodePoolConfig.Autoscaling.MaxNodeCount, - MinNodeCount: npt.NodePoolConfig.Autoscaling.MinNodeCount, - }, - Config: mqlGkeNodeConfig{ - Accelerators: accs, - BootDiskKmsKey: npt.NodePoolConfig.Config.BootDiskKmsKey, - LocalSsdCount: npt.NodePoolConfig.Config.LocalSsdCount, - MachineType: npt.NodePoolConfig.Config.MachineType, - MinCpuPlatform: npt.NodePoolConfig.Config.MinCpuPlatform, - Preemptible: npt.NodePoolConfig.Config.Preemptible, - Spot: npt.NodePoolConfig.Config.Spot, - }, - Locations: npt.NodePoolConfig.Locations, - }, - Roles: npt.Roles, + Roles: npt.Roles, + } + if npt.NodePoolConfig == nil { + return result + } + result.NodePoolConfig.Locations = npt.NodePoolConfig.Locations + if npt.NodePoolConfig.Autoscaling != nil { + result.NodePoolConfig.Autoscaling = mqlGkeNodePoolAutoscalingConfig{ + MaxNodeCount: npt.NodePoolConfig.Autoscaling.MaxNodeCount, + MinNodeCount: npt.NodePoolConfig.Autoscaling.MinNodeCount, + } + } + if npt.NodePoolConfig.Config != nil { + accs := make([]mqlGkeNodePoolAccelerator, 0, len(npt.NodePoolConfig.Config.Accelerators)) + for _, acc := range npt.NodePoolConfig.Config.Accelerators { + accs = append(accs, mqlGkeNodePoolAccelerator{ + AcceleratorCount: acc.AcceleratorCount, + AcceleratorType: acc.AcceleratorType, + GpuPartitionSize: acc.GpuPartitionSize, + }) + } + result.NodePoolConfig.Config = mqlGkeNodeConfig{ + Accelerators: accs, + BootDiskKmsKey: npt.NodePoolConfig.Config.BootDiskKmsKey, + LocalSsdCount: npt.NodePoolConfig.Config.LocalSsdCount, + MachineType: npt.NodePoolConfig.Config.MachineType, + MinCpuPlatform: npt.NodePoolConfig.Config.MinCpuPlatform, + Preemptible: npt.NodePoolConfig.Config.Preemptible, + Spot: npt.NodePoolConfig.Config.Spot, + } } + return result } func instanceGroupConfigToMql(runtime *plugin.Runtime, igc *dataproc.InstanceGroupConfig, id string) (plugin.Resource, error) { diff --git a/providers/gcp/resources/discovery.go b/providers/gcp/resources/discovery.go index 9c4e9d93d7..65a475ce6b 100644 --- a/providers/gcp/resources/discovery.go +++ b/providers/gcp/resources/discovery.go @@ -794,7 +794,7 @@ func discoverProject(conn *connection.GcpConnection, gcpProject *mqlGcpProject, return nil, storage.Error } buckets := storage.Data.GetBuckets() - if buckets == nil { + if buckets.Error != nil { return nil, buckets.Error } for i := range buckets.Data { @@ -1205,12 +1205,12 @@ func (a *GcrImages) Name() string { func (a *GcrImages) ListRepository(repository string, recursive bool) ([]*inventory.Asset, error) { repo, err := name.NewRepository(repository) if err != nil { - log.Fatal().Err(err).Str("repository", repository).Msg("could not create repository") + return nil, fmt.Errorf("could not create repository %s: %w", repository, err) } auth, err := google.Keychain.Resolve(repo.Registry) if err != nil { - log.Fatal().Err(err).Str("repository", repository).Msg("failed to get auth for repository") + return nil, fmt.Errorf("failed to get auth for repository %s: %w", repository, err) } imgs := []*inventory.Asset{} diff --git a/providers/gcp/resources/filestore.go b/providers/gcp/resources/filestore.go index 5f204f4e33..b531be0937 100644 --- a/providers/gcp/resources/filestore.go +++ b/providers/gcp/resources/filestore.go @@ -115,7 +115,7 @@ func (g *mqlGcpProjectFilestoreService) instances() ([]any, error) { "description": llx.StringData(instance.Description), "tier": llx.StringData(instance.Tier.String()), "state": llx.StringData(instance.State.String()), - "createTime": llx.TimeData(instance.CreateTime.AsTime()), + "createTime": llx.TimeDataPtr(timestampAsTimePtr(instance.CreateTime)), "labels": llx.MapData(convert.MapToInterfaceMap(instance.Labels), types.String), "fileShares": llx.ArrayData(fileShares, types.Resource("gcp.project.filestoreService.instance.fileShare")), "networks": llx.ArrayData(networks, types.Resource("gcp.project.filestoreService.instance.network")), diff --git a/providers/gcp/resources/gke.go b/providers/gcp/resources/gke.go index d3aabc6b1f..e119c5a4ad 100644 --- a/providers/gcp/resources/gke.go +++ b/providers/gcp/resources/gke.go @@ -1028,6 +1028,9 @@ func (g *mqlGcpProjectGkeServiceClusterNetworkConfig) network() (*mqlGcpProjectC // Format is projects/project-1/global/networks/net-1 params := strings.Split(networkPath, "/") + if len(params) < 2 { + return nil, errors.New("malformed network path: " + networkPath) + } res, err := CreateResource(g.MqlRuntime, "gcp.project.computeService.network", map[string]*llx.RawData{ "name": llx.StringData(params[len(params)-1]), "projectId": llx.StringData(params[1]), @@ -1046,6 +1049,9 @@ func (g *mqlGcpProjectGkeServiceClusterNetworkConfig) subnetwork() (*mqlGcpProje // Format is projects/project-1/regions/us-central1/subnetworks/subnet-1 params := strings.Split(subnetPath, "/") + if len(params) < 6 { + return nil, errors.New("malformed subnetwork path: " + subnetPath) + } regionUrl := strings.SplitN(subnetPath, "/subnetworks", 2) res, err := NewResource(g.MqlRuntime, "gcp.project.computeService.subnetwork", map[string]*llx.RawData{ "name": llx.StringData(params[len(params)-1]), diff --git a/providers/gcp/resources/kms.go b/providers/gcp/resources/kms.go index fdb8a050ea..d83b1b67f9 100644 --- a/providers/gcp/resources/kms.go +++ b/providers/gcp/resources/kms.go @@ -338,8 +338,8 @@ func (g *mqlGcpProjectKmsServiceKeyring) cryptokeys() ([]any, error) { "name": llx.StringData(parseResourceName(k.Name)), "primary": llx.ResourceData(mqlPrimary, "gcp.project.kmsService.keyring.cryptokey.version"), "purpose": llx.StringData(k.Purpose.String()), - "created": llx.TimeData(k.CreateTime.AsTime()), - "nextRotation": llx.TimeData(k.NextRotationTime.AsTime()), + "created": llx.TimeDataPtr(timestampAsTimePtr(k.CreateTime)), + "nextRotation": llx.TimeDataPtr(timestampAsTimePtr(k.NextRotationTime)), "rotationPeriod": llx.TimeDataPtr(mqlRotationPeriod), "versionTemplate": llx.DictData(versionTemplate), "labels": llx.MapData(convert.MapToInterfaceMap(k.Labels), types.String), @@ -347,6 +347,9 @@ func (g *mqlGcpProjectKmsServiceKeyring) cryptokeys() ([]any, error) { "destroyScheduledDuration": llx.TimeDataPtr(mqlDestroyScheduledDuration), "cryptoKeyBackend": llx.StringData(k.CryptoKeyBackend), }) + if err != nil { + return nil, err + } keys = append(keys, mqlKey) } @@ -390,6 +393,9 @@ func (g *mqlGcpProjectKmsServiceKeyringCryptokey) versions() ([]any, error) { } mqlVersion, err := cryptoKeyVersionToMql(g.MqlRuntime, v) + if err != nil { + return nil, err + } versions = append(versions, mqlVersion) } return versions, nil @@ -438,11 +444,17 @@ func (g *mqlGcpProjectKmsServiceKeyringCryptokey) iamPolicy() ([]any, error) { func cryptoKeyVersionToMql(runtime *plugin.Runtime, v *kmspb.CryptoKeyVersion) (plugin.Resource, error) { var mqlAttestation plugin.Resource if v.Attestation != nil { + var caviumCerts, googleCardCerts, googlePartitionCerts []any + if v.Attestation.CertChains != nil { + caviumCerts = convert.SliceAnyToInterface(v.Attestation.CertChains.CaviumCerts) + googleCardCerts = convert.SliceAnyToInterface(v.Attestation.CertChains.GoogleCardCerts) + googlePartitionCerts = convert.SliceAnyToInterface(v.Attestation.CertChains.GooglePartitionCerts) + } mqlAttestationCertChains, err := CreateResource(runtime, "gcp.project.kmsService.keyring.cryptokey.version.attestation.certificatechains", map[string]*llx.RawData{ "cryptoKeyVersionName": llx.StringData(v.Name), - "caviumCerts": llx.ArrayData(convert.SliceAnyToInterface(v.Attestation.CertChains.CaviumCerts), types.String), - "googleCardCerts": llx.ArrayData(convert.SliceAnyToInterface(v.Attestation.CertChains.GoogleCardCerts), types.String), - "googlePartitionCerts": llx.ArrayData(convert.SliceAnyToInterface(v.Attestation.CertChains.GooglePartitionCerts), types.String), + "caviumCerts": llx.ArrayData(caviumCerts, types.String), + "googleCardCerts": llx.ArrayData(googleCardCerts, types.String), + "googlePartitionCerts": llx.ArrayData(googlePartitionCerts, types.String), }) if err != nil { return nil, err diff --git a/providers/gcp/resources/pubsub.go b/providers/gcp/resources/pubsub.go index 350992a0d0..4330a78372 100644 --- a/providers/gcp/resources/pubsub.go +++ b/providers/gcp/resources/pubsub.go @@ -571,6 +571,9 @@ func (g *mqlGcpProjectPubsubServiceTopic) iamPolicy() ([]any, error) { return nil, err } + if policy.InternalProto == nil { + return nil, nil + } bindings := policy.InternalProto.Bindings res := make([]any, 0, len(bindings)) topicPath := fmt.Sprintf("projects/%s/topics/%s", projectId, name) @@ -623,6 +626,9 @@ func (g *mqlGcpProjectPubsubServiceSubscription) iamPolicy() ([]any, error) { return nil, err } + if policy.InternalProto == nil { + return nil, nil + } bindings := policy.InternalProto.Bindings res := make([]any, 0, len(bindings)) subPath := fmt.Sprintf("projects/%s/subscriptions/%s", projectId, name) diff --git a/providers/gcp/resources/redis.go b/providers/gcp/resources/redis.go index 7b99d627c3..b6c7769e5a 100644 --- a/providers/gcp/resources/redis.go +++ b/providers/gcp/resources/redis.go @@ -173,7 +173,7 @@ func (g *mqlGcpProjectRedisService) instances() ([]any, error) { "replicaCount": llx.IntData(instance.ReplicaCount), "readEndpointPort": llx.IntData(instance.ReadEndpointPort), "authEnabled": llx.BoolData(instance.AuthEnabled), - "createTime": llx.TimeData(instance.CreateTime.AsTime()), + "createTime": llx.TimeDataPtr(timestampAsTimePtr(instance.CreateTime)), "labels": llx.MapData(convert.MapToInterfaceMap(instance.Labels), types.String), "redisConfigs": llx.MapData(convert.MapToInterfaceMap(instance.RedisConfigs), types.String), "persistenceConfig": llx.DictData(persistenceConfig), @@ -531,7 +531,7 @@ func (g *mqlGcpProjectRedisService) clusters() ([]any, error) { "name": llx.StringData(cluster.Name), "uid": llx.StringData(cluster.Uid), "state": llx.StringData(cluster.State.String()), - "createTime": llx.TimeData(cluster.CreateTime.AsTime()), + "createTime": llx.TimeDataPtr(timestampAsTimePtr(cluster.CreateTime)), "authorizationMode": llx.StringData(cluster.AuthorizationMode.String()), "transitEncryptionMode": llx.StringData(cluster.TransitEncryptionMode.String()), "nodeType": llx.StringData(cluster.NodeType.String()), diff --git a/providers/gcp/resources/sql.go b/providers/gcp/resources/sql.go index 1abe2b033c..c2fd5e8740 100644 --- a/providers/gcp/resources/sql.go +++ b/providers/gcp/resources/sql.go @@ -200,6 +200,9 @@ func (g *mqlGcpProjectSqlService) instances() ([]any, error) { } s := instance.Settings + if s == nil { + s = &sqladmin.Settings{} + } dbFlags := make(map[string]string) for _, f := range s.DatabaseFlags { dbFlags[f.Name] = f.Value @@ -224,10 +227,14 @@ func (g *mqlGcpProjectSqlService) instances() ([]any, error) { RetainedBackups int64 `json:"retainedBackups"` RetentionUnit string `json:"retentionUnit"` } - mqlRetention, err := convert.JsonToDict(mqlRetentionSettings{ - RetainedBackups: s.BackupConfiguration.BackupRetentionSettings.RetainedBackups, - RetentionUnit: s.BackupConfiguration.BackupRetentionSettings.RetentionUnit, - }) + var retSettings mqlRetentionSettings + if s.BackupConfiguration.BackupRetentionSettings != nil { + retSettings = mqlRetentionSettings{ + RetainedBackups: s.BackupConfiguration.BackupRetentionSettings.RetainedBackups, + RetentionUnit: s.BackupConfiguration.BackupRetentionSettings.RetentionUnit, + } + } + mqlRetention, err := convert.JsonToDict(retSettings) if err != nil { return err }