Skip to content

Commit

Permalink
feat(report): add end of service life flag to OS metadata (#1142)
Browse files Browse the repository at this point in the history
Co-authored-by: knqyf263 <knqyf263@gmail.com>
  • Loading branch information
AndreyLevchenko and knqyf263 committed Jul 27, 2021
1 parent c489e31 commit 214fe82
Show file tree
Hide file tree
Showing 17 changed files with 443 additions and 336 deletions.
14 changes: 6 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/fanal v0.0.0-20210719144537-c73c1e9f21bf
github.com/aquasecurity/fanal v0.0.0-20210722114116-f7a3626ddffb
github.com/aquasecurity/go-dep-parser v0.0.0-20210520015931-0dd56983cc62
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
Expand All @@ -24,7 +24,7 @@ require (
github.com/fatih/color v1.10.0
github.com/go-redis/redis/v8 v8.4.0
github.com/goccy/go-yaml v1.8.2 // indirect
github.com/golang/protobuf v1.4.3
github.com/golang/protobuf v1.5.2
github.com/google/go-containerregistry v0.1.2
github.com/google/go-github/v33 v33.0.0
github.com/google/wire v0.4.0
Expand All @@ -41,18 +41,16 @@ require (
github.com/open-policy-agent/opa v0.25.2
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/spf13/afero v1.2.2
github.com/spf13/afero v1.6.0
github.com/stretchr/objx v0.3.0 // indirect
github.com/stretchr/testify v1.7.0
github.com/testcontainers/testcontainers-go v0.9.1-0.20210218153226-c8e070a2f18d
github.com/twitchtv/twirp v8.1.0+incompatible
github.com/urfave/cli/v2 v2.3.0
go.uber.org/zap v1.16.0
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
go.uber.org/zap v1.17.0
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
google.golang.org/protobuf v1.25.0
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
google.golang.org/protobuf v1.26.0
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
Expand Down
220 changes: 166 additions & 54 deletions go.sum

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions pkg/rpc/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ func NewScanner(customHeaders CustomHeaders, s rpc.Scanner) Scanner {
}

// Scan scans the image
func (s Scanner) Scan(target string, imageID string, layerIDs []string, options types.ScanOptions) (report.Results, *ftypes.OS, bool, error) {
func (s Scanner) Scan(target, artifactKey string, blobKeys []string, options types.ScanOptions) (report.Results, *ftypes.OS, error) {
ctx := WithCustomHeaders(context.Background(), http.Header(s.customHeaders))

var res *rpc.ScanResponse
err := r.Retry(func() error {
var err error
res, err = s.client.Scan(ctx, &rpc.ScanRequest{
Target: target,
ArtifactId: imageID,
BlobIds: layerIDs,
ArtifactId: artifactKey,
BlobIds: blobKeys,
Options: &rpc.ScanOptions{
VulnType: options.VulnType,
SecurityChecks: options.SecurityChecks,
Expand All @@ -64,8 +64,8 @@ func (s Scanner) Scan(target string, imageID string, layerIDs []string, options
return err
})
if err != nil {
return nil, nil, false, xerrors.Errorf("failed to detect vulnerabilities via RPC: %w", err)
return nil, nil, xerrors.Errorf("failed to detect vulnerabilities via RPC: %w", err)
}

return r.ConvertFromRPCResults(res.Results), r.ConvertFromRPCOS(res.Os), res.Eosl, nil
return r.ConvertFromRPCResults(res.Results), r.ConvertFromRPCOS(res.Os), nil
}
7 changes: 3 additions & 4 deletions pkg/rpc/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ func TestScanner_Scan(t *testing.T) {
Os: &common.OS{
Family: "alpine",
Name: "3.11",
Eosl: true,
},
Eosl: true,
Results: []*scanner.Result{
{
Target: "alpine:3.11",
Expand Down Expand Up @@ -226,8 +226,8 @@ func TestScanner_Scan(t *testing.T) {
wantOS: &ftypes.OS{
Family: "alpine",
Name: "3.11",
Eosl: true,
},
wantEosl: true,
},
{
name: "sad path: Scan returns an error",
Expand Down Expand Up @@ -269,7 +269,7 @@ func TestScanner_Scan(t *testing.T) {
mockClient.ApplyScanExpectation(tt.scanExpectation)

s := NewScanner(tt.fields.customHeaders, mockClient)
gotResults, gotOS, gotEosl, err := s.Scan(tt.args.target, tt.args.imageID, tt.args.layerIDs, tt.args.options)
gotResults, gotOS, err := s.Scan(tt.args.target, tt.args.imageID, tt.args.layerIDs, tt.args.options)

if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
Expand All @@ -281,7 +281,6 @@ func TestScanner_Scan(t *testing.T) {

assert.Equal(t, tt.wantResults, gotResults)
assert.Equal(t, tt.wantOS, gotOS)
assert.Equal(t, tt.wantEosl, gotEosl)
})
}
}
5 changes: 3 additions & 2 deletions pkg/rpc/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ func ConvertFromRPCOS(rpcOS *common.OS) *ftypes.OS {
return &ftypes.OS{
Family: rpcOS.Family,
Name: rpcOS.Name,
Eosl: rpcOS.Eosl,
}
}

Expand Down Expand Up @@ -468,11 +469,12 @@ func ConvertToMissingBlobsRequest(imageID string, layerIDs []string) *cache.Miss
}

// ConvertToRPCScanResponse converts report.Result to ScanResponse
func ConvertToRPCScanResponse(results report.Results, os *ftypes.OS, eosl bool) *scanner.ScanResponse {
func ConvertToRPCScanResponse(results report.Results, os *ftypes.OS) *scanner.ScanResponse {
rpcOS := &common.OS{}
if os != nil {
rpcOS.Family = os.Family
rpcOS.Name = os.Name
rpcOS.Eosl = os.Eosl
}

var rpcResults []*scanner.Result
Expand All @@ -489,7 +491,6 @@ func ConvertToRPCScanResponse(results report.Results, os *ftypes.OS, eosl bool)

return &scanner.ScanResponse{
Os: rpcOS,
Eosl: eosl,
Results: rpcResults,
}
}
4 changes: 2 additions & 2 deletions pkg/rpc/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ func (s *ScanServer) Scan(_ context.Context, in *rpcScanner.ScanRequest) (*rpcSc
SecurityChecks: in.Options.SecurityChecks,
ListAllPackages: in.Options.ListAllPackages,
}
results, os, eosl, err := s.localScanner.Scan(in.Target, in.ArtifactId, in.BlobIds, options)
results, os, err := s.localScanner.Scan(in.Target, in.ArtifactId, in.BlobIds, options)
if err != nil {
return nil, xerrors.Errorf("failed scan, %s: %w", in.Target, err)
}

for i := range results {
s.resultClient.FillVulnerabilityInfo(results[i].Vulnerabilities, results[i].Type)
}
return rpc.ConvertToRPCScanResponse(results, os, eosl), nil
return rpc.ConvertToRPCScanResponse(results, os), nil
}

// CacheServer implements the cache
Expand Down
3 changes: 2 additions & 1 deletion pkg/rpc/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,16 @@ func TestScanServer_Scan(t *testing.T) {
OsFound: &ftypes.OS{
Family: "alpine",
Name: "3.11",
Eosl: true,
},
},
},
want: &rpcScanner.ScanResponse{
Os: &common.OS{
Family: "alpine",
Name: "3.11",
Eosl: true,
},
Eosl: false,
Results: []*rpcScanner.Result{
{
Target: "alpine:3.11 (alpine 3.11)",
Expand Down
16 changes: 9 additions & 7 deletions pkg/scanner/local/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,30 @@ func NewScanner(applier Applier, ospkgDetector OspkgDetector) Scanner {
}

// Scan scans the artifact and return results.
func (s Scanner) Scan(target, versionedArtifactID string, versionedBlobIDs []string, options types.ScanOptions) (
report.Results, *ftypes.OS, bool, error) {
artifactDetail, err := s.applier.ApplyLayers(versionedArtifactID, versionedBlobIDs)
func (s Scanner) Scan(target string, artifactKey string, blobKeys []string, options types.ScanOptions) (report.Results, *ftypes.OS, error) {
artifactDetail, err := s.applier.ApplyLayers(artifactKey, blobKeys)
switch {
case errors.Is(err, analyzer.ErrUnknownOS):
log.Logger.Debug("OS is not detected and vulnerabilities in OS packages are not detected.")
case errors.Is(err, analyzer.ErrNoPkgsDetected):
log.Logger.Warn("No OS package is detected. Make sure you haven't deleted any files that contain information about the installed packages.")
log.Logger.Warn(`e.g. files under "/lib/apk/db/", "/var/lib/dpkg/" and "/var/lib/rpm"`)
case err != nil:
return nil, nil, false, xerrors.Errorf("failed to apply layers: %w", err)
return nil, nil, xerrors.Errorf("failed to apply layers: %w", err)
}

var eosl bool
var results report.Results

// Scan OS packages and programming language dependencies
// Scan OS packages and language-specific dependencies
if utils.StringInSlice(types.SecurityCheckVulnerability, options.SecurityChecks) {
var vulnResults report.Results
vulnResults, eosl, err = s.checkVulnerabilities(target, artifactDetail, options)
if err != nil {
return nil, nil, false, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
return nil, nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
}
if artifactDetail.OS != nil {
artifactDetail.OS.Eosl = eosl
}
results = append(results, vulnResults...)
}
Expand All @@ -88,7 +90,7 @@ func (s Scanner) Scan(target, versionedArtifactID string, versionedBlobIDs []str
results = append(results, configResults...)
}

return results, artifactDetail.OS, eosl, nil
return results, artifactDetail.OS, nil
}

func (s Scanner) checkVulnerabilities(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) (
Expand Down
7 changes: 3 additions & 4 deletions pkg/scanner/local/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ func TestScanner_Scan(t *testing.T) {
ospkgDetectExpectations []OspkgDetectorDetectExpectation
wantResults report.Results
wantOS *ftypes.OS
wantEosl bool
wantErr string
}{
{
Expand Down Expand Up @@ -109,7 +108,7 @@ func TestScanner_Scan(t *testing.T) {
},
},
},
Eosl: false,
Eosl: true,
},
},
},
Expand Down Expand Up @@ -150,6 +149,7 @@ func TestScanner_Scan(t *testing.T) {
wantOS: &ftypes.OS{
Family: "alpine",
Name: "3.11",
Eosl: true,
},
},
{
Expand Down Expand Up @@ -1008,7 +1008,7 @@ func TestScanner_Scan(t *testing.T) {
ospkgDetector.ApplyDetectExpectations(tt.ospkgDetectExpectations)

s := NewScanner(applier, ospkgDetector)
gotResults, gotOS, gotEosl, err := s.Scan(tt.args.target, "", tt.args.layerIDs, tt.args.options)
gotResults, gotOS, err := s.Scan(tt.args.target, "", tt.args.layerIDs, tt.args.options)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
require.Contains(t, err.Error(), tt.wantErr, tt.name)
Expand All @@ -1019,7 +1019,6 @@ func TestScanner_Scan(t *testing.T) {

assert.Equal(t, tt.wantResults, gotResults)
assert.Equal(t, tt.wantOS, gotOS)
assert.Equal(t, tt.wantEosl, gotEosl)

applier.AssertExpectations(t)
ospkgDetector.AssertExpectations(t)
Expand Down
28 changes: 10 additions & 18 deletions pkg/scanner/mock_driver.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions pkg/scanner/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ type Scanner struct {

// Driver defines operations of scanner
type Driver interface {
Scan(target string, imageID string, layerIDs []string, options types.ScanOptions) (
results report.Results, osFound *ftypes.OS, eols bool, err error)
Scan(target string, artifactKey string, blobKeys []string, options types.ScanOptions) (
results report.Results, osFound *ftypes.OS, err error)
}

// NewScanner is the factory method of Scanner
Expand All @@ -98,11 +98,12 @@ func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (r
return report.Report{}, xerrors.Errorf("failed analysis: %w", err)
}

results, osFound, eosl, err := s.driver.Scan(artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options)
results, osFound, err := s.driver.Scan(artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options)
if err != nil {
return report.Report{}, xerrors.Errorf("scan failed: %w", err)
}
if eosl {

if osFound != nil && osFound.Eosl {
log.Logger.Warnf("This OS version is no longer supported by the distribution: %s %s", osFound.Family, osFound.Name)
log.Logger.Warnf("The vulnerability detection may be insufficient because security updates are not provided")
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/scanner/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func TestScanner_ScanArtifact(t *testing.T) {
OsFound: &ftypes.OS{
Family: "alpine",
Name: "3.10",
Eosl: true,
},
Eols: true,
},
},
want: report.Report{
Expand All @@ -96,6 +96,7 @@ func TestScanner_ScanArtifact(t *testing.T) {
OS: &ftypes.OS{
Family: "alpine",
Name: "3.10",
Eosl: true,
},
RepoTags: []string{"alpine:3.11"},
RepoDigests: []string{"alpine@sha256:0bd0e9e03a022c3b0226667621da84fc9bf562a9056130424b5bfbd8bcb0397f"},
Expand Down
Loading

0 comments on commit 214fe82

Please sign in to comment.