diff --git a/go.mod b/go.mod index 04ee7a44a..48eb15a73 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/hashicorp/hcl/v2 v2.3.0 github.com/hashicorp/terraform v0.12.28 github.com/pelletier/go-toml v1.8.0 + github.com/pkg/errors v0.9.1 github.com/spf13/afero v1.3.2 github.com/zclconf/go-cty v1.2.1 go.uber.org/zap v1.9.1 diff --git a/pkg/notifications/notifiers.go b/pkg/notifications/notifiers.go index baf5a2db9..add3b8e1f 100644 --- a/pkg/notifications/notifiers.go +++ b/pkg/notifications/notifiers.go @@ -21,6 +21,7 @@ import ( "os" "reflect" + "github.com/accurics/terrascan/pkg/utils" "github.com/pelletier/go-toml" "go.uber.org/zap" ) @@ -87,24 +88,34 @@ func NewNotifiers(configFile string) ([]Notifier, error) { notifierTypes := keyTomlConfig.Keys() // create notifiers + var allErrs error for _, nType := range notifierTypes { + if !IsNotifierSupported(nType) { + zap.S().Errorf("notifier type '%s' not supported", nType) + allErrs = utils.WrapError(errNotifierNotSupported, allErrs) + continue + } + // check if toml config present for notifier type nTypeConfig := keyTomlConfig.Get(nType) - if nTypeConfig == nil { + if nTypeConfig.(*toml.Tree).String() == "" { zap.S().Errorf("notifier '%v' config not present", nType) - return notifiers, errTomlKeyNotPresent + allErrs = utils.WrapError(errTomlKeyNotPresent, allErrs) + continue } // create a new notifier n, err := NewNotifier(nType) if err != nil { + allErrs = utils.WrapError(err, allErrs) continue } // populate data err = n.Init(nTypeConfig) if err != nil { + allErrs = utils.WrapError(err, allErrs) continue } @@ -113,7 +124,7 @@ func NewNotifiers(configFile string) ([]Notifier, error) { } // return list of notifiers - return notifiers, nil + return notifiers, allErrs } // IsNotifierSupported returns true/false depending on whether the notifier diff --git a/pkg/notifications/notifiers_test.go b/pkg/notifications/notifiers_test.go new file mode 100644 index 000000000..2f71af0c9 --- /dev/null +++ b/pkg/notifications/notifiers_test.go @@ -0,0 +1,91 @@ +package notifications + +import ( + "reflect" + "testing" + + "github.com/accurics/terrascan/pkg/notifications/webhook" +) + +func TestNewNotifier(t *testing.T) { + + table := []struct { + name string + nType string + wantType Notifier + wantErr error + }{ + { + name: "valid notifier", + nType: "webhook", + wantType: &webhook.Webhook{}, + wantErr: nil, + }, + { + name: "invalid notifier", + nType: "notthere", + wantErr: errNotifierNotSupported, + }, + } + + for _, tt := range table { + t.Run(tt.name, func(t *testing.T) { + gotType, gotErr := NewNotifier(tt.nType) + if !reflect.DeepEqual(gotType, tt.wantType) { + t.Errorf("got: '%v', want: '%v'", gotType, tt.wantType) + } + if !reflect.DeepEqual(gotErr, tt.wantErr) { + t.Errorf("incorrect error; got: '%v', want: '%v'", gotErr, tt.wantErr) + } + }) + } +} + +func TestNewNotifiers(t *testing.T) { + + table := []struct { + name string + configFile string + wantErr error + }{ + { + name: "config not present", + configFile: "notthere", + wantErr: errNotPresent, + }, + { + name: "invalid toml", + configFile: "testdata/invalid.toml", + wantErr: errTomlLoadConfig, + }, + { + name: "key not present", + configFile: "testdata/nokey.toml", + wantErr: errTomlKeyNotPresent, + }, + { + name: "invalid notifier", + configFile: "testdata/invalid-notifier-type.toml", + wantErr: errNotifierNotSupported, + }, + { + name: "empty notifier config", + configFile: "testdata/empty-notifier-config.toml", + wantErr: errTomlKeyNotPresent, + }, + { + name: "invalid notifier config", + configFile: "testdata/invalid-notifier-config.toml", + wantErr: nil, + }, + } + + for _, tt := range table { + t.Run(tt.name, func(t *testing.T) { + _, gotErr := NewNotifiers(tt.configFile) + if !reflect.DeepEqual(gotErr, tt.wantErr) { + t.Errorf("incorrect error; got: '%v', want: '%v'", gotErr, tt.wantErr) + } + }) + } +} diff --git a/pkg/notifications/testdata/empty-notifier-config.toml b/pkg/notifications/testdata/empty-notifier-config.toml new file mode 100644 index 000000000..299652e1f --- /dev/null +++ b/pkg/notifications/testdata/empty-notifier-config.toml @@ -0,0 +1,2 @@ +[notifications] + [notifications.webhook] diff --git a/pkg/notifications/testdata/invalid-notifier-config.toml b/pkg/notifications/testdata/invalid-notifier-config.toml new file mode 100644 index 000000000..4b2914425 --- /dev/null +++ b/pkg/notifications/testdata/invalid-notifier-config.toml @@ -0,0 +1,4 @@ +[notifications] + [notifications.webhook] + key1 = "val1" + key2 = "val2" diff --git a/pkg/notifications/testdata/invalid-notifier-type.toml b/pkg/notifications/testdata/invalid-notifier-type.toml new file mode 100644 index 000000000..74c795e09 --- /dev/null +++ b/pkg/notifications/testdata/invalid-notifier-type.toml @@ -0,0 +1,6 @@ +# terrascan configuration file + +# notifications configuration +[notifications] + [notifications.invalid] + url = "https://httpbin.org/post" diff --git a/pkg/notifications/testdata/invalid.toml b/pkg/notifications/testdata/invalid.toml new file mode 100644 index 000000000..030ffe2ec --- /dev/null +++ b/pkg/notifications/testdata/invalid.toml @@ -0,0 +1 @@ +I am an invalid toml diff --git a/pkg/notifications/testdata/nokey.toml b/pkg/notifications/testdata/nokey.toml new file mode 100644 index 000000000..b2529fbd5 --- /dev/null +++ b/pkg/notifications/testdata/nokey.toml @@ -0,0 +1,2 @@ +[somefield] +somekey = "somevalue" diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go index 3cb31d1ba..8105e022b 100644 --- a/pkg/runtime/executor_test.go +++ b/pkg/runtime/executor_test.go @@ -151,6 +151,20 @@ func TestInit(t *testing.T) { wantIacProvider: &tfv12.TfV12{}, wantNotifiers: []notifications.Notifier{&webhook.Webhook{}}, }, + { + name: "invalid notifier", + executor: Executor{ + filePath: "./testdata/testfile", + dirPath: "", + cloudType: "aws", + iacType: "terraform", + iacVersion: "v12", + configFile: "testdata/invalid-notifier.toml", + }, + wantErr: fmt.Errorf("notifier not supported"), + wantIacProvider: &tfv12.TfV12{}, + wantNotifiers: []notifications.Notifier{&webhook.Webhook{}}, + }, { name: "config not present", executor: Executor{