mirror of https://github.com/hashicorp/boundary
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
438 lines
9.8 KiB
438 lines
9.8 KiB
package event
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/eventlogger"
|
|
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestHclogFormatter_Process(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
|
|
f, e := newFilter(`op == "match-filter"`)
|
|
require.NoError(t, e)
|
|
|
|
testPredicate := newPredicate([]*filter{f}, nil)
|
|
|
|
tests := []struct {
|
|
name string
|
|
formatter *hclogFormatterFilter
|
|
e *eventlogger.Event
|
|
wantErrContains string
|
|
want []string
|
|
}{
|
|
{
|
|
name: "nil event",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
wantErrContains: "event is nil",
|
|
},
|
|
{
|
|
name: "invalid-event-type",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
e: &eventlogger.Event{Type: eventlogger.EventType("invalid-type")},
|
|
wantErrContains: "unknown event type invalid-type",
|
|
},
|
|
{
|
|
name: "sys-text",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(SystemType),
|
|
Payload: &sysEvent{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Op: Op("text"),
|
|
Data: map[string]any{
|
|
"msg": "hello",
|
|
},
|
|
},
|
|
},
|
|
want: []string{
|
|
"[INFO] system event:",
|
|
"data:msg=hello",
|
|
"version=v0.1",
|
|
"op=text",
|
|
},
|
|
},
|
|
{
|
|
name: "observation-text",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(ObservationType),
|
|
Payload: map[string]any{
|
|
"id": "1",
|
|
"version": observationVersion,
|
|
"latency-ms": 10,
|
|
},
|
|
},
|
|
want: []string{
|
|
"[INFO] observation event:",
|
|
"latency-ms=10",
|
|
"id=1",
|
|
"version=v0.1",
|
|
},
|
|
},
|
|
{
|
|
name: "observation-json",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: true,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(ObservationType),
|
|
Payload: map[string]any{
|
|
"id": "1",
|
|
"version": observationVersion,
|
|
"latency-ms": 10,
|
|
},
|
|
},
|
|
want: []string{
|
|
"{\"@level\":\"info\",\"@message\":\"observation event\"",
|
|
"\"latency-ms\":10",
|
|
"\"id\":\"1\"",
|
|
"\"version\":\"v0.1\"}\n",
|
|
},
|
|
},
|
|
{
|
|
name: "err-text",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(ErrorType),
|
|
Payload: &err{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Error: ErrInvalidParameter.Error(),
|
|
Op: Op("text"),
|
|
},
|
|
},
|
|
want: []string{
|
|
"[ERROR] error event:",
|
|
"error=\"invalid parameter\"",
|
|
"id=1",
|
|
"version=v0.1",
|
|
"op=text",
|
|
},
|
|
},
|
|
{
|
|
name: "err-json",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: true,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(ErrorType),
|
|
Payload: &err{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Error: ErrInvalidParameter.Error(),
|
|
Op: Op("text"),
|
|
},
|
|
},
|
|
want: []string{
|
|
"{\"@level\":\"error\",\"@message\":\"error event\"",
|
|
"\"error\":\"invalid parameter\"",
|
|
"\"id\":\"1\"",
|
|
"\"version\":\"v0.1\"",
|
|
"\"op\":\"text\"",
|
|
},
|
|
},
|
|
{
|
|
name: "err-text-with-optional",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(ErrorType),
|
|
Payload: &err{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Error: ErrInvalidParameter.Error(),
|
|
Op: Op("text"),
|
|
Info: map[string]any{"name": "alice"},
|
|
},
|
|
},
|
|
want: []string{
|
|
"[ERROR] error event:",
|
|
"error=\"invalid parameter\"",
|
|
"id=1",
|
|
"version=v0.1",
|
|
"info:name=alice",
|
|
"op=text",
|
|
},
|
|
},
|
|
{
|
|
name: "filter-match",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
predicate: testPredicate,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(SystemType),
|
|
Payload: &sysEvent{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Op: Op("match-filter"),
|
|
Data: map[string]any{
|
|
"msg": "hello",
|
|
},
|
|
},
|
|
},
|
|
want: []string{
|
|
"[INFO] system event:",
|
|
"data:msg=hello",
|
|
"version=v0.1",
|
|
"op=match-filter",
|
|
},
|
|
},
|
|
{
|
|
name: "filter-no-match",
|
|
formatter: &hclogFormatterFilter{
|
|
jsonFormat: false,
|
|
predicate: testPredicate,
|
|
},
|
|
e: &eventlogger.Event{
|
|
Type: eventlogger.EventType(SystemType),
|
|
Payload: &sysEvent{
|
|
Id: "1",
|
|
Version: errorVersion,
|
|
Op: Op("doesn't match"),
|
|
Data: map[string]any{
|
|
"msg": "hello",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
e, err := tt.formatter.Process(ctx, tt.e)
|
|
if tt.wantErrContains != "" {
|
|
require.Error(err)
|
|
assert.Contains(err.Error(), tt.wantErrContains)
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
if len(tt.want) == 0 {
|
|
assert.Nil(e)
|
|
return
|
|
}
|
|
assert.NotNil(e)
|
|
var b []byte
|
|
var ok bool
|
|
switch tt.formatter.jsonFormat {
|
|
case true:
|
|
b, ok = e.Format(string(JSONHclogSinkFormat))
|
|
case false:
|
|
b, ok = e.Format(string(TextHclogSinkFormat))
|
|
}
|
|
t.Log(string(b))
|
|
require.True(ok)
|
|
for _, txt := range tt.want {
|
|
assert.Contains(string(b), txt)
|
|
}
|
|
})
|
|
}
|
|
t.Run("with-signing", func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
wrapper := testWrapper(t)
|
|
f, err := newHclogFormatterFilter(true) // produce json formatted events
|
|
require.NoError(err)
|
|
require.NoError(f.Rotate(wrapper))
|
|
require.NotNil(f.signer)
|
|
|
|
e := &eventlogger.Event{
|
|
Type: eventlogger.EventType(AuditType),
|
|
Payload: &audit{
|
|
Id: "1",
|
|
Version: auditVersion,
|
|
Auth: &Auth{UserName: "alice"},
|
|
},
|
|
}
|
|
|
|
gotEvent, err := f.Process(ctx, e)
|
|
require.NoError(err)
|
|
b, ok := gotEvent.Format(string(JSONHclogSinkFormat))
|
|
require.True(ok)
|
|
var rep map[string]any
|
|
require.NoError(json.Unmarshal(b, &rep))
|
|
assert.NotEmpty(rep["serialized"])
|
|
assert.NotEmpty(rep["serialized_hmac"])
|
|
})
|
|
}
|
|
|
|
func Test_hclogFormatterFilter_Name(t *testing.T) {
|
|
t.Parallel()
|
|
t.Run("simple", func(t *testing.T) {
|
|
ff := &hclogFormatterFilter{}
|
|
assert.Equal(t, hclogNodeName, ff.Name())
|
|
})
|
|
}
|
|
|
|
func Test_hclogFormatterFilter_Reopen(t *testing.T) {
|
|
t.Parallel()
|
|
t.Run("simple", func(t *testing.T) {
|
|
ff := &hclogFormatterFilter{}
|
|
assert.Equal(t, nil, ff.Reopen())
|
|
})
|
|
}
|
|
|
|
func Test_hclogFormatterFilter_Type(t *testing.T) {
|
|
t.Parallel()
|
|
t.Run("simple", func(t *testing.T) {
|
|
ff := &hclogFormatterFilter{}
|
|
assert.Equal(t, eventlogger.NodeTypeFormatterFilter, ff.Type())
|
|
})
|
|
}
|
|
|
|
func Test_newHclogFormatterFilter(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
jsonFormat bool
|
|
opt []Option
|
|
wantErr bool
|
|
wantIsError error
|
|
wantErrContains string
|
|
wantAllow []string
|
|
wantDeny []string
|
|
}{
|
|
{
|
|
name: "no-opts",
|
|
},
|
|
{
|
|
name: "bad-allow-filter",
|
|
jsonFormat: true,
|
|
opt: []Option{
|
|
WithAllow("foo=;22", "foo==bar"),
|
|
},
|
|
wantErr: true,
|
|
wantErrContains: "invalid allow filter 'foo=;22'",
|
|
},
|
|
{
|
|
name: "bad-deny-filter",
|
|
jsonFormat: true,
|
|
opt: []Option{
|
|
WithDeny("foo=;22", "foo==bar"),
|
|
},
|
|
wantErr: true,
|
|
wantErrContains: "invalid deny filter 'foo=;22'",
|
|
},
|
|
{
|
|
name: "empty-allow-filter",
|
|
jsonFormat: true,
|
|
opt: []Option{
|
|
WithAllow(""),
|
|
},
|
|
wantErr: true,
|
|
wantErrContains: "missing filter",
|
|
},
|
|
{
|
|
name: "empty-deny-filter",
|
|
jsonFormat: true,
|
|
opt: []Option{
|
|
WithDeny(""),
|
|
},
|
|
wantErr: true,
|
|
wantErrContains: "missing filter",
|
|
},
|
|
{
|
|
name: "valid-filters",
|
|
jsonFormat: true,
|
|
opt: []Option{
|
|
WithAllow("alice==friend", "bob==friend"),
|
|
WithDeny("eve==acquaintance", "fido!=dog"),
|
|
},
|
|
wantAllow: []string{"alice==friend", "bob==friend"},
|
|
wantDeny: []string{"eve==acquaintance", "fido!=dog"},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
got, err := newHclogFormatterFilter(tt.jsonFormat, tt.opt...)
|
|
if tt.wantErr {
|
|
require.Error(err)
|
|
assert.Nil(got)
|
|
if tt.wantIsError != nil {
|
|
assert.ErrorIs(err, tt.wantIsError)
|
|
}
|
|
if tt.wantErrContains != "" {
|
|
assert.Contains(err.Error(), tt.wantErrContains)
|
|
}
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
assert.NotNil(got)
|
|
|
|
assert.Equal(tt.jsonFormat, got.jsonFormat)
|
|
|
|
assert.Len(got.allow, len(tt.wantAllow))
|
|
for _, f := range got.allow {
|
|
assert.Contains(tt.wantAllow, f.raw)
|
|
}
|
|
assert.Len(got.deny, len(tt.wantDeny)+1) // +1 since there's always a default deny
|
|
defs, err := defaultHclogEventsDenyFilters()
|
|
require.NoError(err)
|
|
for _, f := range defs {
|
|
tt.wantDeny = append(tt.wantDeny, f.raw)
|
|
}
|
|
for _, f := range got.deny {
|
|
assert.Contains(tt.wantDeny, f.raw)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_hclogFormatterFilter_Rotate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
f *hclogFormatterFilter
|
|
w wrapping.Wrapper
|
|
wantIsError error
|
|
wantErrContains string
|
|
}{
|
|
{
|
|
name: "missing-wrapper",
|
|
f: &hclogFormatterFilter{},
|
|
wantIsError: ErrInvalidParameter,
|
|
wantErrContains: "missing wrapper",
|
|
},
|
|
{
|
|
name: "valid",
|
|
f: &hclogFormatterFilter{},
|
|
w: testWrapper(t),
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
err := tt.f.Rotate(tt.w)
|
|
if tt.wantIsError != nil {
|
|
require.Error(err)
|
|
assert.ErrorIs(err, tt.wantIsError)
|
|
if tt.wantErrContains != "" {
|
|
assert.Contains(err.Error(), tt.wantErrContains)
|
|
}
|
|
return
|
|
}
|
|
assert.NotNil(tt.f.signer)
|
|
})
|
|
}
|
|
}
|