github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/ospkg/rocky/rocky.go (about) 1 package rocky 2 3 import ( 4 "time" 5 6 version "github.com/knqyf263/go-rpm-version" 7 "golang.org/x/xerrors" 8 "k8s.io/utils/clock" 9 10 "github.com/aquasecurity/trivy-db/pkg/vulnsrc/rocky" 11 osver "github.com/devseccon/trivy/pkg/detector/ospkg/version" 12 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 13 "github.com/devseccon/trivy/pkg/log" 14 "github.com/devseccon/trivy/pkg/scanner/utils" 15 "github.com/devseccon/trivy/pkg/types" 16 ) 17 18 var ( 19 eolDates = map[string]time.Time{ 20 // Source: 21 // https://endoflife.date/rocky-linux 22 "8": time.Date(2029, 5, 31, 23, 59, 59, 0, time.UTC), 23 "9": time.Date(2032, 5, 31, 23, 59, 59, 0, time.UTC), 24 } 25 ) 26 27 type options struct { 28 clock clock.Clock 29 } 30 31 type option func(*options) 32 33 func WithClock(c clock.Clock) option { 34 return func(opts *options) { 35 opts.clock = c 36 } 37 } 38 39 // Scanner implements the Rocky Linux scanner 40 type Scanner struct { 41 vs *rocky.VulnSrc 42 *options 43 } 44 45 // NewScanner is the factory method for Scanner 46 func NewScanner(opts ...option) *Scanner { 47 o := &options{ 48 clock: clock.RealClock{}, 49 } 50 51 for _, opt := range opts { 52 opt(o) 53 } 54 return &Scanner{ 55 vs: rocky.NewVulnSrc(), 56 options: o, 57 } 58 } 59 60 // Detect vulnerabilities in package using Rocky Linux scanner 61 func (s *Scanner) Detect(osVer string, _ *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) { 62 log.Logger.Info("Detecting Rocky Linux vulnerabilities...") 63 64 osVer = osver.Major(osVer) 65 log.Logger.Debugf("Rocky Linux: os version: %s", osVer) 66 log.Logger.Debugf("Rocky Linux: the number of packages: %d", len(pkgs)) 67 68 var vulns []types.DetectedVulnerability 69 var skipPkgs []string 70 for _, pkg := range pkgs { 71 if pkg.Modularitylabel != "" { 72 skipPkgs = append(skipPkgs, pkg.Name) 73 continue 74 } 75 pkgName := addModularNamespace(pkg.Name, pkg.Modularitylabel) 76 advisories, err := s.vs.Get(osVer, pkgName, pkg.Arch) 77 if err != nil { 78 return nil, xerrors.Errorf("failed to get Rocky Linux advisories: %w", err) 79 } 80 81 installed := utils.FormatVersion(pkg) 82 installedVersion := version.NewVersion(installed) 83 84 for _, adv := range advisories { 85 fixedVersion := version.NewVersion(adv.FixedVersion) 86 if installedVersion.LessThan(fixedVersion) { 87 vuln := types.DetectedVulnerability{ 88 VulnerabilityID: adv.VulnerabilityID, 89 PkgID: pkg.ID, 90 PkgName: pkg.Name, 91 InstalledVersion: installed, 92 FixedVersion: fixedVersion.String(), 93 PkgRef: pkg.Ref, 94 Layer: pkg.Layer, 95 DataSource: adv.DataSource, 96 Custom: adv.Custom, 97 } 98 vulns = append(vulns, vuln) 99 } 100 } 101 } 102 if len(skipPkgs) > 0 { 103 log.Logger.Infof("Skipped detection of these packages: %q because modular packages cannot be detected correctly due to a bug in Rocky Linux Errata. See also: https://forums.rockylinux.org/t/some-errata-missing-in-comparison-with-rhel-and-almalinux/3843", skipPkgs) 104 } 105 106 return vulns, nil 107 } 108 109 // IsSupportedVersion checks if the version is supported. 110 func (s *Scanner) IsSupportedVersion(osFamily ftypes.OSType, osVer string) bool { 111 return osver.Supported(s.clock, eolDates, osFamily, osver.Major(osVer)) 112 } 113 114 func addModularNamespace(name, label string) string { 115 // e.g. npm, nodejs:12:8030020201124152102:229f0a1c => nodejs:12::npm 116 var count int 117 for i, r := range label { 118 if r == ':' { 119 count++ 120 } 121 if count == 2 { 122 return label[:i] + "::" + name 123 } 124 } 125 return name 126 }