Skip to content

Commit a94123e

Browse files
committed
chainguard: add chainguard and wolfi support
Signed-off-by: RTann <[email protected]>
1 parent 6710a18 commit a94123e

File tree

6 files changed

+310
-86
lines changed

6 files changed

+310
-86
lines changed

alpine/parser.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/quay/claircore"
1111
"github.com/quay/claircore/libvuln/driver"
12+
"github.com/quay/claircore/updater/secdb"
1213
)
1314

1415
const (
@@ -22,15 +23,15 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln
2223
zlog.Info(ctx).Msg("starting parse")
2324
defer r.Close()
2425

25-
var db SecurityDB
26+
var db secdb.SecurityDB
2627
if err := json.NewDecoder(r).Decode(&db); err != nil {
2728
return nil, err
2829
}
2930
return u.parse(ctx, &db)
3031
}
3132

3233
// parse parses the alpine SecurityDB
33-
func (u *updater) parse(ctx context.Context, sdb *SecurityDB) ([]*claircore.Vulnerability, error) {
34+
func (u *updater) parse(ctx context.Context, sdb *secdb.SecurityDB) ([]*claircore.Vulnerability, error) {
3435
out := []*claircore.Vulnerability{}
3536
for _, pkg := range sdb.Packages {
3637
if err := ctx.Err(); err != nil {

alpine/secdb_test.go

Lines changed: 0 additions & 82 deletions
This file was deleted.

chainguard/distributionscanner.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package chainguard
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"errors"
7+
"fmt"
8+
"github.com/quay/zlog"
9+
"io/fs"
10+
"runtime/trace"
11+
12+
"github.com/quay/claircore"
13+
"github.com/quay/claircore/indexer"
14+
"github.com/quay/claircore/osrelease"
15+
)
16+
17+
const (
18+
scannerName = "chainguard"
19+
scannerVersion = "1"
20+
scannerKind = "distribution"
21+
22+
chainguard = `chainguard`
23+
wolfi = `wolfi`
24+
)
25+
26+
var (
27+
_ indexer.DistributionScanner = (*DistributionScanner)(nil)
28+
_ indexer.VersionedScanner = (*DistributionScanner)(nil)
29+
)
30+
31+
// DistributionScanner attempts to discover if a layer
32+
// displays characteristics of a chainguard or wolfi distribution.
33+
type DistributionScanner struct{}
34+
35+
// Name implements scanner.VersionedScanner.
36+
func (*DistributionScanner) Name() string { return scannerName }
37+
38+
// Version implements scanner.VersionedScanner.
39+
func (*DistributionScanner) Version() string { return scannerVersion }
40+
41+
// Kind implements scanner.VersionedScanner.
42+
func (*DistributionScanner) Kind() string { return scannerKind }
43+
44+
// Scan will inspect the layer for an os-release
45+
// and determine if it represents a chainguard or wolfi release.
46+
//
47+
// If the file is not found, or the file does not represent a chainguard nor wolfi release,
48+
// (nil, nil) is returned.
49+
func (s *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) {
50+
defer trace.StartRegion(ctx, "Scanner.Scan").End()
51+
ctx = zlog.ContextWithValues(ctx,
52+
"component", "chainguard/DistributionScanner.Scan",
53+
"version", s.Version(),
54+
"layer", l.Hash.String())
55+
zlog.Debug(ctx).Msg("start")
56+
defer zlog.Debug(ctx).Msg("done")
57+
58+
sys, err := l.FS()
59+
if err != nil {
60+
return nil, fmt.Errorf("chainguard: unable to open layer: %w", err)
61+
}
62+
63+
b, err := fs.ReadFile(sys, osrelease.Path)
64+
switch {
65+
case errors.Is(err, nil):
66+
m, err := osrelease.Parse(ctx, bytes.NewReader(b))
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
switch id := m[`ID`]; id {
72+
case chainguard, wolfi:
73+
return []*claircore.Distribution{
74+
{
75+
Name: m[`NAME`],
76+
DID: id,
77+
// Neither chainguard nor wolfi images are considered to be "versioned".
78+
// Explicitly set the version to the empty string for clarity.
79+
Version: "",
80+
PrettyName: m[`PRETTY_NAME`],
81+
},
82+
}, nil
83+
default:
84+
// This is neither chainguard nor wolfi.
85+
return nil, nil
86+
}
87+
case errors.Is(err, fs.ErrNotExist):
88+
// os-release file must exist in chainguard and wolfi images.
89+
return nil, nil
90+
default:
91+
return nil, err
92+
}
93+
}

chainguard/ecosystem.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package chainguard
2+
3+
import (
4+
"context"
5+
6+
"github.com/quay/claircore/apk"
7+
"github.com/quay/claircore/indexer"
8+
"github.com/quay/claircore/linux"
9+
)
10+
11+
// NewEcosystem provides the set of scanners and coalescers for the chainguard ecosystem
12+
func NewEcosystem(_ context.Context) *indexer.Ecosystem {
13+
return &indexer.Ecosystem{
14+
PackageScanners: func(ctx context.Context) ([]indexer.PackageScanner, error) {
15+
return []indexer.PackageScanner{&apk.Scanner{}}, nil
16+
},
17+
DistributionScanners: func(ctx context.Context) ([]indexer.DistributionScanner, error) {
18+
return []indexer.DistributionScanner{&DistributionScanner{}}, nil
19+
},
20+
RepositoryScanners: func(ctx context.Context) ([]indexer.RepositoryScanner, error) {
21+
return []indexer.RepositoryScanner{}, nil
22+
},
23+
Coalescer: func(ctx context.Context) (indexer.Coalescer, error) {
24+
return linux.NewCoalescer(), nil
25+
},
26+
}
27+
}

0 commit comments

Comments
 (0)