-
Notifications
You must be signed in to change notification settings - Fork 4.1k
/
broker_test.go
209 lines (179 loc) · 5.88 KB
/
broker_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package audit
import (
"context"
"crypto/sha256"
"testing"
"time"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
)
// testAuditBackend will create an audit.Backend (which expects to use the eventlogger).
// NOTE: this will create the backend, it does not care whether Enterprise only options are in place.
func testAuditBackend(t *testing.T, path string, config map[string]string) Backend {
t.Helper()
headersCfg := &HeadersConfig{
headerSettings: make(map[string]*HeaderSettings),
view: nil,
}
view := &logical.InmemStorage{}
se := &logical.StorageEntry{Key: "salt", Value: []byte("juan")}
err := view.Put(context.Background(), se)
require.NoError(t, err)
cfg := &BackendConfig{
SaltView: view,
SaltConfig: &salt.Config{
HMAC: sha256.New,
HMACType: "hmac-sha256",
},
Logger: corehelpers.NewTestLogger(t),
Config: config,
MountPath: path,
}
be, err := NewSyslogBackend(cfg, headersCfg)
require.NoError(t, err)
require.NotNil(t, be)
return be
}
// TestAuditBroker_Deregister_Multiple ensures that we can call deregister multiple
// times without issue if is no matching backend registered.
func TestAuditBroker_Deregister_Multiple(t *testing.T) {
t.Parallel()
l := corehelpers.NewTestLogger(t)
a, err := NewBroker(l)
require.NoError(t, err)
require.NotNil(t, a)
err = a.Deregister(context.Background(), "foo")
require.NoError(t, err)
err = a.Deregister(context.Background(), "foo2")
require.NoError(t, err)
}
// TestAuditBroker_Register_MultipleFails checks for failure when we try to
// re-register an audit backend.
func TestAuditBroker_Register_MultipleFails(t *testing.T) {
t.Parallel()
l := corehelpers.NewTestLogger(t)
a, err := NewBroker(l)
require.NoError(t, err)
require.NotNil(t, a)
path := "b2-no-filter"
noFilterBackend := testAuditBackend(t, path, map[string]string{})
err = a.Register(noFilterBackend, false)
require.NoError(t, err)
err = a.Register(noFilterBackend, false)
require.Error(t, err)
require.EqualError(t, err, "backend already registered 'b2-no-filter': invalid configuration")
}
// BenchmarkAuditBroker_File_Request_DevNull Attempts to register a single `file`
// audit device on the broker, which points at /dev/null.
// It will then attempt to benchmark how long it takes Vault to complete logging
// a request, this really only shows us how Vault can handle lots of calls to the
// broker to trigger the eventlogger pipelines that audit devices are configured as.
// Since we aren't writing anything to file or doing any I/O.
// This test used to live in the file package for the file backend, but once the
// move to eventlogger was complete, there wasn't a way to create a file backend
// and manually just write to the underlying file itself, the old code used to do
// formatting and writing all together, but we've split this up with eventlogger
// with different nodes in a pipeline (think 1 audit device:1 pipeline) each
// handling a responsibility, for example:
// filter nodes filter events, so you can select which ones make it to your audit log
// formatter nodes format the events (to JSON/JSONX and perform HMACing etc)
// sink nodes handle sending the formatted data to a file, syslog or socket.
func BenchmarkAuditBroker_File_Request_DevNull(b *testing.B) {
backendConfig := &BackendConfig{
Config: map[string]string{
"path": "/dev/null",
},
MountPath: "test",
SaltConfig: &salt.Config{},
SaltView: &logical.InmemStorage{},
Logger: hclog.NewNullLogger(),
}
sink, err := NewFileBackend(backendConfig, nil)
require.NoError(b, err)
broker, err := NewBroker(nil)
require.NoError(b, err)
err = broker.Register(sink, false)
require.NoError(b, err)
in := &logical.LogInput{
Auth: &logical.Auth{
ClientToken: "foo",
Accessor: "bar",
EntityID: "foobarentity",
DisplayName: "testtoken",
NoDefaultPolicy: true,
Policies: []string{"root"},
TokenType: logical.TokenTypeService,
},
Request: &logical.Request{
Operation: logical.UpdateOperation,
Path: "/foo",
Connection: &logical.Connection{
RemoteAddr: "127.0.0.1",
},
WrapInfo: &logical.RequestWrapInfo{
TTL: 60 * time.Second,
},
Headers: map[string][]string{
"foo": {"bar"},
},
},
}
ctx := namespace.RootContext(context.Background())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := broker.LogRequest(ctx, in); err != nil {
panic(err)
}
}
})
}
// TestBroker_isContextViable_basics checks the expected result of isContextViable
// for basic inputs such as nil and a never-ending context.
func TestBroker_isContextViable_basics(t *testing.T) {
t.Parallel()
require.False(t, isContextViable(nil))
require.True(t, isContextViable(context.Background()))
}
// TestBroker_isContextViable_timeouts checks the expected result of isContextViable
// for various timeout durations.
func TestBroker_isContextViable_timeouts(t *testing.T) {
t.Parallel()
tests := map[string]struct {
timeout time.Duration
expected bool
}{
"2s-smaller-deadline": {
timeout: timeout - 2*time.Second,
expected: false,
},
"same-deadline": {
timeout: timeout,
expected: false, // Expected as a near miss
},
"same-deadline-plus": {
timeout: timeout + 5*time.Millisecond,
expected: true,
},
"2x-longer-deadline": {
timeout: timeout * 2,
expected: true,
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), tc.timeout)
t.Cleanup(func() { cancel() })
require.Equal(t, tc.expected, isContextViable(ctx))
})
}
}