Skip to content

Commit 4b9a0d9

Browse files
committed
deepen audit architecture seams
1 parent 103e53f commit 4b9a0d9

19 files changed

Lines changed: 1990 additions & 1412 deletions

File tree

cmd/auditServer.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ var auditServerCmd = &cobra.Command{
3434
if err != nil {
3535
return err
3636
}
37-
server, err := auditserver.New(logger)
37+
settings, err := auditServerRuntimeSettings()
38+
if err != nil {
39+
return fmt.Errorf("failed to create audit server: %w", err)
40+
}
41+
server, err := auditserver.New(logger, settings)
3842
if err != nil {
3943
return fmt.Errorf("failed to create audit server: %w", err)
4044
}

cmd/auditServer_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ limitations under the License.
1616
package cmd
1717

1818
import (
19+
"path/filepath"
1920
"testing"
21+
"time"
2022

23+
"github.com/ncode/vault-audit-filter/pkg/auditserver"
2124
"github.com/spf13/viper"
2225
"github.com/stretchr/testify/assert"
2326
"github.com/stretchr/testify/require"
@@ -56,6 +59,76 @@ func TestAuditServerCmd_ValidConfig(t *testing.T) {
5659
assert.NotNil(t, auditServerCmd.RunE)
5760
}
5861

62+
func TestAuditServerRuntimeSettingsFromViper(t *testing.T) {
63+
viper.Reset()
64+
logPath := filepath.Join(t.TempDir(), "audit.log")
65+
viper.Set("vault.audit_protocol", "tcp")
66+
viper.Set("async.queue_size", 9)
67+
viper.Set("async.workers", 3)
68+
viper.Set("async.enqueue_mode", "wait")
69+
viper.Set("async.enqueue_timeout", "13ms")
70+
viper.Set("async.timeout", "19ms")
71+
viper.Set("async.durable.enabled", true)
72+
viper.Set("async.durable.dir", t.TempDir())
73+
viper.Set("async.retry.max_attempts", 6)
74+
viper.Set("async.retry.backoff", "29ms")
75+
viper.Set("rule_groups", []map[string]interface{}{{
76+
"name": "configured",
77+
"rules": []string{"Request.Operation == 'read'"},
78+
"log_file": map[string]interface{}{"file_path": logPath, "max_size": 1},
79+
}})
80+
81+
settings, err := auditServerRuntimeSettings()
82+
require.NoError(t, err)
83+
assert.Equal(t, "tcp", settings.AuditProtocol)
84+
assert.Equal(t, 9, settings.Async.QueueSize)
85+
assert.Equal(t, 3, settings.Async.Workers)
86+
assert.Equal(t, "wait", settings.Async.EnqueueMode)
87+
assert.Equal(t, 13*time.Millisecond, settings.Async.EnqueueTimeout)
88+
assert.Equal(t, 19*time.Millisecond, settings.Async.Timeout)
89+
assert.True(t, settings.Async.Durable.Enabled)
90+
assert.Equal(t, 6, settings.Async.Retry.MaxAttempts)
91+
assert.Equal(t, 29*time.Millisecond, settings.Async.Retry.Backoff)
92+
require.Len(t, settings.RuleGroups, 1)
93+
assert.Equal(t, "configured", settings.RuleGroups[0].Name)
94+
assert.Equal(t, logPath, settings.RuleGroups[0].LogFile.FilePath)
95+
}
96+
97+
func TestAuditServerRuntimeSettings_InvalidAsyncValuesFallBackToDefaults(t *testing.T) {
98+
viper.Reset()
99+
viper.Set("vault.audit_protocol", "udp")
100+
viper.Set("async.queue_size", 0)
101+
viper.Set("async.workers", -1)
102+
viper.Set("async.enqueue_mode", "invalid")
103+
viper.Set("async.enqueue_timeout", "bad")
104+
viper.Set("async.timeout", "also-bad")
105+
viper.Set("async.durable.dir", "")
106+
viper.Set("async.retry.max_attempts", 0)
107+
viper.Set("async.retry.backoff", "worse")
108+
viper.Set("rule_groups", []map[string]interface{}{})
109+
110+
settings, err := auditServerRuntimeSettings()
111+
require.NoError(t, err)
112+
defaults := auditserver.DefaultRuntimeSettings()
113+
assert.Equal(t, defaults.Async.QueueSize, settings.Async.QueueSize)
114+
assert.Equal(t, defaults.Async.Workers, settings.Async.Workers)
115+
assert.Equal(t, defaults.Async.EnqueueMode, settings.Async.EnqueueMode)
116+
assert.Equal(t, defaults.Async.EnqueueTimeout, settings.Async.EnqueueTimeout)
117+
assert.Equal(t, defaults.Async.Timeout, settings.Async.Timeout)
118+
assert.Equal(t, defaults.Async.Durable.Dir, settings.Async.Durable.Dir)
119+
assert.Equal(t, defaults.Async.Retry.MaxAttempts, settings.Async.Retry.MaxAttempts)
120+
assert.Equal(t, defaults.Async.Retry.Backoff, settings.Async.Retry.Backoff)
121+
}
122+
123+
func TestAuditServerRuntimeSettings_InvalidProtocol(t *testing.T) {
124+
viper.Reset()
125+
viper.Set("vault.audit_protocol", "invalid")
126+
127+
_, err := auditServerRuntimeSettings()
128+
require.Error(t, err)
129+
assert.Contains(t, err.Error(), "unsupported vault.audit_protocol")
130+
}
131+
59132
func TestAuditServerCmd_RunE_InvokesGnetRun(t *testing.T) {
60133
viper.Reset()
61134
viper.Set("vault.audit_address", "bad host")

cmd/audit_config.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
"github.com/ncode/vault-audit-filter/pkg/auditserver"
8+
"github.com/spf13/viper"
9+
)
10+
11+
func auditServerRuntimeSettings() (auditserver.RuntimeSettings, error) {
12+
defaults := auditserver.DefaultRuntimeSettings()
13+
setAuditServerDefaults(defaults)
14+
15+
var ruleGroups []auditserver.RuleGroupConfig
16+
if err := viper.UnmarshalKey("rule_groups", &ruleGroups); err != nil {
17+
logger.Error("Failed to load rule groups", "error", err)
18+
return auditserver.RuntimeSettings{}, fmt.Errorf("failed to load rule groups: %w", err)
19+
}
20+
21+
protocol, err := vaultAuditProtocol()
22+
if err != nil {
23+
return auditserver.RuntimeSettings{}, err
24+
}
25+
26+
settings := defaults
27+
settings.RuleGroups = ruleGroups
28+
settings.AuditProtocol = protocol
29+
settings.Async.QueueSize = viper.GetInt("async.queue_size")
30+
settings.Async.Workers = viper.GetInt("async.workers")
31+
settings.Async.EnqueueMode = viper.GetString("async.enqueue_mode")
32+
settings.Async.EnqueueTimeout = durationSetting("async.enqueue_timeout", defaults.Async.EnqueueTimeout)
33+
settings.Async.Timeout = durationSetting("async.timeout", defaults.Async.Timeout)
34+
settings.Async.Durable.Enabled = viper.GetBool("async.durable.enabled")
35+
settings.Async.Durable.Dir = viper.GetString("async.durable.dir")
36+
settings.Async.Retry.MaxAttempts = viper.GetInt("async.retry.max_attempts")
37+
settings.Async.Retry.Backoff = durationSetting("async.retry.backoff", defaults.Async.Retry.Backoff)
38+
39+
return auditserver.NormalizeRuntimeSettings(settings, logger), nil
40+
}
41+
42+
func setAuditServerDefaults(defaults auditserver.RuntimeSettings) {
43+
viper.SetDefault("async.queue_size", defaults.Async.QueueSize)
44+
viper.SetDefault("async.workers", defaults.Async.Workers)
45+
viper.SetDefault("async.enqueue_mode", defaults.Async.EnqueueMode)
46+
viper.SetDefault("async.enqueue_timeout", defaults.Async.EnqueueTimeout.String())
47+
viper.SetDefault("async.timeout", defaults.Async.Timeout.String())
48+
viper.SetDefault("async.durable.enabled", defaults.Async.Durable.Enabled)
49+
viper.SetDefault("async.durable.dir", defaults.Async.Durable.Dir)
50+
viper.SetDefault("async.retry.max_attempts", defaults.Async.Retry.MaxAttempts)
51+
viper.SetDefault("async.retry.backoff", defaults.Async.Retry.Backoff.String())
52+
}
53+
54+
func durationSetting(key string, fallback time.Duration) time.Duration {
55+
raw := viper.GetString(key)
56+
value, err := time.ParseDuration(raw)
57+
if err != nil || value <= 0 {
58+
logger.Warn("Invalid duration config; using default", "key", key, "value", raw)
59+
return fallback
60+
}
61+
return value
62+
}

cmd/setup.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,13 @@ var setupCmd = &cobra.Command{
4343
return fmt.Errorf("unable to setup vault client: %w", err)
4444
}
4545

46-
err = client.EnableAuditDevice(
47-
viper.GetString("vault.audit_path"),
48-
"socket",
49-
viper.GetString("vault.audit_description"),
50-
map[string]string{
51-
"address": viper.GetString("vault.audit_address"),
52-
"socket_type": protocol,
53-
"description": viper.GetString("vault.audit_description"),
54-
"log_raw": "false",
55-
},
56-
)
46+
err = client.EnableSocketAuditDevice(vault.SocketAuditDeviceSpec{
47+
Path: viper.GetString("vault.audit_path"),
48+
Address: viper.GetString("vault.audit_address"),
49+
Protocol: protocol,
50+
Description: viper.GetString("vault.audit_description"),
51+
LogRaw: false,
52+
})
5753
if err != nil {
5854
return fmt.Errorf("unable to enable audit device: %w", err)
5955
}

0 commit comments

Comments
 (0)