From fb684e06af42ab6fb4c2b6119428ae822e83d1a1 Mon Sep 17 00:00:00 2001 From: Suvarna Rokade Date: Tue, 22 Jun 2021 20:12:02 +0530 Subject: [PATCH] code nits: code refactor for reusability --- pkg/iac-providers/docker/v1/load-dir.go | 61 ++++-------------------- pkg/iac-providers/docker/v1/load-file.go | 45 +++++++++++++++-- pkg/iac-providers/docker/v1/parser.go | 2 +- pkg/iac-providers/docker/v1/types.go | 3 ++ 4 files changed, 53 insertions(+), 58 deletions(-) diff --git a/pkg/iac-providers/docker/v1/load-dir.go b/pkg/iac-providers/docker/v1/load-dir.go index 29865b118..f653b6dd3 100644 --- a/pkg/iac-providers/docker/v1/load-dir.go +++ b/pkg/iac-providers/docker/v1/load-dir.go @@ -17,11 +17,8 @@ package dockerv1 import ( - "crypto/md5" - "encoding/hex" "fmt" "path/filepath" - "strings" "github.com/accurics/terrascan/pkg/iac-providers/output" "github.com/accurics/terrascan/pkg/results" @@ -30,14 +27,13 @@ import ( "go.uber.org/zap" ) -const ( - dockerDirectory string = "docker" - resourceTypeDockerfile string = "dockerfile" -) - // LoadIacDir loads the docker file specified in given folder. func (dc *DockerV1) LoadIacDir(absRootDir string, nonRecursive bool) (output.AllResourceConfigs, error) { + // set the root directory being scanned + dc.absRootDir = absRootDir + allResourcesConfig := make(map[string][]output.ResourceConfig) + fileMap, err := utils.FindFilesBySuffix(absRootDir, []string{DockerFileName}) if err != nil { zap.S().Errorf("error while searching for iac files", zap.String("root dir", absRootDir), zap.Error(err)) @@ -47,61 +43,20 @@ func (dc *DockerV1) LoadIacDir(absRootDir string, nonRecursive bool) (output.All for fileDir, files := range fileMap { for i := range files { file := filepath.Join(fileDir, *files[i]) - data, comments, err := dc.Parse(file) - if err != nil { + var configData output.AllResourceConfigs + if configData, err = dc.LoadIacFile(file); err != nil { errMsg := fmt.Sprintf("error while parsing file %s", file) zap.S().Errorf("error while searching for iac files", zap.String("root dir", absRootDir), errMsg) dc.errIacLoadDirs = multierror.Append(dc.errIacLoadDirs, results.DirScanErr{IacType: "docker", Directory: absRootDir, ErrMessage: errMsg}) continue } - minSeverity, maxSeverity := utils.GetMinMaxSeverity(comments) - sourcePath := file - sourcePath, err = filepath.Rel(absRootDir, file) - if err != nil { - zap.S().Debug("error while getting the relative path for", zap.String("IAC file", file), zap.Error(err)) - } - skipRules := utils.GetSkipRules(comments) - dockerCommand := []string{} - for j := 0; j < len(data); j++ { - dockerCommand = append(dockerCommand, data[j].Cmd) - config := output.ResourceConfig{ - Name: *files[i], - Type: data[j].Cmd, - Line: data[j].Line, - ID: data[j].Cmd + "." + GetresourceIdforDockerfile(file, data[j].Value), - Source: sourcePath, - Config: data[j].Value, - SkipRules: skipRules, - MinSeverity: minSeverity, - MaxSeverity: maxSeverity, - } - allResourcesConfig[data[j].Cmd] = append(allResourcesConfig[data[j].Cmd], config) - - } - config := output.ResourceConfig{ - Name: *files[i], - Type: resourceTypeDockerfile, - Line: 1, - ID: dockerDirectory + "." + GetresourceIdforDockerfile(file, ""), - Source: sourcePath, - Config: dockerCommand, - SkipRules: skipRules, - MinSeverity: minSeverity, - MaxSeverity: maxSeverity, + for key := range configData { + allResourcesConfig[key] = append(allResourcesConfig[key], configData[key]...) } - allResourcesConfig[dockerDirectory] = append(allResourcesConfig[dockerDirectory], config) } } return allResourcesConfig, dc.errIacLoadDirs } - -// GetresourceIdforDockerfile Generates hash of the string to be used as the reference id for docker file -func GetresourceIdforDockerfile(filepath string, value string) (referenceID string) { - hasher := md5.New() - hasher.Write([]byte(filepath + value)) - referenceID = strings.ToLower(hex.EncodeToString(hasher.Sum(nil))) - return -} diff --git a/pkg/iac-providers/docker/v1/load-file.go b/pkg/iac-providers/docker/v1/load-file.go index ddc2893b5..0cd89efe7 100644 --- a/pkg/iac-providers/docker/v1/load-file.go +++ b/pkg/iac-providers/docker/v1/load-file.go @@ -17,15 +17,26 @@ package dockerv1 import ( + "crypto/md5" + "encoding/hex" "errors" "fmt" "path/filepath" + "strconv" + "strings" "github.com/accurics/terrascan/pkg/iac-providers/output" "github.com/accurics/terrascan/pkg/utils" "go.uber.org/zap" ) +const ( + dockerDirectory string = "docker" + resourceTypeDockerfile string = "dockerfile" + // IDConnectorString is string connector used in id creation + IDConnectorString string = "." +) + // LoadIacFile loads the docker file specified func (dc *DockerV1) LoadIacFile(absFilePath string) (allResourcesConfig output.AllResourceConfigs, err error) { allResourcesConfig = make(map[string][]output.ResourceConfig) @@ -45,8 +56,8 @@ func (dc *DockerV1) LoadIacFile(absFilePath string) (allResourcesConfig output.A Name: filepath.Base(absFilePath), Type: data[i].Cmd, Line: data[i].Line, - ID: data[i].Cmd + "." + GetresourceIdforDockerfile(absFilePath, data[i].Value), - Source: filepath.Base(absFilePath), + ID: data[i].Cmd + IDConnectorString + GetresourceIdforDockerfile(absFilePath, data[i].Value, data[i].Line), + Source: dc.getSourceRelativePath(absFilePath), Config: data[i].Value, SkipRules: skipRules, MinSeverity: minSeverity, @@ -55,18 +66,44 @@ func (dc *DockerV1) LoadIacFile(absFilePath string) (allResourcesConfig output.A allResourcesConfig[data[i].Cmd] = append(allResourcesConfig[data[i].Cmd], config) } + + // creates config for entire dockerfile config := output.ResourceConfig{ Name: filepath.Base(absFilePath), Type: resourceTypeDockerfile, Line: 1, - ID: dockerDirectory + "." + GetresourceIdforDockerfile(absFilePath, ""), - Source: filepath.Base(absFilePath), + ID: dockerDirectory + IDConnectorString + GetresourceIdforDockerfile(absFilePath, "", 1), + Source: dc.getSourceRelativePath(absFilePath), Config: dockerCommand, SkipRules: skipRules, MinSeverity: minSeverity, MaxSeverity: maxSeverity, } + allResourcesConfig[dockerDirectory] = append(allResourcesConfig[dockerDirectory], config) return allResourcesConfig, nil } + +// getSourceRelativePath fetches the relative path of file being loaded +func (dc *DockerV1) getSourceRelativePath(sourceFile string) string { + + // rootDir should be empty when file scan was initiated by user + if dc.absRootDir == "" { + return filepath.Base(sourceFile) + } + relPath, err := filepath.Rel(dc.absRootDir, sourceFile) + if err != nil { + zap.S().Debug("error while getting the relative path for", zap.String("IAC file", sourceFile), zap.Error(err)) + return sourceFile + } + return relPath +} + +// GetresourceIdforDockerfile Generates hash of the string to be used as the reference id for docker file +func GetresourceIdforDockerfile(filepath string, value string, lineNumber int) (referenceID string) { + hasher := md5.New() + hasher.Write([]byte(filepath + value + strconv.Itoa(lineNumber))) + referenceID = strings.ToLower(hex.EncodeToString(hasher.Sum(nil))) + return +} diff --git a/pkg/iac-providers/docker/v1/parser.go b/pkg/iac-providers/docker/v1/parser.go index 8947eba23..677b23bde 100644 --- a/pkg/iac-providers/docker/v1/parser.go +++ b/pkg/iac-providers/docker/v1/parser.go @@ -48,8 +48,8 @@ func (dc *DockerV1) ValidateInstruction(node *parser.Node) error { // Parse parses the given dockerfile and gives docker config. func (dc *DockerV1) Parse(filepath string) ([]ResourceConfig, string, error) { config := []ResourceConfig{} - data, err := ioutil.ReadFile(filepath) comments := "" + data, err := ioutil.ReadFile(filepath) if err != nil { zap.S().Error("error loading docker file", filepath, zap.Error(err)) return []ResourceConfig{}, "", err diff --git a/pkg/iac-providers/docker/v1/types.go b/pkg/iac-providers/docker/v1/types.go index c9b1abf24..2f9dce669 100644 --- a/pkg/iac-providers/docker/v1/types.go +++ b/pkg/iac-providers/docker/v1/types.go @@ -21,6 +21,9 @@ import "github.com/hashicorp/go-multierror" // DockerV1 truct implements the IacProvider interface type DockerV1 struct { errIacLoadDirs *multierror.Error + // absRootDir is the root directory being scanned. + // if a file scan was initiated, absRootDir should be empty. + absRootDir string } const (