github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/ospkg/amazon/amazon.go (about)

     1  package amazon
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	version "github.com/knqyf263/go-deb-version"
     8  	"golang.org/x/xerrors"
     9  	"k8s.io/utils/clock"
    10  
    11  	"github.com/aquasecurity/trivy-db/pkg/vulnsrc/amazon"
    12  	osver "github.com/devseccon/trivy/pkg/detector/ospkg/version"
    13  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    14  	"github.com/devseccon/trivy/pkg/log"
    15  	"github.com/devseccon/trivy/pkg/scanner/utils"
    16  	"github.com/devseccon/trivy/pkg/types"
    17  )
    18  
    19  var (
    20  	eolDates = map[string]time.Time{
    21  		// https://aws.amazon.com/jp/blogs/aws/update-on-amazon-linux-ami-end-of-life/
    22  		"1": time.Date(2023, 12, 31, 23, 59, 59, 0, time.UTC),
    23  		// https://aws.amazon.com/amazon-linux-2/faqs/?nc1=h_ls
    24  		"2": time.Date(2025, 6, 30, 23, 59, 59, 0, time.UTC),
    25  		// Amazon Linux 2022 was renamed to 2023. AL2022 is not currently supported.
    26  		"2023": time.Date(2028, 3, 15, 23, 59, 59, 0, time.UTC),
    27  	}
    28  )
    29  
    30  type options struct {
    31  	clock clock.Clock
    32  }
    33  
    34  type option func(*options)
    35  
    36  func WithClock(c clock.Clock) option {
    37  	return func(opts *options) {
    38  		opts.clock = c
    39  	}
    40  }
    41  
    42  // Scanner to scan amazon vulnerabilities
    43  type Scanner struct {
    44  	ac amazon.VulnSrc
    45  	options
    46  }
    47  
    48  // NewScanner is the factory method to return Amazon scanner
    49  func NewScanner(opts ...option) *Scanner {
    50  	o := &options{
    51  		clock: clock.RealClock{},
    52  	}
    53  
    54  	for _, opt := range opts {
    55  		opt(o)
    56  	}
    57  	return &Scanner{
    58  		ac:      amazon.NewVulnSrc(),
    59  		options: *o,
    60  	}
    61  }
    62  
    63  // Detect scans the packages using amazon scanner
    64  func (s *Scanner) Detect(osVer string, _ *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) {
    65  	log.Logger.Info("Detecting Amazon Linux vulnerabilities...")
    66  
    67  	osVer = strings.Fields(osVer)[0]
    68  	if osVer != "2" && osVer != "2022" && osVer != "2023" {
    69  		osVer = "1"
    70  	}
    71  	log.Logger.Debugf("amazon: os version: %s", osVer)
    72  	log.Logger.Debugf("amazon: the number of packages: %d", len(pkgs))
    73  
    74  	var vulns []types.DetectedVulnerability
    75  	for _, pkg := range pkgs {
    76  		advisories, err := s.ac.Get(osVer, pkg.Name)
    77  		if err != nil {
    78  			return nil, xerrors.Errorf("failed to get amazon advisories: %w", err)
    79  		}
    80  
    81  		installed := utils.FormatVersion(pkg)
    82  		if installed == "" {
    83  			continue
    84  		}
    85  
    86  		installedVersion, err := version.NewVersion(installed)
    87  		if err != nil {
    88  			log.Logger.Debugf("failed to parse Amazon Linux installed package version: %s", err)
    89  			continue
    90  		}
    91  
    92  		for _, adv := range advisories {
    93  			fixedVersion, err := version.NewVersion(adv.FixedVersion)
    94  			if err != nil {
    95  				log.Logger.Debugf("failed to parse Amazon Linux package version: %s", err)
    96  				continue
    97  			}
    98  
    99  			if installedVersion.LessThan(fixedVersion) {
   100  				vuln := types.DetectedVulnerability{
   101  					VulnerabilityID:  adv.VulnerabilityID,
   102  					PkgID:            pkg.ID,
   103  					PkgName:          pkg.Name,
   104  					InstalledVersion: installed,
   105  					FixedVersion:     adv.FixedVersion,
   106  					PkgRef:           pkg.Ref,
   107  					Layer:            pkg.Layer,
   108  					Custom:           adv.Custom,
   109  					DataSource:       adv.DataSource,
   110  				}
   111  				vulns = append(vulns, vuln)
   112  			}
   113  		}
   114  	}
   115  	return vulns, nil
   116  }
   117  
   118  // IsSupportedVersion checks if the version is supported.
   119  func (s *Scanner) IsSupportedVersion(osFamily ftypes.OSType, osVer string) bool {
   120  	osVer = strings.Fields(osVer)[0]
   121  	if osVer != "2" && osVer != "2022" && osVer != "2023" {
   122  		osVer = "1"
   123  	}
   124  
   125  	return osver.Supported(s.clock, eolDates, osFamily, osVer)
   126  }