mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 10:12:35 +00:00
VAULT-23122: Audit fix for 'log_raw' issue (#24968)
* Fix for log_raw issue on audit * Updates and test change * changelog * Update test now that the original event won't have the formatted data
This commit is contained in:
@@ -153,10 +153,26 @@ func (f *EntryFormatter) Process(ctx context.Context, e *eventlogger.Event) (*ev
|
|||||||
result = append([]byte(f.prefix), result...)
|
result = append([]byte(f.prefix), result...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the final format.
|
// Copy some properties from the event (and audit event) and store the
|
||||||
e.FormattedAs(f.config.RequiredFormat.String(), result)
|
// format for the next (sink) node to Process.
|
||||||
|
a2 := &AuditEvent{
|
||||||
|
ID: a.ID,
|
||||||
|
Version: a.Version,
|
||||||
|
Subtype: a.Subtype,
|
||||||
|
Timestamp: a.Timestamp,
|
||||||
|
Data: data, // Use the cloned data here rather than a pointer to the original.
|
||||||
|
}
|
||||||
|
|
||||||
return e, nil
|
e2 := &eventlogger.Event{
|
||||||
|
Type: e.Type,
|
||||||
|
CreatedAt: e.CreatedAt,
|
||||||
|
Formatted: make(map[string][]byte), // we are about to set this ourselves.
|
||||||
|
Payload: a2,
|
||||||
|
}
|
||||||
|
|
||||||
|
e2.FormattedAs(f.config.RequiredFormat.String(), result)
|
||||||
|
|
||||||
|
return e2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatRequest attempts to format the specified logical.LogInput into a RequestEntry.
|
// FormatRequest attempts to format the specified logical.LogInput into a RequestEntry.
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ func TestEntryFormatter_Process(t *testing.T) {
|
|||||||
tc := tc
|
tc := tc
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
e := fakeEvent(t, tc.Subtype, tc.RequiredFormat, tc.Data)
|
e := fakeEvent(t, tc.Subtype, tc.Data)
|
||||||
require.NotNil(t, e)
|
require.NotNil(t, e)
|
||||||
|
|
||||||
ss := newStaticSalt(t)
|
ss := newStaticSalt(t)
|
||||||
@@ -326,18 +326,16 @@ func TestEntryFormatter_Process(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processed, err := f.Process(ctx, e)
|
processed, err := f.Process(ctx, e)
|
||||||
b, found := e.Format(string(tc.RequiredFormat))
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case tc.IsErrorExpected:
|
case tc.IsErrorExpected:
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.EqualError(t, err, tc.ExpectedErrorMessage)
|
require.EqualError(t, err, tc.ExpectedErrorMessage)
|
||||||
require.Nil(t, processed)
|
require.Nil(t, processed)
|
||||||
require.False(t, found)
|
|
||||||
require.Nil(t, b)
|
|
||||||
default:
|
default:
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, processed)
|
require.NotNil(t, processed)
|
||||||
|
b, found := processed.Format(string(tc.RequiredFormat))
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.NotNil(t, b)
|
require.NotNil(t, b)
|
||||||
}
|
}
|
||||||
@@ -390,7 +388,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
|
|||||||
require.NotNil(b, sink)
|
require.NotNil(b, sink)
|
||||||
|
|
||||||
// Generate the event
|
// Generate the event
|
||||||
e := fakeEvent(b, RequestType, JSONFormat, in)
|
e := fakeEvent(b, RequestType, in)
|
||||||
require.NotNil(b, e)
|
require.NotNil(b, e)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
@@ -956,6 +954,63 @@ func TestEntryFormatter_FormatResponse_ElideListResponses(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestEntryFormatter_Process_NoMutation tests that the event returned by an
|
||||||
|
// EntryFormatter.Process method is not the same as the one that it accepted.
|
||||||
|
func TestEntryFormatter_Process_NoMutation(t *testing.T) {
|
||||||
|
// Create the formatter node.
|
||||||
|
cfg, err := NewFormatterConfig()
|
||||||
|
require.NoError(t, err)
|
||||||
|
ss := newStaticSalt(t)
|
||||||
|
formatter, err := NewEntryFormatter(cfg, ss)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, formatter)
|
||||||
|
|
||||||
|
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"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
e := fakeEvent(t, RequestType, in)
|
||||||
|
|
||||||
|
e2, err := formatter.Process(namespace.RootContext(nil), e)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, e2)
|
||||||
|
|
||||||
|
// Ensure the pointers are different.
|
||||||
|
require.NotEqual(t, e2, e)
|
||||||
|
|
||||||
|
// Do the same for the audit event in the payload.
|
||||||
|
a, ok := e.Payload.(*AuditEvent)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, a)
|
||||||
|
|
||||||
|
a2, ok := e2.Payload.(*AuditEvent)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, a2)
|
||||||
|
|
||||||
|
require.NotEqual(t, a2, a)
|
||||||
|
}
|
||||||
|
|
||||||
// hashExpectedValueForComparison replicates enough of the audit HMAC process on a piece of expected data in a test,
|
// hashExpectedValueForComparison replicates enough of the audit HMAC process on a piece of expected data in a test,
|
||||||
// so that we can use assert.Equal to compare the expected and output values.
|
// so that we can use assert.Equal to compare the expected and output values.
|
||||||
func (f *EntryFormatter) hashExpectedValueForComparison(input map[string]any) map[string]any {
|
func (f *EntryFormatter) hashExpectedValueForComparison(input map[string]any) map[string]any {
|
||||||
@@ -981,7 +1036,7 @@ func (f *EntryFormatter) hashExpectedValueForComparison(input map[string]any) ma
|
|||||||
|
|
||||||
// fakeEvent will return a new fake event containing audit data based on the
|
// fakeEvent will return a new fake event containing audit data based on the
|
||||||
// specified subtype, format and logical.LogInput.
|
// specified subtype, format and logical.LogInput.
|
||||||
func fakeEvent(tb testing.TB, subtype subtype, format format, input *logical.LogInput) *eventlogger.Event {
|
func fakeEvent(tb testing.TB, subtype subtype, input *logical.LogInput) *eventlogger.Event {
|
||||||
tb.Helper()
|
tb.Helper()
|
||||||
|
|
||||||
date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local)
|
date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local)
|
||||||
|
|||||||
3
changelog/24968.txt
Normal file
3
changelog/24968.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
audit: Fix bug where use of 'log_raw' option could result in other devices logging raw audit data
|
||||||
|
```
|
||||||
@@ -11,9 +11,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
|
|
||||||
"github.com/hashicorp/eventlogger"
|
"github.com/hashicorp/eventlogger"
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ eventlogger.Node = (*SocketSink)(nil)
|
var _ eventlogger.Node = (*SocketSink)(nil)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func NewStdoutSinkNode(format string) (*StdoutSink, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process persists the provided eventlogger.Event to the standard output stream.
|
// Process persists the provided eventlogger.Event to the standard output stream.
|
||||||
func (s *StdoutSink) Process(ctx context.Context, event *eventlogger.Event) (*eventlogger.Event, error) {
|
func (s *StdoutSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
|
||||||
const op = "event.(StdoutSink).Process"
|
const op = "event.(StdoutSink).Process"
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -45,11 +45,11 @@ func (s *StdoutSink) Process(ctx context.Context, event *eventlogger.Event) (*ev
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if event == nil {
|
if e == nil {
|
||||||
return nil, fmt.Errorf("%s: event is nil: %w", op, ErrInvalidParameter)
|
return nil, fmt.Errorf("%s: event is nil: %w", op, ErrInvalidParameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
formattedBytes, found := event.Format(s.requiredFormat)
|
formattedBytes, found := e.Format(s.requiredFormat)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, fmt.Errorf("%s: unable to retrieve event formatted as %q", op, s.requiredFormat)
|
return nil, fmt.Errorf("%s: unable to retrieve event formatted as %q", op, s.requiredFormat)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
gsyslog "github.com/hashicorp/go-syslog"
|
|
||||||
|
|
||||||
"github.com/hashicorp/eventlogger"
|
"github.com/hashicorp/eventlogger"
|
||||||
|
gsyslog "github.com/hashicorp/go-syslog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ eventlogger.Node = (*SyslogSink)(nil)
|
var _ eventlogger.Node = (*SyslogSink)(nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user