Skip to content

Commit 62ccd79

Browse files
authored
feat(hook): add system file filter (fanal#263)
1 parent 1c877da commit 62ccd79

File tree

14 files changed

+269
-39
lines changed

14 files changed

+269
-39
lines changed

analyzer/analyzer.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,17 @@ func RegisterConfigAnalyzer(analyzer configAnalyzer) {
5858
type Opener func() ([]byte, error)
5959

6060
type AnalysisResult struct {
61-
m sync.Mutex
62-
OS *types.OS
63-
PackageInfos []types.PackageInfo
64-
Applications []types.Application
65-
Configs []types.Config
61+
m sync.Mutex
62+
OS *types.OS
63+
PackageInfos []types.PackageInfo
64+
Applications []types.Application
65+
Configs []types.Config
66+
SystemInstalledFiles []string // A list of files installed by OS package manager
6667
}
6768

6869
func (r *AnalysisResult) isEmpty() bool {
69-
return r.OS == nil && len(r.PackageInfos) == 0 && len(r.Applications) == 0 && len(r.Configs) == 0
70+
return r.OS == nil && len(r.PackageInfos) == 0 && len(r.Applications) == 0 &&
71+
len(r.Configs) == 0 && len(r.SystemInstalledFiles) == 0
7072
}
7173

7274
func (r *AnalysisResult) Sort() {
@@ -123,6 +125,8 @@ func (r *AnalysisResult) Merge(new *AnalysisResult) {
123125
for _, m := range new.Configs {
124126
r.Configs = append(r.Configs, m)
125127
}
128+
129+
r.SystemInstalledFiles = append(r.SystemInstalledFiles, new.SystemInstalledFiles...)
126130
}
127131

128132
type Analyzer struct {

analyzer/pkg/dpkg/dpkg.go

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,11 @@ import (
99
"regexp"
1010
"strings"
1111

12-
"github.com/aquasecurity/fanal/types"
13-
14-
"github.com/aquasecurity/fanal/utils"
15-
16-
mapset "github.com/deckarep/golang-set"
12+
debVersion "github.com/knqyf263/go-deb-version"
1713

1814
"github.com/aquasecurity/fanal/analyzer"
19-
20-
debVersion "github.com/knqyf263/go-deb-version"
15+
"github.com/aquasecurity/fanal/types"
16+
"github.com/aquasecurity/fanal/utils"
2117
)
2218

2319
func init() {
@@ -50,9 +46,9 @@ func (a debianPkgAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.An
5046
}, nil
5147
}
5248

53-
func (a debianPkgAnalyzer) parseDpkginfo(scanner *bufio.Scanner) (pkgs []types.Package) {
49+
func (a debianPkgAnalyzer) parseDpkginfo(scanner *bufio.Scanner) []types.Package {
5450
var pkg *types.Package
55-
pkgMap := mapset.NewSet()
51+
pkgMap := map[string]*types.Package{}
5652

5753
for scanner.Scan() {
5854
line := strings.TrimSpace(scanner.Text())
@@ -63,20 +59,15 @@ func (a debianPkgAnalyzer) parseDpkginfo(scanner *bufio.Scanner) (pkgs []types.P
6359

6460
pkg = a.parseDpkgPkg(scanner)
6561
if pkg != nil {
66-
pkgMap.Add(*pkg)
62+
pkgMap[pkg.Name+"-"+pkg.Version] = pkg
6763
}
6864
}
69-
pkgs = mapsetToSlice(pkgMap)
70-
return pkgs
71-
}
7265

73-
func mapsetToSlice(features mapset.Set) []types.Package {
74-
uniqueLayerFeatures := make([]types.Package, 0, features.Cardinality())
75-
for f := range features.Iter() {
76-
feature := f.(types.Package)
77-
uniqueLayerFeatures = append(uniqueLayerFeatures, feature)
66+
pkgs := make([]types.Package, 0, len(pkgMap))
67+
for _, p := range pkgMap {
68+
pkgs = append(pkgs, *p)
7869
}
79-
return uniqueLayerFeatures
70+
return pkgs
8071
}
8172

8273
func (a debianPkgAnalyzer) parseDpkgPkg(scanner *bufio.Scanner) (pkg *types.Package) {

analyzer/pkg/dpkg/dpkg_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/kylelemons/godebug/pretty"
1212
)
1313

14-
func TestParseApkInfo(t *testing.T) {
14+
func TestParseDpkgInfo(t *testing.T) {
1515
var tests = map[string]struct {
1616
path string
1717
pkgs []types.Package

analyzer/pkg/rpm/rpm.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var requiredFiles = []string{
2828
type rpmPkgAnalyzer struct{}
2929

3030
func (a rpmPkgAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) {
31-
parsedPkgs, err := a.parsePkgInfo(target.Content)
31+
parsedPkgs, installedFiles, err := a.parsePkgInfo(target.Content)
3232
if err != nil {
3333
return nil, xerrors.Errorf("failed to parse rpmdb: %w", err)
3434
}
@@ -40,37 +40,40 @@ func (a rpmPkgAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.Analy
4040
Packages: parsedPkgs,
4141
},
4242
},
43+
SystemInstalledFiles: installedFiles,
4344
}, nil
4445
}
4546

46-
func (a rpmPkgAnalyzer) parsePkgInfo(packageBytes []byte) (pkgs []types.Package, err error) {
47+
func (a rpmPkgAnalyzer) parsePkgInfo(packageBytes []byte) ([]types.Package, []string, error) {
4748
tmpDir, err := ioutil.TempDir("", "rpm")
4849
defer os.RemoveAll(tmpDir)
4950
if err != nil {
50-
return nil, xerrors.Errorf("failed to create a temp dir: %w", err)
51+
return nil, nil, xerrors.Errorf("failed to create a temp dir: %w", err)
5152
}
5253

5354
filename := filepath.Join(tmpDir, "Packages")
5455
err = ioutil.WriteFile(filename, packageBytes, 0700)
5556
if err != nil {
56-
return nil, xerrors.Errorf("failed to write a package file: %w", err)
57+
return nil, nil, xerrors.Errorf("failed to write a package file: %w", err)
5758
}
5859

5960
// rpm-python 4.11.3 rpm-4.11.3-35.el7.src.rpm
6061
// Extract binary package names because RHSA refers to binary package names.
6162
db, err := rpmdb.Open(filename)
6263
if err != nil {
63-
return nil, xerrors.Errorf("failed to open RPM DB: %w", err)
64+
return nil, nil, xerrors.Errorf("failed to open RPM DB: %w", err)
6465
}
6566

6667
// equivalent:
6768
// new version: rpm -qa --qf "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{SOURCERPM} %{ARCH}\n"
6869
// old version: rpm -qa --qf "%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{SOURCERPM} %{ARCH}\n"
6970
pkgList, err := db.ListPackages()
7071
if err != nil {
71-
return nil, xerrors.Errorf("failed to list packages", err)
72+
return nil, nil, xerrors.Errorf("failed to list packages", err)
7273
}
7374

75+
var pkgs []types.Package
76+
var installedFiles []string
7477
for _, pkg := range pkgList {
7578
arch := pkg.Arch
7679
if arch == "" {
@@ -84,6 +87,11 @@ func (a rpmPkgAnalyzer) parsePkgInfo(packageBytes []byte) (pkgs []types.Package,
8487
srcName, srcVer, srcRel = splitFileName(pkg.SourceRpm)
8588
}
8689

90+
files, err := pkg.InstalledFiles()
91+
if err != nil {
92+
return nil, nil, xerrors.Errorf("unable to get installed files: %w", err)
93+
}
94+
8795
p := types.Package{
8896
Name: pkg.Name,
8997
Epoch: pkg.Epoch,
@@ -98,9 +106,10 @@ func (a rpmPkgAnalyzer) parsePkgInfo(packageBytes []byte) (pkgs []types.Package,
98106
License: pkg.License,
99107
}
100108
pkgs = append(pkgs, p)
109+
installedFiles = append(installedFiles, files...)
101110
}
102111

103-
return pkgs, nil
112+
return pkgs, installedFiles, nil
104113
}
105114

106115
// splitFileName returns a name, version, release, epoch, arch

analyzer/pkg/rpm/rpm_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ func TestParseRpmInfo(t *testing.T) {
584584
bytes, err := ioutil.ReadFile(tc.path)
585585
require.NoError(t, err)
586586

587-
pkgs, err := a.parsePkgInfo(bytes)
587+
pkgs, _, err := a.parsePkgInfo(bytes)
588588
require.NoError(t, err)
589589

590590
sort.Slice(tc.pkgs, func(i, j int) bool {

artifact/image/image.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ func (a Artifact) inspectLayer(ctx context.Context, diffID string) (types.BlobIn
229229
OS: result.OS,
230230
PackageInfos: result.PackageInfos,
231231
Applications: result.Applications,
232+
SystemFiles: result.SystemInstalledFiles,
232233
OpaqueDirs: opqDirs,
233234
WhiteoutFiles: whFiles,
234235
}

artifact/local/fs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
9999
PackageInfos: result.PackageInfos,
100100
Applications: result.Applications,
101101
Misconfigurations: misconfs,
102+
SystemFiles: result.SystemInstalledFiles,
102103
}
103104

104105
if err = a.hookManager.CallHooks(&blobInfo); err != nil {

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/go-git/go-git/v5 v5.4.2
1717
github.com/go-redis/redis/v8 v8.11.3
1818
github.com/golang-jwt/jwt v3.2.2+incompatible
19+
github.com/google/flatbuffers v1.12.1 // indirect
1920
github.com/google/go-containerregistry v0.6.0
2021
github.com/google/uuid v1.3.0 // indirect
2122
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -25,7 +26,7 @@ require (
2526
github.com/hashicorp/hcl/v2 v2.10.1 // indirect
2627
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
2728
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
28-
github.com/knqyf263/go-rpmdb v0.0.0-20201215100354-a9e3110d8ee1
29+
github.com/knqyf263/go-rpmdb v0.0.0-20210911072402-73bd0ce46c49
2930
github.com/knqyf263/nested v0.0.1
3031
github.com/kylelemons/godebug v1.1.0
3132
github.com/mitchellh/mapstructure v1.4.1

go.sum

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,9 @@ github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Z
650650
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
651651
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
652652
github.com/google/crfs v0.0.0-20191108021818-71d77da419c9/go.mod h1:etGhoOqfwPkooV6aqoX3eBGQOJblqdoc9XvWOeuxpPw=
653-
github.com/google/flatbuffers v1.12.0 h1:N8EguYFm2wwdpoNcpchQY0tPs85vOJkboFb2dPxmixo=
654653
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
654+
github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=
655+
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
655656
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
656657
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
657658
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -863,8 +864,8 @@ github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GX
863864
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8=
864865
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d h1:X4cedH4Kn3JPupAwwWuo4AzYp16P0OyLO9d7OnMZc/c=
865866
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d/go.mod h1:o8sgWoz3JADecfc/cTYD92/Et1yMqMy0utV1z+VaZao=
866-
github.com/knqyf263/go-rpmdb v0.0.0-20201215100354-a9e3110d8ee1 h1:sRDvjjWoHLWAxtPXBKYRJp8Ot4ugxYE/ZyADl3jzc1g=
867-
github.com/knqyf263/go-rpmdb v0.0.0-20201215100354-a9e3110d8ee1/go.mod h1:RDPNeIkU5NWXtt0OMEoILyxwUC/DyXeRtK295wpqSi0=
867+
github.com/knqyf263/go-rpmdb v0.0.0-20210911072402-73bd0ce46c49 h1:QazJZdFn/ApQh8OHepQiCKXGZ0QE08Bu8BnS10aHgvE=
868+
github.com/knqyf263/go-rpmdb v0.0.0-20210911072402-73bd0ce46c49/go.mod h1:RDPNeIkU5NWXtt0OMEoILyxwUC/DyXeRtK295wpqSi0=
868869
github.com/knqyf263/nested v0.0.1 h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc=
869870
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
870871
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

hook/all/import.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package all
22

33
import (
4+
_ "github.com/aquasecurity/fanal/hook/filter"
45
_ "github.com/aquasecurity/fanal/hook/nodejs"
56
_ "github.com/aquasecurity/fanal/hook/python"
67
_ "github.com/aquasecurity/fanal/hook/ruby"

0 commit comments

Comments
 (0)