Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/nullify.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
severity_threshold: medium
ignore_dirs: ["data"]
ignore_pattens: ["*d"]
email_notifications: ["notifications@nullify.cloud", "noreply@nullify.cloud"]
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/nullify-platform/config-file-parser
go 1.19

require (
github.com/gobwas/glob v0.2.3
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v3 v3.0.1
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
Expand Down
1 change: 1 addition & 0 deletions pkg/models/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package models
type Configuration struct {
SeverityThreshold string `yaml:"severity_threshold"`
IgnoreDirs []string `yaml:"ignore_dirs"`
IgnorePatterns []string `yaml:"ignore_patterns"`
EmailNotifications []string `yaml:"email_notifications"`
SecretsWhitelist []string `yaml:"secrets_whitelist"`
}
1 change: 1 addition & 0 deletions pkg/parser/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ func NewDefaultConfig() *models.Configuration {
return &models.Configuration{
SeverityThreshold: DefaultSeverityThreshold,
IgnoreDirs: []string{},
IgnorePatterns: []string{},
}
}
26 changes: 26 additions & 0 deletions pkg/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestParseConfiguration(t *testing.T) {
expected: &models.Configuration{
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
IgnorePatterns: nil,
SecretsWhitelist: nil,
},
},
Expand All @@ -35,6 +36,7 @@ func TestParseConfiguration(t *testing.T) {
expected: &models.Configuration{
SeverityThreshold: models.SeverityHigh,
IgnoreDirs: []string{"data"},
IgnorePatterns: []string{"*d"},
SecretsWhitelist: []string{"secretPassword", "superSecretPassword"},
},
},
Expand All @@ -44,6 +46,7 @@ func TestParseConfiguration(t *testing.T) {
expected: &models.Configuration{
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
IgnorePatterns: nil,
SecretsWhitelist: nil,
},
},
Expand All @@ -53,6 +56,7 @@ func TestParseConfiguration(t *testing.T) {
expected: &models.Configuration{
SeverityThreshold: models.SeverityLow,
IgnoreDirs: nil,
IgnorePatterns: nil,
SecretsWhitelist: nil,
},
},
Expand All @@ -62,6 +66,7 @@ func TestParseConfiguration(t *testing.T) {
expected: &models.Configuration{
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
IgnorePatterns: nil,
SecretsWhitelist: []string{"password"},
},
},
Expand All @@ -72,6 +77,27 @@ func TestParseConfiguration(t *testing.T) {
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
SecretsWhitelist: nil,
IgnorePatterns: nil,
},
},
{
name: "user provided empty ignore patterns",
data: `ignore_patterns: `,
expected: &models.Configuration{
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
IgnorePatterns: nil,
SecretsWhitelist: nil,
},
},
{
name: "user provided glob in ignore patterns",
data: `ignore_patterns: ["*d"]`,
expected: &models.Configuration{
SeverityThreshold: models.SeverityMedium,
IgnoreDirs: nil,
IgnorePatterns: []string{"*d"},
SecretsWhitelist: nil,
},
},
} {
Expand Down
21 changes: 21 additions & 0 deletions pkg/validator/glob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package validator

import (
"github.com/gobwas/glob"
"github.com/nullify-platform/config-file-parser/pkg/models"
)

func ValidateGlob(config *models.Configuration) bool {
if config.IgnorePatterns == nil {
return true
}

for _, pattern := range config.IgnorePatterns {
_, err := glob.Compile(pattern)
if err != nil {
return false
}
}

return true
}
115 changes: 115 additions & 0 deletions pkg/validator/glob_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package validator

import (
"fmt"
"testing"

"github.com/nullify-platform/config-file-parser/pkg/models"
"github.com/nullify-platform/config-file-parser/pkg/parser"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestValidGlobs(t *testing.T) {
for _, scenario := range []struct {
name string
config *models.Configuration
expected bool
}{
{
config: &models.Configuration{},
expected: true,
},
{
config: &models.Configuration{IgnorePatterns: []string{}},
expected: true,
},
{
config: &models.Configuration{IgnorePatterns: []string{"*[abc]"}},
expected: true,
},
{
config: &models.Configuration{IgnorePatterns: []string{"*[abc]", "*d"}},
expected: true,
},
{
config: &models.Configuration{IgnorePatterns: []string{"*[abc"}},
expected: false,
},
{
config: &models.Configuration{IgnorePatterns: []string{"*d", "*[abc"}},
expected: false,
},
{
config: &models.Configuration{IgnorePatterns: []string{"*[abc", "*d"}},
expected: false,
},
} {
t.Run(scenario.name, func(t *testing.T) {
isValid := ValidateGlob(scenario.config)
assert.Equalf(t, isValid, scenario.expected, fmt.Sprintf("failed test, globs: %s, len: %d\n", scenario.config.IgnorePatterns, len(scenario.config.IgnorePatterns)))
})
}
}

const validGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns: ["*[abc]"]
email_notifications: ["hello@gmail.com"]
`
const emptyGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns: ["*[abc]", "*d"]
email_notifications: ["hello@gmail.com"]
`

const twoValidGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns:
email_notifications: ["hello@gmail.com"]
`

const invalidGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns: ["*[abc"]
email_notifications: ["hello@gmail.com"]
`

const endInvalidGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns: ["*d", "*[abc"]
email_notifications: ["hello@gmail.com"]
`

const startInvalidGlob string = `
severity_threshold: medium
ignore_dirs: ["data"]
ignore_patterns: ["*[abc", "*d"]
email_notifications: ["hello@gmail.com"]
`

func TestParsingAndValidGlobs(t *testing.T) {
config1, err := parser.ParseConfiguration([]byte(validGlob))
require.NoError(t, err)
require.Equal(t, true, ValidateGlob(config1))
config2, err := parser.ParseConfiguration([]byte(emptyGlob))
require.NoError(t, err)
require.Equal(t, true, ValidateGlob(config2))
config3, err := parser.ParseConfiguration([]byte(twoValidGlob))
require.NoError(t, err)
require.Equal(t, true, ValidateGlob(config3))
config4, err := parser.ParseConfiguration([]byte(endInvalidGlob))
require.NoError(t, err)
require.Equal(t, false, ValidateGlob(config4))
config5, err := parser.ParseConfiguration([]byte(startInvalidGlob))
require.NoError(t, err)
require.Equal(t, false, ValidateGlob(config5))
config6, err := parser.ParseConfiguration([]byte(invalidGlob))
require.NoError(t, err)
require.Equal(t, false, ValidateGlob(config6))
}
2 changes: 1 addition & 1 deletion pkg/validator/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import (

// ValidateConfig return true if provided configuration is valid
func ValidateConfig(config *models.Configuration) bool {
return ValidateSeverityThreshold(config) && ValidateEmail(config)
return ValidateSeverityThreshold(config) && ValidateEmail(config) && ValidateGlob(config)
}