Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial commit * update * add apk analyzer * add dpkg analyzer * Analyze docker image * Update README * Pull image * Support private registry and use cache * fix test * fix for merge * add rpm analyzer * add tmp gcr * Add test * fix tmp : fix gcr bug on reg package * fetch gcr container from credential * use no auth docker token * update alpine os analyzer * continue package if no files found * ignore vendor * check OS * add soft link file path * Add rpm * update comment * Support library * Add rpm analyzer without rpm command
- Loading branch information
Showing
52 changed files
with
5,630 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,7 @@ | |
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
.idea | ||
main | ||
|
||
vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
language: go | ||
|
||
go: | ||
- "1.12" | ||
before_install: | ||
- go get github.com/mattn/goveralls | ||
- go get golang.org/x/tools/cmd/cover | ||
script: | ||
- env GO111MODULE=on go test -v -covermode=count -coverprofile=coverage.out ./... | ||
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN | ||
addons: | ||
apt: | ||
packages: | ||
- rpm | ||
- libdb-dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export GO111MODULE=on | ||
|
||
.PHONY: deps | ||
deps: | ||
go get -d | ||
|
||
.PHONY: devel-deps | ||
devel-deps: deps | ||
GO111MODULE=off go get \ | ||
golang.org/x/lint/golint \ | ||
github.com/mattn/goveralls | ||
|
||
.PHONY: test | ||
test: deps | ||
go test ./... | ||
|
||
.PHONY: lint | ||
lint: devel-deps | ||
go vet ./... | ||
golint -set_exit_status | ||
|
||
.PHONY: cover | ||
cover: devel-deps | ||
goveralls | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
# fanal | ||
Static Analysis Library for Containers | ||
|
||
[![GoDoc](https://godoc.org/github.com/knqyf263/fanal?status.svg)](https://godoc.org/github.com/knqyf263/fanal) | ||
[![Build Status](https://travis-ci.org/knqyf263/fanal.svg?branch=master)](https://travis-ci.org/knqyf263/fanal) | ||
[![Coverage Status](https://coveralls.io/repos/github/knqyf263/fanal/badge.svg?branch=master)](https://coveralls.io/github/knqyf263/fanal?branch=master) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/knqyf263/fanal)](https://goreportcard.com/report/github.com/knqyf263/fanal) | ||
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/knqyf263/fanal/blob/master/LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package analyzer | ||
|
||
import ( | ||
"context" | ||
"io" | ||
"time" | ||
|
||
"golang.org/x/xerrors" | ||
|
||
"github.com/knqyf263/fanal/extractor" | ||
"github.com/knqyf263/go-dep-parser/pkg/types" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
var ( | ||
osAnalyzers []OSAnalyzer | ||
pkgAnalyzers []PkgAnalyzer | ||
libAnalyzers []LibraryAnalyzer | ||
|
||
// ErrUnknownOS occurs when unknown OS is analyzed. | ||
ErrUnknownOS = errors.New("Unknown OS") | ||
// ErrPkgAnalysis occurs when the analysis of packages is failed. | ||
ErrPkgAnalysis = errors.New("Failed to analyze packages") | ||
) | ||
|
||
type OSAnalyzer interface { | ||
Analyze(extractor.FileMap) (OS, error) | ||
RequiredFiles() []string | ||
} | ||
|
||
type PkgAnalyzer interface { | ||
Analyze(extractor.FileMap) ([]Package, error) | ||
RequiredFiles() []string | ||
} | ||
|
||
type FilePath string | ||
|
||
type LibraryAnalyzer interface { | ||
Analyze(extractor.FileMap) (map[FilePath][]types.Library, error) | ||
RequiredFiles() []string | ||
} | ||
|
||
type OS struct { | ||
Name string | ||
Family string | ||
} | ||
|
||
type Package struct { | ||
Name string | ||
Version string | ||
Release string | ||
Epoch int | ||
Type string | ||
} | ||
|
||
var ( | ||
TypeBinary = "binary" | ||
TypeSource = "source" | ||
) | ||
|
||
type SrcPackage struct { | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
BinaryNames []string `json:"binaryNames"` | ||
} | ||
|
||
func RegisterOSAnalyzer(analyzer OSAnalyzer) { | ||
osAnalyzers = append(osAnalyzers, analyzer) | ||
} | ||
|
||
func RegisterPkgAnalyzer(analyzer PkgAnalyzer) { | ||
pkgAnalyzers = append(pkgAnalyzers, analyzer) | ||
} | ||
|
||
func RegisterLibraryAnalyzer(analyzer LibraryAnalyzer) { | ||
libAnalyzers = append(libAnalyzers, analyzer) | ||
} | ||
|
||
func RequiredFilenames() []string { | ||
filenames := []string{} | ||
for _, analyzer := range osAnalyzers { | ||
filenames = append(filenames, analyzer.RequiredFiles()...) | ||
} | ||
for _, analyzer := range pkgAnalyzers { | ||
filenames = append(filenames, analyzer.RequiredFiles()...) | ||
} | ||
for _, analyzer := range libAnalyzers { | ||
filenames = append(filenames, analyzer.RequiredFiles()...) | ||
} | ||
return filenames | ||
} | ||
|
||
func Analyze(ctx context.Context, imageName string) (filesMap extractor.FileMap, err error) { | ||
e := extractor.NewDockerExtractor(extractor.DockerOption{Timeout: 600 * time.Second}) | ||
filesMap, err = e.Extract(ctx, imageName, RequiredFilenames()) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Failed to extract files") | ||
} | ||
return filesMap, nil | ||
} | ||
|
||
func AnalyzeFromFile(ctx context.Context, r io.ReadCloser) (filesMap extractor.FileMap, err error) { | ||
e := extractor.NewDockerExtractor(extractor.DockerOption{}) | ||
filesMap, err = e.ExtractFromFile(ctx, r, RequiredFilenames()) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Failed to extract files") | ||
} | ||
return filesMap, nil | ||
} | ||
|
||
func GetOS(filesMap extractor.FileMap) (OS, error) { | ||
for _, analyzer := range osAnalyzers { | ||
os, err := analyzer.Analyze(filesMap) | ||
if err != nil { | ||
continue | ||
} | ||
return os, nil | ||
} | ||
return OS{}, ErrUnknownOS | ||
|
||
} | ||
|
||
func GetPackages(filesMap extractor.FileMap) ([]Package, error) { | ||
for _, analyzer := range pkgAnalyzers { | ||
pkgs, err := analyzer.Analyze(filesMap) | ||
if err != nil { | ||
continue | ||
} | ||
return pkgs, nil | ||
} | ||
return nil, ErrUnknownOS | ||
} | ||
|
||
func CheckPackage(pkg *Package) bool { | ||
return pkg.Name != "" && pkg.Version != "" | ||
} | ||
|
||
func GetLibraries(filesMap extractor.FileMap) (map[FilePath][]types.Library, error) { | ||
results := map[FilePath][]types.Library{} | ||
for _, analyzer := range libAnalyzers { | ||
libMap, err := analyzer.Analyze(filesMap) | ||
if err != nil { | ||
return nil, xerrors.Errorf("failed to analyze libraries: %w", err) | ||
} | ||
|
||
for filePath, libs := range libMap { | ||
results[filePath] = libs | ||
} | ||
} | ||
return results, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package bundler | ||
|
||
import ( | ||
"bytes" | ||
"path/filepath" | ||
|
||
"github.com/knqyf263/fanal/analyzer" | ||
"github.com/knqyf263/fanal/extractor" | ||
"github.com/knqyf263/fanal/utils" | ||
"github.com/knqyf263/go-dep-parser/pkg/bundler" | ||
"github.com/knqyf263/go-dep-parser/pkg/types" | ||
"golang.org/x/xerrors" | ||
) | ||
|
||
func init() { | ||
analyzer.RegisterLibraryAnalyzer(&bundlerLibraryAnalyzer{}) | ||
} | ||
|
||
type bundlerLibraryAnalyzer struct{} | ||
|
||
func (a bundlerLibraryAnalyzer) Analyze(fileMap extractor.FileMap) (map[analyzer.FilePath][]types.Library, error) { | ||
libMap := map[analyzer.FilePath][]types.Library{} | ||
requiredFiles := a.RequiredFiles() | ||
|
||
for filename, content := range fileMap { | ||
basename := filepath.Base(filename) | ||
if !utils.StringInSlice(basename, requiredFiles) { | ||
continue | ||
} | ||
|
||
r := bytes.NewBuffer(content) | ||
libs, err := bundler.Parse(r) | ||
if err != nil { | ||
return nil, xerrors.Errorf("invalid Gemfile.lock format: %w", err) | ||
} | ||
libMap[analyzer.FilePath(filename)] = libs | ||
} | ||
return libMap, nil | ||
} | ||
|
||
func (a bundlerLibraryAnalyzer) RequiredFiles() []string { | ||
return []string{"Gemfile.lock"} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package composer | ||
|
||
import ( | ||
"bytes" | ||
"path/filepath" | ||
|
||
"github.com/knqyf263/fanal/analyzer" | ||
"github.com/knqyf263/fanal/extractor" | ||
"github.com/knqyf263/fanal/utils" | ||
"github.com/knqyf263/go-dep-parser/pkg/composer" | ||
"github.com/knqyf263/go-dep-parser/pkg/types" | ||
"golang.org/x/xerrors" | ||
) | ||
|
||
func init() { | ||
analyzer.RegisterLibraryAnalyzer(&composerLibraryAnalyzer{}) | ||
} | ||
|
||
type composerLibraryAnalyzer struct{} | ||
|
||
func (a composerLibraryAnalyzer) Analyze(fileMap extractor.FileMap) (map[analyzer.FilePath][]types.Library, error) { | ||
libMap := map[analyzer.FilePath][]types.Library{} | ||
requiredFiles := a.RequiredFiles() | ||
|
||
for filename, content := range fileMap { | ||
basename := filepath.Base(filename) | ||
if !utils.StringInSlice(basename, requiredFiles) { | ||
continue | ||
} | ||
|
||
r := bytes.NewBuffer(content) | ||
libs, err := composer.Parse(r) | ||
if err != nil { | ||
return nil, xerrors.Errorf("invalid composer.lock format: %w", err) | ||
} | ||
libMap[analyzer.FilePath(filename)] = libs | ||
} | ||
return libMap, nil | ||
} | ||
|
||
func (a composerLibraryAnalyzer) RequiredFiles() []string { | ||
return []string{"composer.lock"} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package npm | ||
|
||
import ( | ||
"bytes" | ||
"path/filepath" | ||
|
||
"github.com/knqyf263/fanal/analyzer" | ||
"github.com/knqyf263/fanal/extractor" | ||
"github.com/knqyf263/fanal/utils" | ||
"github.com/knqyf263/go-dep-parser/pkg/npm" | ||
"github.com/knqyf263/go-dep-parser/pkg/types" | ||
"golang.org/x/xerrors" | ||
) | ||
|
||
func init() { | ||
analyzer.RegisterLibraryAnalyzer(&npmLibraryAnalyzer{}) | ||
} | ||
|
||
type npmLibraryAnalyzer struct{} | ||
|
||
func (a npmLibraryAnalyzer) Analyze(fileMap extractor.FileMap) (map[analyzer.FilePath][]types.Library, error) { | ||
libMap := map[analyzer.FilePath][]types.Library{} | ||
requiredFiles := a.RequiredFiles() | ||
|
||
for filename, content := range fileMap { | ||
basename := filepath.Base(filename) | ||
if !utils.StringInSlice(basename, requiredFiles) { | ||
continue | ||
} | ||
|
||
r := bytes.NewBuffer(content) | ||
libs, err := npm.Parse(r) | ||
if err != nil { | ||
return nil, xerrors.Errorf("invalid package-lock.json format: %w", err) | ||
} | ||
libMap[analyzer.FilePath(filename)] = libs | ||
} | ||
return libMap, nil | ||
} | ||
|
||
func (a npmLibraryAnalyzer) RequiredFiles() []string { | ||
return []string{"package-lock.json"} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package pipenv | ||
|
||
import ( | ||
"bytes" | ||
"path/filepath" | ||
|
||
"github.com/knqyf263/fanal/analyzer" | ||
"github.com/knqyf263/fanal/extractor" | ||
"github.com/knqyf263/fanal/utils" | ||
"github.com/knqyf263/go-dep-parser/pkg/pipenv" | ||
"github.com/knqyf263/go-dep-parser/pkg/types" | ||
"golang.org/x/xerrors" | ||
) | ||
|
||
func init() { | ||
analyzer.RegisterLibraryAnalyzer(&pipenvLibraryAnalyzer{}) | ||
} | ||
|
||
type pipenvLibraryAnalyzer struct{} | ||
|
||
func (a pipenvLibraryAnalyzer) Analyze(fileMap extractor.FileMap) (map[analyzer.FilePath][]types.Library, error) { | ||
libMap := map[analyzer.FilePath][]types.Library{} | ||
requiredFiles := a.RequiredFiles() | ||
|
||
for filename, content := range fileMap { | ||
basename := filepath.Base(filename) | ||
if !utils.StringInSlice(basename, requiredFiles) { | ||
continue | ||
} | ||
|
||
r := bytes.NewBuffer(content) | ||
libs, err := pipenv.Parse(r) | ||
if err != nil { | ||
return nil, xerrors.Errorf("invalid Pipfile.lock format: %w", err) | ||
} | ||
libMap[analyzer.FilePath(filename)] = libs | ||
} | ||
return libMap, nil | ||
} | ||
|
||
func (a pipenvLibraryAnalyzer) RequiredFiles() []string { | ||
return []string{"Pipfile.lock"} | ||
} |
Oops, something went wrong.