Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for openEuler OS. #6475

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/docs/coverage/os/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Trivy supports operating systems for
| [Photon OS](photon.md) | 1.0, 2.0, 3.0, 4.0 | tndf/yum/rpm |
| [Debian GNU/Linux](debian.md) | 7, 8, 9, 10, 11, 12 | apt/dpkg |
| [Ubuntu](ubuntu.md) | All versions supported by Canonical | apt/dpkg |
| [openEuler](openeuler.md) | All versions supported by openEuler | dnf/yum/rpm |
| [OSs with installed Conda](conda.md) | - | conda |

## Supported container images
Expand Down
47 changes: 47 additions & 0 deletions docs/docs/coverage/os/openeuler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# openEuler
Trivy supports these scanners for OS packages.

| Scanner | Supported |
| :-----------: | :-------: |
| SBOM | ✓ |
| Vulnerability | ✓ |
| License | ✓ |

Please see [here](index.md#supported-os) for supported versions.

The table below outlines the features offered by Trivy.

| Feature | Supported |
|:------------------------------------:|:---------:|
| Unfixed vulnerabilities | - |
| [Dependency graph][dependency-graph] | ✓ |

## SBOM
Trivy detects packages that have been installed through package managers such as `dnf` and `yum`.

## Vulnerability
openEuler offers its [own security advisories][cvrf], and these are utilized when scanning openEuler for vulnerabilities.

### Data Source
See [here](../../scanner/vulnerability.md#data-sources).

### Severity
Trivy calculates the severity of a vulnerability based on the severity provided in [openEuler Security Data][cvrf].

The table below is the mapping of openEuler's severity to Trivy's severity levels.

| openEuler | Trivy |
| :---------: | :------: |
| Low | Low |
| Medium | Medium |
| High | High |
| Critical | Critical |

## License
Trivy identifies licenses by examining the metadata of RPM packages.


[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[cvrf]: https://repo.openeuler.org/security/data/cvrf/

[vulnerability statuses]: ../../configuration/filtering.md#by-status
2 changes: 2 additions & 0 deletions docs/docs/scanner/vulnerability.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ See [here](../coverage/os/index.md#supported-os) for the supported OSes.
| CBL-Mariner | [OVAL][mariner] |
| OpenSUSE/SLES | [CVRF][suse] |
| Photon OS | [Photon Security Advisory][photon] |
| openEuler | [openEuler Security Data][openeuler] |

#### Data Source Selection
Trivy **only** consumes security advisories from the sources listed in the above table.
Expand Down Expand Up @@ -289,6 +290,7 @@ Total: 7 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 3, CRITICAL: 2)
[suse]: http://ftp.suse.com/pub/projects/security/cvrf/
[photon]: https://packages.vmware.com/photon/photon_cve_metadata/
[mariner]: https://github.com/microsoft/CBL-MarinerVulnerabilityData/
[openeuler]: https://repo.openeuler.org/security/data/cvrf

[php-ghsa]: https://github.com/advisories?query=ecosystem%3Acomposer
[python-ghsa]: https://github.com/advisories?query=ecosystem%3Apip
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ require (
github.com/aquasecurity/testdocker v0.0.0-20240613070307-2c3868d658ac
github.com/aquasecurity/tml v0.6.1
github.com/aquasecurity/trivy-checks v0.13.0
github.com/aquasecurity/trivy-db v0.0.0-20240701103400-8e907467e9ab
github.com/aquasecurity/trivy-db v0.0.0-20240715065409-18cd78038bd4
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b
github.com/aws/aws-sdk-go-v2 v1.30.1
Expand Down Expand Up @@ -393,3 +393,5 @@ require (
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)

replace github.com/aquasecurity/trivy-db => github.com/wjunLu/trivy-db v0.0.0-20240719013321-3cd70a420ce7
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -771,8 +771,6 @@ github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gw
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
github.com/aquasecurity/trivy-checks v0.13.0 h1:na6PTdY4U0uK/fjz3HNRYBxvYSJ8vgTb57a5T8Y5t9w=
github.com/aquasecurity/trivy-checks v0.13.0/go.mod h1:Xec/SMVGV66I7RgUqOX9MEr+YxBqHXDVLTYmpspPi3E=
github.com/aquasecurity/trivy-db v0.0.0-20240701103400-8e907467e9ab h1:EmpLGFgRJOstPWDpL4KW+Xap4zRYxyctXDTj5luMQdE=
github.com/aquasecurity/trivy-db v0.0.0-20240701103400-8e907467e9ab/go.mod h1:f+wSW9D5txv8S+tw4D4WNOibaUJYwvNnQuQlGQ8gO6c=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8=
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b h1:h7gsIzHyrxpQnayOuQI0kX7+8rVcqhV6G5bM3KVFyJU=
Expand Down Expand Up @@ -2057,6 +2055,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/wjunLu/trivy-db v0.0.0-20240719013321-3cd70a420ce7 h1:oivbt7TL+anq1Sf/lpQCPGBnSZMyHCUGBzwUYNFbvGw=
github.com/wjunLu/trivy-db v0.0.0-20240719013321-3cd70a420ce7/go.mod h1:0T6oy2t1Iedt+yi3Ml5cpOYp5FZT4MI1/mx+3p+PIs8=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
Expand Down
2 changes: 2 additions & 0 deletions pkg/detector/ospkg/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/aquasecurity/trivy/pkg/detector/ospkg/chainguard"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/debian"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/mariner"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/openeuler"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/oracle"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/photon"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/redhat"
Expand Down Expand Up @@ -46,6 +47,7 @@ var (
ftypes.Photon: photon.NewScanner(),
ftypes.Wolfi: wolfi.NewScanner(),
ftypes.Chainguard: chainguard.NewScanner(),
ftypes.OpenEuler: openeuler.NewScanner(),
}
)

Expand Down
97 changes: 97 additions & 0 deletions pkg/detector/ospkg/openeuler/openeuler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package openeuler

import (
"context"
"strings"
"time"

version "github.com/knqyf263/go-rpm-version"
"golang.org/x/xerrors"

openeuler "github.com/aquasecurity/trivy-db/pkg/vulnsrc/openeuler"
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/aquasecurity/trivy/pkg/types"
)

var (
openeulerEOLDates = map[string]time.Time{
// Source: https://www.openeuler.org/zh/other/lifecycle/
"20.09": time.Date(2021, 3, 31, 23, 59, 59, 0, time.UTC),
"21.03": time.Date(2021, 9, 30, 23, 59, 59, 0, time.UTC),
"21.09": time.Date(2022, 3, 31, 23, 59, 59, 0, time.UTC),
"22.09": time.Date(2023, 3, 31, 23, 59, 59, 0, time.UTC),
"23.03": time.Date(2023, 9, 30, 23, 59, 59, 0, time.UTC),
"23.09": time.Date(2024, 3, 31, 23, 59, 59, 0, time.UTC),
"20.03-LTS": time.Date(2022, 3, 31, 23, 59, 59, 0, time.UTC),
"22.03-LTS": time.Date(2024, 3, 31, 23, 59, 59, 0, time.UTC),
"20.03-LTS-SP1": time.Date(2022, 12, 31, 23, 59, 59, 0, time.UTC),
"20.03-LTS-SP2": time.Date(2022, 3, 31, 23, 59, 59, 0, time.UTC),
"20.03-LTS-SP3": time.Date(2023, 12, 31, 23, 59, 59, 0, time.UTC),
"20.03-LTS-SP4": time.Date(2026, 3, 31, 23, 59, 59, 0, time.UTC),
"22.03-LTS-SP1": time.Date(2024, 12, 31, 23, 59, 59, 0, time.UTC),
"22.03-LTS-SP2": time.Date(2024, 3, 31, 23, 59, 59, 0, time.UTC),
"22.03-LTS-SP3": time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
"22.03-LTS-SP4": time.Date(2028, 3, 31, 23, 59, 59, 0, time.UTC),
"24.03-LTS": time.Date(2026, 3, 31, 23, 59, 59, 0, time.UTC),
}
)

// Scanner implements the openEuler scanner
type Scanner struct {
vs openeuler.VulnSrc
}

// NewScanner is the factory method for Scanner
func NewScanner() *Scanner {
return &Scanner{
vs: openeuler.NewVulnSrc(),
}
}

// Detect scans and returns the vulnerabilities
func (s *Scanner) Detect(ctx context.Context, osVer string, _ *ftypes.Repository, pkgs []ftypes.Package) ([]types.DetectedVulnerability, error) {
log.InfoContext(ctx, "Detecting openEuler vulnerabilities...", log.String("os_version", osVer),
log.Int("pkg_num", len(pkgs)))

var vulns []types.DetectedVulnerability
for _, pkg := range pkgs {
srcName := pkg.SrcName
if srcName == "" {
srcName = pkg.Name
}
advisories, err := s.vs.Get(osVer, srcName, pkg.Arch)
if err != nil {
return nil, xerrors.Errorf("failed to get openEuler advisory: %w", err)
}

installed, _, _ := strings.Cut(utils.FormatVersion(pkg), ".oe")
srcVersion, _, _ := strings.Cut(utils.FormatSrcVersion(pkg), ".oe")
sourceVersion := version.NewVersion(srcVersion)
for _, adv := range advisories {
fixedVersion := version.NewVersion(adv.FixedVersion)
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgID: pkg.ID,
PkgName: pkg.Name,
InstalledVersion: installed,
PkgIdentifier: pkg.Identifier,
Layer: pkg.Layer,
Custom: adv.Custom,
DataSource: adv.DataSource,
}
if sourceVersion.LessThan(fixedVersion) {
vuln.FixedVersion = adv.FixedVersion
vulns = append(vulns, vuln)
}
}
}
return vulns, nil
}

// IsSupportedVersion checks if OSFamily can be scanned using openEuler scanner
func (s *Scanner) IsSupportedVersion(ctx context.Context, osFamily ftypes.OSType, osVer string) bool {
return osver.Supported(ctx, openeulerEOLDates, osFamily, osVer)
}
158 changes: 158 additions & 0 deletions pkg/detector/ospkg/openeuler/openeuler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package openeuler_test

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/aquasecurity/trivy-db/pkg/db"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/internal/dbtest"
"github.com/aquasecurity/trivy/pkg/clock"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/openeuler"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
)

func TestScanner_Detect(t *testing.T) {
type args struct {
osVer string
pkgs []ftypes.Package
}
tests := []struct {
name string
args args
fixtures []string
want []types.DetectedVulnerability
wantErr string
}{
{
name: "happy path",
fixtures: []string{
"testdata/fixtures/openeuler.yaml",
"testdata/fixtures/data-source.yaml",
},
args: args{
osVer: "22.03-LTS-SP2",
pkgs: []ftypes.Package{
{
Name: "perf",
Version: "5.10.0",
Arch: "x86_64",
Release: "153.48.0.125",
SrcName: "postgresql",
SrcVersion: "5.10.0",
SrcRelease: "153.48.0.125",
Layer: ftypes.Layer{
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
},
},
},
},
want: []types.DetectedVulnerability{
{
PkgName: "perf",
VulnerabilityID: "openEuler-SA-2024-1349",
InstalledVersion: "5.10.0-153.48.0.125",
FixedVersion: "5.10.0-153.48.0.126",
Layer: ftypes.Layer{
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
},
DataSource: &dbTypes.DataSource{
ID: vulnerability.OpenEuler,
Name: "openEuler CVRF",
URL: "https://repo.openeuler.org/security/data/cvrf",
},
},
},
},
{
name: "broken bucket",
fixtures: []string{
"testdata/fixtures/invalid.yaml",
"testdata/fixtures/data-source.yaml",
},
args: args{
osVer: "22.03-LTS-SP2",
pkgs: []ftypes.Package{
{
Name: "perf",
Version: "1.6-r0",
SrcName: "perf",
SrcVersion: "1.6-r0",
},
},
},
wantErr: "failed to get openEuler advisories",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_ = dbtest.InitDB(t, tt.fixtures)
defer db.Close()

s := openeuler.NewScanner()
got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs)
if tt.wantErr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}

func TestScanner_IsSupportedVersion(t *testing.T) {
type args struct {
osFamily ftypes.OSType
osVer string
}
tests := []struct {
name string
now time.Time
args args
want bool
}{
{
name: "openEuler-20.03-LTS",
now: time.Date(2021, 5, 31, 23, 59, 59, 0, time.UTC),
args: args{
osFamily: "openEuler",
osVer: "20.03-LTS",
},
want: true,
},
{
name: "21.09",
now: time.Date(2022, 5, 31, 23, 59, 59, 0, time.UTC),
args: args{
osFamily: "openEuler",
osVer: "21.09",
},
want: false,
},
{
name: "22.03-LTS-SP3",
now: time.Date(2023, 5, 2, 23, 59, 59, 0, time.UTC),
args: args{
osFamily: "openEuler",
osVer: "22.03-LTS-SP3",
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := clock.With(context.Background(), tt.now)
s := openeuler.NewScanner()
got := s.IsSupportedVersion(ctx, tt.args.osFamily, tt.args.osVer)
assert.Equal(t, tt.want, got)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- bucket: data-source
pairs:
- key: openEuler-22.03-LTS-SP2
value:
ID: "openeuler"
Name: "openEuler CVRF"
URL: "https://repo.openeuler.org/security/data/cvrf"
9 changes: 9 additions & 0 deletions pkg/detector/ospkg/openeuler/testdata/fixtures/invalid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- bucket: openEuler-22.03-LTS-SP2
pairs:
- bucket: perf
pairs:
- key: CVE-2021-47014
value:
FixedVersion:
- foo
- bar
Loading