Skip to content

Commit 4e4d00a

Browse files
authored
feat: add trivy-based sbom artifact generation support (#4088)
fixes issue #4067 Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
1 parent d8fb198 commit 4e4d00a

12 files changed

Lines changed: 712 additions & 29 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ vendor/
3333
examples/config-sync-localhost.json
3434
node_modules
3535
zot-test
36+
37+
.gotmp/

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ZUI_BUILD_PATH := ""
3131
ZUI_VERSION := commit-34deb3d
3232
ZUI_REPO_OWNER := project-zot
3333
ZUI_REPO_NAME := zui
34-
SWAGGER_VERSION := v1.16.2
34+
SWAGGER_VERSION := v1.16.6
3535
STACKER := $(TOOLSDIR)/bin/stacker
3636
STACKER_VERSION := v1.1.0-rc3
3737
KIND := $(TOOLSDIR)/bin/kind
@@ -364,7 +364,7 @@ check: ./.golangci.yaml $(GOLINTER)
364364
.PHONY: swagger
365365
swagger:
366366
swag -v || go install github.com/swaggo/swag/cmd/swag@$(SWAGGER_VERSION)
367-
swag init --parseDependency -o swagger -g pkg/api/routes.go -q
367+
swag init --parseDependency --exclude pkg/extensions/search/cve/trivy -o swagger -g pkg/api/routes.go -q
368368

369369
.PHONY: update-licenses
370370
# note: for predictable output of below sort command we use locale LC_ALL=C

examples/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,8 @@ A minimal configuration only sets how often the DB is refreshed; zot applies def
12961296

12971297
To set those options explicitly (for example to mirror standalone Trivy’s `--vuln-severity-source` behavior), use a `trivy` object under `cve`:
12981298

1299-
- [config-cve-trivy.json](config-cve-trivy.json) — shows optional `dbRepository`, `javaDBRepository`, and `vulnSeveritySources`.
1299+
- [config-cve-trivy.json](config-cve-trivy.json) — shows optional `dbRepository`, `javaDBRepository`, `vulnSeveritySources`, and `sbom`.
13001300

13011301
`vulnSeveritySources` is a list of source names in priority order (for example `auto`, `nvd`, or vendor IDs such as `redhat`, `alpine`). If omitted, zot defaults it to `["auto"]`, consistent with the Trivy CLI. See [Trivy: severity selection](https://trivy.dev/docs/latest/scanner/vulnerability/#severity-selection).
1302+
1303+
`sbom.enable` lets zot generate SBOMs while scanning and store them as OCI artifacts attached to the scanned image. `sbom.format` supports `spdx-json` (default) and `cyclonedx`.

examples/config-sbom-trivy.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"distSpecVersion": "1.1.1",
3+
"storage": {
4+
"rootDirectory": "/tmp/zot"
5+
},
6+
"http": {
7+
"address": "127.0.0.1",
8+
"port": "8080"
9+
},
10+
"log": {
11+
"level": "debug",
12+
"output": "/tmp/zot.log"
13+
},
14+
"extensions": {
15+
"ui": {
16+
"enable": true
17+
},
18+
"search": {
19+
"enable": true,
20+
"cve": {
21+
"updateInterval": "24h",
22+
"trivy": {
23+
"dbRepository": "ghcr.io/aquasecurity/trivy-db",
24+
"javaDBRepository": "ghcr.io/aquasecurity/trivy-java-db",
25+
"vulnSeveritySources": ["auto"],
26+
"sbom": {
27+
"enable": true,
28+
"format": "spdx-json"
29+
}
30+
}
31+
}
32+
}
33+
}
34+
}

pkg/cli/server/config_reloader_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestConfigReloader(t *testing.T) {
2020

2121
defer func() { os.Args = oldArgs }()
2222

23-
Convey("reload access control config", t, func(c C) {
23+
Convey("reload access control config", t, func(conveyCtx C) {
2424
port := test.GetFreePort()
2525
baseURL := test.GetBaseURL(port)
2626

@@ -79,7 +79,7 @@ func TestConfigReloader(t *testing.T) {
7979

8080
go func() {
8181
err = cli.NewServerRootCmd().Execute()
82-
So(err, ShouldBeNil)
82+
conveyCtx.So(err, ShouldBeNil)
8383
}()
8484

8585
test.WaitTillServerReady(baseURL)
@@ -173,7 +173,7 @@ func TestConfigReloader(t *testing.T) {
173173
})
174174
})
175175

176-
Convey("reload gc config", t, func(c C) {
176+
Convey("reload gc config", t, func(ctx C) {
177177
port := test.GetFreePort()
178178
baseURL := test.GetBaseURL(port)
179179

@@ -214,7 +214,7 @@ func TestConfigReloader(t *testing.T) {
214214

215215
go func() {
216216
err = cli.NewServerRootCmd().Execute()
217-
So(err, ShouldBeNil)
217+
ctx.So(err, ShouldBeNil)
218218
}()
219219

220220
test.WaitTillServerReady(baseURL)
@@ -300,7 +300,7 @@ func TestConfigReloader(t *testing.T) {
300300
})
301301
})
302302

303-
Convey("reload sync config", t, func(c C) {
303+
Convey("reload sync config", t, func(ctx C) {
304304
port := test.GetFreePort()
305305
baseURL := test.GetBaseURL(port)
306306

@@ -352,7 +352,7 @@ func TestConfigReloader(t *testing.T) {
352352

353353
go func() {
354354
err = cli.NewServerRootCmd().Execute()
355-
So(err, ShouldBeNil)
355+
ctx.So(err, ShouldBeNil)
356356
}()
357357

358358
test.WaitTillServerReady(baseURL)
@@ -450,7 +450,7 @@ func TestConfigReloader(t *testing.T) {
450450
})
451451
})
452452

453-
Convey("reload scrub and CVE config", t, func(c C) {
453+
Convey("reload scrub and CVE config", t, func(ctx C) {
454454
port := test.GetFreePort()
455455
baseURL := test.GetBaseURL(port)
456456

@@ -495,7 +495,7 @@ func TestConfigReloader(t *testing.T) {
495495

496496
go func() {
497497
err = cli.NewServerRootCmd().Execute()
498-
So(err, ShouldBeNil)
498+
ctx.So(err, ShouldBeNil)
499499
}()
500500

501501
test.WaitTillServerReady(baseURL)
@@ -591,7 +591,7 @@ func TestConfigReloader(t *testing.T) {
591591
So(found, ShouldBeTrue)
592592
})
593593

594-
Convey("reload bad config", t, func(c C) {
594+
Convey("reload bad config", t, func(conveyCtx C) {
595595
port := test.GetFreePort()
596596
baseURL := test.GetBaseURL(port)
597597

@@ -643,7 +643,7 @@ func TestConfigReloader(t *testing.T) {
643643

644644
go func() {
645645
err = cli.NewServerRootCmd().Execute()
646-
So(err, ShouldBeNil)
646+
conveyCtx.So(err, ShouldBeNil)
647647
}()
648648

649649
test.WaitTillServerReady(baseURL)

pkg/cli/server/extensions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ func TestServeSearchEnabledDefaultCVEDB(t *testing.T) {
968968
// The default config handling logic will convert the 1h interval to a 2h interval
969969
substring := "\"Search\":{\"Enable\":true,\"CVE\":{\"UpdateInterval\":7200000000000,\"Trivy\":" +
970970
"{\"DBRepository\":\"ghcr.io/aquasecurity/trivy-db\",\"JavaDBRepository\":\"ghcr.io/aquasecurity/trivy-java-db\"," +
971-
"\"VulnSeveritySources\":[\"auto\"]}}}"
971+
"\"VulnSeveritySources\":[\"auto\"],\"SBOM\":null}}}"
972972

973973
found, err := ReadLogFileAndSearchString(logPath, substring, readLogFileTimeout)
974974

pkg/extensions/config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ type TrivyConfig struct {
6363
// VulnSeveritySources controls Trivy's severity source selection (same as Trivy's --vuln-severity-source).
6464
// If empty, zot will default it to ["auto"].
6565
VulnSeveritySources []string
66+
SBOM *SBOMConfig
67+
}
68+
69+
type SBOMConfig struct {
70+
Enable bool
71+
// Format controls the generated SBOM output format.
72+
// Supported values are "spdx-json" (default) and "cyclonedx".
73+
Format string
6674
}
6775

6876
type MetricsConfig struct {

0 commit comments

Comments
 (0)