Skip to content

Commit

Permalink
Fail fast if rule name prefix will cause rule names to not be complia…
Browse files Browse the repository at this point in the history
…nt to RFC1035 (#7)

* Adding check for rule name prefix during init to fail fast

* Moving config to its own package

* Adding tests to config pkg
  • Loading branch information
fallard84 committed Dec 22, 2020
1 parent 0c6dc4f commit 1036c11
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 75 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ api_url: <API_URL> # when install, default is "localhost:8080"
api_key: <API_KEY> # Add your API key generated with `cscli bouncers add --name <bouncer_name>`
```

### Rule name prefix requirements

The rule name generated must comply with [RFC1035](https://tools.ietf.org/html/rfc1035).
Since two random words (maximum 19 characters) are appended to the rule name prefix to
create unique rule names, this checks that the rule name prefix be 1-44 characters long
and match the regular expression `^(?:[a-z](?:[-a-z0-9]{0,43})?)\$. The first character
must be a lowercase letter, and all following characters must be a dash, lowercase letter, or
digit.

## Authentication

### GCP
Expand Down
67 changes: 0 additions & 67 deletions config.go

This file was deleted.

4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ require (
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/crowdsecurity/crowdsec v1.0.2
github.com/crowdsecurity/go-cs-bouncer v0.0.0-20201130114000-e5b8016e5bf3
github.com/sethvargo/go-diceware v0.2.0
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.6.1
github.com/tjarratt/babble v0.0.0-20191209142150-eecdf8c2339d
github.com/zhexuany/wordGenerator v0.0.0-20161102120352-1f13e790d534
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
google.golang.org/api v0.36.0
google.golang.org/appengine v1.6.7
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
gopkg.in/yaml.v2 v2.4.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,8 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sethvargo/go-diceware v0.2.0 h1:3QzXGqUe0UR9y1XYSz1dxGS+fKtXOxRqqKjy+cG1yTI=
github.com/sethvargo/go-diceware v0.2.0/go.mod h1:II+37A5sTGAtg3zd/JqyVQ8qqAjSm/2r2X6qkVZDjyg=
github.com/sevlyar/go-daemon v0.1.5/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
Expand Down
9 changes: 5 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/coreos/go-systemd/daemon"
csbouncer "github.com/crowdsecurity/go-cs-bouncer"
"github.com/fallard84/cs-cloud-firewall-bouncer/pkg/config"
"github.com/fallard84/cs-cloud-firewall-bouncer/pkg/firewall"
"github.com/fallard84/cs-cloud-firewall-bouncer/pkg/models"
"github.com/fallard84/cs-cloud-firewall-bouncer/pkg/providers"
Expand Down Expand Up @@ -72,7 +73,7 @@ func handleSignals(firewallBouncers []*firewall.Bouncer) {
os.Exit(code)
}

func getProviderClients(config bouncerConfig) ([]providers.CloudClient, error) {
func getProviderClients(config config.BouncerConfig) ([]providers.CloudClient, error) {
cloudClients := []providers.CloudClient{}
if (models.GCPConfig{}) != config.CloudProviders.GCP {
gcpClient, err := gcp.NewClient(&config.CloudProviders.GCP)
Expand All @@ -96,7 +97,7 @@ func getProviderClients(config bouncerConfig) ([]providers.CloudClient, error) {
return cloudClients, nil
}

func getFirewallBouncers(config bouncerConfig) ([]*firewall.Bouncer, error) {
func getFirewallBouncers(config config.BouncerConfig) ([]*firewall.Bouncer, error) {
clients, err := getProviderClients(config)
if err != nil {
log.Fatalf("unable to get provider client: %s", err.Error())
Expand All @@ -111,7 +112,7 @@ func getFirewallBouncers(config bouncerConfig) ([]*firewall.Bouncer, error) {

func main() {
var err error
log.Infof("%s", name)
log.Infof("%s %s", name, version.Version)
configPath := flag.String("c", "", "path to config file")
verbose := flag.Bool("v", false, "set verbose mode")

Expand All @@ -121,7 +122,7 @@ func main() {
log.Fatalf("configuration file is required")
}

config, err := newConfig(*configPath)
config, err := config.NewConfig(*configPath)
if err != nil {
log.Fatalf("unable to load configuration: %s", err)
}
Expand Down
93 changes: 93 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package config

import (
"fmt"
"io/ioutil"
"regexp"
"strings"

"github.com/crowdsecurity/crowdsec/pkg/types"
log "github.com/sirupsen/logrus"

"github.com/fallard84/cs-cloud-firewall-bouncer/pkg/models"
"gopkg.in/natefinch/lumberjack.v2"
"gopkg.in/yaml.v2"
)

type BouncerConfig struct {
CloudProviders models.CloudProviders `yaml:"cloud_providers"`
RuleNamePrefix string `yaml:"rule_name_prefix"`
UpdateFrequency string `yaml:"update_frequency"`
Daemon bool `yaml:"daemonize"`
LogMode string `yaml:"log_mode"`
LogDir string `yaml:"log_dir"`
LogLevel log.Level `yaml:"log_level"`
APIUrl string `yaml:"api_url"`
APIKey string `yaml:"api_key"`
}

// checkRuleNamePrefixValid validates that the rule name prefix complies specific requirements.
// The rule name generated must comply with RFC1035. Since two random words (maximum 19 characters)
// are appended to the rule name prefix to create unique rule names, this checks that
// the rule name prefix be 1-44 characters long and match the regular expression `^(?:[a-z](?:[-a-z0-9]{0,43})?)$. The first
// character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or
// digit.
func checkRuleNamePrefixValid(ruleNamePrefix string) error {
re := regexp.MustCompile(`^(?:[a-z](?:[-a-z0-9]{0,43})?)$`)
match := re.MatchString(ruleNamePrefix)
if !match {
return fmt.Errorf("rule_name_prefix %s does not match the following regex: %s", ruleNamePrefix, re.String())
}
return nil
}

func GenerateConfig(configBuff []byte) (*BouncerConfig, error) {

config := &BouncerConfig{}
if err := yaml.UnmarshalStrict(configBuff, &config); err != nil {
return &BouncerConfig{}, fmt.Errorf("failed to unmarshal yaml config file: %v", err)
}

config.RuleNamePrefix = strings.ToLower(config.RuleNamePrefix)

if config.RuleNamePrefix == "" {
return &BouncerConfig{}, fmt.Errorf("rule_name_prefix must be specified")
}

if err := checkRuleNamePrefixValid(config.RuleNamePrefix); err != nil {
return &BouncerConfig{}, err
}

/*Configure logging*/
if err := types.SetDefaultLoggerConfig(config.LogMode, config.LogDir, config.LogLevel); err != nil {
log.Fatal(err.Error())
}
if config.LogMode == "file" {
if config.LogDir == "" {
config.LogDir = "/var/log/"
}
var LogOutput *lumberjack.Logger //io.Writer
LogOutput = &lumberjack.Logger{
Filename: config.LogDir + "/cs-cloud-firewall-bouncer.log",
MaxSize: 500, //megabytes
MaxBackups: 3,
MaxAge: 28, //days
Compress: true, //disabled by default
}
log.SetOutput(LogOutput)
log.SetFormatter(&log.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true})
} else if config.LogMode != "stdout" {
return &BouncerConfig{}, fmt.Errorf("log mode '%s' unknown, expecting 'file' or 'stdout'", config.LogMode)
}
return config, nil
}

func NewConfig(configPath string) (*BouncerConfig, error) {

configBuff, err := ioutil.ReadFile(configPath)

if err != nil {
return &BouncerConfig{}, fmt.Errorf("failed to read %s : %v", configPath, err)
}
return GenerateConfig(configBuff)
}
Loading

0 comments on commit 1036c11

Please sign in to comment.