* 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
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/* Vuls - Vulnerability Scanner
 | 
						|
Copyright (C) 2016  Future Corporation , Japan.
 | 
						|
 | 
						|
This program is free software: you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation, either version 3 of the License, or
 | 
						|
(at your option) any later version.
 | 
						|
 | 
						|
This program is distributed in the hope that it will be useful,
 | 
						|
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
GNU General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
package scan
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/knqyf263/fanal/analyzer"
 | 
						|
	"golang.org/x/xerrors"
 | 
						|
 | 
						|
	"github.com/future-architect/vuls/config"
 | 
						|
	"github.com/future-architect/vuls/models"
 | 
						|
	"github.com/future-architect/vuls/util"
 | 
						|
	fanalos "github.com/knqyf263/fanal/analyzer/os"
 | 
						|
	godeptypes "github.com/knqyf263/go-dep-parser/pkg/types"
 | 
						|
 | 
						|
	// Register library analyzers
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/bundler"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/cargo"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/composer"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/npm"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/pipenv"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/poetry"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/library/yarn"
 | 
						|
 | 
						|
	// Register os analyzers
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/os/alpine"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/os/amazonlinux"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/os/debianbase"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/os/opensuse"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/os/redhatbase"
 | 
						|
 | 
						|
	// Register package analyzers
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/pkg/apk"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/pkg/dpkg"
 | 
						|
	_ "github.com/knqyf263/fanal/analyzer/pkg/rpmcmd"
 | 
						|
)
 | 
						|
 | 
						|
// inherit OsTypeInterface
 | 
						|
type image struct {
 | 
						|
	base
 | 
						|
}
 | 
						|
 | 
						|
// newDummyOS is constructor
 | 
						|
func newDummyOS(c config.ServerInfo) *image {
 | 
						|
	d := &image{
 | 
						|
		base: base{
 | 
						|
			osPackages: osPackages{
 | 
						|
				Packages:  models.Packages{},
 | 
						|
				VulnInfos: models.VulnInfos{},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	d.log = util.NewCustomLogger(c)
 | 
						|
	d.setServerInfo(c)
 | 
						|
	return d
 | 
						|
}
 | 
						|
 | 
						|
func detectContainerImage(c config.ServerInfo) (itsMe bool, containerImage osTypeInterface, err error) {
 | 
						|
	if err = config.IsValidImage(c.Image); err != nil {
 | 
						|
		return false, nil, nil
 | 
						|
	}
 | 
						|
 | 
						|
	os, pkgs, libs, err := scanImage(c)
 | 
						|
	if err != nil {
 | 
						|
		// use Alpine for setErrs
 | 
						|
		return false, newDummyOS(c), err
 | 
						|
	}
 | 
						|
	switch os.Family {
 | 
						|
	case fanalos.OpenSUSELeap, fanalos.OpenSUSETumbleweed, fanalos.OpenSUSE:
 | 
						|
		return false, newDummyOS(c), xerrors.Errorf("Unsupported OS : %s", os.Family)
 | 
						|
	}
 | 
						|
 | 
						|
	libScanners, err := convertLibWithScanner(libs)
 | 
						|
	if err != nil {
 | 
						|
		return false, newDummyOS(c), err
 | 
						|
	}
 | 
						|
 | 
						|
	p := newContainerImage(c, pkgs, libScanners)
 | 
						|
	p.setDistro(os.Family, os.Name)
 | 
						|
	return true, p, nil
 | 
						|
}
 | 
						|
 | 
						|
func convertLibWithScanner(libs map[analyzer.FilePath][]godeptypes.Library) ([]models.LibraryScanner, error) {
 | 
						|
	scanners := []models.LibraryScanner{}
 | 
						|
	for path, pkgs := range libs {
 | 
						|
		scanners = append(scanners, models.LibraryScanner{Path: string(path), Libs: pkgs})
 | 
						|
	}
 | 
						|
	return scanners, nil
 | 
						|
}
 | 
						|
 | 
						|
// scanImage returns os, packages on image layers
 | 
						|
func scanImage(c config.ServerInfo) (os *analyzer.OS, pkgs []analyzer.Package, libs map[analyzer.FilePath][]godeptypes.Library, err error) {
 | 
						|
 | 
						|
	ctx := context.Background()
 | 
						|
	domain := c.Image.Name + ":" + c.Image.Tag
 | 
						|
	util.Log.Info("Start fetch container... ", domain)
 | 
						|
 | 
						|
	// Configure dockerOption
 | 
						|
	dockerOption := c.Image.DockerOption
 | 
						|
	if dockerOption.Timeout == 0 {
 | 
						|
		dockerOption.Timeout = 60 * time.Second
 | 
						|
	}
 | 
						|
	files, err := analyzer.Analyze(ctx, domain, dockerOption)
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, nil, xerrors.Errorf("Failed scan files %q, %w", domain, err)
 | 
						|
	}
 | 
						|
 | 
						|
	containerOs, err := analyzer.GetOS(files)
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, nil, xerrors.Errorf("Failed scan os %q, %w", domain, err)
 | 
						|
	}
 | 
						|
 | 
						|
	pkgs, err = analyzer.GetPackages(files)
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, nil, xerrors.Errorf("Failed scan pkgs %q, %w", domain, err)
 | 
						|
	}
 | 
						|
	libs, err = analyzer.GetLibraries(files)
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, nil, xerrors.Errorf("Failed scan libs %q, %w", domain, err)
 | 
						|
	}
 | 
						|
	return &containerOs, pkgs, libs, nil
 | 
						|
}
 | 
						|
 | 
						|
func convertFanalToVulsPkg(pkgs []analyzer.Package) (map[string]models.Package, map[string]models.SrcPackage) {
 | 
						|
	modelPkgs := map[string]models.Package{}
 | 
						|
	modelSrcPkgs := map[string]models.SrcPackage{}
 | 
						|
	for _, pkg := range pkgs {
 | 
						|
		version := pkg.Version
 | 
						|
		if pkg.Epoch != 0 {
 | 
						|
			version = fmt.Sprintf("%d:%s", pkg.Epoch, pkg.Version)
 | 
						|
		}
 | 
						|
		modelPkgs[pkg.Name] = models.Package{
 | 
						|
			Name:    pkg.Name,
 | 
						|
			Release: pkg.Release,
 | 
						|
			Version: version,
 | 
						|
			Arch:    pkg.Arch,
 | 
						|
		}
 | 
						|
 | 
						|
		// add SrcPacks
 | 
						|
		if pkg.Name != pkg.SrcName {
 | 
						|
			if pack, ok := modelSrcPkgs[pkg.SrcName]; ok {
 | 
						|
				pack.AddBinaryName(pkg.Name)
 | 
						|
				modelSrcPkgs[pkg.SrcName] = pack
 | 
						|
			} else {
 | 
						|
				modelSrcPkgs[pkg.SrcName] = models.SrcPackage{
 | 
						|
					Name:        pkg.SrcName,
 | 
						|
					Version:     pkg.SrcVersion,
 | 
						|
					BinaryNames: []string{pkg.Name},
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return modelPkgs, modelSrcPkgs
 | 
						|
}
 | 
						|
 | 
						|
func newContainerImage(c config.ServerInfo, pkgs []analyzer.Package, libs []models.LibraryScanner) *image {
 | 
						|
	modelPkgs, modelSrcPkgs := convertFanalToVulsPkg(pkgs)
 | 
						|
	d := &image{
 | 
						|
		base: base{
 | 
						|
			osPackages: osPackages{
 | 
						|
				Packages:    modelPkgs,
 | 
						|
				SrcPackages: modelSrcPkgs,
 | 
						|
				VulnInfos:   models.VulnInfos{},
 | 
						|
			},
 | 
						|
			LibraryScanners: libs,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	d.log = util.NewCustomLogger(c)
 | 
						|
	d.setServerInfo(c)
 | 
						|
	return d
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) checkScanMode() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) checkIfSudoNoPasswd() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) checkDeps() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) preCure() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) postScan() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) scanPackages() error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) parseInstalledPackages(string) (models.Packages, models.SrcPackages, error) {
 | 
						|
	return nil, nil, nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *image) detectPlatform() {
 | 
						|
	o.setPlatform(models.Platform{Name: "image"})
 | 
						|
}
 |