diff --git a/pkg/config/types.go b/pkg/config/types.go index 9c5144698..b79a5a658 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -34,9 +34,10 @@ type Severity struct { // Policy struct defines policy specific configurations type Policy struct { - // policy local path - BasePath string `toml:"path,omitempty"` - RepoPath string `toml:"rego_subdir,omitempty"` + // policy local path, inside RepoPath where policies are at + BasePath string `toml:"rego_subdir,omitempty"` + // local filepath where repository containing policies is cached at + RepoPath string `toml:"path,omitempty"` // policy git url and branch RepoURL string `toml:"repo_url,omitempty"` diff --git a/pkg/initialize/run.go b/pkg/initialize/run.go index c0c6cfe2a..799abc1ac 100644 --- a/pkg/initialize/run.go +++ b/pkg/initialize/run.go @@ -20,48 +20,33 @@ import ( "fmt" "io/ioutil" "os" - "strings" "github.com/accurics/terrascan/pkg/config" "github.com/accurics/terrascan/pkg/utils" - "github.com/pkg/errors" "go.uber.org/zap" "gopkg.in/src-d/go-git.v4" gitConfig "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" ) -func validatePolicyConfigPaths(basePath, basePolicyPath string) error { - absoluteBasePath, err := utils.GetAbsPath(basePath) - if err != nil { - return errors.Errorf("invalid basePath %s, error : %v", basePath, err) - } - - absoluteBasePolicyPath, err := utils.GetAbsPath(basePolicyPath) - if err != nil { - return errors.Errorf("invalid basePolicyPath %s, error : %v", basePolicyPath, err) - } - - if !strings.HasPrefix(absoluteBasePolicyPath, absoluteBasePath) { - return errors.Errorf("policy path (%s) does not fall under base repo path's (%s) directory structure", absoluteBasePolicyPath, absoluteBasePath) - } - - return nil -} - // Run initializes terrascan if not done already func Run(isScanCmd bool) error { zap.S().Debug("initializing terrascan") - basePath := config.GetPolicyBasePath() - basePolicyPath := config.GetPolicyRepoPath() + var absoluteRepoPath, absolutePolicyPath string + var err error + policyPath := config.GetPolicyBasePath() + repoPath := config.GetPolicyRepoPath() - if err := validatePolicyConfigPaths(basePath, basePolicyPath); err != nil { + if absoluteRepoPath, absolutePolicyPath, err = utils.GetAbsPolicyConfigPaths(repoPath, policyPath); err != nil { return err } + config.Global.RepoPath = absoluteRepoPath + config.Global.BasePath = absolutePolicyPath + // check if policy paths exist - if path, err := os.Stat(basePolicyPath); err == nil && path.IsDir() { + if path, err := os.Stat(policyPath); err == nil && path.IsDir() { if isScanCmd { return nil } @@ -79,8 +64,8 @@ func Run(isScanCmd bool) error { // DownloadPolicies clones the policies to a local folder func DownloadPolicies() error { - basePath := config.GetPolicyBasePath() - basePolicyPath := config.GetPolicyRepoPath() + policyPath := config.GetPolicyBasePath() + repoPath := config.GetPolicyRepoPath() repoURL := config.GetPolicyRepoURL() branch := config.GetPolicyBranch() @@ -128,16 +113,16 @@ func DownloadPolicies() error { } // cleaning the existing cached policies at basePath - if err = os.RemoveAll(basePath); err != nil { - return fmt.Errorf("failed to clean up the directory '%s'. error: '%v'", basePath, err) + if err = os.RemoveAll(repoPath); err != nil { + return fmt.Errorf("failed to clean up the directory '%s'. error: '%v'", repoPath, err) } - zap.S().Debugf("base directory path : %s", basePath) - zap.S().Debugf("policy directory path : %s", basePolicyPath) + zap.S().Debugf("base directory path : %s", repoPath) + zap.S().Debugf("policy directory path : %s", policyPath) // move the freshly cloned repo from tempPath to basePath - if err = os.Rename(tempPath, basePath); err != nil { - return fmt.Errorf("failed to install policies to '%s'. error: '%v'", basePath, err) + if err = os.Rename(tempPath, repoPath); err != nil { + return fmt.Errorf("failed to install policies to '%s'. error: '%v'", repoPath, err) } return nil diff --git a/pkg/runtime/executor.go b/pkg/runtime/executor.go index f66742795..77e7a3c98 100644 --- a/pkg/runtime/executor.go +++ b/pkg/runtime/executor.go @@ -60,6 +60,11 @@ func NewExecutor(iacType, iacVersion string, cloudType []string, filePath, dirPa return nil, err } + if e.initPolicyPathsFromConfigFile(); err != nil { + zap.S().Error("error initialising policy configuration", zap.Error(err)) + + } + if len(scanRules) > 0 { e.scanRules = scanRules } diff --git a/pkg/runtime/policy.go b/pkg/runtime/policy.go new file mode 100644 index 000000000..36bc4a91c --- /dev/null +++ b/pkg/runtime/policy.go @@ -0,0 +1,36 @@ +package runtime + +import ( + "github.com/accurics/terrascan/pkg/config" + "github.com/accurics/terrascan/pkg/utils" + "go.uber.org/zap" +) + +// read the config file and update scan and skip rules +func (e *Executor) initPolicyPathsFromConfigFile() error { + if e.configFile == "" { + return nil + } + + configReader, err := config.NewTerrascanConfigReader(e.configFile) + if err != nil { + zap.S().Error("error loading config file", zap.Error(err)) + return err + } + + absoluteRepoPath, absolutePolicyPath, err := utils.GetAbsPolicyConfigPaths(config.GetPolicyRepoPath(), config.GetPolicyBasePath()) + if err != nil { + zap.S().Error("error processing provided policy paths", zap.Error(err)) + return err + } + + if len(configReader.GetPolicyConfig().RepoPath) > 0 { + config.Global.RepoPath = absoluteRepoPath + } + + if len(configReader.GetPolicyConfig().BasePath) > 0 { + config.Global.BasePath = absolutePolicyPath + } + + return nil +} diff --git a/pkg/runtime/validate.go b/pkg/runtime/validate.go index 0cbd1674e..99063b974 100644 --- a/pkg/runtime/validate.go +++ b/pkg/runtime/validate.go @@ -101,6 +101,12 @@ func (e *Executor) ValidateInputs() error { e.iacVersion = IacProvider.GetDefaultIacVersion(e.iacType) } + if len(e.policyPath) == 0 { + e.policyPath = policy.GetDefaultPolicyPaths(e.cloudType) + } + + zap.S().Debugf("using policy path %v", e.policyPath) + // check if IaC type is supported if !IacProvider.IsIacSupported(e.iacType, e.iacVersion) { zap.S().Errorf("iac type '%s', version '%s' not supported", e.iacType, e.iacVersion) @@ -116,10 +122,6 @@ func (e *Executor) ValidateInputs() error { } } zap.S().Debugf("cloud type '%s' is supported", strings.Join(e.cloudType, ",")) - if len(e.policyPath) == 0 { - e.policyPath = policy.GetDefaultPolicyPaths(e.cloudType) - } - zap.S().Debugf("using policy path %v", e.policyPath) if len(e.severity) > 0 && !utils.ValidateSeverityInput(e.severity) { return errSeverityNotSupported diff --git a/pkg/utils/policy.go b/pkg/utils/policy.go new file mode 100644 index 000000000..fd5dec81d --- /dev/null +++ b/pkg/utils/policy.go @@ -0,0 +1,32 @@ +package utils + +import ( + "path/filepath" + "strings" + + "github.com/pkg/errors" + "go.uber.org/zap" +) + +// GetAbsPolicyConfigPaths tranforms the provided policy repo path and base path into absolute paths +func GetAbsPolicyConfigPaths(repoPath, policyPath string) (string, string, error) { + absoluteRepoPath, err := GetAbsPath(repoPath) + if err != nil { + return repoPath, policyPath, errors.Errorf("invalid repository path `%s`, error : `%v`", repoPath, err) + } + + absolutePolicyPath, err := GetAbsPath(policyPath) + if err != nil { + return absoluteRepoPath, policyPath, errors.Errorf("invalid policyPath `%s`, error : `%v`", policyPath, err) + } + + if strings.HasPrefix(absolutePolicyPath, absoluteRepoPath) { + return absoluteRepoPath, absolutePolicyPath, nil + } + + zap.S().Debugf("policy path, `%s` ,does not fall under base repo path's `%s` directory structure", absolutePolicyPath, absoluteRepoPath) + zap.S().Debugf("appending policy path: `%s` to the repo path: `%s`. checking ...", policyPath, absoluteRepoPath) + + absolutePolicyPath = filepath.Join(absoluteRepoPath, policyPath) + return absoluteRepoPath, absolutePolicyPath, nil +}