fix(db): fix case when 2 trivy-db were copied at the same time (#8452)

This commit is contained in:
DmitriyLewen
2025-02-28 16:11:27 +06:00
committed by GitHub
parent a99498cdd9
commit bb3cca6018
9 changed files with 80 additions and 36 deletions

8
go.mod
View File

@@ -25,7 +25,7 @@ require (
github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8
github.com/aquasecurity/tml v0.6.1
github.com/aquasecurity/trivy-checks v1.6.1
github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e
github.com/aquasecurity/trivy-db v0.0.0-20250227071930-8bd8a9b89e2d
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48
github.com/aquasecurity/trivy-kubernetes v0.7.0
github.com/aws/aws-sdk-go-v2 v1.34.0
@@ -80,7 +80,7 @@ require (
github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee
github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e
github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08
github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a
github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd
github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44
github.com/mattn/go-shellwords v1.0.12
@@ -437,4 +437,8 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.24.12 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.11 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.10 // indirect
github.com/oklog/ulid/v2 v2.1.0 // indirect
github.com/samber/oops v1.15.0 // indirect
)
replace github.com/aquasecurity/trivy-db => github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612

13
go.sum
View File

@@ -685,6 +685,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612 h1:T/H7M/RT9eSesHJdVVDQybAkTYNKI5RjyIeWpa2jK8o=
github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612/go.mod h1:4bTsQPtMBN8v+UfUlE1aQBN1imftefnDafHBF85+aT8=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
@@ -805,8 +807,6 @@ github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gw
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
github.com/aquasecurity/trivy-checks v1.6.1 h1:ANxKl+c9/k3Uk0YNQwpFBx++CG9Goi5T0YeN7Qimmf4=
github.com/aquasecurity/trivy-checks v1.6.1/go.mod h1:xjHg4ivIIIFD7FFNpGrqxi1pRgAW1EXeG4VlkGiymjI=
github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e h1:O5j5SeCNBrXApgBTOobO06q4LMxJxIhcSGE7H6Y154E=
github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e/go.mod h1:gS8VhlNxhraiq60BBnJw9kGtjeMspQ9E8pX24jCL4jg=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8=
github.com/aquasecurity/trivy-kubernetes v0.7.0 h1:0pRJFSslUYd9xzQIEw1c0mS7k1Vv489nH/LsxeU6yME=
@@ -1534,8 +1534,8 @@ github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e h1:nCgF1JE
github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e/go.mod h1:XFWPTlAcEL733RUjbr0QBybdt6oK2DH7LZk8id2qtd4=
github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd h1:JEIW94K3spsvBI5Xb9PGhKSIza9/jxO1lF30tPCAJlA=
github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd/go.mod h1:3XMMY1M486mWGTD13WPItg6FsgflQR72ZMAkd+gsyoQ=
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 h1:AevUBW4cc99rAF8q8vmddIP8qd/0J5s/UyltGbp66dg=
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08/go.mod h1:JOkBRrE1HvgTyjk6diFtNGgr8XJMtIfiBzkL5krqzVk=
github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a h1:eLvAzVoRfHEOl64OxFhepPf3vj7SKvXY/tFc3BS0b7s=
github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a/go.mod h1:jZ3F25l7DbD7l7DcA8aj7eo1EZ84nbzcQHBB4lCSrI8=
github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd h1:Y30EzvuoVp97b0unb/GOFXzBUKRXZXUN2e0wYmvC+ic=
github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd/go.mod h1:5f7mCJGW9cJb8SDn3z8qodGxpMCOo8d/2nls/tiwRrw=
github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44 h1:VmSjn0UCyfXUNdePDr7uM/uZTnGSp+mKD5+cYkEoLx4=
@@ -1635,6 +1635,8 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/oleiade/reflections v1.0.1 h1:D1XO3LVEYroYskEsoSiGItp9RUxG6jWnCVvrqH0HHQM=
github.com/oleiade/reflections v1.0.1/go.mod h1:rdFxbxq4QXVZWj0F+e9jqjDkc7dbp97vkRixKo2JR60=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -1678,6 +1680,7 @@ github.com/owenrumney/squealer v1.2.10 h1:Yxxy30sOhaK8/FeneHklV0sA6DP4UjUpky2opj
github.com/owenrumney/squealer v1.2.10/go.mod h1:V72uafpqPERMaJ/pA1MwK/dI0QRzLHCLnh6MqYmjFzY=
github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs=
github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
@@ -1769,6 +1772,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/samber/oops v1.15.0 h1:/mF33KAqA2TugU6y/tomFpK6G6mJB7g0aqRyHkaSIeg=
github.com/samber/oops v1.15.0/go.mod h1:9LpLZkpjojEt/of7EpG5o65i/Lp23ddDvGhg2L871Ow=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=

View File

@@ -2,6 +2,7 @@ package db
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
@@ -96,16 +97,24 @@ func NewClient(dbDir string, quiet bool, opts ...Option) *Client {
// NeedsUpdate check is DB needs update
func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool) (bool, error) {
var noRequiredFiles bool
if _, err := os.Stat(db.Path(c.dbDir)); errors.Is(err, os.ErrNotExist) {
log.DebugContext(ctx, "There is no db file")
noRequiredFiles = true
}
meta, err := c.metadata.Get()
if err != nil {
log.DebugContext(ctx, "There is no valid metadata file", log.Err(err))
if skip {
log.ErrorContext(ctx, "The first run cannot skip downloading DB")
return false, xerrors.New("--skip-update cannot be specified on the first run")
}
noRequiredFiles = true
meta = metadata.Metadata{Version: db.SchemaVersion}
}
if skip && noRequiredFiles {
log.ErrorContext(ctx, "The first run cannot skip downloading DB")
return false, xerrors.New("--skip-update cannot be specified on the first run")
}
if db.SchemaVersion < meta.Version {
log.ErrorContext(ctx, "Trivy version is old. Update to the latest version.", log.String("version", cliVersion))
return false, xerrors.Errorf("the version of DB schema doesn't match. Local DB: %d, Expected: %d",

View File

@@ -21,14 +21,16 @@ func TestClient_NeedsUpdate(t *testing.T) {
timeNextUpdateDay2 := time.Date(2019, 10, 2, 0, 0, 0, 0, time.UTC)
tests := []struct {
name string
skip bool
metadata metadata.Metadata
want bool
wantErr string
name string
skip bool
dbFileExists bool
metadata metadata.Metadata
want bool
wantErr string
}{
{
name: "happy path",
name: "happy path",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion,
NextUpdate: timeNextUpdateDay1,
@@ -36,12 +38,19 @@ func TestClient_NeedsUpdate(t *testing.T) {
want: true,
},
{
name: "happy path for first run",
metadata: metadata.Metadata{},
want: true,
name: "happy path for first run",
dbFileExists: true,
metadata: metadata.Metadata{},
want: true,
},
{
name: "happy path with old schema version",
name: "happy path for first run without trivy.db",
dbFileExists: false,
want: true,
},
{
name: "happy path with old schema version",
dbFileExists: true,
metadata: metadata.Metadata{
Version: 0,
NextUpdate: timeNextUpdateDay1,
@@ -49,7 +58,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
want: true,
},
{
name: "happy path with --skip-update",
name: "happy path with --skip-update",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion,
NextUpdate: timeNextUpdateDay1,
@@ -58,7 +68,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
want: false,
},
{
name: "skip downloading DB",
name: "skip downloading DB",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion,
NextUpdate: timeNextUpdateDay2,
@@ -66,7 +77,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
want: false,
},
{
name: "newer schema version",
name: "newer schema version",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion + 1,
NextUpdate: timeNextUpdateDay2,
@@ -75,13 +87,21 @@ func TestClient_NeedsUpdate(t *testing.T) {
db.SchemaVersion+1, db.SchemaVersion),
},
{
name: "--skip-update on the first run",
metadata: metadata.Metadata{},
skip: true,
wantErr: "--skip-update cannot be specified on the first run",
name: "--skip-update without trivy.db on the first run",
dbFileExists: false,
skip: true,
wantErr: "--skip-update cannot be specified on the first run",
},
{
name: "--skip-update with different schema version",
name: "--skip-update without metadata.json on the first run",
dbFileExists: true,
metadata: metadata.Metadata{},
skip: true,
wantErr: "--skip-update cannot be specified on the first run",
},
{
name: "--skip-update with different schema version",
dbFileExists: true,
metadata: metadata.Metadata{
Version: 0,
NextUpdate: timeNextUpdateDay1,
@@ -91,7 +111,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
0, db.SchemaVersion),
},
{
name: "happy with old DownloadedAt",
name: "happy with old DownloadedAt",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion,
NextUpdate: timeNextUpdateDay1,
@@ -100,7 +121,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
want: true,
},
{
name: "skip downloading DB with recent DownloadedAt",
name: "skip downloading DB with recent DownloadedAt",
dbFileExists: true,
metadata: metadata.Metadata{
Version: db.SchemaVersion,
NextUpdate: timeNextUpdateDay1,
@@ -119,6 +141,11 @@ func TestClient_NeedsUpdate(t *testing.T) {
require.NoError(t, err)
}
if tt.dbFileExists {
err := db.Init(dbDir)
require.NoError(t, err)
}
// Set a fake time
ctx := clock.With(context.Background(), time.Date(2019, 10, 1, 0, 0, 0, 0, time.UTC))
@@ -138,7 +165,6 @@ func TestClient_NeedsUpdate(t *testing.T) {
}
func TestClient_Download(t *testing.T) {
tests := []struct {
name string
input string

View File

@@ -155,7 +155,7 @@ func TestDriver_Detect(t *testing.T) {
pkgName: "symfony/symfony",
pkgVer: "5.1.5",
},
wantErr: "failed to unmarshal advisory JSON",
wantErr: "json unmarshal error",
},
{
name: "duplicated version in advisory",

View File

@@ -107,7 +107,7 @@ func TestScanner_Detect(t *testing.T) {
},
},
},
wantErr: "failed to unmarshal advisory JSON",
wantErr: "failed to get debian advisories",
},
}
for _, tt := range tests {

View File

@@ -331,7 +331,7 @@ func TestScanner_Detect(t *testing.T) {
},
},
},
wantErr: "failed to unmarshal advisory JSON",
wantErr: "failed to get Oracle Linux advisory",
},
}

View File

@@ -86,7 +86,7 @@ func TestScanner_Detect(t *testing.T) {
},
},
},
wantErr: "failed to get Photon advisories",
wantErr: "failed to get Photon Linux advisory",
},
}
for _, tt := range tests {

View File

@@ -209,7 +209,7 @@ func TestScanner_Detect(t *testing.T) {
},
},
},
wantErr: "failed to get SUSE advisories",
wantErr: "failed to get SUSE advisory",
},
}
for _, tt := range tests {