Skip to content

Commit

Permalink
terrascan init and config refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Devang Gaur committed Mar 10, 2021
1 parent c61f306 commit 5b9f3fa
Show file tree
Hide file tree
Showing 17 changed files with 191 additions and 95 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ require (
github.com/zclconf/go-cty v1.7.1
go.uber.org/zap v1.16.0
golang.org/x/mod v0.4.1 // indirect
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
helm.sh/helm/v3 v3.4.0
honnef.co/go/tools v0.1.2 // indirect
honnef.co/go/tools v0.1.3 // indirect
sigs.k8s.io/kustomize/api v0.7.2
)
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,8 @@ golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b h1:lAZ0/chPUDWwjqosYR0X4M490zQhMsiJ4K3DbA7o+3g=
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down Expand Up @@ -1476,8 +1478,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.2 h1:SMdYLJl312RXuxXziCCHhRsp/tvct9cGKey0yv95tZM=
honnef.co/go/tools v0.1.2/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
honnef.co/go/tools v0.1.0 h1:AWNL1W1i7f0wNZ8VwOKNJ0sliKvOF/adn0EHenfUh+c=
honnef.co/go/tools v0.1.0/go.mod h1:XtegFAyX/PfluP4921rXU5IkjkqBCDnUq4W8VCIoKvM=
honnef.co/go/tools v0.1.1 h1:EVDuO03OCZwpV2t/tLLxPmPiomagMoBOgfPt0FM+4IY=
honnef.co/go/tools v0.1.1/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.19.0 h1:XyrFIJqTYZJ2DU7FBE/bSPz7b1HvbVBuBf07oeo6eTc=
k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw=
k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA=
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/color-console_windows.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build windows

/*
Copyright (C) 2020 Accurics, Inc.
Expand All @@ -14,8 +16,6 @@
limitations under the License.
*/

// +build windows

package cli

import (
Expand Down
18 changes: 17 additions & 1 deletion pkg/cli/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ import (
"github.com/accurics/terrascan/pkg/config"
"github.com/accurics/terrascan/pkg/logging"
"github.com/spf13/cobra"
"go.uber.org/zap"
)

const configEnvvarName = "TERRASCAN_CONFIG"

// RegisterCommand Registers a new command under the base command
func RegisterCommand(baseCommand *cobra.Command, command *cobra.Command) {
baseCommand.AddCommand(command)
Expand All @@ -43,8 +46,21 @@ func Execute() {
cobra.OnInitialize(func() {
// Set up the logger
logging.Init(LogType, LogLevel)

var configfile string
if len(ConfigFile) > 0 {
configfile = ConfigFile
}

if len(configfile) == 0 {
configfile = os.Getenv(configEnvvarName)
}

// Make sure we load the global config from the specified config file
config.LoadGlobalConfig(ConfigFile)
if err := config.LoadGlobalConfig(configfile); err != nil {
zap.S().Error("error while loading global config", zap.Error(err))
}

})

// parse the flags but hack around to avoid exiting with error code 2 on help
Expand Down
2 changes: 2 additions & 0 deletions pkg/cli/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"path/filepath"
"testing"

"github.com/accurics/terrascan/pkg/config"
"github.com/accurics/terrascan/pkg/iac-providers/output"
"github.com/accurics/terrascan/pkg/policy"
"github.com/accurics/terrascan/pkg/results"
Expand All @@ -38,6 +39,7 @@ func TestMain(m *testing.M) {
}

func setup() {
config.LoadGlobalConfig("")
// to download the policies for Run test
// downloads the policies at $HOME/.terrascan
initial(nil, nil, false)
Expand Down
4 changes: 2 additions & 2 deletions pkg/config/config-reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestNewTerrascanConfigReader(t *testing.T) {
},
}
testPolicy := Policy{
BasePath: "custom-path",
RepoPath: "rego-subdir",
RepoPath: "custom-path",
BasePath: "rego-subdir",
RepoURL: "https://repository/url",
Branch: "branch-name",
}
Expand Down
104 changes: 76 additions & 28 deletions pkg/config/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,87 +17,135 @@
package config

import (
"os"
"path/filepath"

"github.com/accurics/terrascan/pkg/utils"
"go.uber.org/zap"
)

const (
policyRepoURL = "https://github.com/accurics/terrascan.git"
policyBranch = "master"
configEnvvarName = "TERRASCAN_CONFIG"
policyConfigKey = "policy"
defaultPolicyRepoURL = "https://github.com/accurics/terrascan.git"
defaultPolicyBranch = "master"
)

var (
policyRepoPath = filepath.Join(utils.GetHomeDir(), ".terrascan")
policyBasePath = filepath.Join(policyRepoPath, "pkg", "policies", "opa", "rego")
defaultPolicyRepoPath = filepath.Join("pkg", "policies", "opa", "rego")
defaultBasePolicyPath = filepath.Join(utils.GetHomeDir(), ".terrascan")
)

func init() {
// If the user specifies a config file in TERRASCAN_CONFIG,
// overwrite the defaults with the values from that file.
// Retain the defaults for members not specified in the file.
if err := LoadGlobalConfig(os.Getenv(configEnvvarName)); err != nil {
zap.S().Error("error while loading global config", zap.Error(err))
}
}

// LoadGlobalConfig loads policy configuration from specified configFile
// into var Global.Policy. Members of Global.Policy that are not specified
// in configFile will get default values
func LoadGlobalConfig(configFile string) error {
// Start with the defaults
Global.Policy = Policy{
BasePath: policyBasePath,
RepoPath: policyRepoPath,
RepoURL: policyRepoURL,
Branch: policyBranch,
BasePath: defaultBasePolicyPath,
RepoPath: defaultPolicyRepoPath,
RepoURL: defaultPolicyRepoURL,
Branch: defaultPolicyBranch,
}

if configFile == "" {
zap.S().Debug("global config env variable is not specified")
return nil
zap.S().Debug("configFile is not specified for loading global config")
} else {
zap.S().Debugf("loading global config from: %s", configFile)
}

configReader, err := NewTerrascanConfigReader(configFile)
if err != nil {
return err
}

if len(configReader.GetPolicyConfig().BasePath) > 0 && len(configReader.GetPolicyConfig().RepoPath) == 0 {
zap.S().Warnf("policy base path specified in configfile %s, but rego_subdir path not specified.", configFile)
}

if len(configReader.GetPolicyConfig().RepoPath) > 0 && len(configReader.GetPolicyConfig().BasePath) == 0 {
zap.S().Warnf("policy rego_subdir specified in configfile %s, but base path not specified.", configFile)
}

if len(configReader.GetPolicyConfig().BasePath) > 0 {
Global.Policy.BasePath = configReader.GetPolicyConfig().BasePath
Global.BasePath = configReader.GetPolicyConfig().BasePath
}

if len(configReader.GetPolicyConfig().RepoPath) > 0 {
Global.Policy.RepoPath = configReader.GetPolicyConfig().RepoPath
Global.RepoPath = configReader.GetPolicyConfig().RepoPath
}

absolutePolicyBasePath, absolutePolicyRepoPath, err := utils.GetAbsPolicyConfigPaths(GetPolicyBasePath(), GetPolicyRepoPath())
if err != nil {
zap.S().Error("error processing provided policy paths", zap.Error(err))
return err
}

Global.Policy.BasePath = absolutePolicyBasePath
Global.Policy.RepoPath = absolutePolicyRepoPath

if len(configReader.GetPolicyConfig().RepoURL) > 0 {
Global.Policy.RepoURL = configReader.GetPolicyConfig().RepoURL
}
if len(configReader.GetPolicyConfig().Branch) > 0 {
Global.Policy.Branch = configReader.GetPolicyConfig().Branch
}

if len(configReader.GetRules().ScanRules) > 0 {
Global.Rules.ScanRules = configReader.GetRules().ScanRules
}

if len(configReader.GetRules().SkipRules) > 0 {
Global.Rules.SkipRules = configReader.GetRules().SkipRules
}

if len(configReader.GetSeverity().Level) > 0 {
Global.Severity.Level = configReader.GetSeverity().Level
}

// get config for 'notifications'
if len(configReader.GetNotifications()) > 0 {
Global.Notifications = configReader.GetNotifications()
}

zap.S().Debugf("global config loaded")

return nil
}

// GetPolicyBasePath returns policy base path as set in global config
// GetPolicyBasePath returns the configured policy base path
func GetPolicyBasePath() string {
return Global.Policy.BasePath
}

// GetPolicyRepoPath return path to the policies repo locally downloaded
// GetPolicyRepoPath return the configured path to the policies repo locally downloaded
func GetPolicyRepoPath() string {
return Global.Policy.RepoPath
}

// GetPolicyRepoURL returns policy repo url
// GetPolicyRepoURL returns the configured policy repo url
func GetPolicyRepoURL() string {
return Global.Policy.RepoURL
}

// GetPolicyBranch returns policy repo url
// GetPolicyBranch returns the configured policy repo url
func GetPolicyBranch() string {
return Global.Policy.Branch
}

// GetScanRules returns the configured scan rules
func GetScanRules() []string {
return Global.Rules.ScanRules
}

// GetSkipRules returns the configured skips rules
func GetSkipRules() []string {
return Global.Rules.SkipRules
}

// GetSeverityLevel returns the configured severity level
func GetSeverityLevel() string {
return Global.Severity.Level
}

// GetNotifications returns the configured notifier map
func GetNotifications() map[string]Notifier {
return Global.Notifications
}
20 changes: 10 additions & 10 deletions pkg/config/global_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,29 @@ func TestLoadGlobalConfig(t *testing.T) {
args: args{
configFile: "",
},
policyBasePath: policyBasePath,
policyRepoPath: policyRepoPath,
repoURL: policyRepoURL,
branchName: policyBranch,
policyBasePath: defaultBasePolicyPath,
policyRepoPath: defaultPolicyRepoPath,
repoURL: defaultPolicyRepoURL,
branchName: defaultPolicyBranch,
},
{
name: "global config file specified but doesn't exist",
args: args{
configFile: "test.toml",
},
wantErr: true,
policyBasePath: policyBasePath,
policyRepoPath: policyRepoPath,
repoURL: policyRepoURL,
branchName: policyBranch,
policyBasePath: defaultBasePolicyPath,
policyRepoPath: defaultPolicyRepoPath,
repoURL: defaultPolicyRepoURL,
branchName: defaultPolicyBranch,
},
{
name: "valid global config file specified",
args: args{
configFile: testConfigFile,
},
policyBasePath: "custom-path",
policyRepoPath: "rego-subdir",
policyBasePath: "rego-subdir",
policyRepoPath: "custom-path",
repoURL: "https://repository/url",
branchName: "branch-name",
},
Expand Down
3 changes: 2 additions & 1 deletion pkg/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ type Severity struct {

// Policy struct defines policy specific configurations
type Policy struct {
// policy local path
// policy local path, inside RepoPath where policies are at
BasePath string `toml:"path,omitempty"`
// local filepath where repository containing policies is cached at
RepoPath string `toml:"rego_subdir,omitempty"`

// policy git url and branch
Expand Down
27 changes: 15 additions & 12 deletions pkg/initialize/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,12 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing"
)

var (
basePath = config.GetPolicyRepoPath()
basePolicyPath = config.GetPolicyBasePath()
repoURL = config.GetPolicyRepoURL()
branch = config.GetPolicyBranch()
)

// Run initializes terrascan if not done already
func Run(isScanCmd bool) error {
zap.S().Debug("initializing terrascan")

// check if policy paths exist
if path, err := os.Stat(basePolicyPath); err == nil && path.IsDir() {
if path, err := os.Stat(config.GetPolicyRepoPath()); err == nil && path.IsDir() {
if isScanCmd {
return nil
}
Expand All @@ -57,6 +50,12 @@ func Run(isScanCmd bool) error {

// DownloadPolicies clones the policies to a local folder
func DownloadPolicies() error {

policyBasePath := config.GetPolicyBasePath()
policyRepoPath := config.GetPolicyRepoPath()
repoURL := config.GetPolicyRepoURL()
branch := config.GetPolicyBranch()

zap.S().Debug("downloading policies")

tempPath, err := ioutil.TempDir("", "terrascan-")
Expand All @@ -72,6 +71,7 @@ func DownloadPolicies() error {
r, err := git.PlainClone(tempPath, false, &git.CloneOptions{
URL: repoURL,
})

if err != nil {
return fmt.Errorf("failed to download policies. error: '%v'", err)
}
Expand Down Expand Up @@ -100,13 +100,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(policyBasePath); err != nil {
return fmt.Errorf("failed to clean up the directory '%s'. error: '%v'", policyBasePath, err)
}

zap.S().Debugf("base directory path : %s", policyBasePath)
zap.S().Debugf("policy directory path : %s", policyRepoPath)

// 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, policyBasePath); err != nil {
return fmt.Errorf("failed to install policies to '%s'. error: '%v'", policyBasePath, err)
}

return nil
Expand Down
Loading

0 comments on commit 5b9f3fa

Please sign in to comment.