diff --git a/aws/table_aws_ecr_image_scan_finding.go b/aws/table_aws_ecr_image_scan_finding.go index 687a31021..417ec29f9 100644 --- a/aws/table_aws_ecr_image_scan_finding.go +++ b/aws/table_aws_ecr_image_scan_finding.go @@ -24,9 +24,8 @@ func tableAwsEcrImageScanFinding(_ context.Context) *plugin.Table { Name: "aws_ecr_image_scan_finding", Description: "AWS ECR Image Scan Finding", List: &plugin.ListConfig{ - ParentHydrate: listAwsEcrImageTags, - Hydrate: listAwsEcrImageScanFindings, - Tags: map[string]string{"service": "ecr", "action": "DescribeImageScanFindings"}, + Hydrate: listAwsEcrImageScanFindings, + Tags: map[string]string{"service": "ecr", "action": "DescribeImageScanFindings"}, IgnoreConfig: &plugin.IgnoreConfig{ ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"RepositoryNotFoundException", "ImageNotFoundException", "ScanNotFoundException"}), }, @@ -36,8 +35,8 @@ func tableAwsEcrImageScanFinding(_ context.Context) *plugin.Table { // image_digest as it's more common/friendly to use. KeyColumns: []*plugin.KeyColumn{ {Name: "repository_name", Require: plugin.Required}, - {Name: "image_tag", Require: plugin.Optional}, - {Name: "image_digest", Require: plugin.Optional}, + {Name: "image_tag", Require: plugin.AnyOf}, + {Name: "image_digest", Require: plugin.AnyOf}, }, }, GetMatrixItemFunc: SupportedRegionMatrix(ecrv1.EndpointsID), @@ -122,7 +121,6 @@ func tableAwsEcrImageScanFinding(_ context.Context) *plugin.Table { // // LIST FUNCTION func listAwsEcrImageScanFindings(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { - repositoryTag := h.Item.(*RepositoryImage) // Create Session svc, err := ECRClient(ctx, d) @@ -134,13 +132,10 @@ func listAwsEcrImageScanFindings(ctx context.Context, d *plugin.QueryData, h *pl imageDigest := d.EqualsQuals["image_digest"] repositoryName := d.EqualsQuals["repository_name"] - if imageTag != nil && imageTag.GetStringValue() != *repositoryTag.ImageTag { - return nil, nil + if imageTag == nil && imageDigest == nil { + return nil, errors.New("image_tag or image_digest must be provided") } - if repositoryName != nil && repositoryName.GetStringValue() != *repositoryTag.RepositoryName { - return nil, nil - } - + // Limiting the results maxLimit := int32(1000) if d.QueryContext.Limit != nil { @@ -152,11 +147,11 @@ func listAwsEcrImageScanFindings(ctx context.Context, d *plugin.QueryData, h *pl input := &ecr.DescribeImageScanFindingsInput{ MaxResults: aws.Int32(maxLimit), - RepositoryName: repositoryTag.RepositoryName, + RepositoryName: aws.String(repositoryName.GetStringValue()), } imageInfo := &types.ImageIdentifier{ - ImageTag: repositoryTag.ImageTag, + ImageTag: aws.String(imageTag.GetStringValue()), } // Ideally, both image_tag and image_digest could be used. @@ -238,69 +233,3 @@ func listAwsEcrImageScanFindings(ctx context.Context, d *plugin.QueryData, h *pl return nil, err } - -//// Parent Hydrate - -type RepositoryImage struct { - RepositoryName *string - ImageTag *string -} - -// To preserve the existing table behavior (fetching findings based on image tags), we have retained the parent function. -// Making `image_tags` an optional or `anyof` qualifier alters the query plan for complex join queries, causing query execution errors. -// This issue is detailed here: https://github.com/turbot/steampipe-plugin-aws/issues/2367 -func listAwsEcrImageTags(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { - - repoName := d.EqualsQuals["repository_name"].GetStringValue() - - // Limiting the results - maxLimit := int32(100) - - // Create Session - svc, err := ECRClient(ctx, d) - if err != nil { - plugin.Logger(ctx).Error("aws_ecr_image.listAwsEcrImageTags", "connection_error", err) - return nil, err - } - - // Build the params - params := &ecr.DescribeImagesInput{ - RepositoryName: &repoName, - MaxResults: aws.Int32(maxLimit), - } - - paginator := ecr.NewDescribeImagesPaginator(svc, params, func(o *ecr.DescribeImagesPaginatorOptions) { - o.Limit = maxLimit - o.StopOnDuplicateToken = true - }) - - // List call - for paginator.HasMorePages() { - // apply rate limiting - d.WaitForListRateLimit(ctx) - - output, err := paginator.NextPage(ctx) - if err != nil { - var ae smithy.APIError - if errors.As(err, &ae) { - if ae.ErrorCode() == "RepositoryNotFoundException" { - return nil, nil - } - } - plugin.Logger(ctx).Error("aws_ecr_image.listAwsEcrImageTags", "api_error", err) - return nil, err - } - - for _, items := range output.ImageDetails { - for _, tags := range items.ImageTags { - imageDetails := &RepositoryImage{ - RepositoryName: items.RepositoryName, - ImageTag: &tags, - } - d.StreamListItem(ctx, imageDetails) - } - } - } - - return nil, nil -}