github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/ospkg/suse/suse.go (about) 1 package suse 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 susecvrf "github.com/aquasecurity/trivy-db/pkg/vulnsrc/suse-cvrf" 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 slesEolDates = map[string]time.Time{ 20 // Source: https://www.suse.com/lifecycle/ 21 "10": time.Date(2007, 12, 31, 23, 59, 59, 0, time.UTC), 22 "10.1": time.Date(2008, 11, 30, 23, 59, 59, 0, time.UTC), 23 "10.2": time.Date(2010, 4, 11, 23, 59, 59, 0, time.UTC), 24 "10.3": time.Date(2011, 10, 11, 23, 59, 59, 0, time.UTC), 25 "10.4": time.Date(2013, 7, 31, 23, 59, 59, 0, time.UTC), 26 "11": time.Date(2010, 12, 31, 23, 59, 59, 0, time.UTC), 27 "11.1": time.Date(2012, 8, 31, 23, 59, 59, 0, time.UTC), 28 "11.2": time.Date(2014, 1, 31, 23, 59, 59, 0, time.UTC), 29 "11.3": time.Date(2016, 1, 31, 23, 59, 59, 0, time.UTC), 30 "11.4": time.Date(2019, 3, 31, 23, 59, 59, 0, time.UTC), 31 "12": time.Date(2016, 6, 30, 23, 59, 59, 0, time.UTC), 32 "12.1": time.Date(2017, 5, 31, 23, 59, 59, 0, time.UTC), 33 "12.2": time.Date(2018, 3, 31, 23, 59, 59, 0, time.UTC), 34 "12.3": time.Date(2019, 1, 30, 23, 59, 59, 0, time.UTC), 35 "12.4": time.Date(2020, 6, 30, 23, 59, 59, 0, time.UTC), 36 "12.5": time.Date(2024, 10, 31, 23, 59, 59, 0, time.UTC), 37 "15": time.Date(2019, 12, 31, 23, 59, 59, 0, time.UTC), 38 "15.1": time.Date(2021, 1, 31, 23, 59, 59, 0, time.UTC), 39 "15.2": time.Date(2021, 12, 31, 23, 59, 59, 0, time.UTC), 40 "15.3": time.Date(2022, 12, 31, 23, 59, 59, 0, time.UTC), 41 "15.4": time.Date(2023, 12, 31, 23, 59, 59, 0, time.UTC), 42 "15.5": time.Date(2028, 12, 31, 23, 59, 59, 0, time.UTC), 43 // 6 months after SLES 15 SP7 release 44 // "15.6": time.Date(2028, 12, 31, 23, 59, 59, 0, time.UTC), 45 } 46 47 opensuseEolDates = map[string]time.Time{ 48 // Source: https://en.opensuse.org/Lifetime 49 "42.1": time.Date(2017, 5, 17, 23, 59, 59, 0, time.UTC), 50 "42.2": time.Date(2018, 1, 26, 23, 59, 59, 0, time.UTC), 51 "42.3": time.Date(2019, 6, 30, 23, 59, 59, 0, time.UTC), 52 "15.0": time.Date(2019, 12, 3, 23, 59, 59, 0, time.UTC), 53 "15.1": time.Date(2020, 11, 30, 23, 59, 59, 0, time.UTC), 54 "15.2": time.Date(2021, 11, 30, 23, 59, 59, 0, time.UTC), 55 "15.3": time.Date(2022, 11, 30, 23, 59, 59, 0, time.UTC), 56 "15.4": time.Date(2023, 11, 30, 23, 59, 59, 0, time.UTC), 57 "15.5": time.Date(2024, 12, 31, 23, 59, 59, 0, time.UTC), 58 } 59 ) 60 61 type options struct { 62 clock clock.Clock 63 } 64 65 type option func(*options) 66 67 func WithClock(c clock.Clock) option { 68 return func(opts *options) { 69 opts.clock = c 70 } 71 } 72 73 // Type defines SUSE type 74 type Type int 75 76 const ( 77 // SUSEEnterpriseLinux is Linux Enterprise version 78 SUSEEnterpriseLinux Type = iota 79 // OpenSUSE for open versions 80 OpenSUSE 81 ) 82 83 // Scanner implements the SUSE scanner 84 type Scanner struct { 85 vs susecvrf.VulnSrc 86 *options 87 } 88 89 // NewScanner is the factory method for Scanner 90 func NewScanner(t Type, opts ...option) *Scanner { 91 o := &options{ 92 clock: clock.RealClock{}, 93 } 94 95 for _, opt := range opts { 96 opt(o) 97 } 98 99 switch t { 100 case SUSEEnterpriseLinux: 101 return &Scanner{ 102 vs: susecvrf.NewVulnSrc(susecvrf.SUSEEnterpriseLinux), 103 options: o, 104 } 105 case OpenSUSE: 106 return &Scanner{ 107 vs: susecvrf.NewVulnSrc(susecvrf.OpenSUSE), 108 options: o, 109 } 110 } 111 return nil 112 } 113 114 // Detect scans and returns the vulnerabilities 115 func (s *Scanner) Detect(osVer string, _ *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) { 116 log.Logger.Info("Detecting SUSE vulnerabilities...") 117 log.Logger.Debugf("SUSE: os version: %s", osVer) 118 log.Logger.Debugf("SUSE: the number of packages: %d", len(pkgs)) 119 120 var vulns []types.DetectedVulnerability 121 for _, pkg := range pkgs { 122 advisories, err := s.vs.Get(osVer, pkg.Name) 123 if err != nil { 124 return nil, xerrors.Errorf("failed to get SUSE advisory: %w", err) 125 } 126 127 installed := utils.FormatVersion(pkg) 128 installedVersion := version.NewVersion(installed) 129 for _, adv := range advisories { 130 fixedVersion := version.NewVersion(adv.FixedVersion) 131 vuln := types.DetectedVulnerability{ 132 VulnerabilityID: adv.VulnerabilityID, 133 PkgID: pkg.ID, 134 PkgName: pkg.Name, 135 InstalledVersion: installed, 136 PkgRef: pkg.Ref, 137 Layer: pkg.Layer, 138 Custom: adv.Custom, 139 DataSource: adv.DataSource, 140 } 141 if installedVersion.LessThan(fixedVersion) { 142 vuln.FixedVersion = adv.FixedVersion 143 vulns = append(vulns, vuln) 144 } 145 } 146 } 147 return vulns, nil 148 } 149 150 // IsSupportedVersion checks if OSFamily can be scanned using SUSE scanner 151 func (s *Scanner) IsSupportedVersion(osFamily ftypes.OSType, osVer string) bool { 152 if osFamily == ftypes.SLES { 153 return osver.Supported(s.clock, slesEolDates, osFamily, osVer) 154 } 155 return osver.Supported(s.clock, opensuseEolDates, osFamily, osVer) 156 }