Skip to content

Commit f893559

Browse files
authored
fix: move openvex packages as subcomponents (#366)
Signed-off-by: Sertac Ozercan <[email protected]>
1 parent 1a7c070 commit f893559

File tree

8 files changed

+84
-65
lines changed

8 files changed

+84
-65
lines changed

go.mod

+4-7
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ require (
2828
google.golang.org/grpc v1.58.2
2929
)
3030

31-
require (
32-
github.com/sagikazarmark/locafero v0.3.0 // indirect
33-
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
34-
github.com/sourcegraph/conc v0.3.0 // indirect
35-
go.uber.org/multierr v1.11.0 // indirect
36-
)
37-
3831
require (
3932
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
4033
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
@@ -102,9 +95,12 @@ require (
10295
github.com/prometheus/client_model v0.4.0 // indirect
10396
github.com/prometheus/common v0.44.0 // indirect
10497
github.com/prometheus/procfs v0.10.1 // indirect
98+
github.com/sagikazarmark/locafero v0.3.0 // indirect
99+
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
105100
github.com/samber/lo v1.38.1 // indirect
106101
github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect
107102
github.com/shibumi/go-pathspec v1.3.0 // indirect
103+
github.com/sourcegraph/conc v0.3.0 // indirect
108104
github.com/spdx/tools-golang v0.5.1 // indirect
109105
github.com/spf13/afero v1.10.0 // indirect
110106
github.com/spf13/cast v1.5.1 // indirect
@@ -123,6 +119,7 @@ require (
123119
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
124120
go.opentelemetry.io/otel/trace v1.14.0 // indirect
125121
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
122+
go.uber.org/multierr v1.11.0 // indirect
126123
golang.org/x/crypto v0.13.0 // indirect
127124
golang.org/x/mod v0.12.0 // indirect
128125
golang.org/x/net v0.15.0 // indirect

pkg/patch/patch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func patchWithContext(ctx context.Context, image, reportFile, patchedTag, workin
156156
}
157157
// vex document must contain at least one statement
158158
if output != "" && len(validatedManifest.Updates) > 0 {
159-
return vex.TryOutputVexDocument(validatedManifest, pkgmgr, format, output)
159+
return vex.TryOutputVexDocument(validatedManifest, pkgmgr, patchedImageName, format, output)
160160
}
161161
return nil
162162
}

pkg/types/types.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ type UpdatePackage struct {
99
Name string `json:"name"`
1010
InstalledVersion string `json:"installedVersion"`
1111
FixedVersion string `json:"fixedVersion"`
12-
VulnerabilityID string `json:"vulnerability"`
12+
VulnerabilityID string `json:"vulnerabilityID"`
1313
}
1414

1515
type UpdatePackages []UpdatePackage
1616

1717
type UpdateManifest struct {
18-
OSType string `json:"ostype"`
19-
OSVersion string `json:"osversion"`
18+
OSType string `json:"osType"`
19+
OSVersion string `json:"osVersion"`
2020
Arch string `json:"arch"`
2121
Updates UpdatePackages `json:"updates"`
2222
}

pkg/vex/openvex.go

+16-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ var (
2626

2727
type OpenVex struct{}
2828

29-
func (o *OpenVex) CreateVEXDocument(updates *types.UpdateManifest, pkgmgr pkgmgr.PackageManager) (string, error) {
29+
func (o *OpenVex) CreateVEXDocument(
30+
updates *types.UpdateManifest,
31+
patchedImageName string,
32+
pkgmgr pkgmgr.PackageManager,
33+
) (string, error) {
3034
t := now()
3135
doc := v
3236
doc.Timestamp = &t
@@ -43,9 +47,15 @@ func (o *OpenVex) CreateVEXDocument(updates *types.UpdateManifest, pkgmgr pkgmgr
4347
}
4448
doc.Metadata.ID = id
4549

50+
imageProduct := vex.Product{
51+
Component: vex.Component{
52+
ID: "pkg:oci/" + patchedImageName,
53+
},
54+
}
55+
4656
pkgType := pkgmgr.GetPackageType()
4757
for _, u := range updates.Updates {
48-
product := vex.Product{
58+
subComponent := vex.Subcomponent{
4959
Component: vex.Component{
5060
// syntax is "pkg:<pkgType>/<osType>/<packageName>@<installedVersion>?arch=<arch>"
5161
ID: "pkg:" + pkgType + "/" + updates.OSType + "/" + u.Name + "@" + u.FixedVersion + "?arch=" + updates.Arch,
@@ -57,22 +67,21 @@ func (o *OpenVex) CreateVEXDocument(updates *types.UpdateManifest, pkgmgr pkgmgr
5767
for i := range doc.Statements {
5868
if doc.Statements[i].Vulnerability.ID == u.VulnerabilityID {
5969
found = true
60-
doc.Statements[i].Products = append(doc.Statements[i].Products, product)
70+
doc.Statements[i].Products[0].Subcomponents = append(doc.Statements[i].Products[0].Subcomponents, subComponent)
6171
}
6272
}
6373
if found {
6474
continue
6575
}
6676

6777
// otherwise, create new statement
78+
imageProduct.Subcomponents = []vex.Subcomponent{subComponent}
6879
doc.Statements = append(doc.Statements, vex.Statement{
6980
Vulnerability: vex.Vulnerability{
7081
ID: u.VulnerabilityID,
7182
},
72-
Products: []vex.Product{
73-
product,
74-
},
75-
Status: "fixed",
83+
Products: []vex.Product{imageProduct},
84+
Status: "fixed",
7685
})
7786
}
7887

pkg/vex/openvex_test.go

+28-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
1414
workingFolder := "/tmp"
1515
alpineManager, _ := pkgmgr.GetPackageManager("alpine", config, workingFolder)
1616
debianManager, _ := pkgmgr.GetPackageManager("debian", config, workingFolder)
17+
patchedImageName := "foo.io/bar:latest"
1718
t.Setenv("COPA_VEX_AUTHOR", "test author")
1819

1920
// mock time
@@ -24,8 +25,9 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
2425
id = func() (string, error) { return "https://openvex.dev/test", nil }
2526

2627
type args struct {
27-
updates *types.UpdateManifest
28-
pkgmgr pkgmgr.PackageManager
28+
updates *types.UpdateManifest
29+
pkgmgr pkgmgr.PackageManager
30+
patchedImageName string
2931
}
3032
tests := []struct {
3133
name string
@@ -38,6 +40,7 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
3840
name: "valid openvex document",
3941
o: &OpenVex{},
4042
args: args{
43+
patchedImageName: patchedImageName,
4144
updates: &types.UpdateManifest{
4245
Updates: []types.UpdatePackage{
4346
{
@@ -66,7 +69,12 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
6669
},
6770
"products": [
6871
{
69-
"@id": "pkg:apk/alpine/[email protected]?arch=x86_64"
72+
"@id": "pkg:oci/foo.io/bar:latest",
73+
"subcomponents": [
74+
{
75+
"@id": "pkg:apk/alpine/[email protected]?arch=x86_64"
76+
}
77+
]
7078
}
7179
],
7280
"status": "fixed"
@@ -80,6 +88,7 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
8088
name: "valid openvex document with multiple statements and multiple vulnerabilities",
8189
o: &OpenVex{},
8290
args: args{
91+
patchedImageName: patchedImageName,
8392
updates: &types.UpdateManifest{
8493
Updates: []types.UpdatePackage{
8594
{
@@ -114,10 +123,15 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
114123
},
115124
"products": [
116125
{
117-
"@id": "pkg:apk/alpine/[email protected]?arch=x86_64"
118-
},
119-
{
120-
"@id": "pkg:deb/debian/[email protected]?arch=x86_64"
126+
"@id": "pkg:oci/foo.io/bar:latest",
127+
"subcomponents": [
128+
{
129+
"@id": "pkg:apk/alpine/[email protected]?arch=x86_64"
130+
},
131+
{
132+
"@id": "pkg:deb/debian/[email protected]?arch=x86_64"
133+
}
134+
]
121135
}
122136
],
123137
"status": "fixed"
@@ -128,7 +142,12 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
128142
},
129143
"products": [
130144
{
131-
"@id": "pkg:deb/debian/[email protected]?arch=x86_64"
145+
"@id": "pkg:oci/foo.io/bar:latest",
146+
"subcomponents": [
147+
{
148+
"@id": "pkg:deb/debian/[email protected]?arch=x86_64"
149+
}
150+
]
132151
}
133152
],
134153
"status": "fixed"
@@ -142,7 +161,7 @@ func TestOpenVex_CreateVEXDocument(t *testing.T) {
142161
for _, tt := range tests {
143162
t.Run(tt.name, func(t *testing.T) {
144163
o := &OpenVex{}
145-
got, err := o.CreateVEXDocument(tt.args.updates, tt.args.pkgmgr)
164+
got, err := o.CreateVEXDocument(tt.args.updates, tt.args.patchedImageName, tt.args.pkgmgr)
146165
if (err != nil) != tt.wantErr {
147166
t.Errorf("OpenVex.CreateVEXDocument() error = %v, wantErr %v", err, tt.wantErr)
148167
return

pkg/vex/vex.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ import (
99
)
1010

1111
type Vex interface {
12-
CreateVEXDocument(updates *types.UpdateManifest, pkgmgr pkgmgr.PackageManager) (string, error)
12+
CreateVEXDocument(updates *types.UpdateManifest, patchedImageName string, pkgmgr pkgmgr.PackageManager) (string, error)
1313
}
1414

15-
func TryOutputVexDocument(updates *types.UpdateManifest, pkgmgr pkgmgr.PackageManager, format, file string) error {
15+
func TryOutputVexDocument(updates *types.UpdateManifest, pkgmgr pkgmgr.PackageManager, patchedImageName, format, file string) error {
1616
var doc string
1717
var err error
1818

1919
switch format {
2020
case "openvex":
2121
ov := &OpenVex{}
22-
doc, err = ov.CreateVEXDocument(updates, pkgmgr)
22+
doc, err = ov.CreateVEXDocument(updates, patchedImageName, pkgmgr)
2323
if err != nil {
2424
return err
2525
}

pkg/vex/vex_test.go

+17-13
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ func TestTryOutputVexDocument(t *testing.T) {
1212
config := &buildkit.Config{}
1313
workingFolder := "/tmp"
1414
alpineManager, _ := pkgmgr.GetPackageManager("alpine", config, workingFolder)
15+
patchedImageName := "patched"
1516

1617
type args struct {
17-
updates *types.UpdateManifest
18-
pkgmgr pkgmgr.PackageManager
19-
format string
20-
file string
18+
updates *types.UpdateManifest
19+
pkgmgr pkgmgr.PackageManager
20+
patchedImageName string
21+
format string
22+
file string
2123
}
2224
tests := []struct {
2325
name string
@@ -27,27 +29,29 @@ func TestTryOutputVexDocument(t *testing.T) {
2729
{
2830
name: "invalid format",
2931
args: args{
30-
updates: &types.UpdateManifest{},
31-
pkgmgr: nil,
32-
format: "fakevex",
33-
file: "",
32+
updates: &types.UpdateManifest{},
33+
pkgmgr: nil,
34+
patchedImageName: patchedImageName,
35+
format: "fakevex",
36+
file: "",
3437
},
3538
wantErr: true,
3639
},
3740
{
3841
name: "valid format",
3942
args: args{
40-
updates: &types.UpdateManifest{},
41-
pkgmgr: alpineManager,
42-
format: "openvex",
43-
file: "/tmp/test",
43+
updates: &types.UpdateManifest{},
44+
pkgmgr: alpineManager,
45+
patchedImageName: patchedImageName,
46+
format: "openvex",
47+
file: "/tmp/test",
4448
},
4549
wantErr: false,
4650
},
4751
}
4852
for _, tt := range tests {
4953
t.Run(tt.name, func(t *testing.T) {
50-
if err := TryOutputVexDocument(tt.args.updates, tt.args.pkgmgr, tt.args.format, tt.args.file); (err != nil) != tt.wantErr {
54+
if err := TryOutputVexDocument(tt.args.updates, tt.args.pkgmgr, tt.args.patchedImageName, tt.args.format, tt.args.file); (err != nil) != tt.wantErr {
5155
t.Errorf("TryOutputVexDocument() error = %v, wantErr %v", err, tt.wantErr)
5256
}
5357
})

website/docs/output.md

+12-22
Original file line numberDiff line numberDiff line change
@@ -35,37 +35,27 @@ This will generate a VEX Document that looks like:
3535
```json
3636
{
3737
"@context": "https://openvex.dev/ns",
38-
"@id": "https://openvex.dev/docs/public/vex-6f15c26e0410a4d44e0af4062f4b883fbc19a98e57baf131715d942213e5002a",
38+
"@id": "https://openvex.dev/docs/public/vex-a6c44ec1d79e9dd4190dc01b4ecf7527ebb26bd37c01e32e6efcd203ae00d2a5",
3939
"author": "Project Copacetic",
40-
"timestamp": "2023-08-25T21:40:23.891230545Z",
40+
"timestamp": "2023-10-11T00:15:00.114768055Z",
4141
"version": 1,
4242
"tooling": "Project Copacetic",
4343
"statements": [
4444
{
4545
"vulnerability": {
46-
"@id": "CVE-2021-3995"
46+
"@id": "CVE-2021-22945"
4747
},
4848
"products": [
4949
{
50-
"@id": "pkg:deb/debian/bsdutils@1:2.36.1-8?arch=amd64"
51-
},
52-
{
53-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
54-
},
55-
{
56-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
57-
},
58-
{
59-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
60-
},
61-
{
62-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
63-
},
64-
{
65-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
66-
},
67-
{
68-
"@id": "pkg:deb/debian/[email protected]?arch=amd64"
50+
"@id": "pkg:oci/docker.io/library/nginx:1.21.6-patched",
51+
"subcomponents": [
52+
{
53+
"@id": "pkg:deb/debian/[email protected]+deb11u2?arch=amd64"
54+
},
55+
{
56+
"@id": "pkg:deb/debian/[email protected]+deb11u2?arch=amd64"
57+
}
58+
]
6959
}
7060
],
7161
"status": "fixed"

0 commit comments

Comments
 (0)