Skip to content

Commit

Permalink
add support for YAML format for terrascan config file (#816)
Browse files Browse the repository at this point in the history
  • Loading branch information
kanchwala-yusuf committed May 28, 2021
1 parent 23bb0ae commit afc2a18
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 21 deletions.
2 changes: 2 additions & 0 deletions config/terrascan.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# notifications configuration
[notifications]
[notifications.webhook]
type = "webhook"
[notifications.webhook.config]
url = "https://httpbin.org/post"

# scan and skip rules configuration
Expand Down
16 changes: 16 additions & 0 deletions config/terrascan.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
notifications:
webhook:
type: webhook
config:
url: 'https://httpbin.org/post'
webhook1:
type: webhook
config:
url: 'https://httpbin.org/post'
rules:
scan-rules:
- AWS.S3Bucket.DS.High.1043
- AWS.S3Bucket.IAM.High.0370
skip-rules:
- AWS.S3Bucket.DS.High.1043
- AWS.S3Bucket.IAM.High.0370
22 changes: 21 additions & 1 deletion pkg/config/config-reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"

"github.com/pelletier/go-toml"
"go.uber.org/zap"
"gopkg.in/yaml.v3"
)

const (
tomlExtension = ".toml"
yamlExtension1 = ".yaml"
yamlExtension2 = ".yml"
)

var (
Expand Down Expand Up @@ -62,9 +70,21 @@ func NewTerrascanConfigReader(fileName string) (*TerrascanConfigReader, error) {
return configReader, ErrTomlLoadConfig
}

if err = toml.Unmarshal(data, &configReader.config); err != nil {
// check the extension of the file and decode using the file contents
// using the relevant package
switch filepath.Ext(fileName) {
case tomlExtension:
err = toml.Unmarshal(data, &configReader.config)
case yamlExtension1, yamlExtension2:
err = yaml.Unmarshal(data, &configReader.config)
default:
err = fmt.Errorf("file format %q not support for terrascan config file",
filepath.Ext(fileName))
}
if err != nil {
return configReader, err
}

return configReader, nil
}

Expand Down
89 changes: 89 additions & 0 deletions pkg/config/config-reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ func TestNewTerrascanConfigReader(t *testing.T) {
wantErr: true,
want: &TerrascanConfigReader{},
},
{
name: "invalid config file format",
args: args{
fileName: "test.invalid",
},
wantErr: true,
want: &TerrascanConfigReader{},
},
{
name: "invalid toml config file",
args: args{
Expand All @@ -79,6 +87,14 @@ func TestNewTerrascanConfigReader(t *testing.T) {
wantErr: true,
want: &TerrascanConfigReader{},
},
{
name: "invalid yaml config file",
args: args{
fileName: "testdata/invalid.yaml",
},
wantErr: true,
want: &TerrascanConfigReader{},
},
{
name: "valid toml config file with partial fields",
args: args{
Expand Down Expand Up @@ -155,6 +171,79 @@ func TestNewTerrascanConfigReader(t *testing.T) {
Policy: testPolicy,
Rules: testRules,
},
{
name: "invalid yaml config file",
args: args{
fileName: "testdata/invalid.yaml",
},
wantErr: true,
want: &TerrascanConfigReader{},
},
{
name: "valid yaml config file with all fields",
args: args{
fileName: "testdata/terrascan-config-all-fields.yaml",
},
want: &TerrascanConfigReader{
config: TerrascanConfig{
Policy: testPolicy,
Notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Rules: testRules,
},
},
assertGetters: true,
notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Policy: testPolicy,
Rules: testRules,
},
{
name: "valid yaml config file with all fields and severity defined",
args: args{
fileName: "testdata/terrascan-config-severity.yml",
},
want: &TerrascanConfigReader{
config: TerrascanConfig{
Policy: testPolicy,
Notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Rules: testRules,
Severity: highSeverity,
},
},
assertGetters: true,
notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Policy: testPolicy,
Rules: testRules,
},
{
name: "valid yaml config file with all fields and categories defined",
args: args{
fileName: "testdata/terrascan-config-category.yaml",
},
want: &TerrascanConfigReader{
config: TerrascanConfig{
Policy: testPolicy,
Notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Rules: testRules,
Category: categoryList,
},
},
assertGetters: true,
notifications: map[string]Notifier{
"webhook1": testNotifier,
},
Policy: testPolicy,
Rules: testRules,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions pkg/config/testdata/invalid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid yaml file
19 changes: 19 additions & 0 deletions pkg/config/testdata/terrascan-config-all-fields.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
policy:
path: custom-path
rego_subdir: rego-subdir
repo_url: 'https://repository/url'
branch: branch-name
notifications:
webhook1:
type: webhook
config:
url: testurl1
rules:
scan-rules:
- rule.1
- rule.2
- rule.3
- rule.4
- rule.5
skip-rules:
- rule.1
23 changes: 23 additions & 0 deletions pkg/config/testdata/terrascan-config-category.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
policy:
path: custom-path
rego_subdir: rego-subdir
repo_url: 'https://repository/url'
branch: branch-name
notifications:
webhook1:
type: webhook
config:
url: testurl1
rules:
scan-rules:
- rule.1
- rule.2
- rule.3
- rule.4
- rule.5
skip-rules:
- rule.1
category:
list:
- category.1
- category.2
21 changes: 21 additions & 0 deletions pkg/config/testdata/terrascan-config-severity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
policy:
path: custom-path
rego_subdir: rego-subdir
repo_url: 'https://repository/url'
branch: branch-name
notifications:
webhook1:
type: webhook
config:
url: testurl1
rules:
scan-rules:
- rule.1
- rule.2
- rule.3
- rule.4
- rule.5
skip-rules:
- rule.1
severity:
level: high
40 changes: 20 additions & 20 deletions pkg/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,52 +21,52 @@ var global *TerrascanConfig

// TerrascanConfig struct defines global variables/configurations across terrascan
type TerrascanConfig struct {
Policy `toml:"policy,omitempty"`
Notifications map[string]Notifier `toml:"notifications,omitempty"`
Rules `toml:"rules,omitempty"`
Category `toml:"category,omitempty"`
Severity `toml:"severity,omitempty"`
K8sAdmissionControl `toml:"k8s-admission-control,omitempty"`
Policy `toml:"policy,omitempty" yaml:"policy,omitempty"`
Notifications map[string]Notifier `toml:"notifications,omitempty" yaml:"notifications,omitempty"`
Rules `toml:"rules,omitempty" yaml:"rules,omitempty"`
Category `toml:"category,omitempty" yaml:"category,omitempty"`
Severity `toml:"severity,omitempty" yaml:"severity,omitempty"`
K8sAdmissionControl `toml:"k8s-admission-control,omitempty" yaml:"k8s-admission-control,omitempty"`
}

// Category defines the categories of violations that you want to be reported
type Category struct {
List []string `toml:"list"`
List []string `toml:"list" yaml:"list"`
}

// Severity defines the minimum level of severity of violations that you want to be reported
type Severity struct {
Level string `toml:"level"`
Level string `toml:"level" yaml:"level"`
}

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

// policy git url and branch
RepoURL string `toml:"repo_url,omitempty"`
Branch string `toml:"branch,omitempty"`
RepoURL string `toml:"repo_url,omitempty" yaml:"repo_url,omitempty"`
Branch string `toml:"branch,omitempty" yaml:"branch,omitempty"`
}

// Notifier represent a single notification in the terrascan config file
type Notifier struct {
NotifierType string `toml:"type"`
NotifierConfig interface{} `toml:"config"`
NotifierType string `toml:"type" yaml:"type"`
NotifierConfig interface{} `toml:"config" yaml:"config"`
}

// Rules represents scan and skip rules in the terrascan config file
type Rules struct {
ScanRules []string `toml:"scan-rules,omitempty"`
SkipRules []string `toml:"skip-rules,omitempty"`
ScanRules []string `toml:"scan-rules,omitempty" yaml:"scan-rules,omitempty"`
SkipRules []string `toml:"skip-rules,omitempty" yaml:"skip-rules,omitempty"`
}

// K8sAdmissionControl deny rules in the terrascan config file
type K8sAdmissionControl struct {
Dashboard bool `toml:"dashboard,omitempty"`
DeniedSeverity string `toml:"denied-severity,omitempty"`
Categories []string `toml:"denied-categories,omitempty"`
SaveRequests bool `toml:"save-requests,omitempty"`
Dashboard bool `toml:"dashboard,omitempty" yaml:"dashboard,omitempty"`
DeniedSeverity string `toml:"denied-severity,omitempty" yaml:"denied-severity,omitempty"`
Categories []string `toml:"denied-categories,omitempty" yaml:"denied-categories,omitempty"`
SaveRequests bool `toml:"save-requests,omitempty" yaml:"save-requests,omitempty"`
}

0 comments on commit afc2a18

Please sign in to comment.