Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 839925c

Browse files
committed
Switch to GraphQL CVE query
1 parent dcd3cef commit 839925c

File tree

6 files changed

+92
-19
lines changed

6 files changed

+92
-19
lines changed

query/async.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import (
2323
)
2424

2525
type queryResult struct {
26-
Cves []types.Cve
27-
BaseImages []types.BaseImageMatch
28-
Image *types.BaseImage
29-
Error error
26+
Vulnerabilities []types.VulnerabilitiesByPurl
27+
BaseImages []types.BaseImageMatch
28+
Image *types.BaseImage
29+
Error error
3030
}
3131

3232
func ForCvesAndBaseImagesAsync(sb *types.Sbom, includeCves bool, includeBaseImages bool, workspace string, apiKey string) *types.Sbom {
@@ -36,15 +36,15 @@ func ForCvesAndBaseImagesAsync(sb *types.Sbom, includeCves bool, includeBaseImag
3636
wg.Add(1)
3737
go func() {
3838
defer wg.Done()
39-
cves, err := QueryCves(sb, "", workspace, apiKey)
39+
cves, err := ForVulnerabilitiesInGraphQL(sb)
4040
if err != nil {
4141
resultChan <- queryResult{
4242
Error: err,
4343
}
4444
}
4545
if cves != nil {
4646
resultChan <- queryResult{
47-
Cves: *cves,
47+
Vulnerabilities: cves.VulnerabilitiesByPackage,
4848
}
4949
}
5050
}()
@@ -87,8 +87,8 @@ func ForCvesAndBaseImagesAsync(sb *types.Sbom, includeCves bool, includeBaseImag
8787
if result.BaseImages != nil {
8888
sb.Source.BaseImages = result.BaseImages
8989
}
90-
if result.Cves != nil {
91-
sb.Vulnerabilities = result.Cves
90+
if result.Vulnerabilities != nil {
91+
sb.Vulnerabilities = result.Vulnerabilities
9292
}
9393
if result.Image != nil {
9494
sb.Source.Image.Details = result.Image

query/query.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
package query
1818

1919
import (
20+
"context"
2021
_ "embed"
2122
"fmt"
2223
"net/http"
2324
"strings"
2425

2526
"github.com/docker/index-cli-plugin/internal"
2627
"github.com/docker/index-cli-plugin/types"
28+
"github.com/hasura/go-graphql-client"
2729

2830
"github.com/atomist-skills/go-skill"
2931
"github.com/pkg/errors"
@@ -132,3 +134,32 @@ func query(query string, name string, workspace string, apiKey string) (*http.Re
132134
skill.Log.Debugf("Query response %s", resp.Status)
133135
return resp, nil
134136
}
137+
138+
func ForVulnerabilitiesInGraphQL(sb *types.Sbom) (*types.VulnerabilitiesByPurls, error) {
139+
url := "https://api.dso.docker.com/v1/graphql"
140+
client := graphql.NewClient(url, nil)
141+
142+
purls := make([]string, 0)
143+
for _, p := range sb.Artifacts {
144+
purls = append(purls, p.Purl)
145+
}
146+
147+
variables := map[string]interface{}{
148+
"purls": purls,
149+
}
150+
151+
var q types.VulnerabilitiesByPurls
152+
err := client.Query(context.Background(), &q, variables)
153+
if err != nil {
154+
fmt.Sprintf("error %v", err)
155+
return nil, errors.Wrapf(err, "failed to run query")
156+
}
157+
if len(q.VulnerabilitiesByPackage) > 0 {
158+
if len(q.VulnerabilitiesByPackage) == 1 {
159+
skill.Log.Infof("Detected 1 vulnerable package")
160+
} else {
161+
skill.Log.Infof("Detected %d vulnerable packages", len(q.VulnerabilitiesByPackage))
162+
}
163+
}
164+
return &q, nil
165+
}

sbom/diff.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ import (
2323

2424
"github.com/anchore/packageurl-go"
2525
"github.com/docker/cli/cli/command"
26-
"github.com/docker/index-cli-plugin/format"
27-
"github.com/docker/index-cli-plugin/internal"
2826
"github.com/docker/index-cli-plugin/types"
2927
"github.com/gookit/color"
3028
"github.com/jedib0t/go-pretty/v6/table"
@@ -79,7 +77,7 @@ func DiffImages(image1 string, image2 string, cli command.Cli, workspace string,
7977
}
8078

8179
diffPackages(result1, result2)
82-
diffCves(result1, result2)
80+
//diffCves(result1, result2)
8381
return nil
8482
}
8583

@@ -235,7 +233,7 @@ type CveEntry struct {
235233

236234
type CveMap map[string]CveEntry
237235

238-
func diffCves(result1, result2 ImageIndexResult) {
236+
/*func diffCves(result1, result2 ImageIndexResult) {
239237
dc := 0
240238
cves := make(CveMap)
241239
for _, c := range result1.Sbom.Vulnerabilities {
@@ -329,4 +327,4 @@ func diffCves(result1, result2 ImageIndexResult) {
329327
fmt.Println(t.Render())
330328
}
331329
332-
}
330+
}*/

sbom/index.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ type ImageIndexResult struct {
4343
func indexImageAsync(wg *sync.WaitGroup, image string, cli command.Cli, resultChan chan<- ImageIndexResult) {
4444
defer wg.Done()
4545
sbom, err := IndexImage(image, cli)
46-
cves, err := query.QueryCves(sbom, "", "", "")
46+
cves, err := query.ForVulnerabilitiesInGraphQL(sbom)
4747
if err == nil {
48-
sbom.Vulnerabilities = *cves
48+
sbom.Vulnerabilities = cves.VulnerabilitiesByPackage
4949
}
5050
resultChan <- ImageIndexResult{
5151
Input: image,

types/graphql_types.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright © 2022 Docker, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package types
218

319
type BaseImage struct {
@@ -48,3 +64,31 @@ type BaseImagesByDiffIdsQuery struct {
4864
type ImageByDigestQuery struct {
4965
ImageDetailsByDigest BaseImage `graphql:"imageDetailsByDigest(context: {}, digest: $digest, platform: {os: $os, architecture: $architecture, variant: $variant})"`
5066
}
67+
68+
type Vulnerability struct {
69+
Source string `graphql:"source" json:"source,omitempty"`
70+
SourceId string `graphql:"sourceId" json:"source_id,omitempty"`
71+
Description string `graphql:"description" json:"description,omitempty"`
72+
VulnerableRange string `graphql:"vulnerableRange" json:"vulnerable_range,omitempty"`
73+
FixedBy string `graphql:"fixedBy" json:"fixed_by,omitempty"`
74+
Url string `graphql:"url" json:"url,omitempty"`
75+
Cvss struct {
76+
Score float32 `graphql:"score" json:"score,omitempty"`
77+
Severity string `graphql:"severity" json:"severity,omitempty"`
78+
Vector string `graphql:"vector" json:"vector,omitempty"`
79+
Version string `graphql:"version" json:"version,omitempty"`
80+
} `graphql:"cvss" json:"cvss,omitempty"`
81+
Cwes []struct {
82+
CweId string `graphql:"cweId" json:"cwe_id,omitempty"`
83+
Name string `graphql:"description" json:"name,omitempty"`
84+
} `graphql:"cwes" json:"cwes,omitempty"`
85+
}
86+
87+
type VulnerabilitiesByPurl struct {
88+
Purl string `graphql:"purl" json:"purl,omitempty"`
89+
Vulnerabilities []Vulnerability `graphql:"vulnerabilities" json:"vulnerabilities,omitempty"`
90+
}
91+
92+
type VulnerabilitiesByPurls struct {
93+
VulnerabilitiesByPackage []VulnerabilitiesByPurl `graphql:"vulnerabilitiesByPackage(context: {}, packageUrls: $purls)"`
94+
}

types/types.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ type Source struct {
130130
}
131131

132132
type Sbom struct {
133-
Source Source `json:"source"`
134-
Artifacts []Package `json:"artifacts"`
135-
Vulnerabilities []Cve `json:"vulnerabilities,omitempty"`
136-
Descriptor Descriptor `json:"descriptor"`
133+
Source Source `json:"source"`
134+
Artifacts []Package `json:"artifacts"`
135+
Vulnerabilities []VulnerabilitiesByPurl `json:"vulnerabilities,omitempty"`
136+
Descriptor Descriptor `json:"descriptor"`
137137
}
138138

139139
type Package struct {

0 commit comments

Comments
 (0)