add Library Scan (with image scan) (#829)

* add static container image scan

* server has many staticContainers

* use go module

* for staticContainer

* fix typo

* fix setErrs error

* change name : StaticContainer -> Image

* add scan -images-only flag

* fix makefile

* fix makefile for go module

* use rpmcmd instead of rpm

* add scrutinizer.yml

* change scrutinizer.yml

* fix scrutinizer.yml

* fix scrutinizer.yml

* fix scrutinizer.yml

* fix scrutinizer.yml

* delete scrutinizer

* add report test

* add sourcePackages and Arch

* fix for sider

* fix staticContainer -> image

* init scan library

* add library scan for servers

* fix tui bug

* fix lint error

* divide WpPackageFixStats and LibraryPackageFixedIns

* fix error

* Delete libManager_test.go

* stop use alpine os if err occurred in container

* merge upstream/master

* Delete libManager.go

* update goval-dictionary

* fix go.mod

* update Readme

* add feature : auto detect lockfiles
This commit is contained in:
Tomoya Amachi
2019-06-12 18:50:07 +09:00
committed by Kota Kanbe
parent 10942f7c08
commit abcea1a14d
22 changed files with 1531 additions and 1161 deletions

141
models/library.go Normal file
View File

@@ -0,0 +1,141 @@
package models
import (
"path/filepath"
"github.com/future-architect/vuls/util"
"github.com/knqyf263/trivy/pkg/scanner/library"
"github.com/knqyf263/trivy/pkg/vulnsrc/vulnerability"
"golang.org/x/xerrors"
"github.com/knqyf263/go-dep-parser/pkg/types"
"github.com/knqyf263/go-version"
)
// LibraryScanner has libraries information
type LibraryScanner struct {
Path string
Libs []types.Library
}
// Scan : scan target library
func (s LibraryScanner) Scan() ([]VulnInfo, error) {
scanner := library.NewScanner(filepath.Base(string(s.Path)))
if scanner == nil {
return nil, xerrors.New("unknown file type")
}
util.Log.Info("Updating library db...")
err := scanner.UpdateDB()
if err != nil {
return nil, xerrors.Errorf("failed to update %s advisories: %w", scanner.Type(), err)
}
var vulnerabilities []VulnInfo
for _, pkg := range s.Libs {
v, err := version.NewVersion(pkg.Version)
if err != nil {
util.Log.Debugf("new version cant detected %s@%s", pkg.Name, pkg.Version)
continue
}
tvulns, err := scanner.Detect(pkg.Name, v)
if err != nil {
return nil, xerrors.Errorf("failed to detect %s vulnerabilities: %w", scanner.Type(), err)
}
vulns := s.convertFanalToVuln(tvulns)
vulnerabilities = append(vulnerabilities, vulns...)
}
return vulnerabilities, nil
}
func (s LibraryScanner) convertFanalToVuln(tvulns []vulnerability.DetectedVulnerability) (vulns []VulnInfo) {
for _, tvuln := range tvulns {
vinfo, _ := s.getVulnDetail(tvuln)
vulns = append(vulns, vinfo)
}
return vulns
}
func (s LibraryScanner) getVulnDetail(tvuln vulnerability.DetectedVulnerability) (vinfo VulnInfo, err error) {
details, err := vulnerability.Get(tvuln.VulnerabilityID)
if err != nil {
return vinfo, err
} else if len(details) == 0 {
return vinfo, xerrors.Errorf("Unknown vulnID : %s", tvuln.VulnerabilityID)
}
vinfo.CveID = tvuln.VulnerabilityID
vinfo.CveContents = getCveContents(details)
if tvuln.FixedVersion != "" {
vinfo.LibraryFixedIns = []LibraryFixedIn{
{
Key: s.GetLibraryKey(),
Name: tvuln.PkgName,
FixedIn: tvuln.FixedVersion,
},
}
}
return vinfo, nil
}
func getCveContents(details map[string]vulnerability.Vulnerability) (contents map[CveContentType]CveContent) {
contents = map[CveContentType]CveContent{}
for source, detail := range details {
refs := []Reference{}
for _, refURL := range detail.References {
refs = append(refs, Reference{Source: refURL, Link: refURL})
}
content := CveContent{
Type: NewCveContentType(source),
CveID: detail.ID,
Title: detail.Title,
Summary: detail.Description,
Cvss3Score: detail.CvssScoreV3,
Cvss3Severity: string(detail.SeverityV3),
Cvss2Score: detail.CvssScore,
Cvss2Severity: string(detail.Severity),
References: refs,
//SourceLink string `json:"sourceLink"`
//Cvss2Vector string `json:"cvss2Vector"`
//Cvss3Vector string `json:"cvss3Vector"`
//Cvss3Severity string `json:"cvss3Severity"`
//Cpes []Cpe `json:"cpes,omitempty"`
//CweIDs []string `json:"cweIDs,omitempty"`
//Published time.Time `json:"published"`
//LastModified time.Time `json:"lastModified"`
//Mitigation string `json:"mitigation"` // RedHat API
//Optional map[string]string `json:"optional,omitempty"`
}
contents[NewCveContentType(source)] = content
}
return contents
}
// LibraryMap is filename and library type
var LibraryMap = map[string]string{
"package-lock.json": "node",
"yarn.lock": "node",
"Gemfile.lock": "ruby",
"Cargo.lock": "rust",
"composer.json": "php",
"Pipfile.lock": "python",
"poetry.lock": "python",
}
// GetLibraryKey returns target library key
func (s LibraryScanner) GetLibraryKey() string {
fileName := filepath.Base(s.Path)
return LibraryMap[fileName]
}
// LibraryFixedIn has library fixed information
type LibraryFixedIn struct {
Key string `json:"key,omitempty"`
Name string `json:"name,omitempty"`
FixedIn string `json:"fixedIn,omitempty"`
}