Skip to content

Commit

Permalink
fix minor logging issues (crowdsecurity#264)
Browse files Browse the repository at this point in the history
* Silence terminal detection

* CI: debug helper for systemd units

* Fix minor logging issues

 - pre-create a file with chmod 0600, or change them if the file already exists
 - don't log fatal, panic .. twice to stderr
 - default log_mode = stdout
 - calling code from crowdsec/pkg/types would create an empty $LogDir/crowdsec.log (??),
   this dependency is removed

* fix metric parsing error
  • Loading branch information
mmetc authored Apr 27, 2023
1 parent 6062710 commit bc299f3
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 103 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[packages]
pytest-cs = {ref = "0.7.13", git = "https://github.com/crowdsecurity/pytest-cs.git"}
pytest-cs = {ref = "0.7.14", git = "https://github.com/crowdsecurity/pytest-cs.git"}
pytest-dotenv = "0.5.2"
pytest-dependency = "0.5.1"
pexpect = "4.8.0"
Expand Down
26 changes: 17 additions & 9 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 6 additions & 13 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/writer"
"golang.org/x/sync/errgroup"

"github.com/crowdsecurity/cs-firewall-bouncer/pkg/backend"
Expand Down Expand Up @@ -142,14 +141,6 @@ func Execute() {
os.Exit(0)
}

log.AddHook(&writer.Hook{ // Send logs with level fatal to stderr
Writer: os.Stderr,
LogLevels: []log.Level{
log.PanicLevel,
log.FatalLevel,
},
})

log.Infof("crowdsec-firewall-bouncer %s", version.VersionStr())

if configPath == nil || *configPath == "" {
Expand All @@ -166,15 +157,17 @@ func Execute() {
log.Fatalf("unable to load configuration: %s", err)
}

cfg.ConfigureLogging(config)
if err = cfg.ConfigureLogging(config); err != nil {
log.Fatalf("unable to configure logging: %s", err)
}

if *verbose {
log.SetLevel(log.DebugLevel)
}

backend, err := backend.NewBackend(config)
if err != nil {
log.Fatalf(err.Error())
log.Fatal(err)
}

if *testConfig {
Expand All @@ -183,7 +176,7 @@ func Execute() {
}

if err = backend.Init(); err != nil {
log.Fatalf(err.Error())
log.Fatal(err)
}
// No call to fatalf after this point
defer backendCleanup(backend)
Expand All @@ -196,7 +189,7 @@ func Execute() {
}
bouncer.UserAgent = fmt.Sprintf("%s/%s", name, version.VersionStr())
if err := bouncer.Init(); err != nil {
log.Errorf(err.Error())
log.Error(err)
return
}

Expand Down
102 changes: 27 additions & 75 deletions pkg/cfg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import (
"io"

log "github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
"gopkg.in/yaml.v2"

"github.com/crowdsecurity/crowdsec/pkg/types"
"github.com/crowdsecurity/crowdsec/pkg/yamlpatch"
"github.com/crowdsecurity/cs-firewall-bouncer/pkg/types"
)

type PrometheusConfig struct {
Expand All @@ -34,25 +33,25 @@ const (
)

type BouncerConfig struct {
Mode string `yaml:"mode"` // ipset,iptables,tc
PidDir string `yaml:"pid_dir"`
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"`
CompressLogs *bool `yaml:"compress_logs,omitempty"`
LogMaxSize int `yaml:"log_max_size,omitempty"`
LogMaxFiles int `yaml:"log_max_files,omitempty"`
LogMaxAge int `yaml:"log_max_age,omitempty"`
DisableIPV6 bool `yaml:"disable_ipv6"`
DenyAction string `yaml:"deny_action"`
DenyLog bool `yaml:"deny_log"`
DenyLogPrefix string `yaml:"deny_log_prefix"`
BlacklistsIpv4 string `yaml:"blacklists_ipv4"`
BlacklistsIpv6 string `yaml:"blacklists_ipv6"`
SetType string `yaml:"ipset_type"`
SetSize int `yaml:"ipset_size"`
Mode string `yaml:"mode"` // ipset,iptables,tc
PidDir string `yaml:"pid_dir"`
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"`
CompressLogs *bool `yaml:"compress_logs,omitempty"`
LogMaxSize int `yaml:"log_max_size,omitempty"`
LogMaxFiles int `yaml:"log_max_files,omitempty"`
LogMaxAge int `yaml:"log_max_age,omitempty"`
DisableIPV6 bool `yaml:"disable_ipv6"`
DenyAction string `yaml:"deny_action"`
DenyLog bool `yaml:"deny_log"`
DenyLogPrefix string `yaml:"deny_log_prefix"`
BlacklistsIpv4 string `yaml:"blacklists_ipv4"`
BlacklistsIpv6 string `yaml:"blacklists_ipv6"`
SetType string `yaml:"ipset_type"`
SetSize int `yaml:"ipset_size"`

// specific to iptables, following https://github.com/crowdsecurity/cs-firewall-bouncer/issues/19
IptablesChains []string `yaml:"iptables_chains"`
Expand All @@ -78,7 +77,6 @@ func MergedConfig(configPath string) ([]byte, error) {
return nil, err
}
return data, nil

}

func NewConfig(reader io.Reader) (*BouncerConfig, error) {
Expand Down Expand Up @@ -197,62 +195,16 @@ func nftablesConfig(config *BouncerConfig) error {
return nil
}

func ConfigureLogging(config *BouncerConfig) {
var LogOutput *lumberjack.Logger // io.Writer

/* Configure logging */
if err := types.SetDefaultLoggerConfig(config.LogMode, config.LogDir, config.LogLevel, config.LogMaxSize,
config.LogMaxFiles, config.LogMaxAge, config.CompressLogs, false); err != nil {
log.Fatal(err.Error())
}

if config.LogMode == "file" {
if config.LogDir == "" {
config.LogDir = "/var/log/"
}

_maxsize := 500

if config.LogMaxSize != 0 {
_maxsize = config.LogMaxSize
}

_maxfiles := 3

if config.LogMaxFiles != 0 {
_maxfiles = config.LogMaxFiles
}

_maxage := 30

if config.LogMaxAge != 0 {
_maxage = config.LogMaxAge
}

_compress := true

if config.CompressLogs != nil {
_compress = *config.CompressLogs
}

LogOutput = &lumberjack.Logger{
Filename: config.LogDir + "/crowdsec-firewall-bouncer.log",
MaxSize: _maxsize, // megabytes
MaxBackups: _maxfiles,
MaxAge: _maxage, // days
Compress: _compress, // disabled by default
}
log.SetOutput(LogOutput)
log.SetFormatter(&log.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true})
}
}

func validateConfig(config BouncerConfig) error {
if config.Mode == "" || config.LogMode == "" {
return fmt.Errorf("config does not contain mode and log mode")
if config.Mode == "" {
return fmt.Errorf("config does not contain 'mode'")
}

if config.LogMode != "stdout" && config.LogMode != "file" {
switch config.LogMode {
case "":
config.LogMode = "stdout"
case "stdout", "file":
default:
return fmt.Errorf("log mode '%s' unknown, expecting 'file' or 'stdout'", config.LogMode)
}

Expand Down
44 changes: 44 additions & 0 deletions pkg/cfg/fileperms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cfg

import (
"fmt"
"os"
"path/filepath"
)

// setLogFilePermissions sets the permissions of the log file to 0600.
// If the file does not exist, it will be created.
// lumberjack will then respect our permissions.
// https://github.com/natefinch/lumberjack/issues/82
func setLogFilePermissions(logDir string, logFile string) (string, error) {
err := os.MkdirAll(logDir, 0755)
if err != nil {
return "", fmt.Errorf("failed to create log directory: %w", err)
}

logPath := filepath.Join(logDir, logFile)

st, err := os.Stat(logPath)
if err != nil {
if !os.IsNotExist(err) {
return "", fmt.Errorf("failed to check file existence: %w", err)
}
file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return "", fmt.Errorf("failed to create file: %w", err)
}
file.Close()
return logPath, nil
}

if st.IsDir() {
return "", fmt.Errorf("expected a file, found a directory: %s", logPath)
}

err = os.Chmod(logPath, 0600)
if err != nil {
return "", fmt.Errorf("failed to change file permissions: %w", err)
}

return logPath, nil
}
Loading

0 comments on commit bc299f3

Please sign in to comment.