Skip to content

Commit

Permalink
feat: support writing audit events to stdout for log
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Phelps <[email protected]>
  • Loading branch information
markphelps committed May 26, 2024
1 parent 6aeb487 commit 47c3608
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 45 deletions.
8 changes: 4 additions & 4 deletions internal/cmd/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"go.flipt.io/flipt/internal/server/analytics/clickhouse"
"go.flipt.io/flipt/internal/server/audit"
"go.flipt.io/flipt/internal/server/audit/cloud"
"go.flipt.io/flipt/internal/server/audit/logfile"
"go.flipt.io/flipt/internal/server/audit/log"
"go.flipt.io/flipt/internal/server/audit/template"
"go.flipt.io/flipt/internal/server/audit/webhook"
authmiddlewaregrpc "go.flipt.io/flipt/internal/server/authn/middleware/grpc"
Expand Down Expand Up @@ -350,10 +350,10 @@ func NewGRPCServer(
// audit sinks configuration
sinks := make([]audit.Sink, 0)

if cfg.Audit.Sinks.LogFile.Enabled {
logFileSink, err := logfile.NewSink(logger, cfg.Audit.Sinks.LogFile.File)
if cfg.Audit.Sinks.Log.Enabled {
logFileSink, err := log.NewSink(logger, cfg.Audit.Sinks.Log.File)
if err != nil {
return nil, fmt.Errorf("opening file at path: %s", cfg.Audit.Sinks.LogFile.File)
return nil, fmt.Errorf("opening file at path: %s", cfg.Audit.Sinks.Log.File)
}

sinks = append(sinks, logFileSink)
Expand Down
14 changes: 5 additions & 9 deletions internal/config/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type AuditConfig struct {

// Enabled returns true if any nested sink is enabled
func (c AuditConfig) Enabled() bool {
return c.Sinks.LogFile.Enabled || c.Sinks.Webhook.Enabled || c.Sinks.Cloud.Enabled
return c.Sinks.Log.Enabled || c.Sinks.Webhook.Enabled || c.Sinks.Cloud.Enabled
}

func (c AuditConfig) IsZero() bool {
Expand Down Expand Up @@ -52,10 +52,6 @@ func (c *AuditConfig) setDefaults(v *viper.Viper) error {
}

func (c *AuditConfig) validate() error {
if c.Sinks.LogFile.Enabled && c.Sinks.LogFile.File == "" {
return errors.New("file not specified")
}

if c.Sinks.Webhook.Enabled {
if c.Sinks.Webhook.URL == "" && len(c.Sinks.Webhook.Templates) == 0 {
return errors.New("url or template(s) not provided")
Expand All @@ -80,7 +76,7 @@ func (c *AuditConfig) validate() error {
// SinksConfig contains configuration held in structures for the different sinks
// that we will send audits to.
type SinksConfig struct {
LogFile LogFileSinkConfig `json:"log,omitempty" mapstructure:"log" yaml:"log,omitempty"`
Log LogSinkConfig `json:"log,omitempty" mapstructure:"log" yaml:"log,omitempty"`
Webhook WebhookSinkConfig `json:"webhook,omitempty" mapstructure:"webhook" yaml:"webhook,omitempty"`
Cloud CloudSinkConfig `json:"cloud,omitempty" mapstructure:"cloud" yaml:"cloud,omitempty"`
}
Expand All @@ -99,9 +95,9 @@ type WebhookSinkConfig struct {
Templates []WebhookTemplate `json:"templates,omitempty" mapstructure:"templates" yaml:"templates,omitempty"`
}

// LogFileSinkConfig contains fields that hold configuration for sending audits
// to a log file.
type LogFileSinkConfig struct {
// LogSinkConfig contains fields that hold configuration for sending audits
// to a log.
type LogSinkConfig struct {
Enabled bool `json:"enabled,omitempty" mapstructure:"enabled" yaml:"enabled,omitempty"`
File string `json:"file,omitempty" mapstructure:"file" yaml:"file,omitempty"`
}
Expand Down
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ func Default() *Config {

Audit: AuditConfig{
Sinks: SinksConfig{
LogFile: LogFileSinkConfig{
Log: LogSinkConfig{
Enabled: false,
File: "",
},
Expand Down
12 changes: 8 additions & 4 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ func TestLoad(t *testing.T) {

cfg.Audit = AuditConfig{
Sinks: SinksConfig{
LogFile: LogFileSinkConfig{
Log: LogSinkConfig{
Enabled: true,
File: "/path/to/logs.txt",
},
Expand Down Expand Up @@ -827,9 +827,13 @@ func TestLoad(t *testing.T) {
wantErr: errors.New("flush period below 2 minutes or greater than 5 minutes"),
},
{
name: "file not specified",
path: "./testdata/audit/invalid_enable_without_file.yml",
wantErr: errors.New("file not specified"),
name: "file not specified",
path: "./testdata/audit/enable_without_file.yml",
expected: func() *Config {
cfg := Default()
cfg.Audit.Sinks.Log.Enabled = true
return cfg
},
},
{
name: "url or template not specified",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package logfile
package log

import (
"context"
Expand Down Expand Up @@ -42,12 +42,12 @@ func (osFS) MkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm)
}

const sinkType = "logfile"
const sinkType = "log"

// Sink is the structure in charge of sending Audits to a specified file location.
// Sink is the structure in charge of sending audit events to a specified file location.
type Sink struct {
logger *zap.Logger
file file
f file
mtx sync.Mutex
enc *json.Encoder
}
Expand All @@ -59,26 +59,33 @@ func NewSink(logger *zap.Logger, path string) (audit.Sink, error) {

// newSink is the constructor for a Sink visible for testing.
func newSink(logger *zap.Logger, path string, fs filesystem) (audit.Sink, error) {
// check if path exists, if not create it
dir := filepath.Dir(path)
if _, err := fs.Stat(dir); err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("checking log directory: %w", err)
var f file

if path == "" {
f = os.Stdout
} else {
// check if path exists, if not create it
dir := filepath.Dir(path)
if _, err := fs.Stat(dir); err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("checking log directory: %w", err)
}

if err := fs.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("creating log directory: %w", err)
}
}

if err := fs.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("creating log directory: %w", err)
var err error
f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return nil, fmt.Errorf("opening log file: %w", err)
}
}

f, err := fs.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return nil, fmt.Errorf("opening log file: %w", err)
}

return &Sink{
logger: logger,
file: f,
f: f,
enc: json.NewEncoder(f),
}, nil
}
Expand All @@ -91,7 +98,7 @@ func (l *Sink) SendAudits(ctx context.Context, events []audit.Event) error {
for _, e := range events {
err := l.enc.Encode(e)
if err != nil {
l.logger.Error("failed to write audit event to file", zap.String("file", l.file.Name()), zap.Error(err))
l.logger.Error("failed to write audit event", zap.String("file", l.f.Name()), zap.Error(err))
result = multierror.Append(result, err)
}
}
Expand All @@ -102,7 +109,7 @@ func (l *Sink) SendAudits(ctx context.Context, events []audit.Event) error {
func (l *Sink) Close() error {
l.mtx.Lock()
defer l.mtx.Unlock()
return l.file.Close()
return l.f.Close()
}

func (l *Sink) String() string {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package logfile
package log

import (
"bytes"
Expand Down Expand Up @@ -29,7 +29,7 @@ func TestNewSink_NewFile(t *testing.T) {
require.NoError(t, err)

require.NotNil(t, sink)
assert.Equal(t, "logfile", sink.String())
assert.Equal(t, "log", sink.String())

require.NoError(t, sink.Close())
}
Expand All @@ -51,7 +51,7 @@ func TestNewSink_ExistingFile(t *testing.T) {
require.NoError(t, err)

require.NotNil(t, sink)
assert.Equal(t, "logfile", sink.String())
assert.Equal(t, "log", sink.String())

require.NoError(t, sink.Close())
}
Expand Down Expand Up @@ -86,7 +86,7 @@ func TestNewSink_DirNotExists(t *testing.T) {
require.NoError(t, err)

require.NotNil(t, sink)
assert.Equal(t, "logfile", sink.String())
assert.Equal(t, "log", sink.String())

require.NoError(t, sink.Close())
})
Expand Down
2 changes: 1 addition & 1 deletion internal/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (r *Reporter) ping(_ context.Context, f file) error {
auditSinks := []string{}

if r.cfg.Audit.Enabled() {
if r.cfg.Audit.Sinks.LogFile.Enabled {
if r.cfg.Audit.Sinks.Log.Enabled {
auditSinks = append(auditSinks, "log")
}
if r.cfg.Audit.Sinks.Webhook.Enabled {
Expand Down
6 changes: 3 additions & 3 deletions internal/telemetry/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func TestPing(t *testing.T) {
},
Audit: config.AuditConfig{
Sinks: config.SinksConfig{
LogFile: config.LogFileSinkConfig{
Log: config.LogSinkConfig{
Enabled: false,
},
},
Expand All @@ -277,7 +277,7 @@ func TestPing(t *testing.T) {
},
Audit: config.AuditConfig{
Sinks: config.SinksConfig{
LogFile: config.LogFileSinkConfig{
Log: config.LogSinkConfig{
Enabled: true,
},
},
Expand Down Expand Up @@ -359,7 +359,7 @@ func TestPing(t *testing.T) {
},
Audit: config.AuditConfig{
Sinks: config.SinksConfig{
LogFile: config.LogFileSinkConfig{
Log: config.LogSinkConfig{
Enabled: true,
},
Webhook: config.WebhookSinkConfig{
Expand Down

0 comments on commit 47c3608

Please sign in to comment.