From 1cfe155a3a812272e059e0ea3a9a3f568e0851b2 Mon Sep 17 00:00:00 2001 From: maito1201 <49754654+maito1201@users.noreply.github.com> Date: Wed, 9 Feb 2022 09:30:44 +0900 Subject: [PATCH] feat(fedora): support fedora (#1367) * feat(fedora): support fedora * fix(fedora): fix modular package scan * fix(fedora): check needs-restarting, oval arch, add source link Co-authored-by: MaineK00n --- README.md | 8 +-- config/os.go | 9 +++ config/os_test.go | 65 ++++++++++++++++++ constant/constant.go | 3 + contrib/trivy/pkg/converter.go | 1 + go.mod | 16 ++--- go.sum | 29 +++++---- models/cvecontents.go | 6 ++ models/scanresults_test.go | 5 ++ models/vulninfos.go | 2 +- oval/redhat.go | 29 ++++++++- oval/util.go | 37 +++++++++-- oval/util_test.go | 82 +++++++++++++++++++++++ scanner/fedora.go | 116 +++++++++++++++++++++++++++++++++ scanner/redhatbase.go | 114 +++++++++++++++++++++----------- scanner/serverapi.go | 2 + scanner/utils.go | 2 +- 17 files changed, 454 insertions(+), 72 deletions(-) create mode 100644 scanner/fedora.go diff --git a/README.md b/README.md index dd913310..f5d234dd 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Vuls is a tool created to solve the problems listed above. It has the following [Supports major Linux/FreeBSD](https://vuls.io/docs/en/supported-os.html) -- Alpine, Amazon Linux, CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Raspbian, RHEL, SUSE Enterprise Linux, and Ubuntu +- Alpine, Amazon Linux, CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Raspbian, RHEL, SUSE Enterprise Linux, Fedora, and Ubuntu - FreeBSD - Cloud, on-premise, Running Docker Container @@ -106,15 +106,15 @@ Vuls is a tool created to solve the problems listed above. It has the following - Scan without root privilege, no dependencies - Almost no load on the scan target server -- Offline mode scan with no internet access. (CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Red Hat, and Ubuntu) +- Offline mode scan with no internet access. (CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Red Hat, Fedora, and Ubuntu) [Fast Root Scan](https://vuls.io/docs/en/architecture-fast-root-scan.html) - Scan with root privilege - Almost no load on the scan target server -- Detect processes affected by update using yum-ps (Amazon Linux, CentOS, Alma Linux, Rocky Linux, Oracle Linux, and RedHat) +- Detect processes affected by update using yum-ps (Amazon Linux, CentOS, Alma Linux, Rocky Linux, Oracle Linux, Fedora, and RedHat) - Detect processes which updated before but not restarting yet using checkrestart of debian-goodies (Debian and Ubuntu) -- Offline mode scan with no internet access. (CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Red Hat, and Ubuntu) +- Offline mode scan with no internet access. (CentOS, Alma Linux, Rocky Linux, Debian, Oracle Linux, Red Hat, Fedora, and Ubuntu) ### [Remote, Local scan mode, Server mode](https://vuls.io/docs/en/architecture-remote-local.html) diff --git a/config/os.go b/config/os.go index 409c5968..25a7c96c 100644 --- a/config/os.go +++ b/config/os.go @@ -189,6 +189,15 @@ func GetEOL(family, release string) (eol EOL, found bool) { "12": {StandardSupportUntil: time.Date(2024, 6, 30, 23, 59, 59, 0, time.UTC)}, "13": {StandardSupportUntil: time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)}, }[major(release)] + case constant.Fedora: + // https://docs.fedoraproject.org/en-US/releases/eol/ + // https://endoflife.date/fedora + eol, found = map[string]EOL{ + "32": {StandardSupportUntil: time.Date(2021, 5, 25, 23, 59, 59, 0, time.UTC)}, + "33": {StandardSupportUntil: time.Date(2021, 11, 30, 23, 59, 59, 0, time.UTC)}, + "34": {StandardSupportUntil: time.Date(2022, 5, 17, 23, 59, 59, 0, time.UTC)}, + "35": {StandardSupportUntil: time.Date(2022, 12, 7, 23, 59, 59, 0, time.UTC)}, + }[major(release)] } return } diff --git a/config/os_test.go b/config/os_test.go index e06e6c41..e9c654e2 100644 --- a/config/os_test.go +++ b/config/os_test.go @@ -406,6 +406,71 @@ func TestEOL_IsStandardSupportEnded(t *testing.T) { extEnded: true, found: true, }, + // Fedora + { + name: "Fedora 32 supported", + fields: fields{family: Fedora, release: "32"}, + now: time.Date(2021, 5, 25, 23, 59, 59, 0, time.UTC), + stdEnded: false, + extEnded: false, + found: true, + }, + { + name: "Fedora 32 eol on 2021-5-25", + fields: fields{family: Fedora, release: "32"}, + now: time.Date(2021, 5, 26, 23, 59, 59, 0, time.UTC), + stdEnded: true, + extEnded: true, + found: true, + }, + { + name: "Fedora 33 supported", + fields: fields{family: Fedora, release: "33"}, + now: time.Date(2021, 11, 30, 23, 59, 59, 0, time.UTC), + stdEnded: false, + extEnded: false, + found: true, + }, + { + name: "Fedora 33 eol on 2021-5-26", + fields: fields{family: Fedora, release: "32"}, + now: time.Date(2021, 5, 27, 23, 59, 59, 0, time.UTC), + stdEnded: true, + extEnded: true, + found: true, + }, + { + name: "Fedora 34 supported", + fields: fields{family: Fedora, release: "34"}, + now: time.Date(2022, 5, 17, 23, 59, 59, 0, time.UTC), + stdEnded: false, + extEnded: false, + found: true, + }, + { + name: "Fedora 32 eol on 2022-5-17", + fields: fields{family: Fedora, release: "34"}, + now: time.Date(2022, 5, 18, 23, 59, 59, 0, time.UTC), + stdEnded: true, + extEnded: true, + found: true, + }, + { + name: "Fedora 35 supported", + fields: fields{family: Fedora, release: "35"}, + now: time.Date(2022, 12, 7, 23, 59, 59, 0, time.UTC), + stdEnded: false, + extEnded: false, + found: true, + }, + { + name: "Fedora 35 eol on 2022-12-7", + fields: fields{family: Fedora, release: "35"}, + now: time.Date(2022, 12, 8, 23, 59, 59, 0, time.UTC), + stdEnded: true, + extEnded: true, + found: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/constant/constant.go b/constant/constant.go index d1f667c5..84020db1 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -64,4 +64,7 @@ const ( // DeepSecurity is DeepSecurity = "deepsecurity" + + //Fedora is + Fedora = "fedora" ) diff --git a/contrib/trivy/pkg/converter.go b/contrib/trivy/pkg/converter.go index d2577a99..0467f71f 100644 --- a/contrib/trivy/pkg/converter.go +++ b/contrib/trivy/pkg/converter.go @@ -197,6 +197,7 @@ func IsTrivySupportedOS(family string) bool { os.SLES: struct{}{}, os.Photon: struct{}{}, os.Alpine: struct{}{}, + // os.Fedora: struct{}{}, not supported yet } _, ok := supportedFamilies[family] return ok diff --git a/go.mod b/go.mod index 18c59fdb..f59e3b7b 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/vulsio/go-kev v0.1.0 github.com/vulsio/go-msfdb v0.2.1-0.20211028071756-4a9759bd9f14 github.com/vulsio/gost v0.4.1-0.20211028071837-7ad032a6ffa8 - github.com/vulsio/goval-dictionary v0.6.1-0.20220128223409-c451db7b6a62 + github.com/vulsio/goval-dictionary v0.6.1-0.20220204031431-f58917681372 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 @@ -123,16 +123,16 @@ require ( github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.2.0 // indirect github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.9.0 // indirect - github.com/jackc/pgx/v4 v4.14.0 // indirect + github.com/jackc/pgtype v1.9.1 // indirect + github.com/jackc/pgx/v4 v4.14.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.3 // indirect + github.com/jinzhu/now v1.1.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 // indirect github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-sqlite3 v1.14.9 // indirect + github.com/mattn/go-sqlite3 v1.14.11 // indirect github.com/mitchellh/copystructure v1.1.1 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect @@ -143,14 +143,14 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/spf13/afero v1.8.0 // indirect + github.com/spf13/afero v1.8.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.10.0 // indirect github.com/stretchr/objx v0.3.0 // indirect github.com/stretchr/testify v1.7.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect - github.com/ulikunitz/xz v0.5.8 // indirect + github.com/ulikunitz/xz v0.5.10 // indirect github.com/ymomoi/goval-parser v0.0.0-20170813122243-0a0be1dd9d08 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect @@ -166,7 +166,7 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gorm.io/gorm v1.22.4 // indirect + gorm.io/gorm v1.22.5 // indirect k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect moul.io/http2curl v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 79e73974..ea9cd55f 100644 --- a/go.sum +++ b/go.sum @@ -818,8 +818,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE= github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4= github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZcN5ttKpZLfa/wSo5iLw= @@ -1078,8 +1079,9 @@ github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI github.com/jackc/pgtype v1.8.0/go.mod h1:PqDKcEBtllAtk/2p6z6SHdXW5UB+MhE75tUol2OKexE= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.9.0 h1:/SH1RxEtltvJgsDqp3TbiTFApD3mey3iygpuEGeuBXk= github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= @@ -1091,8 +1093,9 @@ github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CI github.com/jackc/pgx/v4 v4.12.0/go.mod h1:fE547h6VulLPA3kySjfnSG/e2D861g/50JlVUa/ub60= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= -github.com/jackc/pgx/v4 v4.14.0 h1:TgdrmgnM7VY72EuSQzBbBd4JA1RLqJolrw9nQVZABVc= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -1113,8 +1116,9 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -1278,8 +1282,9 @@ github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lL github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= +github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1622,8 +1627,8 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= -github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk= +github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1713,8 +1718,9 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -1755,8 +1761,8 @@ github.com/vulsio/go-msfdb v0.2.1-0.20211028071756-4a9759bd9f14 h1:2uYZw2gQ0kymw github.com/vulsio/go-msfdb v0.2.1-0.20211028071756-4a9759bd9f14/go.mod h1:NGdcwWxCK/ES8vZ/crzREqI69S5gH1MivCpSp1pa2Rc= github.com/vulsio/gost v0.4.1-0.20211028071837-7ad032a6ffa8 h1:jqsECpLRp1EAXGOdhPxHzqYjWP5l980GjJ8s/AUYH/4= github.com/vulsio/gost v0.4.1-0.20211028071837-7ad032a6ffa8/go.mod h1:DaWLus8dJ4DdhVsBe5TAEEZ3IdoTMIb/z2StR4Bhb7Q= -github.com/vulsio/goval-dictionary v0.6.1-0.20220128223409-c451db7b6a62 h1:dB8hpDQkwE0bc6884ywmeWt8VNVJGJUeeG/ydOiD+Io= -github.com/vulsio/goval-dictionary v0.6.1-0.20220128223409-c451db7b6a62/go.mod h1:IKhnwL5J/kv6/qKHsTN/CyZfJKeXAvcETVso4g573Hw= +github.com/vulsio/goval-dictionary v0.6.1-0.20220204031431-f58917681372 h1:jUtrzCcBb/ZR1zWHynPyConahasbbiGkQgLWY68bIZc= +github.com/vulsio/goval-dictionary v0.6.1-0.20220204031431-f58917681372/go.mod h1:aSJK5KAr0o+A0ccgdtQHvaMiAjXEv813QWcEtLr+mvo= 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/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= @@ -2624,8 +2630,9 @@ gorm.io/gorm v1.21.10/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.21.11/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.22.4 h1:8aPcyEJhY0MAt8aY6Dc524Pn+pO29K+ydu+e/cXSpQM= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= +gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= +gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= diff --git a/models/cvecontents.go b/models/cvecontents.go index 30ba4456..db06879f 100644 --- a/models/cvecontents.go +++ b/models/cvecontents.go @@ -319,6 +319,8 @@ func NewCveContentType(name string) CveContentType { return Jvn case "redhat", "centos", "alma", "rocky": return RedHat + case "fedora": + return Fedora case "oracle": return Oracle case "ubuntu": @@ -377,6 +379,9 @@ const ( // Amazon is Amazon Linux Amazon CveContentType = "amazon" + // Fedora is Fedora Linux + Fedora CveContentType = "fedora" + // SUSE is SUSE Linux SUSE CveContentType = "suse" @@ -410,6 +415,7 @@ var AllCveContetTypes = CveContentTypes{ Ubuntu, UbuntuAPI, Amazon, + Fedora, SUSE, WpScan, Trivy, diff --git a/models/scanresults_test.go b/models/scanresults_test.go index edf4c88a..d4292814 100644 --- a/models/scanresults_test.go +++ b/models/scanresults_test.go @@ -86,6 +86,11 @@ func TestIsDisplayUpdatableNum(t *testing.T) { family: constant.Alpine, expected: true, }, + { + mode: []byte{config.Fast}, + family: constant.Fedora, + expected: true, + }, } for i, tt := range tests { diff --git a/models/vulninfos.go b/models/vulninfos.go index 02bf146c..34839b88 100644 --- a/models/vulninfos.go +++ b/models/vulninfos.go @@ -256,7 +256,7 @@ type VulnInfo struct { CveID string `json:"cveID,omitempty"` Confidences Confidences `json:"confidences,omitempty"` AffectedPackages PackageFixStatuses `json:"affectedPackages,omitempty"` - DistroAdvisories DistroAdvisories `json:"distroAdvisories,omitempty"` // for Amazon, RHEL, FreeBSD + DistroAdvisories DistroAdvisories `json:"distroAdvisories,omitempty"` // for Amazon, RHEL, Fedora, FreeBSD CveContents CveContents `json:"cveContents,omitempty"` Exploits []Exploit `json:"exploits,omitempty"` Metasploits []Metasploit `json:"metasploits,omitempty"` diff --git a/oval/redhat.go b/oval/redhat.go index 205fbf11..9ecd71c4 100644 --- a/oval/redhat.go +++ b/oval/redhat.go @@ -15,7 +15,7 @@ import ( ovalmodels "github.com/vulsio/goval-dictionary/models" ) -// RedHatBase is the base struct for RedHat, CentOS, Alma and Rocky +// RedHatBase is the base struct for RedHat, CentOS, Alma, Rocky and Fedora type RedHatBase struct { Base } @@ -57,6 +57,15 @@ func (o RedHatBase) FillWithOval(r *models.ScanResult) (nCVEs int, err error) { vuln.CveContents[models.RedHat][i] = cont } } + case models.Fedora: + for _, d := range vuln.DistroAdvisories { + if conts, ok := vuln.CveContents[models.Fedora]; ok { + for i, cont := range conts { + cont.SourceLink = "https://bodhi.fedoraproject.org/updates/" + d.AdvisoryID + vuln.CveContents[models.Fedora][i] = cont + } + } + } case models.Oracle: if conts, ok := vuln.CveContents[models.Oracle]; ok { for i, cont := range conts { @@ -390,3 +399,21 @@ func NewRocky(cnf config.VulnDictInterface) Rocky { }, } } + +// Fedora is the interface for RedhatBase OVAL +type Fedora struct { + // Base + RedHatBase +} + +// NewFedora creates OVAL client for Fedora Linux +func NewFedora(cnf config.VulnDictInterface) Fedora { + return Fedora{ + RedHatBase{ + Base{ + family: constant.Fedora, + Cnf: cnf, + }, + }, + } +} diff --git a/oval/util.go b/oval/util.go index ecaa1a7d..04038c68 100644 --- a/oval/util.go +++ b/oval/util.go @@ -5,6 +5,7 @@ package oval import ( "encoding/json" + "fmt" "net/http" "regexp" "sort" @@ -308,6 +309,8 @@ func getDefsByPackNameFromOvalDB(driver db.DB, r *models.ScanResult) (relatedDef return } +var modularVersionPattern = regexp.MustCompile(`.+\.module(?:\+el|_f)\d{1,2}.*`) + func isOvalDefAffected(def ovalmodels.Definition, req request, family string, running models.Kernel, enabledMods []string) (affected, notFixedYet bool, fixedIn string, err error) { for _, ovalPack := range def.AffectedPacks { if req.packName != ovalPack.Name { @@ -315,9 +318,9 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru } switch family { - case constant.Oracle, constant.Amazon: + case constant.Oracle, constant.Amazon, constant.Fedora: if ovalPack.Arch == "" { - logging.Log.Infof("Arch is needed to detect Vulns for Amazon and Oracle Linux, but empty. You need refresh OVAL maybe. oval: %#v, defID: %s", ovalPack, def.DefinitionID) + logging.Log.Infof("Arch is needed to detect Vulns for Amazon Linux, Oracle Linux and Fedora, but empty. You need refresh OVAL maybe. oval: %#v, defID: %s", ovalPack, def.DefinitionID) continue } } @@ -331,10 +334,24 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru continue } + // There is a modular package and a non-modular package with the same name. (e.g. fedora 35 community-mysql) + if ovalPack.ModularityLabel == "" && modularVersionPattern.MatchString(req.versionRelease) { + continue + } else if ovalPack.ModularityLabel != "" && !modularVersionPattern.MatchString(req.versionRelease) { + continue + } + isModularityLabelEmptyOrSame := false if ovalPack.ModularityLabel != "" { + // expect ovalPack.ModularityLabel e.g. RedHat: nginx:1.16, Fedora: mysql:8.0:3520211031142409:f27b74a8 + ss := strings.Split(ovalPack.ModularityLabel, ":") + if len(ss) < 2 { + logging.Log.Warnf("Invalid modularitylabel format in oval package. Maybe it is necessary to fix modularitylabel of goval-dictionary. expected: ${name}:${stream}(:${version}:${context}:${arch}), actual: %s", ovalPack.ModularityLabel) + continue + } + modularityNameStreamLabel := fmt.Sprintf("%s:%s", ss[0], ss[1]) for _, mod := range enabledMods { - if mod == ovalPack.ModularityLabel { + if mod == modularityNameStreamLabel { isModularityLabelEmptyOrSame = true break } @@ -348,7 +365,7 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru if running.Release != "" { switch family { - case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle: + case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle, constant.Fedora: // For kernel related packages, ignore OVAL information with different major versions if _, ok := kernelRelatedPackNames[ovalPack.Name]; ok { if util.Major(ovalPack.Version) != util.Major(running.Release) { @@ -378,12 +395,13 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru // If the version of installed is less than in OVAL switch family { case constant.RedHat, + constant.Fedora, constant.Amazon, + constant.Oracle, constant.SUSEEnterpriseServer, constant.Debian, - constant.Ubuntu, constant.Raspbian, - constant.Oracle: + constant.Ubuntu: // Use fixed state in OVAL for these distros. return true, false, ovalPack.Version, nil } @@ -440,7 +458,8 @@ func lessThan(family, newVer string, packInOVAL ovalmodels.Package) (bool, error case constant.Oracle, constant.SUSEEnterpriseServer, - constant.Amazon: + constant.Amazon, + constant.Fedora: vera := rpmver.NewVersion(newVer) verb := rpmver.NewVersion(packInOVAL.Version) return vera.LessThan(verb), nil @@ -488,6 +507,8 @@ func NewOVALClient(family string, cnf config.GovalDictConf) (Client, error) { return NewAlpine(&cnf), nil case constant.Amazon: return NewAmazon(&cnf), nil + case constant.Fedora: + return NewFedora(&cnf), nil case constant.FreeBSD, constant.Windows: return nil, nil case constant.ServerTypePseudo: @@ -510,6 +531,8 @@ func GetFamilyInOval(familyInScanResult string) (string, error) { return constant.Ubuntu, nil case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky: return constant.RedHat, nil + case constant.Fedora: + return constant.Fedora, nil case constant.Oracle: return constant.Oracle, nil case constant.SUSEEnterpriseServer: diff --git a/oval/util_test.go b/oval/util_test.go index 9c2805fd..6b02a82e 100644 --- a/oval/util_test.go +++ b/oval/util_test.go @@ -1621,6 +1621,88 @@ func TestIsOvalDefAffected(t *testing.T) { affected: false, notFixedYet: false, }, + // dnf module 4 (long modularitylabel) + { + in: in{ + family: constant.Fedora, + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "community-mysql", + Version: "0:8.0.27-1.module_f35+13269+c9322734", + Arch: "x86_64", + NotFixedYet: false, + ModularityLabel: "mysql:8.0:3520211031142409:f27b74a8", + }, + }, + }, + req: request{ + packName: "community-mysql", + arch: "x86_64", + versionRelease: "8.0.26-1.module_f35+12627+b26747dd", + }, + mods: []string{ + "mysql:8.0", + }, + }, + affected: true, + notFixedYet: false, + fixedIn: "0:8.0.27-1.module_f35+13269+c9322734", + }, + // dnf module 5 (req is non-modular package, oval is modular package) + { + in: in{ + family: constant.Fedora, + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "community-mysql", + Version: "0:8.0.27-1.module_f35+13269+c9322734", + Arch: "x86_64", + NotFixedYet: false, + ModularityLabel: "mysql:8.0:3520211031142409:f27b74a8", + }, + }, + }, + req: request{ + packName: "community-mysql", + arch: "x86_64", + versionRelease: "8.0.26-1.fc35", + }, + mods: []string{ + "mysql:8.0", + }, + }, + affected: false, + notFixedYet: false, + }, + // dnf module 6 (req is modular package, oval is non-modular package) + { + in: in{ + family: constant.Fedora, + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "community-mysql", + Version: "0:8.0.27-1.fc35", + Arch: "x86_64", + NotFixedYet: false, + ModularityLabel: "", + }, + }, + }, + req: request{ + packName: "community-mysql", + arch: "x86_64", + versionRelease: "8.0.26-1.module_f35+12627+b26747dd", + }, + mods: []string{ + "mysql:8.0", + }, + }, + affected: false, + notFixedYet: false, + }, // .ksplice1. { in: in{ diff --git a/scanner/fedora.go b/scanner/fedora.go new file mode 100644 index 00000000..d66cce48 --- /dev/null +++ b/scanner/fedora.go @@ -0,0 +1,116 @@ +package scanner + +import ( + "github.com/future-architect/vuls/config" + "github.com/future-architect/vuls/logging" + "github.com/future-architect/vuls/models" +) + +// inherit OsTypeInterface +type fedora struct { + redhatBase +} + +// NewFedora is constructor +func newFedora(c config.ServerInfo) *fedora { + r := &fedora{ + redhatBase{ + base: base{ + osPackages: osPackages{ + Packages: models.Packages{}, + VulnInfos: models.VulnInfos{}, + }, + }, + sudo: rootPrivFedora{}, + }, + } + r.log = logging.NewNormalLogger() + r.setServerInfo(c) + return r +} + +func (o *fedora) checkScanMode() error { + return nil +} + +func (o *fedora) checkDeps() error { + if o.getServerInfo().Mode.IsFast() { + return o.execCheckDeps(o.depsFast()) + } else if o.getServerInfo().Mode.IsFastRoot() { + return o.execCheckDeps(o.depsFastRoot()) + } else { + return o.execCheckDeps(o.depsDeep()) + } +} + +func (o *fedora) depsFast() []string { + if o.getServerInfo().Mode.IsOffline() { + return []string{} + } + + // repoquery + return []string{"dnf-utils"} +} + +func (o *fedora) depsFastRoot() []string { + if o.getServerInfo().Mode.IsOffline() { + return []string{} + } + + // repoquery + return []string{"dnf-utils"} +} + +func (o *fedora) depsDeep() []string { + return o.depsFastRoot() +} + +func (o *fedora) checkIfSudoNoPasswd() error { + if o.getServerInfo().Mode.IsFast() { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsFast()) + } else if o.getServerInfo().Mode.IsFastRoot() { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsFastRoot()) + } else { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsDeep()) + } +} + +func (o *fedora) sudoNoPasswdCmdsFast() []cmd { + return []cmd{} +} + +func (o *fedora) sudoNoPasswdCmdsFastRoot() []cmd { + if !o.ServerInfo.IsContainer() { + return []cmd{ + {"repoquery -h", exitStatusZero}, + {"needs-restarting", exitStatusZero}, + {"which which", exitStatusZero}, + {"stat /proc/1/exe", exitStatusZero}, + {"ls -l /proc/1/exe", exitStatusZero}, + {"cat /proc/1/maps", exitStatusZero}, + {"lsof -i -P -n", exitStatusZero}, + } + } + return []cmd{ + {"repoquery -h", exitStatusZero}, + {"needs-restarting", exitStatusZero}, + } +} + +func (o *fedora) sudoNoPasswdCmdsDeep() []cmd { + return o.sudoNoPasswdCmdsFastRoot() +} + +type rootPrivFedora struct{} + +func (o rootPrivFedora) repoquery() bool { + return false +} + +func (o rootPrivFedora) yumMakeCache() bool { + return false +} + +func (o rootPrivFedora) yumPS() bool { + return false +} diff --git a/scanner/redhatbase.go b/scanner/redhatbase.go index e585d1ee..556479f9 100644 --- a/scanner/redhatbase.go +++ b/scanner/redhatbase.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "regexp" + "strconv" "strings" "github.com/future-architect/vuls/config" @@ -16,19 +17,38 @@ import ( ver "github.com/knqyf263/go-rpm-version" ) +var releasePattern = regexp.MustCompile(`(.*) release (\d[\d\.]*)`) + // https://github.com/serverspec/specinfra/blob/master/lib/specinfra/helper/detect_os/redhat.rb func detectRedhat(c config.ServerInfo) (bool, osTypeInterface) { if r := exec(c, "ls /etc/fedora-release", noSudo); r.isSuccess() { - logging.Log.Warnf("Fedora not tested yet: %s", r) - return true, &unknown{} + if r := exec(c, "cat /etc/fedora-release", noSudo); r.isSuccess() { + fed := newFedora(c) + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + if len(result) != 3 { + logging.Log.Warnf("Failed to parse Fedora version: %s", r) + return true, fed + } + release := result[2] + ver, err := strconv.Atoi(release) + if err != nil { + logging.Log.Warnf("Failed to parse Fedora version: %s", release) + return true, fed + } + if ver < 32 { + logging.Log.Warnf("Versions prior to Fedora 32 are not supported, detected version is %s", release) + return true, fed + } + fed.setDistro(constant.Fedora, release) + return true, fed + } } if r := exec(c, "ls /etc/oracle-release", noSudo); r.isSuccess() { // Need to discover Oracle Linux first, because it provides an // /etc/redhat-release that matches the upstream distribution if r := exec(c, "cat /etc/oracle-release", noSudo); r.isSuccess() { - re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) - result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) if len(result) != 3 { logging.Log.Warnf("Failed to parse Oracle Linux version: %s", r) return true, newOracle(c) @@ -41,37 +61,9 @@ func detectRedhat(c config.ServerInfo) (bool, osTypeInterface) { } } - // https://bugzilla.redhat.com/show_bug.cgi?id=1332025 - // CentOS cloud image - if r := exec(c, "ls /etc/centos-release", noSudo); r.isSuccess() { - if r := exec(c, "cat /etc/centos-release", noSudo); r.isSuccess() { - re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) - result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) - if len(result) != 3 { - logging.Log.Warnf("Failed to parse CentOS version: %s", r) - return true, newCentOS(c) - } - - release := result[2] - switch strings.ToLower(result[1]) { - case "centos", "centos linux": - cent := newCentOS(c) - cent.setDistro(constant.CentOS, release) - return true, cent - case "centos stream": - cent := newCentOS(c) - cent.setDistro(constant.CentOS, fmt.Sprintf("stream%s", release)) - return true, cent - default: - logging.Log.Warnf("Failed to parse CentOS: %s", r) - } - } - } - if r := exec(c, "ls /etc/almalinux-release", noSudo); r.isSuccess() { if r := exec(c, "cat /etc/almalinux-release", noSudo); r.isSuccess() { - re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) - result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) if len(result) != 3 { logging.Log.Warnf("Failed to parse Alma version: %s", r) return true, newAlma(c) @@ -91,8 +83,7 @@ func detectRedhat(c config.ServerInfo) (bool, osTypeInterface) { if r := exec(c, "ls /etc/rocky-release", noSudo); r.isSuccess() { if r := exec(c, "cat /etc/rocky-release", noSudo); r.isSuccess() { - re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) - result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) if len(result) != 3 { logging.Log.Warnf("Failed to parse Rocky version: %s", r) return true, newRocky(c) @@ -110,21 +101,66 @@ func detectRedhat(c config.ServerInfo) (bool, osTypeInterface) { } } + // https://bugzilla.redhat.com/show_bug.cgi?id=1332025 + // CentOS cloud image + if r := exec(c, "ls /etc/centos-release", noSudo); r.isSuccess() { + if r := exec(c, "cat /etc/centos-release", noSudo); r.isSuccess() { + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + if len(result) != 3 { + logging.Log.Warnf("Failed to parse CentOS version: %s", r) + return true, newCentOS(c) + } + + release := result[2] + switch strings.ToLower(result[1]) { + case "centos", "centos linux": + cent := newCentOS(c) + cent.setDistro(constant.CentOS, release) + return true, cent + case "centos stream": + cent := newCentOS(c) + cent.setDistro(constant.CentOS, fmt.Sprintf("stream%s", release)) + return true, cent + case "alma", "almalinux": + alma := newAlma(c) + alma.setDistro(constant.Alma, release) + return true, alma + case "rocky", "rocky linux": + rocky := newRocky(c) + rocky.setDistro(constant.Rocky, release) + return true, rocky + default: + logging.Log.Warnf("Failed to parse CentOS: %s", r) + } + } + } + if r := exec(c, "ls /etc/redhat-release", noSudo); r.isSuccess() { // https://www.rackaid.com/blog/how-to-determine-centos-or-red-hat-version/ // e.g. // $ cat /etc/redhat-release // CentOS release 6.5 (Final) if r := exec(c, "cat /etc/redhat-release", noSudo); r.isSuccess() { - re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) - result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + result := releasePattern.FindStringSubmatch(strings.TrimSpace(r.Stdout)) if len(result) != 3 { logging.Log.Warnf("Failed to parse RedHat/CentOS version: %s", r) return true, newCentOS(c) } release := result[2] + ver, err := strconv.Atoi(release) + if err != nil { + logging.Log.Warnf("Failed to parse RedHat/CentOS version number: %s", release) + return true, newCentOS(c) + } + if ver < 5 { + logging.Log.Warnf("Versions prior to RedHat/CentOS 5 are not supported, detected version is %s", release) + } switch strings.ToLower(result[1]) { + case "fedora": + fed := newFedora(c) + fed.setDistro(constant.Fedora, release) + return true, fed case "centos", "centos linux": cent := newCentOS(c) cent.setDistro(constant.CentOS, release) @@ -519,7 +555,7 @@ func (o *redhatBase) isExecNeedsRestarting() bool { // TODO zypper ps // https://github.com/future-architect/vuls/issues/696 return false - case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle: + case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle, constant.Fedora: majorVersion, err := o.Distro.MajorVersion() if err != nil || majorVersion < 6 { o.log.Errorf("Not implemented yet: %s, err: %+v", o.Distro, err) @@ -698,7 +734,7 @@ func (o *redhatBase) rpmQf() string { func (o *redhatBase) detectEnabledDnfModules() ([]string, error) { switch o.Distro.Family { - case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky: + case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Fedora: //TODO OracleLinux default: return nil, nil diff --git a/scanner/serverapi.go b/scanner/serverapi.go index b8844ec7..9692d6ee 100644 --- a/scanner/serverapi.go +++ b/scanner/serverapi.go @@ -225,6 +225,8 @@ func ParseInstalledPkgs(distro config.Distro, kernel models.Kernel, pkgList stri osType = &oracle{redhatBase: redhatBase{base: base}} case constant.Amazon: osType = &amazon{redhatBase: redhatBase{base: base}} + case constant.Fedora: + osType = &fedora{redhatBase: redhatBase{base: base}} default: return models.Packages{}, models.SrcPackages{}, xerrors.Errorf("Server mode for %s is not implemented yet", base.Distro.Family) } diff --git a/scanner/utils.go b/scanner/utils.go index a37b6f51..5bc38fda 100644 --- a/scanner/utils.go +++ b/scanner/utils.go @@ -26,7 +26,7 @@ func isRunningKernel(pack models.Package, family string, kernel models.Kernel) ( } return false, false - case constant.RedHat, constant.Oracle, constant.CentOS, constant.Alma, constant.Rocky, constant.Amazon: + case constant.RedHat, constant.Oracle, constant.CentOS, constant.Alma, constant.Rocky, constant.Amazon, constant.Fedora: switch pack.Name { case "kernel", "kernel-devel", "kernel-core", "kernel-modules", "kernel-uek": ver := fmt.Sprintf("%s-%s.%s", pack.Version, pack.Release, pack.Arch)