Skip to content

ROX-12238: Add node analysis package #911

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

Merged
merged 3 commits into from
Sep 9, 2022
Merged
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
8 changes: 4 additions & 4 deletions cmd/clair/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/stackrox/rox/pkg/utils"
"github.com/stackrox/scanner/api"
"github.com/stackrox/scanner/database"
"github.com/stackrox/scanner/pkg/tarutil"
"github.com/stackrox/scanner/pkg/analyzer"
"github.com/stackrox/scanner/pkg/updater"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -64,9 +64,9 @@ func DefaultConfig() Config {
GRPCPort: 8443,
},
LogLevel: "info",
MaxExtractableFileSizeMB: tarutil.DefaultMaxExtractableFileSizeMB,
MaxELFExecutableFileSizeMB: tarutil.DefaultMaxELFExecutableFileSizeMB,
MaxImageFileReaderBufferSizeMB: tarutil.DefaultMaxLazyReaderBufferSizeMB,
MaxExtractableFileSizeMB: analyzer.DefaultMaxExtractableFileSizeMB,
MaxELFExecutableFileSizeMB: analyzer.DefaultMaxELFExecutableFileSizeMB,
MaxImageFileReaderBufferSizeMB: analyzer.DefaultMaxLazyReaderBufferSizeMB,
CentralEndpoint: "https://central.stackrox.svc",
SensorEndpoint: "https://sensor.stackrox.svc",
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/clair/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/stackrox/scanner/api"
"github.com/stackrox/scanner/pkg/tarutil"
"github.com/stackrox/scanner/pkg/analyzer"
"github.com/stretchr/testify/assert"
)

Expand All @@ -23,7 +23,7 @@ func TestLoadConfig(t *testing.T) {
}, cfg.API)

assert.Equal(t, 5*time.Minute, cfg.Updater.Interval)
assert.Equal(t, int64(tarutil.DefaultMaxExtractableFileSizeMB), cfg.MaxExtractableFileSizeMB)
assert.Equal(t, int64(analyzer.DefaultMaxExtractableFileSizeMB), cfg.MaxExtractableFileSizeMB)
assert.Equal(t, int64(400), cfg.MaxELFExecutableFileSizeMB)
assert.Equal(t, int64(150), cfg.MaxImageFileReaderBufferSizeMB)
assert.Equal(t, "https://central.stackrox.svc", cfg.CentralEndpoint)
Expand Down
8 changes: 4 additions & 4 deletions cmd/clair/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ import (
"github.com/stackrox/scanner/cpe/nvdtoolscache"
"github.com/stackrox/scanner/database"
k8scache "github.com/stackrox/scanner/k8s/cache"
"github.com/stackrox/scanner/pkg/analyzer"
"github.com/stackrox/scanner/pkg/clairify/metrics"
"github.com/stackrox/scanner/pkg/clairify/server"
"github.com/stackrox/scanner/pkg/env"
"github.com/stackrox/scanner/pkg/formatter"
"github.com/stackrox/scanner/pkg/ioutils"
"github.com/stackrox/scanner/pkg/repo2cpe"
"github.com/stackrox/scanner/pkg/tarutil"
"github.com/stackrox/scanner/pkg/updater"
"github.com/stackrox/scanner/pkg/version"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -227,19 +227,19 @@ func main() {

// Set the max extractable file size from the config.
if config.MaxExtractableFileSizeMB > 0 {
tarutil.SetMaxExtractableFileSize(config.MaxExtractableFileSizeMB * 1024 * 1024)
analyzer.SetMaxExtractableFileSize(config.MaxExtractableFileSizeMB * 1024 * 1024)
log.Infof("Max extractable file size set to %d MB", config.MaxExtractableFileSizeMB)
}

// Set the max ELF executable file size from the config.
if config.MaxELFExecutableFileSizeMB > 0 {
tarutil.SetMaxELFExecutableFileSize(config.MaxELFExecutableFileSizeMB * 1024 * 1024)
analyzer.SetMaxELFExecutableFileSize(config.MaxELFExecutableFileSizeMB * 1024 * 1024)
log.Infof("Max ELF executable file size set to %d MB", config.MaxELFExecutableFileSizeMB)
}

// Set the max lazy reader buffer size from the config.
if config.MaxImageFileReaderBufferSizeMB > 0 {
tarutil.SetMaxLazyReaderBufferSize(config.MaxImageFileReaderBufferSizeMB * 1024 * 1024)
analyzer.SetMaxLazyReaderBufferSize(config.MaxImageFileReaderBufferSizeMB * 1024 * 1024)
log.Infof("Max image file reader buffer size set to %d MB", config.MaxImageFileReaderBufferSizeMB)
}

Expand Down
5 changes: 3 additions & 2 deletions localdev/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/stackrox/scanner/cpe/nvdtoolscache"
"github.com/stackrox/scanner/database"
"github.com/stackrox/scanner/ext/imagefmt"
"github.com/stackrox/scanner/pkg/analyzer"
"github.com/stackrox/scanner/pkg/component"
"github.com/stackrox/scanner/pkg/tarutil"
"github.com/stackrox/scanner/singletons/requiredfilenames"
Expand Down Expand Up @@ -78,8 +79,8 @@ func analyzeLocalImage(path string) {

// Extract
var matcher manifestMatcher
tarutil.SetMaxExtractableFileSize(1024 * 1024 * 1024)
tarutil.SetMaxELFExecutableFileSize(1024 * 1024 * 1024)
analyzer.SetMaxExtractableFileSize(1024 * 1024 * 1024)
analyzer.SetMaxELFExecutableFileSize(1024 * 1024 * 1024)
filemap, err := tarutil.ExtractFiles(f, &matcher)
if err != nil {
panic(err)
Expand Down
67 changes: 65 additions & 2 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,79 @@ import (
"github.com/stackrox/scanner/pkg/elf"
)

const (
// DefaultMaxELFExecutableFileSizeMB is the default value for the max ELF executable file we analyze.
DefaultMaxELFExecutableFileSizeMB = 800

// DefaultMaxLazyReaderBufferSizeMB is the default maximum lazy reader buffer size. Any file data beyond this
// limit is backed by temporary files on disk.
DefaultMaxLazyReaderBufferSizeMB = 100

// DefaultMaxExtractableFileSizeMB is the default value for the max extractable file size.
DefaultMaxExtractableFileSizeMB = 200

// ElfHeaderSize is the size of an ELF header based on https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html.
ElfHeaderSize = 16
)

var (
maxExtractableFileSize int64 = DefaultMaxExtractableFileSizeMB * 1024 * 1024
maxELFExecutableFileSize int64 = DefaultMaxELFExecutableFileSizeMB * 1024 * 1024
maxLazyReaderBufferSize int64 = DefaultMaxLazyReaderBufferSizeMB * 1024 * 1024
)

// SetMaxExtractableFileSize sets the max extractable file size. It is NOT
// thread-safe, and callers must ensure that it is called only when no scans are
// in progress (ex: during initialization). See comments on the
// maxExtractableFileSize variable for more details on its purpose.
func SetMaxExtractableFileSize(val int64) {
maxExtractableFileSize = val
}

// GetMaxExtractableFileSize returns the maximum size of a single file within a
// tarball that will be extracted. This protects against malicious files that may
// be used in an attempt to perform a Denial of Service attack.
func GetMaxExtractableFileSize() int64 {
return maxExtractableFileSize
}

// GetMaxLazyReaderBufferSize returns the maximum lazy reader buffer size. Any
// file data beyond this limit is backed by temporary files on disk.
func GetMaxLazyReaderBufferSize() int64 {
return maxLazyReaderBufferSize
}

// SetMaxLazyReaderBufferSize sets the max lazy reader buffer size. It is NOT
// thread-safe, and callers must ensure that it is called only when no scans are
// in progress (ex: during initialization). See comments on the
// maxLazyReaderBufferSize variable for more details on its purpose.
func SetMaxLazyReaderBufferSize(val int64) {
maxLazyReaderBufferSize = val
}

// GetMaxELFExecutableFileSize returns the maximum size of an ELF executable file
// tarball that will be analyzed.
func GetMaxELFExecutableFileSize() int64 {
return maxELFExecutableFileSize
}

// SetMaxELFExecutableFileSize sets the max ELF executable file size. It is NOT
// thread-safe, and callers must ensure that it is called only when no scans are
// in progress (ex: during initialization). See comments on the
// maxELFExecutableFileSize variable for more details on its purpose.
func SetMaxELFExecutableFileSize(val int64) {
maxELFExecutableFileSize = val
}

// Analyzer defines the functions for analyzing images and extracting the components present in them.
type Analyzer interface {
ProcessFile(filePath string, fi os.FileInfo, contents io.ReaderAt) []*component.Component
}

// Files stores information on a sub-set of files being analyzed from an image.
// Files stores information on a sub-set of files being analyzed.
// It provides methods to retrieve information from individual files, or list
// them based on some prefix.
type Files interface {

// Get returns the data about a file if it exists, otherwise set exists to false.
Get(path string) (data FileData, exists bool)

Expand Down
6 changes: 4 additions & 2 deletions pkg/analyzer/analyzertest/fake_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ type FakeFile interface {
}

// NewFakeFile creates a new fake file from the given path and contents.
func NewFakeFile(fullPath string, contents []byte) FakeFile {
func NewFakeFile(fullPath string, contents []byte, mode os.FileMode) FakeFile {
return fakeFile{
fullPath: fullPath,
contents: contents,
mode: mode,
}
}

type fakeFile struct {
fullPath string
contents []byte
mode os.FileMode
}

func (f fakeFile) FullPath() string {
Expand All @@ -45,7 +47,7 @@ func (f fakeFile) Name() string {
}

func (f fakeFile) Mode() os.FileMode {
return 0644
return f.mode
}

func (f fakeFile) IsDir() bool {
Expand Down
2 changes: 1 addition & 1 deletion pkg/analyzer/gem/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func TestMatching(t *testing.T) {
a := Analyzer()
f := analyzertest.NewFakeFile("usr/local/bundle/specifications/rails-4.2.5.1.gemspec", []byte(validRailsSpec))
f := analyzertest.NewFakeFile("usr/local/bundle/specifications/rails-4.2.5.1.gemspec", []byte(validRailsSpec), 0644)
cs := a.ProcessFile(f.FullPath(), f.FileInfo(), f.Contents())
assert.Len(t, cs, 1)
}
Loading