Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion central/graphql/resolvers/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ func (resolver *clusterResolver) Subject(ctx context.Context, args struct{ Name
return resolver.root.wrapSubject(k8srbac.GetSubject(subjectName, bindings))
}

func (resolver *clusterResolver) Images(ctx context.Context, args PaginatedQuery) ([]*imageResolver, error) {
func (resolver *clusterResolver) Images(ctx context.Context, args PaginatedQuery) ([]ImageResolver, error) {
defer metrics.SetGraphQLOperationDurationTime(time.Now(), pkgMetrics.Cluster, "Images")
return resolver.root.Images(resolver.clusterScopeContext(ctx), args)
}
Expand Down
75 changes: 65 additions & 10 deletions central/graphql/resolvers/components_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ func (resolver *imageScanResolver) Components(_ context.Context, args PaginatedQ
pagination := query.GetPagination()
query.Pagination = nil

// This purely exists to make it easier when we do a second pass to remove the storage.Image proto later on, technically this code would work without this.
if features.FlattenImageData.Enabled() {
vulns, err := mapImageV2sToComponentResolvers(resolver.root, []*storage.ImageV2{
{
Scan: resolver.data,
},
}, query)

return paginate(pagination, vulns, err)
}
vulns, err := mapImagesToComponentResolvers(resolver.root, []*storage.Image{
{
Scan: resolver.data,
Expand Down Expand Up @@ -181,7 +191,7 @@ func (eicr *EmbeddedImageScanComponentResolver) VulnCounter(_ context.Context, _
}

// Images are the images that contain the Component.
func (eicr *EmbeddedImageScanComponentResolver) Images(ctx context.Context, args PaginatedQuery) ([]*imageResolver, error) {
func (eicr *EmbeddedImageScanComponentResolver) Images(ctx context.Context, args PaginatedQuery) ([]ImageResolver, error) {
// Convert to query, but link the fields for the search.
query, err := args.AsV1QueryOrEmpty()
if err != nil {
Expand Down Expand Up @@ -316,23 +326,40 @@ func (eicr *EmbeddedImageScanComponentResolver) NodeCount(ctx context.Context, a
return nodeLoader.CountFromQuery(ctx, query)
}

func (eicr *EmbeddedImageScanComponentResolver) loadImages(ctx context.Context, query *v1.Query) ([]*imageResolver, error) {
imageLoader, err := loaders.GetImageLoader(ctx)
if err != nil {
return nil, err
}
func (eicr *EmbeddedImageScanComponentResolver) loadImages(ctx context.Context, query *v1.Query) ([]ImageResolver, error) {

pagination := query.GetPagination()
query.Pagination = nil

query, err = search.AddAsConjunction(eicr.componentQuery(), query)
query, err := search.AddAsConjunction(eicr.componentQuery(), query)
if err != nil {
return nil, err
}

query.Pagination = pagination

return eicr.root.wrapImages(imageLoader.FromQuery(ctx, query))
if features.FlattenImageData.Enabled() {
imageV2Loader, err := loaders.GetImageV2Loader(ctx)
if err != nil {
return nil, err
}
resolvers, err := eicr.root.wrapImageV2s(imageV2Loader.FromQuery(ctx, query))
res := make([]ImageResolver, 0, len(resolvers))
for i, resolver := range resolvers {
res[i] = resolver
}
return res, err
}
imageLoader, err := loaders.GetImageLoader(ctx)
if err != nil {
return nil, err
}
resolvers, err := eicr.root.wrapImages(imageLoader.FromQuery(ctx, query))
res := make([]ImageResolver, 0, len(resolvers))
for i, resolver := range resolvers {
res[i] = resolver
}
return res, err
}

func (eicr *EmbeddedImageScanComponentResolver) loadDeployments(ctx context.Context, query *v1.Query) ([]*deploymentResolver, error) {
Expand Down Expand Up @@ -367,7 +394,13 @@ func (eicr *EmbeddedImageScanComponentResolver) getDeploymentBaseQuery(ctx conte
}

// Create a query that finds all of the deployments that contain at least one of the infected images.
return search.NewQueryBuilder().AddExactMatches(search.ImageSHA, search.ResultsToIDs(results)...).ProtoQuery(), nil
var searchField search.FieldLabel
if features.FlattenImageData.Enabled() {
searchField = search.ImageID
} else {
searchField = search.ImageSHA
}
return search.NewQueryBuilder().AddExactMatches(searchField, search.ResultsToIDs(results)...).ProtoQuery(), nil
}

func (eicr *EmbeddedImageScanComponentResolver) componentQuery() *v1.Query {
Expand All @@ -380,8 +413,30 @@ func (eicr *EmbeddedImageScanComponentResolver) componentQuery() *v1.Query {
// Static helpers.
//////////////////

// Map the images that matched a query to the image components it contains.
type canGetScan interface {
GetScan() *storage.ImageScan
}

// Map the image v1s that matched a query to the image components it contains.
func mapImagesToComponentResolvers(root *Resolver, images []*storage.Image, query *v1.Query) ([]*EmbeddedImageScanComponentResolver, error) {
mappedImages := make([]canGetScan, 0, len(images))
for _, image := range images {
mappedImages = append(mappedImages, image)
}
return mapAnyImageToComponentResolvers(root, mappedImages, query)
}

// Map the image v1s that matched a query to the image components it contains.
func mapImageV2sToComponentResolvers(root *Resolver, images []*storage.ImageV2, query *v1.Query) ([]*EmbeddedImageScanComponentResolver, error) {
mappedImages := make([]canGetScan, 0, len(images))
for _, image := range images {
mappedImages = append(mappedImages, image)
}
return mapAnyImageToComponentResolvers(root, mappedImages, query)
}

// Map the images that matched a query to the image components it contains.
func mapAnyImageToComponentResolvers(root *Resolver, images []canGetScan, query *v1.Query) ([]*EmbeddedImageScanComponentResolver, error) {
query, _ = search.FilterQueryWithMap(query, mappings.ComponentOptionsMap)
componentPred, err := componentPredicateFactory.GeneratePredicate(query)
if err != nil {
Expand Down
13 changes: 10 additions & 3 deletions central/graphql/resolvers/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/stackrox/rox/central/processindicator/service"
v1 "github.com/stackrox/rox/generated/api/v1"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/features"
pkgMetrics "github.com/stackrox/rox/pkg/metrics"
"github.com/stackrox/rox/pkg/search"
"github.com/stackrox/rox/pkg/search/paginated"
Expand Down Expand Up @@ -510,7 +511,7 @@ func (resolver *deploymentResolver) ServiceAccountID(ctx context.Context) (strin
return results[0].ID, nil
}

func (resolver *deploymentResolver) Images(ctx context.Context, args PaginatedQuery) ([]*imageResolver, error) {
func (resolver *deploymentResolver) Images(ctx context.Context, args PaginatedQuery) ([]ImageResolver, error) {
defer metrics.SetGraphQLOperationDurationTime(time.Now(), pkgMetrics.Deployments, "Images")
if !resolver.hasImages() {
return nil, nil
Expand Down Expand Up @@ -662,8 +663,14 @@ func (resolver *deploymentResolver) ContainerTerminationCount(ctx context.Contex

func (resolver *deploymentResolver) hasImages() bool {
for _, c := range resolver.data.GetContainers() {
if c.GetImage().GetId() != "" {
return true
if features.FlattenImageData.Enabled() {
if c.GetImage().GetIdV2() != "" {
return true
}
} else {
if c.GetImage().GetId() != "" {
return true
}
}
}
return false
Expand Down
6 changes: 6 additions & 0 deletions central/graphql/resolvers/gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ var (
reflect.TypeOf((*storage.FalsePositiveRequest)(nil)),
reflect.TypeOf((*storage.Group)(nil)),
reflect.TypeOf((*storage.Image)(nil)),
reflect.TypeOf((*storage.ImageV2)(nil)),
reflect.TypeOf((*storage.K8SRole)(nil)),
reflect.TypeOf((*storage.K8SRoleBinding)(nil)),
reflect.TypeOf((*storage.ListAlert)(nil)),
reflect.TypeOf((*storage.ListDeployment)(nil)),
reflect.TypeOf((*storage.ListImage)(nil)),
reflect.TypeOf((*storage.ListImageV2)(nil)),
reflect.TypeOf((*storage.ListSecret)(nil)),
reflect.TypeOf((*storage.MitreAttackVector)(nil)),
reflect.TypeOf((*storage.NetworkFlow)(nil)),
Expand Down Expand Up @@ -83,6 +85,10 @@ var (
ParentType: reflect.TypeOf(storage.Image{}),
FieldName: "Scan",
},
{
ParentType: reflect.TypeOf(storage.ImageV2{}),
FieldName: "Scan",
},
{
ParentType: reflect.TypeOf(storage.ImageScan{}),
FieldName: "Components",
Expand Down
Loading
Loading