mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-06 14:47:01 +02:00
unexport as much as possible in the audit package (#28039)
This commit is contained in:
parent
88975a6c24
commit
a19195c901
@ -20,9 +20,9 @@ const (
|
||||
optionMode = "mode"
|
||||
)
|
||||
|
||||
var _ Backend = (*FileBackend)(nil)
|
||||
var _ Backend = (*fileBackend)(nil)
|
||||
|
||||
type FileBackend struct {
|
||||
type fileBackend struct {
|
||||
*backend
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ func NewFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Back
|
||||
}
|
||||
|
||||
// newFileBackend creates a backend and configures all nodes including a file sink.
|
||||
func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBackend, error) {
|
||||
func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*fileBackend, error) {
|
||||
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
|
||||
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -60,7 +60,7 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := &FileBackend{backend: bec}
|
||||
b := &fileBackend{backend: bec}
|
||||
|
||||
// normalize file path if configured for stdout
|
||||
if strings.EqualFold(filePath, stdout) {
|
||||
@ -89,9 +89,9 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// configureSinkNode is used internally by FileBackend to create and configure the
|
||||
// configureSinkNode is used internally by fileBackend to create and configure the
|
||||
// sink node on the backend.
|
||||
func (b *FileBackend) configureSinkNode(name string, filePath string, format format, opt ...event.Option) error {
|
||||
func (b *fileBackend) configureSinkNode(name string, filePath string, format format, opt ...event.Option) error {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return fmt.Errorf("name is required: %w", ErrExternalOptions)
|
||||
@ -143,7 +143,7 @@ func (b *FileBackend) configureSinkNode(name string, filePath string, format for
|
||||
}
|
||||
|
||||
// Reload will trigger the reload action on the sink node for this backend.
|
||||
func (b *FileBackend) Reload() error {
|
||||
func (b *fileBackend) Reload() error {
|
||||
for _, n := range b.nodeMap {
|
||||
if n.Type() == eventlogger.NodeTypeSink {
|
||||
return n.Reopen()
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// TestFileBackend_newFileBackend_fallback ensures that we get the correct errors
|
||||
// in CE when we try to enable a FileBackend with enterprise options like fallback
|
||||
// in CE when we try to enable a fileBackend with enterprise options like fallback
|
||||
// and filter.
|
||||
func TestFileBackend_newFileBackend_fallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
@ -62,7 +62,7 @@ func TestFileBackend_newFileBackend_fallback(t *testing.T) {
|
||||
name := name
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
be, err := newFileBackend(tc.backendConfig, &NoopHeaderFormatter{})
|
||||
be, err := newFileBackend(tc.backendConfig, &noopHeaderFormatter{})
|
||||
|
||||
if tc.isErrorExpected {
|
||||
require.Error(t, err)
|
||||
@ -97,13 +97,13 @@ func TestFileBackend_newFileBackend_FilterFormatterSink(t *testing.T) {
|
||||
Logger: hclog.NewNullLogger(),
|
||||
}
|
||||
|
||||
b, err := newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
b, err := newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
|
||||
|
||||
// Try without filter option
|
||||
delete(cfg, "filter")
|
||||
b, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
b, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, b.nodeIDList, 2)
|
||||
@ -133,14 +133,14 @@ func TestBackend_IsFallback(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
be, err := newFileBackend(cfg, &NoopHeaderFormatter{})
|
||||
be, err := newFileBackend(cfg, &noopHeaderFormatter{})
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
|
||||
|
||||
// Remove the option and try again
|
||||
delete(cfg.Config, "fallback")
|
||||
|
||||
be, err = newFileBackend(cfg, &NoopHeaderFormatter{})
|
||||
be, err = newFileBackend(cfg, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, be)
|
||||
require.Equal(t, false, be.IsFallback())
|
||||
|
@ -38,7 +38,7 @@ func TestAuditFile_fileModeNew(t *testing.T) {
|
||||
SaltView: &logical.InmemStorage{},
|
||||
Logger: hclog.NewNullLogger(),
|
||||
}
|
||||
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
_, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := os.Stat(file)
|
||||
@ -71,7 +71,7 @@ func TestAuditFile_fileModeExisting(t *testing.T) {
|
||||
Logger: hclog.NewNullLogger(),
|
||||
}
|
||||
|
||||
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
_, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := os.Stat(f.Name())
|
||||
@ -105,7 +105,7 @@ func TestAuditFile_fileMode0000(t *testing.T) {
|
||||
Logger: hclog.NewNullLogger(),
|
||||
}
|
||||
|
||||
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
_, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := os.Stat(f.Name())
|
||||
@ -134,7 +134,7 @@ func TestAuditFile_EventLogger_fileModeNew(t *testing.T) {
|
||||
Logger: hclog.NewNullLogger(),
|
||||
}
|
||||
|
||||
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
|
||||
_, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := os.Stat(file)
|
||||
@ -267,7 +267,7 @@ func TestFileBackend_newFileBackend(t *testing.T) {
|
||||
},
|
||||
MountPath: tc.mountPath,
|
||||
}
|
||||
b, err := newFileBackend(cfg, &NoopHeaderFormatter{})
|
||||
b, err := newFileBackend(cfg, &noopHeaderFormatter{})
|
||||
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
|
@ -35,14 +35,17 @@ type noopWrapper struct {
|
||||
backend *NoopAudit
|
||||
}
|
||||
|
||||
// NoopAuditEventListener is a callback used by noopWrapper.Process() to notify
|
||||
// of each received audit event.
|
||||
type NoopAuditEventListener func(*AuditEvent)
|
||||
|
||||
func (n *NoopAudit) SetListener(listener NoopAuditEventListener) {
|
||||
// SetListener provides a callback func to the NoopAudit which can be invoked
|
||||
// during processing of the Event.
|
||||
//
|
||||
// Deprecated: SetListener should not be used in new tests.
|
||||
func (n *NoopAudit) SetListener(listener func(event *Event)) {
|
||||
n.listener = listener
|
||||
}
|
||||
|
||||
// NoopAudit only exists to allow legacy tests to continue working.
|
||||
//
|
||||
// Deprecated: NoopAudit should not be used in new tests.
|
||||
type NoopAudit struct {
|
||||
Config *BackendConfig
|
||||
|
||||
@ -68,16 +71,16 @@ type NoopAudit struct {
|
||||
nodeIDList []eventlogger.NodeID
|
||||
nodeMap map[eventlogger.NodeID]eventlogger.Node
|
||||
|
||||
listener NoopAuditEventListener
|
||||
listener func(event *Event)
|
||||
}
|
||||
|
||||
// NoopHeaderFormatter can be used within no-op audit devices to do nothing when
|
||||
// noopHeaderFormatter can be used within no-op audit devices to do nothing when
|
||||
// it comes to only allow configured headers to appear in the result.
|
||||
// Whatever is passed in will be returned (nil becomes an empty map) in lowercase.
|
||||
type NoopHeaderFormatter struct{}
|
||||
type noopHeaderFormatter struct{}
|
||||
|
||||
// ApplyConfig implements the relevant interface to make NoopHeaderFormatter an HeaderFormatter.
|
||||
func (f *NoopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string][]string, _ Salter) (result map[string][]string, retErr error) {
|
||||
// ApplyConfig implements the relevant interface to make noopHeaderFormatter an HeaderFormatter.
|
||||
func (f *noopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string][]string, _ Salter) (result map[string][]string, retErr error) {
|
||||
if len(headers) < 1 {
|
||||
return map[string][]string{}, nil
|
||||
}
|
||||
@ -95,6 +98,8 @@ func (f *NoopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string]
|
||||
// NewNoopAudit should be used to create a NoopAudit as it handles creation of a
|
||||
// predictable salt and wraps eventlogger nodes so information can be retrieved on
|
||||
// what they've seen or formatted.
|
||||
//
|
||||
// Deprecated: NewNoopAudit only exists to allow legacy tests to continue working.
|
||||
func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
|
||||
view := &logical.InmemStorage{}
|
||||
|
||||
@ -122,7 +127,7 @@ func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
|
||||
nodeMap: make(map[eventlogger.NodeID]eventlogger.Node, 2),
|
||||
}
|
||||
|
||||
cfg, err := newFormatterConfig(&NoopHeaderFormatter{}, nil)
|
||||
cfg, err := newFormatterConfig(&noopHeaderFormatter{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -158,6 +163,8 @@ func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
|
||||
// NoopAuditFactory should be used when the test needs a way to access bytes that
|
||||
// have been formatted by the pipeline during audit requests.
|
||||
// The records parameter will be repointed to the one used within the pipeline.
|
||||
//
|
||||
// Deprecated: NoopAuditFactory only exists to allow legacy tests to continue working.
|
||||
func NoopAuditFactory(records **[][]byte) Factory {
|
||||
return func(config *BackendConfig, _ HeaderFormatter) (Backend, error) {
|
||||
n, err := NewNoopAudit(config)
|
||||
@ -184,7 +191,7 @@ func (n *noopWrapper) Process(ctx context.Context, e *eventlogger.Event) (*event
|
||||
var err error
|
||||
|
||||
// We're expecting audit events since this is an audit device.
|
||||
a, ok := e.Payload.(*AuditEvent)
|
||||
a, ok := e.Payload.(*Event)
|
||||
if !ok {
|
||||
return nil, errors.New("cannot parse payload as an audit event")
|
||||
}
|
||||
@ -244,7 +251,7 @@ func (n *noopWrapper) Process(ctx context.Context, e *eventlogger.Event) (*event
|
||||
// formatted headers that would have made it to the logs via the sink node.
|
||||
// They only appear in requests.
|
||||
if a.Subtype == RequestType {
|
||||
reqEntry := &Entry{}
|
||||
reqEntry := &entry{}
|
||||
err = json.Unmarshal(b, &reqEntry)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse formatted audit entry data: %w", err)
|
||||
@ -336,6 +343,7 @@ func (n *NoopAudit) IsFallback() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Deprecated: TestNoopAudit only exists to allow legacy tests to continue working.
|
||||
func TestNoopAudit(t *testing.T, path string, config map[string]string) *NoopAudit {
|
||||
cfg := &BackendConfig{
|
||||
Config: config,
|
||||
|
@ -18,9 +18,9 @@ const (
|
||||
optionWriteTimeout = "write_timeout"
|
||||
)
|
||||
|
||||
var _ Backend = (*SocketBackend)(nil)
|
||||
var _ Backend = (*socketBackend)(nil)
|
||||
|
||||
type SocketBackend struct {
|
||||
type socketBackend struct {
|
||||
*backend
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ func NewSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Ba
|
||||
}
|
||||
|
||||
// newSocketBackend creates a backend and configures all nodes including a socket sink.
|
||||
func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*SocketBackend, error) {
|
||||
func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*socketBackend, error) {
|
||||
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
|
||||
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -78,7 +78,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b := &SocketBackend{backend: bec}
|
||||
b := &socketBackend{backend: bec}
|
||||
|
||||
// Configure the sink.
|
||||
cfg, err := newFormatterConfig(headersConfig, conf.Config)
|
||||
@ -94,7 +94,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *SocketBackend) configureSinkNode(name string, address string, format format, opts ...event.Option) error {
|
||||
func (b *socketBackend) configureSinkNode(name string, address string, format format, opts ...event.Option) error {
|
||||
sinkNodeID, err := event.GenerateNodeID()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating random NodeID for sink node: %w", err)
|
||||
@ -115,7 +115,7 @@ func (b *SocketBackend) configureSinkNode(name string, address string, format fo
|
||||
}
|
||||
|
||||
// Reload will trigger the reload action on the sink node for this backend.
|
||||
func (b *SocketBackend) Reload() error {
|
||||
func (b *socketBackend) Reload() error {
|
||||
for _, n := range b.nodeMap {
|
||||
if n.Type() == eventlogger.NodeTypeSink {
|
||||
return n.Reopen()
|
||||
|
@ -114,7 +114,7 @@ func TestSocketBackend_newSocketBackend(t *testing.T) {
|
||||
},
|
||||
MountPath: tc.mountPath,
|
||||
}
|
||||
b, err := newSocketBackend(cfg, &NoopHeaderFormatter{})
|
||||
b, err := newSocketBackend(cfg, &noopHeaderFormatter{})
|
||||
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
|
@ -15,9 +15,9 @@ const (
|
||||
optionTag = "tag"
|
||||
)
|
||||
|
||||
var _ Backend = (*SyslogBackend)(nil)
|
||||
var _ Backend = (*syslogBackend)(nil)
|
||||
|
||||
type SyslogBackend struct {
|
||||
type syslogBackend struct {
|
||||
*backend
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ func NewSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Ba
|
||||
}
|
||||
|
||||
// newSyslogBackend creates a backend and configures all nodes including a socket sink.
|
||||
func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*SyslogBackend, error) {
|
||||
func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*syslogBackend, error) {
|
||||
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
|
||||
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -68,7 +68,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b := &SyslogBackend{backend: bec}
|
||||
b := &syslogBackend{backend: bec}
|
||||
|
||||
// Configure the sink.
|
||||
cfg, err := newFormatterConfig(headersConfig, conf.Config)
|
||||
@ -84,7 +84,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *SyslogBackend) configureSinkNode(name string, format format, opts ...event.Option) error {
|
||||
func (b *syslogBackend) configureSinkNode(name string, format format, opts ...event.Option) error {
|
||||
sinkNodeID, err := event.GenerateNodeID()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating random NodeID for sink node: %w: %w", ErrInternal, err)
|
||||
@ -104,6 +104,6 @@ func (b *SyslogBackend) configureSinkNode(name string, format format, opts ...ev
|
||||
}
|
||||
|
||||
// Reload will trigger the reload action on the sink node for this backend.
|
||||
func (b *SyslogBackend) Reload() error {
|
||||
func (b *syslogBackend) Reload() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func TestSyslogBackend_newSyslogBackend(t *testing.T) {
|
||||
},
|
||||
MountPath: tc.mountPath,
|
||||
}
|
||||
b, err := newSyslogBackend(cfg, &NoopHeaderFormatter{})
|
||||
b, err := newSyslogBackend(cfg, &noopHeaderFormatter{})
|
||||
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
|
@ -25,7 +25,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
}{
|
||||
"happy-path-json": {
|
||||
config: map[string]string{
|
||||
"format": JSONFormat.String(),
|
||||
"format": jsonFormat.String(),
|
||||
"hmac_accessor": "true",
|
||||
"log_raw": "true",
|
||||
"elide_list_responses": "true",
|
||||
@ -39,7 +39,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
},
|
||||
"happy-path-jsonx": {
|
||||
config: map[string]string{
|
||||
"format": JSONxFormat.String(),
|
||||
"format": jsonxFormat.String(),
|
||||
"hmac_accessor": "true",
|
||||
"log_raw": "true",
|
||||
"elide_list_responses": "true",
|
||||
@ -65,7 +65,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
},
|
||||
"invalid-hmac-accessor": {
|
||||
config: map[string]string{
|
||||
"format": JSONFormat.String(),
|
||||
"format": jsonFormat.String(),
|
||||
"hmac_accessor": "maybe",
|
||||
},
|
||||
want: formatterConfig{},
|
||||
@ -74,7 +74,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
},
|
||||
"invalid-log-raw": {
|
||||
config: map[string]string{
|
||||
"format": JSONFormat.String(),
|
||||
"format": jsonFormat.String(),
|
||||
"hmac_accessor": "true",
|
||||
"log_raw": "maybe",
|
||||
},
|
||||
@ -84,7 +84,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
},
|
||||
"invalid-elide-bool": {
|
||||
config: map[string]string{
|
||||
"format": JSONFormat.String(),
|
||||
"format": jsonFormat.String(),
|
||||
"hmac_accessor": "true",
|
||||
"log_raw": "true",
|
||||
"elide_list_responses": "maybe",
|
||||
@ -95,11 +95,11 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
},
|
||||
"prefix": {
|
||||
config: map[string]string{
|
||||
"format": JSONFormat.String(),
|
||||
"format": jsonFormat.String(),
|
||||
"prefix": "foo",
|
||||
},
|
||||
want: formatterConfig{
|
||||
requiredFormat: JSONFormat,
|
||||
requiredFormat: jsonFormat,
|
||||
prefix: "foo",
|
||||
hmacAccessor: true,
|
||||
},
|
||||
@ -111,7 +111,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got, err := newFormatterConfig(&NoopHeaderFormatter{}, tc.config)
|
||||
got, err := newFormatterConfig(&noopHeaderFormatter{}, tc.config)
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, tc.expectedMessage)
|
||||
@ -133,7 +133,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
|
||||
func TestBackend_configureFormatterNode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
b, err := newBackend(&NoopHeaderFormatter{}, &BackendConfig{
|
||||
b, err := newBackend(&noopHeaderFormatter{}, &BackendConfig{
|
||||
MountPath: "foo",
|
||||
Logger: hclog.NewNullLogger(),
|
||||
})
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/armon/go-metrics"
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/internal/observability/event"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
@ -270,7 +270,7 @@ func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (retErr e
|
||||
metrics.IncrCounter([]string{"audit", "log_request_failure"}, metricVal)
|
||||
}()
|
||||
|
||||
e, err := NewEvent(RequestType)
|
||||
e, err := newEvent(RequestType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -289,14 +289,14 @@ func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (retErr e
|
||||
// has taken up a lot of time handling the request before audit (request)
|
||||
// is triggered. Pipeline nodes and the eventlogger.Broker may check for a
|
||||
// cancelled context and refuse to process the nodes further.
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
ns, err := nshelper.FromContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("namespace missing from context: %w", err)
|
||||
}
|
||||
|
||||
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer auditCancel()
|
||||
auditContext = namespace.ContextWithNamespace(tempContext, ns)
|
||||
auditContext = nshelper.ContextWithNamespace(tempContext, ns)
|
||||
}
|
||||
|
||||
var status eventlogger.Status
|
||||
@ -352,7 +352,7 @@ func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (retErr
|
||||
metrics.IncrCounter([]string{"audit", "log_response_failure"}, metricVal)
|
||||
}()
|
||||
|
||||
e, err := NewEvent(ResponseType)
|
||||
e, err := newEvent(ResponseType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -371,14 +371,14 @@ func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (retErr
|
||||
// has taken up a lot of time handling the request before audit (response)
|
||||
// is triggered. Pipeline nodes and the eventlogger.Broker may check for a
|
||||
// cancelled context and refuse to process the nodes further.
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
ns, err := nshelper.FromContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("namespace missing from context: %w", err)
|
||||
}
|
||||
|
||||
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer auditCancel()
|
||||
auditContext = namespace.ContextWithNamespace(tempContext, ns)
|
||||
auditContext = nshelper.ContextWithNamespace(tempContext, ns)
|
||||
}
|
||||
|
||||
var status eventlogger.Status
|
||||
|
@ -44,6 +44,6 @@ func (b *Broker) requiredSuccessThresholdSinks() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *AuditEvent) error {
|
||||
func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *Event) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "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"
|
||||
@ -23,7 +23,7 @@ func testAuditBackend(t *testing.T, path string, config map[string]string) Backe
|
||||
t.Helper()
|
||||
|
||||
headersCfg := &HeadersConfig{
|
||||
headerSettings: make(map[string]*HeaderSettings),
|
||||
headerSettings: make(map[string]*headerSettings),
|
||||
view: nil,
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ func BenchmarkAuditBroker_File_Request_DevNull(b *testing.B) {
|
||||
},
|
||||
}
|
||||
|
||||
ctx := namespace.RootContext(context.Background())
|
||||
ctx := nshelper.RootContext(context.Background())
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/go-bexpr"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
@ -71,7 +71,7 @@ func (f *entryFilter) Process(ctx context.Context, e *eventlogger.Event) (*event
|
||||
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
|
||||
}
|
||||
|
||||
a, ok := e.Payload.(*AuditEvent)
|
||||
a, ok := e.Payload.(*Event)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -81,7 +81,7 @@ func (f *entryFilter) Process(ctx context.Context, e *eventlogger.Event) (*event
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
ns, err := nshelper.FromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot obtain namespace: %w", err)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/internal/observability/event"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -117,7 +117,7 @@ func TestEntryFilter_Process_ContextDone(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Fake audit event
|
||||
a, err := NewEvent(RequestType)
|
||||
a, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Fake event logger event
|
||||
@ -184,7 +184,7 @@ func TestEntryFilter_Process_NoAuditDataInPayload(t *testing.T) {
|
||||
l, err := newEntryFilter("operation == foo")
|
||||
require.NoError(t, err)
|
||||
|
||||
a, err := NewEvent(RequestType)
|
||||
a, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure audit data is nil
|
||||
@ -212,7 +212,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
|
||||
l, err := newEntryFilter("mount_type == juan")
|
||||
require.NoError(t, err)
|
||||
|
||||
a, err := NewEvent(RequestType)
|
||||
a, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
|
||||
a.Data = &logical.LogInput{
|
||||
@ -229,7 +229,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
|
||||
Payload: a,
|
||||
}
|
||||
|
||||
ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
|
||||
ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
|
||||
|
||||
e2, err := l.Process(ctx, e)
|
||||
|
||||
@ -245,7 +245,7 @@ func TestEntryFilter_Process_FilterFail(t *testing.T) {
|
||||
l, err := newEntryFilter("mount_type == john and operation == create and namespace == root")
|
||||
require.NoError(t, err)
|
||||
|
||||
a, err := NewEvent(RequestType)
|
||||
a, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
|
||||
a.Data = &logical.LogInput{
|
||||
@ -262,7 +262,7 @@ func TestEntryFilter_Process_FilterFail(t *testing.T) {
|
||||
Payload: a,
|
||||
}
|
||||
|
||||
ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
|
||||
ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
|
||||
|
||||
e2, err := l.Process(ctx, e)
|
||||
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/salt"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
@ -77,7 +77,7 @@ func (*entryFormatter) Type() eventlogger.NodeType {
|
||||
}
|
||||
|
||||
// Process will attempt to parse the incoming event data into a corresponding
|
||||
// audit Request/Response which is serialized to JSON/JSONx and stored within the event.
|
||||
// audit request/response which is serialized to JSON/JSONx and stored within the event.
|
||||
func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *eventlogger.Event, retErr error) {
|
||||
// Return early if the context was cancelled, eventlogger will not carry on
|
||||
// asking nodes to process, so any sink node in the pipeline won't be called.
|
||||
@ -93,7 +93,7 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
|
||||
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
|
||||
}
|
||||
|
||||
a, ok := e.Payload.(*AuditEvent)
|
||||
a, ok := e.Payload.(*Event)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -148,7 +148,7 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
|
||||
return nil, fmt.Errorf("unable to format %s: %w", a.Subtype, err)
|
||||
}
|
||||
|
||||
if f.config.requiredFormat == JSONxFormat {
|
||||
if f.config.requiredFormat == jsonxFormat {
|
||||
var err error
|
||||
result, err = jsonx.EncodeJSONBytes(result)
|
||||
if err != nil {
|
||||
@ -254,45 +254,46 @@ func clone[V any](s V) (V, error) {
|
||||
|
||||
// newAuth takes a logical.Auth and the number of remaining client token uses
|
||||
// (which should be supplied from the logical.Request's client token), and creates
|
||||
// an audit Auth.
|
||||
// an audit auth.
|
||||
// tokenRemainingUses should be the client token remaining uses to include in auth.
|
||||
// This usually can be found in logical.Request.ClientTokenRemainingUses.
|
||||
// NOTE: supplying a nil value for auth will result in a nil return value and
|
||||
// (nil) error. The caller should check the return value before attempting to use it.
|
||||
func newAuth(auth *logical.Auth, tokenRemainingUses int) (*Auth, error) {
|
||||
if auth == nil {
|
||||
// ignore-nil-nil-function-check.
|
||||
func newAuth(input *logical.Auth, tokenRemainingUses int) (*auth, error) {
|
||||
if input == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
extNSPolicies, err := clone(auth.ExternalNamespacePolicies)
|
||||
extNSPolicies, err := clone(input.ExternalNamespacePolicies)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to clone logical auth: external namespace policies: %w", err)
|
||||
}
|
||||
|
||||
identityPolicies, err := clone(auth.IdentityPolicies)
|
||||
identityPolicies, err := clone(input.IdentityPolicies)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to clone logical auth: identity policies: %w", err)
|
||||
}
|
||||
|
||||
metadata, err := clone(auth.Metadata)
|
||||
metadata, err := clone(input.Metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to clone logical auth: metadata: %w", err)
|
||||
}
|
||||
|
||||
policies, err := clone(auth.Policies)
|
||||
policies, err := clone(input.Policies)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to clone logical auth: policies: %w", err)
|
||||
}
|
||||
|
||||
var policyResults *PolicyResults
|
||||
if auth.PolicyResults != nil {
|
||||
policyResults = &PolicyResults{
|
||||
Allowed: auth.PolicyResults.Allowed,
|
||||
GrantingPolicies: make([]PolicyInfo, len(auth.PolicyResults.GrantingPolicies)),
|
||||
var polRes *policyResults
|
||||
if input.PolicyResults != nil {
|
||||
polRes = &policyResults{
|
||||
Allowed: input.PolicyResults.Allowed,
|
||||
GrantingPolicies: make([]policyInfo, len(input.PolicyResults.GrantingPolicies)),
|
||||
}
|
||||
|
||||
for _, p := range auth.PolicyResults.GrantingPolicies {
|
||||
policyResults.GrantingPolicies = append(policyResults.GrantingPolicies, PolicyInfo{
|
||||
for _, p := range input.PolicyResults.GrantingPolicies {
|
||||
polRes.GrantingPolicies = append(polRes.GrantingPolicies, policyInfo{
|
||||
Name: p.Name,
|
||||
NamespaceId: p.NamespaceId,
|
||||
NamespacePath: p.NamespacePath,
|
||||
@ -301,40 +302,40 @@ func newAuth(auth *logical.Auth, tokenRemainingUses int) (*Auth, error) {
|
||||
}
|
||||
}
|
||||
|
||||
tokenPolicies, err := clone(auth.TokenPolicies)
|
||||
tokenPolicies, err := clone(input.TokenPolicies)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to clone logical auth: token policies: %w", err)
|
||||
}
|
||||
|
||||
var tokenIssueTime string
|
||||
if !auth.IssueTime.IsZero() {
|
||||
tokenIssueTime = auth.IssueTime.Format(time.RFC3339)
|
||||
if !input.IssueTime.IsZero() {
|
||||
tokenIssueTime = input.IssueTime.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return &Auth{
|
||||
Accessor: auth.Accessor,
|
||||
ClientToken: auth.ClientToken,
|
||||
DisplayName: auth.DisplayName,
|
||||
EntityCreated: auth.EntityCreated,
|
||||
EntityID: auth.EntityID,
|
||||
return &auth{
|
||||
Accessor: input.Accessor,
|
||||
ClientToken: input.ClientToken,
|
||||
DisplayName: input.DisplayName,
|
||||
EntityCreated: input.EntityCreated,
|
||||
EntityID: input.EntityID,
|
||||
ExternalNamespacePolicies: extNSPolicies,
|
||||
IdentityPolicies: identityPolicies,
|
||||
Metadata: metadata,
|
||||
NoDefaultPolicy: auth.NoDefaultPolicy,
|
||||
NumUses: auth.NumUses,
|
||||
NoDefaultPolicy: input.NoDefaultPolicy,
|
||||
NumUses: input.NumUses,
|
||||
Policies: policies,
|
||||
PolicyResults: policyResults,
|
||||
PolicyResults: polRes,
|
||||
RemainingUses: tokenRemainingUses,
|
||||
TokenPolicies: tokenPolicies,
|
||||
TokenIssueTime: tokenIssueTime,
|
||||
TokenTTL: int64(auth.TTL.Seconds()),
|
||||
TokenType: auth.TokenType.String(),
|
||||
TokenTTL: int64(input.TTL.Seconds()),
|
||||
TokenType: input.TokenType.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newRequest takes a logical.Request and namespace.Namespace, transforms and
|
||||
// aggregates them into an audit Request.
|
||||
func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error) {
|
||||
// aggregates them into an audit request.
|
||||
func newRequest(req *logical.Request, ns *nshelper.Namespace) (*request, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("request cannot be nil")
|
||||
}
|
||||
@ -362,7 +363,7 @@ func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error)
|
||||
wrapTTL = int(req.WrapInfo.TTL / time.Second)
|
||||
}
|
||||
|
||||
return &Request{
|
||||
return &request{
|
||||
ClientCertificateSerialNumber: clientCertSerial,
|
||||
ClientID: req.ClientID,
|
||||
ClientToken: req.ClientToken,
|
||||
@ -377,7 +378,7 @@ func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error)
|
||||
MountRunningSha256: req.MountRunningSha256(),
|
||||
MountRunningVersion: req.MountRunningVersion(),
|
||||
MountType: req.MountType,
|
||||
Namespace: &Namespace{
|
||||
Namespace: &namespace{
|
||||
ID: ns.ID,
|
||||
Path: ns.Path,
|
||||
},
|
||||
@ -393,11 +394,12 @@ func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error)
|
||||
}
|
||||
|
||||
// newResponse takes a logical.Response and logical.Request, transforms and
|
||||
// aggregates them into an audit Response.
|
||||
// aggregates them into an audit response.
|
||||
// isElisionRequired is used to indicate that response 'Data' should be elided.
|
||||
// NOTE: supplying a nil value for response will result in a nil return value and
|
||||
// (nil) error. The caller should check the return value before attempting to use it.
|
||||
func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired bool) (*Response, error) {
|
||||
// ignore-nil-nil-function-check.
|
||||
func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired bool) (*response, error) {
|
||||
if resp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@ -458,12 +460,12 @@ func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired
|
||||
return nil, fmt.Errorf("unable to clone logical response: headers: %w", err)
|
||||
}
|
||||
|
||||
var secret *Secret
|
||||
var s *secret
|
||||
if resp.Secret != nil {
|
||||
secret = &Secret{LeaseID: resp.Secret.LeaseID}
|
||||
s = &secret{LeaseID: resp.Secret.LeaseID}
|
||||
}
|
||||
|
||||
var wrapInfo *ResponseWrapInfo
|
||||
var wrapInfo *responseWrapInfo
|
||||
if resp.WrapInfo != nil {
|
||||
token := resp.WrapInfo.Token
|
||||
if jwtToken := parseVaultTokenFromJWT(token); jwtToken != nil {
|
||||
@ -471,7 +473,7 @@ func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired
|
||||
}
|
||||
|
||||
ttl := int(resp.WrapInfo.TTL / time.Second)
|
||||
wrapInfo = &ResponseWrapInfo{
|
||||
wrapInfo = &responseWrapInfo{
|
||||
TTL: ttl,
|
||||
Token: token,
|
||||
Accessor: resp.WrapInfo.Accessor,
|
||||
@ -486,7 +488,7 @@ func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired
|
||||
return nil, fmt.Errorf("unable to clone logical response: warnings: %w", err)
|
||||
}
|
||||
|
||||
return &Response{
|
||||
return &response{
|
||||
Auth: auth,
|
||||
Data: data,
|
||||
Headers: headers,
|
||||
@ -498,15 +500,15 @@ func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired
|
||||
MountRunningVersion: req.MountRunningVersion(),
|
||||
MountType: req.MountType,
|
||||
Redirect: resp.Redirect,
|
||||
Secret: secret,
|
||||
Secret: s,
|
||||
WrapInfo: wrapInfo,
|
||||
Warnings: warnings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// createEntry takes the AuditEvent and builds an audit Entry.
|
||||
// The Entry will be HMAC'd and elided where required.
|
||||
func (f *entryFormatter) createEntry(ctx context.Context, a *AuditEvent) (*Entry, error) {
|
||||
// createEntry takes the AuditEvent and builds an audit entry.
|
||||
// The entry will be HMAC'd and elided where required.
|
||||
func (f *entryFormatter) createEntry(ctx context.Context, a *Event) (*entry, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
@ -521,7 +523,7 @@ func (f *entryFormatter) createEntry(ctx context.Context, a *AuditEvent) (*Entry
|
||||
return nil, fmt.Errorf("unable to parse request from '%s' audit event: request cannot be nil", a.Subtype)
|
||||
}
|
||||
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
ns, err := nshelper.FromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to retrieve namespace from context: %w", err)
|
||||
}
|
||||
@ -536,7 +538,7 @@ func (f *entryFormatter) createEntry(ctx context.Context, a *AuditEvent) (*Entry
|
||||
return nil, fmt.Errorf("cannot convert request: %w", err)
|
||||
}
|
||||
|
||||
var resp *Response
|
||||
var resp *response
|
||||
if a.Subtype == ResponseType {
|
||||
shouldElide := f.config.elideListResponses && req.Operation == logical.ListOperation
|
||||
resp, err = newResponse(data.Response, data.Request, shouldElide)
|
||||
@ -555,7 +557,7 @@ func (f *entryFormatter) createEntry(ctx context.Context, a *AuditEvent) (*Entry
|
||||
entryType = a.Subtype.String()
|
||||
}
|
||||
|
||||
entry := &Entry{
|
||||
entry := &entry{
|
||||
Auth: auth,
|
||||
Error: outerErr,
|
||||
Forwarded: false,
|
||||
|
@ -42,7 +42,7 @@ type formatterConfig struct {
|
||||
// This should only ever be used in a testing context
|
||||
omitTime bool
|
||||
|
||||
// The required/target format for the event (supported: JSONFormat and JSONxFormat).
|
||||
// The required/target format for the event (supported: jsonFormat and jsonxFormat).
|
||||
requiredFormat format
|
||||
|
||||
// headerFormatter specifies the formatter used for headers that existing in any incoming audit request.
|
||||
@ -58,14 +58,14 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
|
||||
return formatterConfig{}, fmt.Errorf("header formatter is required: %w", ErrInvalidParameter)
|
||||
}
|
||||
|
||||
var opt []Option
|
||||
var opt []option
|
||||
|
||||
if format, ok := config[optionFormat]; ok {
|
||||
if !IsValidFormat(format) {
|
||||
if !isValidFormat(format) {
|
||||
return formatterConfig{}, fmt.Errorf("unsupported %q: %w", optionFormat, ErrExternalOptions)
|
||||
}
|
||||
|
||||
opt = append(opt, WithFormat(format))
|
||||
opt = append(opt, withFormat(format))
|
||||
}
|
||||
|
||||
// Check if hashing of accessor is disabled
|
||||
@ -74,7 +74,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
|
||||
if err != nil {
|
||||
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionHMACAccessor, ErrExternalOptions)
|
||||
}
|
||||
opt = append(opt, WithHMACAccessor(v))
|
||||
opt = append(opt, withHMACAccessor(v))
|
||||
}
|
||||
|
||||
// Check if raw logging is enabled
|
||||
@ -83,7 +83,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
|
||||
if err != nil {
|
||||
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionLogRaw, ErrExternalOptions)
|
||||
}
|
||||
opt = append(opt, WithRaw(v))
|
||||
opt = append(opt, withRaw(v))
|
||||
}
|
||||
|
||||
if elideListResponsesRaw, ok := config[optionElideListResponses]; ok {
|
||||
@ -91,11 +91,11 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
|
||||
if err != nil {
|
||||
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionElideListResponses, ErrExternalOptions)
|
||||
}
|
||||
opt = append(opt, WithElision(v))
|
||||
opt = append(opt, withElision(v))
|
||||
}
|
||||
|
||||
if prefix, ok := config[optionPrefix]; ok {
|
||||
opt = append(opt, WithPrefix(prefix))
|
||||
opt = append(opt, withPrefix(prefix))
|
||||
}
|
||||
|
||||
opts, err := getOpts(opt...)
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-sockaddr"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
|
||||
"github.com/hashicorp/vault/internal/observability/event"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
@ -132,14 +132,14 @@ func TestNewEntryFormatter(t *testing.T) {
|
||||
Options: map[string]string{
|
||||
"format": "json",
|
||||
},
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"default": {
|
||||
Name: "juan",
|
||||
UseStaticSalt: true,
|
||||
Logger: hclog.NewNullLogger(),
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"config-json": {
|
||||
Name: "juan",
|
||||
@ -149,7 +149,7 @@ func TestNewEntryFormatter(t *testing.T) {
|
||||
"format": "json",
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"config-jsonx": {
|
||||
Name: "juan",
|
||||
@ -159,7 +159,7 @@ func TestNewEntryFormatter(t *testing.T) {
|
||||
"format": "jsonx",
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONxFormat,
|
||||
ExpectedFormat: jsonxFormat,
|
||||
},
|
||||
"config-json-prefix": {
|
||||
Name: "juan",
|
||||
@ -170,7 +170,7 @@ func TestNewEntryFormatter(t *testing.T) {
|
||||
"format": "json",
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
ExpectedPrefix: "foo",
|
||||
},
|
||||
"config-jsonx-prefix": {
|
||||
@ -182,7 +182,7 @@ func TestNewEntryFormatter(t *testing.T) {
|
||||
"format": "jsonx",
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONxFormat,
|
||||
ExpectedFormat: jsonxFormat,
|
||||
ExpectedPrefix: "foo",
|
||||
},
|
||||
}
|
||||
@ -245,7 +245,7 @@ func TestEntryFormatter_Type(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestEntryFormatter_Process attempts to run the Process method to convert the
|
||||
// logical.LogInput within an audit event to JSON and JSONx (Entry),
|
||||
// logical.LogInput within an audit event to JSON and JSONx (entry),
|
||||
func TestEntryFormatter_Process(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -261,21 +261,21 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: nil,
|
||||
},
|
||||
"json-response-no-data": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: nil,
|
||||
},
|
||||
"json-request-basic-input": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{Type: "magic"},
|
||||
RootNamespace: true,
|
||||
},
|
||||
@ -283,34 +283,34 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{Type: "magic"},
|
||||
},
|
||||
"json-request-basic-input-and-request-no-ns": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
},
|
||||
"json-response-basic-input-and-request-no-ns": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
},
|
||||
"json-request-basic-input-and-request-with-ns": {
|
||||
IsErrorExpected: false,
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
RootNamespace: true,
|
||||
},
|
||||
"json-response-basic-input-and-request-with-ns": {
|
||||
IsErrorExpected: false,
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONFormat,
|
||||
RequiredFormat: jsonFormat,
|
||||
Data: &logical.LogInput{
|
||||
Request: &logical.Request{ID: "123"},
|
||||
Response: &logical.Response{},
|
||||
@ -321,21 +321,21 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: nil,
|
||||
},
|
||||
"jsonx-response-no-data": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: nil,
|
||||
},
|
||||
"jsonx-request-basic-input": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{Type: "magic"},
|
||||
RootNamespace: true,
|
||||
},
|
||||
@ -343,7 +343,7 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{Type: "magic"},
|
||||
RootNamespace: true,
|
||||
},
|
||||
@ -351,27 +351,27 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
},
|
||||
"jsonx-response-basic-input-and-request-no-ns": {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
},
|
||||
"jsonx-request-basic-input-and-request-with-ns": {
|
||||
IsErrorExpected: false,
|
||||
Subtype: RequestType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
|
||||
RootNamespace: true,
|
||||
},
|
||||
"jsonx-response-basic-input-and-request-with-ns": {
|
||||
IsErrorExpected: false,
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{
|
||||
Request: &logical.Request{ID: "123"},
|
||||
Response: &logical.Response{},
|
||||
@ -382,7 +382,7 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
|
||||
Subtype: ResponseType,
|
||||
RequiredFormat: JSONxFormat,
|
||||
RequiredFormat: jsonxFormat,
|
||||
Data: &logical.LogInput{
|
||||
Auth: &logical.Auth{},
|
||||
},
|
||||
@ -409,7 +409,7 @@ func TestEntryFormatter_Process(t *testing.T) {
|
||||
var ctx context.Context
|
||||
switch {
|
||||
case tc.RootNamespace:
|
||||
ctx = namespace.RootContext(context.Background())
|
||||
ctx = nshelper.RootContext(context.Background())
|
||||
default:
|
||||
ctx = context.Background()
|
||||
}
|
||||
@ -461,7 +461,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
|
||||
},
|
||||
}
|
||||
|
||||
ctx := namespace.RootContext(context.Background())
|
||||
ctx := nshelper.RootContext(context.Background())
|
||||
|
||||
// Create the formatter node.
|
||||
cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil)
|
||||
@ -472,7 +472,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
|
||||
require.NotNil(b, formatter)
|
||||
|
||||
// Create the sink node.
|
||||
sink, err := event.NewFileSink("/dev/null", JSONFormat.String())
|
||||
sink, err := event.NewFileSink("/dev/null", jsonFormat.String())
|
||||
require.NoError(b, err)
|
||||
require.NotNil(b, sink)
|
||||
|
||||
@ -551,12 +551,12 @@ func TestEntryFormatter_Process_Request(t *testing.T) {
|
||||
var ctx context.Context
|
||||
switch {
|
||||
case tc.RootNamespace:
|
||||
ctx = namespace.RootContext(context.Background())
|
||||
ctx = nshelper.RootContext(context.Background())
|
||||
default:
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
auditEvent, err := NewEvent(RequestType)
|
||||
auditEvent, err := newEvent(RequestType)
|
||||
auditEvent.setTimeProvider(&testTimeProvider{})
|
||||
require.NoError(t, err)
|
||||
auditEvent.Data = tc.Input
|
||||
@ -577,18 +577,18 @@ func TestEntryFormatter_Process_Request(t *testing.T) {
|
||||
case tc.ShouldOmitTime:
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
b, ok := e2.Format(JSONFormat.String())
|
||||
b, ok := e2.Format(jsonFormat.String())
|
||||
require.True(t, ok)
|
||||
var entry *Entry
|
||||
var entry *entry
|
||||
err = json.Unmarshal(b, &entry)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, entry.Time)
|
||||
default:
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
b, ok := e2.Format(JSONFormat.String())
|
||||
b, ok := e2.Format(jsonFormat.String())
|
||||
require.True(t, ok)
|
||||
var entry *Entry
|
||||
var entry *entry
|
||||
err = json.Unmarshal(b, &entry)
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, entry.Time)
|
||||
@ -661,12 +661,12 @@ func TestEntryFormatter_Process_ResponseType(t *testing.T) {
|
||||
var ctx context.Context
|
||||
switch {
|
||||
case tc.RootNamespace:
|
||||
ctx = namespace.RootContext(context.Background())
|
||||
ctx = nshelper.RootContext(context.Background())
|
||||
default:
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
auditEvent, err := NewEvent(ResponseType)
|
||||
auditEvent, err := newEvent(ResponseType)
|
||||
auditEvent.setTimeProvider(&testTimeProvider{})
|
||||
require.NoError(t, err)
|
||||
auditEvent.Data = tc.Input
|
||||
@ -688,18 +688,18 @@ func TestEntryFormatter_Process_ResponseType(t *testing.T) {
|
||||
case tc.ShouldOmitTime:
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
b, ok := e2.Format(JSONFormat.String())
|
||||
b, ok := e2.Format(jsonFormat.String())
|
||||
require.True(t, ok)
|
||||
var entry *Entry
|
||||
var entry *entry
|
||||
err = json.Unmarshal(b, &entry)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, entry.Time)
|
||||
default:
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
b, ok := e2.Format(JSONFormat.String())
|
||||
b, ok := e2.Format(jsonFormat.String())
|
||||
require.True(t, ok)
|
||||
var entry *Entry
|
||||
var entry *entry
|
||||
err = json.Unmarshal(b, &entry)
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, entry.Time)
|
||||
@ -807,7 +807,7 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
|
||||
|
||||
// Create an audit event and more generic eventlogger.event to allow us
|
||||
// to process (format).
|
||||
auditEvent, err := NewEvent(RequestType)
|
||||
auditEvent, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
auditEvent.Data = in
|
||||
|
||||
@ -818,10 +818,10 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
|
||||
Payload: auditEvent,
|
||||
}
|
||||
|
||||
e2, err := formatter.Process(namespace.RootContext(nil), e)
|
||||
e2, err := formatter.Process(nshelper.RootContext(nil), e)
|
||||
require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err)
|
||||
|
||||
jsonBytes, ok := e2.Format(JSONFormat.String())
|
||||
jsonBytes, ok := e2.Format(jsonFormat.String())
|
||||
require.True(t, ok)
|
||||
require.Positive(t, len(jsonBytes))
|
||||
|
||||
@ -829,14 +829,14 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
|
||||
t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, expectedResultStr, tc.Prefix)
|
||||
}
|
||||
|
||||
expectedJSON := new(Entry)
|
||||
expectedJSON := new(entry)
|
||||
|
||||
if err := jsonutil.DecodeJSON([]byte(expectedResultStr), &expectedJSON); err != nil {
|
||||
t.Fatalf("bad json: %s", err)
|
||||
}
|
||||
expectedJSON.Request.Namespace = &Namespace{ID: "root"}
|
||||
expectedJSON.Request.Namespace = &namespace{ID: "root"}
|
||||
|
||||
actualJSON := new(Entry)
|
||||
actualJSON := new(entry)
|
||||
if err := jsonutil.DecodeJSON(jsonBytes[len(tc.Prefix):], &actualJSON); err != nil {
|
||||
t.Fatalf("bad json: %s", err)
|
||||
}
|
||||
@ -972,7 +972,7 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
|
||||
|
||||
// Create an audit event and more generic eventlogger.event to allow us
|
||||
// to process (format).
|
||||
auditEvent, err := NewEvent(RequestType)
|
||||
auditEvent, err := newEvent(RequestType)
|
||||
require.NoError(t, err)
|
||||
auditEvent.Data = in
|
||||
|
||||
@ -983,10 +983,10 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
|
||||
Payload: auditEvent,
|
||||
}
|
||||
|
||||
e2, err := formatter.Process(namespace.RootContext(nil), e)
|
||||
e2, err := formatter.Process(nshelper.RootContext(nil), e)
|
||||
require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err)
|
||||
|
||||
jsonxBytes, ok := e2.Format(JSONxFormat.String())
|
||||
jsonxBytes, ok := e2.Format(jsonxFormat.String())
|
||||
require.True(t, ok)
|
||||
require.Positive(t, len(jsonxBytes))
|
||||
|
||||
@ -1071,11 +1071,11 @@ func TestEntryFormatter_ElideListResponses(t *testing.T) {
|
||||
oneInterestingTestCase := tests["Enhanced list (has key_info)"]
|
||||
|
||||
ss := newStaticSalt(t)
|
||||
ctx := namespace.RootContext(context.Background())
|
||||
ctx := nshelper.RootContext(context.Background())
|
||||
var formatter *entryFormatter
|
||||
var err error
|
||||
|
||||
format := func(t *testing.T, config formatterConfig, operation logical.Operation, inputData map[string]any) *Entry {
|
||||
format := func(t *testing.T, config formatterConfig, operation logical.Operation, inputData map[string]any) *entry {
|
||||
formatter, err = newEntryFormatter("juan", config, ss, hclog.NewNullLogger())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, formatter)
|
||||
@ -1085,7 +1085,7 @@ func TestEntryFormatter_ElideListResponses(t *testing.T) {
|
||||
Response: &logical.Response{Data: inputData},
|
||||
}
|
||||
|
||||
auditEvent, err := NewEvent(ResponseType)
|
||||
auditEvent, err := newEvent(ResponseType)
|
||||
require.NoError(t, err)
|
||||
auditEvent.Data = in
|
||||
|
||||
@ -1182,7 +1182,7 @@ func TestEntryFormatter_Process_NoMutation(t *testing.T) {
|
||||
|
||||
e := fakeEvent(t, RequestType, in)
|
||||
|
||||
e2, err := formatter.Process(namespace.RootContext(nil), e)
|
||||
e2, err := formatter.Process(nshelper.RootContext(nil), e)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
|
||||
@ -1245,7 +1245,7 @@ func TestEntryFormatter_Process_Panic(t *testing.T) {
|
||||
|
||||
e := fakeEvent(t, ResponseType, in)
|
||||
|
||||
e2, err := formatter.Process(namespace.RootContext(nil), e)
|
||||
e2, err := formatter.Process(nshelper.RootContext(nil), e)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "panic generating audit log: \"juan\"")
|
||||
require.Nil(t, e2)
|
||||
@ -1282,13 +1282,13 @@ func TestEntryFormatter_Process_NeverLeaksHeaders(t *testing.T) {
|
||||
e := fakeEvent(t, RequestType, input)
|
||||
|
||||
// Process the node.
|
||||
ctx := namespace.RootContext(context.Background())
|
||||
ctx := nshelper.RootContext(context.Background())
|
||||
e2, err := formatter.Process(ctx, e)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, e2)
|
||||
|
||||
// Now check we can retrieve the formatted JSON.
|
||||
jsonFormatted, b2 := e2.Format(JSONFormat.String())
|
||||
jsonFormatted, b2 := e2.Format(jsonFormat.String())
|
||||
require.True(t, b2)
|
||||
require.NotNil(t, jsonFormatted)
|
||||
var input2 *logical.LogInput
|
||||
@ -1328,9 +1328,9 @@ func fakeEvent(tb testing.TB, subtype subtype, input *logical.LogInput) *eventlo
|
||||
|
||||
date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local)
|
||||
|
||||
auditEvent, err := NewEvent(subtype,
|
||||
WithID("123"),
|
||||
WithNow(date),
|
||||
auditEvent, err := newEvent(subtype,
|
||||
withID("123"),
|
||||
withNow(date),
|
||||
)
|
||||
require.NoError(tb, err)
|
||||
require.NotNil(tb, auditEvent)
|
||||
|
@ -20,9 +20,9 @@ var (
|
||||
ErrExternalOptions = errors.New("invalid configuration")
|
||||
)
|
||||
|
||||
// ConvertToExternalError handles converting an error that was generated in Vault
|
||||
// and should appear as-is in the server logs, to an error that can be returned to
|
||||
// calling clients (via the API/CLI).
|
||||
// ConvertToExternalError handles converting an audit related error that was generated
|
||||
// in Vault and should appear as-is in the server logs, to an error that can be
|
||||
// returned to calling clients (via the API/CLI).
|
||||
func ConvertToExternalError(err error) error {
|
||||
// If the error is an internal error, the contents will have been logged, and
|
||||
// we should probably shield the caller from the details.
|
||||
|
@ -23,15 +23,15 @@ const (
|
||||
|
||||
// Audit formats.
|
||||
const (
|
||||
JSONFormat format = "json"
|
||||
JSONxFormat format = "jsonx"
|
||||
jsonFormat format = "json"
|
||||
jsonxFormat format = "jsonx"
|
||||
)
|
||||
|
||||
// Check AuditEvent implements the timeProvider at compile time.
|
||||
var _ timeProvider = (*AuditEvent)(nil)
|
||||
var _ timeProvider = (*Event)(nil)
|
||||
|
||||
// AuditEvent is the audit event.
|
||||
type AuditEvent struct {
|
||||
// Event is the audit event.
|
||||
type Event struct {
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Subtype subtype `json:"subtype"` // the subtype of the audit event.
|
||||
@ -41,14 +41,14 @@ type AuditEvent struct {
|
||||
}
|
||||
|
||||
// setTimeProvider can be used to set a specific time provider which is used when
|
||||
// creating an Entry.
|
||||
// creating an entry.
|
||||
// NOTE: This is primarily used for testing to supply a known time value.
|
||||
func (a *AuditEvent) setTimeProvider(t timeProvider) {
|
||||
func (a *Event) setTimeProvider(t timeProvider) {
|
||||
a.prov = t
|
||||
}
|
||||
|
||||
// timeProvider returns a configured time provider, or the default if not set.
|
||||
func (a *AuditEvent) timeProvider() timeProvider {
|
||||
func (a *Event) timeProvider() timeProvider {
|
||||
if a.prov == nil {
|
||||
return a
|
||||
}
|
||||
@ -62,10 +62,10 @@ type format string
|
||||
// subtype defines the type of audit event.
|
||||
type subtype string
|
||||
|
||||
// NewEvent should be used to create an audit event. The subtype field is needed
|
||||
// newEvent should be used to create an audit event. The subtype field is needed
|
||||
// for audit events. It will generate an ID if no ID is supplied. Supported
|
||||
// options: WithID, WithNow.
|
||||
func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
|
||||
// options: withID, withNow.
|
||||
func newEvent(s subtype, opt ...option) (*Event, error) {
|
||||
// Get the default options
|
||||
opts, err := getOpts(opt...)
|
||||
if err != nil {
|
||||
@ -81,7 +81,7 @@ func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
|
||||
}
|
||||
}
|
||||
|
||||
audit := &AuditEvent{
|
||||
audit := &Event{
|
||||
ID: opts.withID,
|
||||
Timestamp: opts.withNow,
|
||||
Version: version,
|
||||
@ -95,7 +95,7 @@ func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
|
||||
}
|
||||
|
||||
// validate attempts to ensure the audit event in its present state is valid.
|
||||
func (a *AuditEvent) validate() error {
|
||||
func (a *Event) validate() error {
|
||||
if a == nil {
|
||||
return fmt.Errorf("event is nil: %w", ErrInvalidParameter)
|
||||
}
|
||||
@ -133,7 +133,7 @@ func (t subtype) validate() error {
|
||||
// validate ensures that format is one of the set of allowed event formats.
|
||||
func (f format) validate() error {
|
||||
switch f {
|
||||
case JSONFormat, JSONxFormat:
|
||||
case jsonFormat, jsonxFormat:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid format %q: %w", f, ErrInvalidParameter)
|
||||
@ -172,13 +172,13 @@ func (t subtype) String() string {
|
||||
|
||||
// formattedTime returns the UTC time the AuditEvent was created in the RFC3339Nano
|
||||
// format (which removes trailing zeros from the seconds field).
|
||||
func (a *AuditEvent) formattedTime() string {
|
||||
func (a *Event) formattedTime() string {
|
||||
return a.Timestamp.UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
|
||||
// IsValidFormat provides a means to validate whether the supplied format is valid.
|
||||
// isValidFormat provides a means to validate whether the supplied format is valid.
|
||||
// Examples of valid formats are JSON and JSONx.
|
||||
func IsValidFormat(v string) bool {
|
||||
func isValidFormat(v string) bool {
|
||||
err := format(strings.TrimSpace(strings.ToLower(v))).validate()
|
||||
return err == nil
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ func TestAuditEvent_new(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
Options []Option
|
||||
Options []option
|
||||
Subtype subtype
|
||||
Format format
|
||||
IsErrorExpected bool
|
||||
@ -33,47 +33,47 @@ func TestAuditEvent_new(t *testing.T) {
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
|
||||
},
|
||||
"empty-Option": {
|
||||
Options: []Option{},
|
||||
"empty-option": {
|
||||
Options: []option{},
|
||||
Subtype: subtype(""),
|
||||
Format: format(""),
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
|
||||
},
|
||||
"bad-id": {
|
||||
Options: []Option{WithID("")},
|
||||
Options: []option{withID("")},
|
||||
Subtype: ResponseType,
|
||||
Format: JSONFormat,
|
||||
Format: jsonFormat,
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "id cannot be empty",
|
||||
},
|
||||
"good": {
|
||||
Options: []Option{
|
||||
WithID("audit_123"),
|
||||
WithFormat(string(JSONFormat)),
|
||||
WithSubtype(string(ResponseType)),
|
||||
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
Options: []option{
|
||||
withID("audit_123"),
|
||||
withFormat(string(jsonFormat)),
|
||||
withSubtype(string(ResponseType)),
|
||||
withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
},
|
||||
Subtype: RequestType,
|
||||
Format: JSONxFormat,
|
||||
Format: jsonxFormat,
|
||||
IsErrorExpected: false,
|
||||
ExpectedID: "audit_123",
|
||||
ExpectedTimestamp: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
|
||||
ExpectedSubtype: RequestType,
|
||||
ExpectedFormat: JSONxFormat,
|
||||
ExpectedFormat: jsonxFormat,
|
||||
},
|
||||
"good-no-time": {
|
||||
Options: []Option{
|
||||
WithID("audit_123"),
|
||||
WithFormat(string(JSONFormat)),
|
||||
WithSubtype(string(ResponseType)),
|
||||
Options: []option{
|
||||
withID("audit_123"),
|
||||
withFormat(string(jsonFormat)),
|
||||
withSubtype(string(ResponseType)),
|
||||
},
|
||||
Subtype: RequestType,
|
||||
Format: JSONxFormat,
|
||||
Format: jsonxFormat,
|
||||
IsErrorExpected: false,
|
||||
ExpectedID: "audit_123",
|
||||
ExpectedSubtype: RequestType,
|
||||
ExpectedFormat: JSONxFormat,
|
||||
ExpectedFormat: jsonxFormat,
|
||||
IsNowExpected: true,
|
||||
},
|
||||
}
|
||||
@ -84,7 +84,7 @@ func TestAuditEvent_new(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
audit, err := NewEvent(tc.Subtype, tc.Options...)
|
||||
audit, err := newEvent(tc.Subtype, tc.Options...)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
require.Error(t, err)
|
||||
@ -112,7 +112,7 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
Value *AuditEvent
|
||||
Value *Event
|
||||
IsErrorExpected bool
|
||||
ExpectedErrorMessage string
|
||||
}{
|
||||
@ -122,12 +122,12 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
ExpectedErrorMessage: "event is nil: invalid internal parameter",
|
||||
},
|
||||
"default": {
|
||||
Value: &AuditEvent{},
|
||||
Value: &Event{},
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "missing ID: invalid internal parameter",
|
||||
},
|
||||
"id-empty": {
|
||||
Value: &AuditEvent{
|
||||
Value: &Event{
|
||||
ID: "",
|
||||
Version: version,
|
||||
Subtype: RequestType,
|
||||
@ -138,7 +138,7 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
ExpectedErrorMessage: "missing ID: invalid internal parameter",
|
||||
},
|
||||
"version-fiddled": {
|
||||
Value: &AuditEvent{
|
||||
Value: &Event{
|
||||
ID: "audit_123",
|
||||
Version: "magic-v2",
|
||||
Subtype: RequestType,
|
||||
@ -149,7 +149,7 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
ExpectedErrorMessage: "event version unsupported: invalid internal parameter",
|
||||
},
|
||||
"subtype-fiddled": {
|
||||
Value: &AuditEvent{
|
||||
Value: &Event{
|
||||
ID: "audit_123",
|
||||
Version: version,
|
||||
Subtype: subtype("moon"),
|
||||
@ -160,7 +160,7 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
ExpectedErrorMessage: "invalid event subtype \"moon\": invalid internal parameter",
|
||||
},
|
||||
"default-time": {
|
||||
Value: &AuditEvent{
|
||||
Value: &Event{
|
||||
ID: "audit_123",
|
||||
Version: version,
|
||||
Subtype: ResponseType,
|
||||
@ -171,7 +171,7 @@ func TestAuditEvent_Validate(t *testing.T) {
|
||||
ExpectedErrorMessage: "event timestamp cannot be the zero time instant: invalid internal parameter",
|
||||
},
|
||||
"valid": {
|
||||
Value: &AuditEvent{
|
||||
Value: &Event{
|
||||
ID: "audit_123",
|
||||
Version: version,
|
||||
Subtype: ResponseType,
|
||||
@ -373,7 +373,7 @@ func TestAuditEvent_Subtype_String(t *testing.T) {
|
||||
// method returns the correct format.
|
||||
func TestAuditEvent_formattedTime(t *testing.T) {
|
||||
theTime := time.Date(2024, time.March, 22, 10, 0o0, 5, 10, time.UTC)
|
||||
a, err := NewEvent(ResponseType, WithNow(theTime))
|
||||
a, err := newEvent(ResponseType, withNow(theTime))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, "2024-03-22T10:00:05.00000001Z", a.formattedTime())
|
||||
@ -439,7 +439,7 @@ func TestEvent_IsValidFormat(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := IsValidFormat(tc.input)
|
||||
res := isValidFormat(tc.input)
|
||||
require.Equal(t, tc.expected, res)
|
||||
})
|
||||
}
|
||||
|
@ -25,10 +25,10 @@ func hashString(ctx context.Context, salter Salter, data string) (string, error)
|
||||
return salt.GetIdentifiedHMAC(data), nil
|
||||
}
|
||||
|
||||
// hashAuth uses the Salter to hash the supplied Auth (modifying it).
|
||||
// hashAuth uses the Salter to hash the supplied auth (modifying it).
|
||||
// hmacAccessor is used to indicate whether the accessor should also be HMAC'd
|
||||
// when present.
|
||||
func hashAuth(ctx context.Context, salter Salter, auth *Auth, hmacAccessor bool) error {
|
||||
func hashAuth(ctx context.Context, salter Salter, auth *auth, hmacAccessor bool) error {
|
||||
if auth == nil {
|
||||
return nil
|
||||
}
|
||||
@ -50,14 +50,14 @@ func hashAuth(ctx context.Context, salter Salter, auth *Auth, hmacAccessor bool)
|
||||
return nil
|
||||
}
|
||||
|
||||
// hashRequest uses the Salter to hash the supplied Request (modifying it).
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the Request which
|
||||
// hashRequest uses the Salter to hash the supplied request (modifying it).
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the request which
|
||||
// prevents those specific keys from HMAC'd.
|
||||
// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
|
||||
// when present.
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the Request which
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the request which
|
||||
// prevents those specific keys from HMAC'd.
|
||||
func hashRequest(ctx context.Context, salter Salter, req *Request, hmacAccessor bool, nonHMACDataKeys []string) error {
|
||||
func hashRequest(ctx context.Context, salter Salter, req *request, hmacAccessor bool, nonHMACDataKeys []string) error {
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
@ -102,13 +102,13 @@ func hashMap(hashFunc hashCallback, data map[string]interface{}, nonHMACDataKeys
|
||||
return hashStructure(data, hashFunc, nonHMACDataKeys)
|
||||
}
|
||||
|
||||
// hashResponse uses the Salter to hash the supplied Response (modifying it).
|
||||
// hashResponse uses the Salter to hash the supplied response (modifying it).
|
||||
// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
|
||||
// when present.
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the Response which
|
||||
// nonHMACDataKeys is used when hashing any 'Data' field within the response which
|
||||
// prevents those specific keys from HMAC'd.
|
||||
// See: /vault/docs/audit#eliding-list-response-bodies
|
||||
func hashResponse(ctx context.Context, salter Salter, resp *Response, hmacAccessor bool, nonHMACDataKeys []string) error {
|
||||
func hashResponse(ctx context.Context, salter Salter, resp *response, hmacAccessor bool, nonHMACDataKeys []string) error {
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
@ -142,10 +142,10 @@ func hashResponse(ctx context.Context, salter Salter, resp *Response, hmacAccess
|
||||
return nil
|
||||
}
|
||||
|
||||
// hashWrapInfo uses the supplied hashing function to hash ResponseWrapInfo (modifying it).
|
||||
// hashWrapInfo uses the supplied hashing function to hash responseWrapInfo (modifying it).
|
||||
// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
|
||||
// when present.
|
||||
func hashWrapInfo(hashFunc hashCallback, wrapInfo *ResponseWrapInfo, hmacAccessor bool) error {
|
||||
func hashWrapInfo(hashFunc hashCallback, wrapInfo *responseWrapInfo, hmacAccessor bool) error {
|
||||
if wrapInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/salt"
|
||||
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
||||
@ -97,13 +97,13 @@ func TestCopy_response(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSalter is a structure that implements the Salter interface in a trivial
|
||||
// testSalter is a structure that implements the Salter interface in a trivial
|
||||
// manner.
|
||||
type TestSalter struct{}
|
||||
type testSalter struct{}
|
||||
|
||||
// Salt returns a salt.Salt pointer based on dummy data stored in an in-memory
|
||||
// storage instance.
|
||||
func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) {
|
||||
func (*testSalter) Salt(ctx context.Context) (*salt.Salt, error) {
|
||||
inmemStorage := &logical.InmemStorage{}
|
||||
err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
|
||||
Key: "salt",
|
||||
@ -120,7 +120,7 @@ func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) {
|
||||
}
|
||||
|
||||
func TestHashString(t *testing.T) {
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
|
||||
out, err := hashString(context.Background(), salter, "foo")
|
||||
if err != nil {
|
||||
@ -134,7 +134,7 @@ func TestHashString(t *testing.T) {
|
||||
func TestHashAuth(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
Input *logical.Auth
|
||||
Output *Auth
|
||||
Output *auth
|
||||
HMACAccessor bool
|
||||
}{
|
||||
"no-accessor-hmac": {
|
||||
@ -146,7 +146,7 @@ func TestHashAuth(t *testing.T) {
|
||||
},
|
||||
TokenType: logical.TokenTypeService,
|
||||
},
|
||||
&Auth{
|
||||
&auth{
|
||||
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
|
||||
Accessor: "very-accessible",
|
||||
TokenTTL: 3600,
|
||||
@ -164,7 +164,7 @@ func TestHashAuth(t *testing.T) {
|
||||
},
|
||||
TokenType: logical.TokenTypeBatch,
|
||||
},
|
||||
&Auth{
|
||||
&auth{
|
||||
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
|
||||
Accessor: "hmac-sha256:5d6d7c8da5b699ace193ea453bbf77082a8aaca42a474436509487d646a7c0af",
|
||||
TokenTTL: 3600,
|
||||
@ -181,7 +181,7 @@ func TestHashAuth(t *testing.T) {
|
||||
Value: []byte("foo"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
for _, tc := range cases {
|
||||
auditAuth, err := newAuth(tc.Input, 5)
|
||||
require.NoError(t, err)
|
||||
@ -205,7 +205,7 @@ var _ logical.OptMarshaler = &testOptMarshaler{}
|
||||
func TestHashRequest(t *testing.T) {
|
||||
cases := []struct {
|
||||
Input *logical.Request
|
||||
Output *Request
|
||||
Output *request
|
||||
NonHMACDataKeys []string
|
||||
HMACAccessor bool
|
||||
}{
|
||||
@ -218,16 +218,16 @@ func TestHashRequest(t *testing.T) {
|
||||
"om": &testOptMarshaler{S: "bar", I: 1},
|
||||
},
|
||||
},
|
||||
&Request{
|
||||
&request{
|
||||
Data: map[string]interface{}{
|
||||
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
|
||||
"baz": "foobar",
|
||||
"private_key_type": "hmac-sha256:995230dca56fffd310ff591aa404aab52b2abb41703c787cfa829eceb4595bf1",
|
||||
"om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
|
||||
},
|
||||
Namespace: &Namespace{
|
||||
ID: namespace.RootNamespace.ID,
|
||||
Path: namespace.RootNamespace.Path,
|
||||
Namespace: &namespace{
|
||||
ID: nshelper.RootNamespace.ID,
|
||||
Path: nshelper.RootNamespace.Path,
|
||||
},
|
||||
},
|
||||
[]string{"baz"},
|
||||
@ -241,9 +241,9 @@ func TestHashRequest(t *testing.T) {
|
||||
Value: []byte("foo"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
for _, tc := range cases {
|
||||
auditReq, err := newRequest(tc.Input, namespace.RootNamespace)
|
||||
auditReq, err := newRequest(tc.Input, nshelper.RootNamespace)
|
||||
require.NoError(t, err)
|
||||
err = hashRequest(context.Background(), salter, auditReq, tc.HMACAccessor, tc.NonHMACDataKeys)
|
||||
require.NoError(t, err)
|
||||
@ -279,14 +279,14 @@ func TestHashResponse(t *testing.T) {
|
||||
|
||||
nonHMACDataKeys := []string{"baz"}
|
||||
|
||||
expected := &Response{
|
||||
expected := &response{
|
||||
Data: map[string]interface{}{
|
||||
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
|
||||
"baz": "foobar",
|
||||
"bar": now.Format(time.RFC3339Nano),
|
||||
"om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
|
||||
},
|
||||
WrapInfo: &ResponseWrapInfo{
|
||||
WrapInfo: &responseWrapInfo{
|
||||
TTL: 60,
|
||||
Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
|
||||
Accessor: "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390",
|
||||
@ -306,7 +306,7 @@ func TestHashResponse(t *testing.T) {
|
||||
Value: []byte("foo"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
auditResp, err := newResponse(resp, req, false)
|
||||
require.NoError(t, err)
|
||||
err = hashResponse(context.Background(), salter, auditResp, true, nonHMACDataKeys)
|
||||
|
@ -42,7 +42,7 @@ func AuditedHeadersKey() string {
|
||||
return AuditedHeadersSubPath + auditedHeadersEntry
|
||||
}
|
||||
|
||||
type HeaderSettings struct {
|
||||
type headerSettings struct {
|
||||
// HMAC is used to indicate whether the value of the header should be HMAC'd.
|
||||
HMAC bool `json:"hmac"`
|
||||
}
|
||||
@ -51,7 +51,7 @@ type HeaderSettings struct {
|
||||
// headers to the audit logs. It uses a BarrierView to persist the settings.
|
||||
type HeadersConfig struct {
|
||||
// headerSettings stores the current headers that should be audited, and their settings.
|
||||
headerSettings map[string]*HeaderSettings
|
||||
headerSettings map[string]*headerSettings
|
||||
|
||||
// view is the barrier view which should be used to access underlying audit header config data.
|
||||
view durableStorer
|
||||
@ -69,18 +69,18 @@ func NewHeadersConfig(view durableStorer) (*HeadersConfig, error) {
|
||||
// Store the view so that we can reload headers when we 'Invalidate'.
|
||||
return &HeadersConfig{
|
||||
view: view,
|
||||
headerSettings: make(map[string]*HeaderSettings),
|
||||
headerSettings: make(map[string]*headerSettings),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Header attempts to retrieve a copy of the settings associated with the specified header.
|
||||
// The second boolean return parameter indicates whether the header existed in configuration,
|
||||
// it should be checked as when 'false' the returned settings will have the default values.
|
||||
func (a *HeadersConfig) Header(name string) (HeaderSettings, bool) {
|
||||
func (a *HeadersConfig) Header(name string) (headerSettings, bool) {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
var s HeaderSettings
|
||||
var s headerSettings
|
||||
v, ok := a.headerSettings[strings.ToLower(name)]
|
||||
|
||||
if ok {
|
||||
@ -91,16 +91,16 @@ func (a *HeadersConfig) Header(name string) (HeaderSettings, bool) {
|
||||
}
|
||||
|
||||
// Headers returns all existing headers along with a copy of their current settings.
|
||||
func (a *HeadersConfig) Headers() map[string]HeaderSettings {
|
||||
func (a *HeadersConfig) Headers() map[string]headerSettings {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
// We know how many entries the map should have.
|
||||
headers := make(map[string]HeaderSettings, len(a.headerSettings))
|
||||
headers := make(map[string]headerSettings, len(a.headerSettings))
|
||||
|
||||
// Clone the headers
|
||||
for name, setting := range a.headerSettings {
|
||||
headers[name] = HeaderSettings{HMAC: setting.HMAC}
|
||||
headers[name] = headerSettings{HMAC: setting.HMAC}
|
||||
}
|
||||
|
||||
return headers
|
||||
@ -118,10 +118,10 @@ func (a *HeadersConfig) Add(ctx context.Context, header string, hmac bool) error
|
||||
defer a.Unlock()
|
||||
|
||||
if a.headerSettings == nil {
|
||||
a.headerSettings = make(map[string]*HeaderSettings, 1)
|
||||
a.headerSettings = make(map[string]*headerSettings, 1)
|
||||
}
|
||||
|
||||
a.headerSettings[strings.ToLower(header)] = &HeaderSettings{hmac}
|
||||
a.headerSettings[strings.ToLower(header)] = &headerSettings{hmac}
|
||||
entry, err := logical.StorageEntryJSON(auditedHeadersEntry, a.headerSettings)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist audited headers config: %w", err)
|
||||
@ -167,12 +167,12 @@ func (a *HeadersConfig) Remove(ctx context.Context, header string) error {
|
||||
// added to HeadersConfig in order to allow them to appear in audit logs in a raw
|
||||
// format. If the Vault Operator adds their own setting for any of the defaults,
|
||||
// their setting will be honored.
|
||||
func (a *HeadersConfig) DefaultHeaders() map[string]*HeaderSettings {
|
||||
func (a *HeadersConfig) DefaultHeaders() map[string]*headerSettings {
|
||||
// Support deprecated 'x-' prefix (https://datatracker.ietf.org/doc/html/rfc6648)
|
||||
const correlationID = "correlation-id"
|
||||
xCorrelationID := fmt.Sprintf("x-%s", correlationID)
|
||||
|
||||
return map[string]*HeaderSettings{
|
||||
return map[string]*headerSettings{
|
||||
correlationID: {},
|
||||
xCorrelationID: {},
|
||||
}
|
||||
@ -192,7 +192,7 @@ func (a *HeadersConfig) Invalidate(ctx context.Context) error {
|
||||
|
||||
// If we cannot update the stored 'new' headers, we will clear the existing
|
||||
// ones as part of invalidation.
|
||||
headers := make(map[string]*HeaderSettings)
|
||||
headers := make(map[string]*headerSettings)
|
||||
if out != nil {
|
||||
err = out.DecodeJSON(&headers)
|
||||
if err != nil {
|
||||
@ -202,7 +202,7 @@ func (a *HeadersConfig) Invalidate(ctx context.Context) error {
|
||||
|
||||
// Ensure that we are able to case-sensitively access the headers;
|
||||
// necessary for the upgrade case
|
||||
lowerHeaders := make(map[string]*HeaderSettings, len(headers))
|
||||
lowerHeaders := make(map[string]*headerSettings, len(headers))
|
||||
for k, v := range headers {
|
||||
lowerHeaders[strings.ToLower(k)] = v
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func newMockStorage(t *testing.T) *mockStorage {
|
||||
|
||||
func mockAuditedHeadersConfig(t *testing.T) *HeadersConfig {
|
||||
return &HeadersConfig{
|
||||
headerSettings: make(map[string]*HeaderSettings),
|
||||
headerSettings: make(map[string]*headerSettings),
|
||||
view: newMockStorage(t),
|
||||
}
|
||||
}
|
||||
@ -110,13 +110,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
|
||||
t.Fatal("nil value")
|
||||
}
|
||||
|
||||
headers := make(map[string]*HeaderSettings)
|
||||
headers := make(map[string]*headerSettings)
|
||||
err = out.DecodeJSON(&headers)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding header view: %s", err)
|
||||
}
|
||||
|
||||
expected := map[string]*HeaderSettings{
|
||||
expected := map[string]*headerSettings{
|
||||
"x-test-header": {
|
||||
HMAC: false,
|
||||
},
|
||||
@ -148,13 +148,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
|
||||
t.Fatal("nil value")
|
||||
}
|
||||
|
||||
headers = make(map[string]*HeaderSettings)
|
||||
headers = make(map[string]*headerSettings)
|
||||
err = out.DecodeJSON(&headers)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding header view: %s", err)
|
||||
}
|
||||
|
||||
expected["x-vault-header"] = &HeaderSettings{
|
||||
expected["x-vault-header"] = &headerSettings{
|
||||
HMAC: true,
|
||||
}
|
||||
|
||||
@ -184,13 +184,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
|
||||
t.Fatal("nil value")
|
||||
}
|
||||
|
||||
headers := make(map[string]*HeaderSettings)
|
||||
headers := make(map[string]*headerSettings)
|
||||
err = out.DecodeJSON(&headers)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding header view: %s", err)
|
||||
}
|
||||
|
||||
expected := map[string]*HeaderSettings{
|
||||
expected := map[string]*headerSettings{
|
||||
"x-vault-header": {
|
||||
HMAC: true,
|
||||
},
|
||||
@ -218,13 +218,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
|
||||
t.Fatal("nil value")
|
||||
}
|
||||
|
||||
headers = make(map[string]*HeaderSettings)
|
||||
headers = make(map[string]*headerSettings)
|
||||
err = out.DecodeJSON(&headers)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding header view: %s", err)
|
||||
}
|
||||
|
||||
expected = make(map[string]*HeaderSettings)
|
||||
expected = make(map[string]*headerSettings)
|
||||
|
||||
if !reflect.DeepEqual(headers, expected) {
|
||||
t.Fatalf("Expected config didn't match actual. Expected: %#v, Got: %#v", expected, headers)
|
||||
@ -247,7 +247,7 @@ func TestAuditedHeadersConfig_ApplyConfig(t *testing.T) {
|
||||
"Content-Type": {"json"},
|
||||
}
|
||||
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
|
||||
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
|
||||
if err != nil {
|
||||
@ -307,7 +307,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoRequestHeaders(t *testing.T) {
|
||||
err = conf.Add(context.Background(), "X-Vault-HeAdEr", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
|
||||
// Test sending in nil headers first.
|
||||
result, err := conf.ApplyConfig(context.Background(), nil, salter)
|
||||
@ -331,7 +331,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoConfiguredHeaders(t *testing.T) {
|
||||
"Content-Type": {"json"},
|
||||
}
|
||||
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
|
||||
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
|
||||
if err != nil {
|
||||
@ -391,11 +391,11 @@ func TestAuditedHeadersConfig_ApplyConfig_HashStringError(t *testing.T) {
|
||||
|
||||
func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
|
||||
conf := &HeadersConfig{
|
||||
headerSettings: make(map[string]*HeaderSettings),
|
||||
headerSettings: make(map[string]*headerSettings),
|
||||
view: nil,
|
||||
}
|
||||
|
||||
conf.headerSettings = map[string]*HeaderSettings{
|
||||
conf.headerSettings = map[string]*headerSettings{
|
||||
"X-Test-Header": {false},
|
||||
"X-Vault-Header": {true},
|
||||
}
|
||||
@ -406,7 +406,7 @@ func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
|
||||
"Content-Type": {"json"},
|
||||
}
|
||||
|
||||
salter := &TestSalter{}
|
||||
salter := &testSalter{}
|
||||
|
||||
// Reset the timer since we did a lot above
|
||||
b.ResetTimer()
|
||||
@ -449,7 +449,7 @@ func TestAuditedHeaders_invalidate(t *testing.T) {
|
||||
require.Len(t, ahc.headerSettings, 0)
|
||||
|
||||
// Store some data using the view.
|
||||
fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
|
||||
fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
|
||||
fakeBytes1, err := json.Marshal(fakeHeaders1)
|
||||
require.NoError(t, err)
|
||||
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
|
||||
@ -463,7 +463,7 @@ func TestAuditedHeaders_invalidate(t *testing.T) {
|
||||
require.True(t, ok)
|
||||
|
||||
// Do it again with more headers and random casing.
|
||||
fakeHeaders2 := map[string]*HeaderSettings{
|
||||
fakeHeaders2 := map[string]*headerSettings{
|
||||
"x-magic-header": {},
|
||||
"x-even-MORE-magic-header": {},
|
||||
}
|
||||
@ -493,7 +493,7 @@ func TestAuditedHeaders_invalidate_nil_view(t *testing.T) {
|
||||
require.Len(t, ahc.headerSettings, 0)
|
||||
|
||||
// Store some data using the view.
|
||||
fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
|
||||
fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
|
||||
fakeBytes1, err := json.Marshal(fakeHeaders1)
|
||||
require.NoError(t, err)
|
||||
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
|
||||
@ -597,7 +597,7 @@ func TestAuditedHeaders_invalidate_defaults(t *testing.T) {
|
||||
require.Len(t, ahc.headerSettings, 0)
|
||||
|
||||
// Store some data using the view.
|
||||
fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
|
||||
fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
|
||||
fakeBytes1, err := json.Marshal(fakeHeaders1)
|
||||
require.NoError(t, err)
|
||||
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
|
||||
@ -614,7 +614,7 @@ func TestAuditedHeaders_invalidate_defaults(t *testing.T) {
|
||||
require.False(t, s.HMAC)
|
||||
|
||||
// Add correlation ID specifically with HMAC and make sure it doesn't get blasted away.
|
||||
fakeHeaders1 = map[string]*HeaderSettings{"x-magic-header": {}, "X-Correlation-ID": {HMAC: true}}
|
||||
fakeHeaders1 = map[string]*headerSettings{"x-magic-header": {}, "X-Correlation-ID": {HMAC: true}}
|
||||
fakeBytes1, err = json.Marshal(fakeHeaders1)
|
||||
require.NoError(t, err)
|
||||
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
|
||||
|
@ -34,7 +34,7 @@ func processManual(ctx context.Context, data *logical.LogInput, ids []eventlogge
|
||||
}
|
||||
|
||||
// Create an audit event.
|
||||
a, err := NewEvent(RequestType)
|
||||
a, err := newEvent(RequestType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
nshelper "github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/internal/observability/event"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -32,7 +32,7 @@ func TestProcessManual_NilData(t *testing.T) {
|
||||
ids = append(ids, sinkId)
|
||||
nodes[sinkId] = sinkNode
|
||||
|
||||
err := processManual(namespace.RootContext(context.Background()), nil, ids, nodes)
|
||||
err := processManual(nshelper.RootContext(context.Background()), nil, ids, nodes)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "data cannot be nil")
|
||||
}
|
||||
@ -76,7 +76,7 @@ func TestProcessManual_BadIDs(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, tc.IDs, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, tc.IDs, nodes)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, tc.ExpectedErrorMessage)
|
||||
})
|
||||
@ -103,7 +103,7 @@ func TestProcessManual_NoNodes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "nodes are required")
|
||||
}
|
||||
@ -130,7 +130,7 @@ func TestProcessManual_IdNodeMismatch(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "node not found: ")
|
||||
}
|
||||
@ -153,7 +153,7 @@ func TestProcessManual_NotEnoughNodes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "minimum of 2 ids are required")
|
||||
}
|
||||
@ -181,7 +181,7 @@ func TestProcessManual_LastNodeNotSink(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "last node must be a filter or sink")
|
||||
}
|
||||
@ -210,7 +210,7 @@ func TestProcessManualEndWithSink(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ func TestProcessManual_EndWithFilter(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
data := newData(requestId)
|
||||
|
||||
err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
|
||||
err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Option is how options are passed as arguments.
|
||||
type Option func(*options) error
|
||||
// option is how options are passed as arguments.
|
||||
type option func(*options) error
|
||||
|
||||
// options are used to represent configuration for a audit related nodes.
|
||||
type options struct {
|
||||
@ -29,15 +29,15 @@ type options struct {
|
||||
func getDefaultOptions() options {
|
||||
return options{
|
||||
withNow: time.Now(),
|
||||
withFormat: JSONFormat,
|
||||
withFormat: jsonFormat,
|
||||
withHMACAccessor: true,
|
||||
}
|
||||
}
|
||||
|
||||
// getOpts applies each supplied Option and returns the fully configured options.
|
||||
// Each Option is applied in the order it appears in the argument list, so it is
|
||||
// possible to supply the same Option numerous times and the 'last write wins'.
|
||||
func getOpts(opt ...Option) (options, error) {
|
||||
// getOpts applies each supplied option and returns the fully configured options.
|
||||
// Each option is applied in the order it appears in the argument list, so it is
|
||||
// possible to supply the same option numerous times and the 'last write wins'.
|
||||
func getOpts(opt ...option) (options, error) {
|
||||
opts := getDefaultOptions()
|
||||
for _, o := range opt {
|
||||
if o == nil {
|
||||
@ -50,8 +50,8 @@ func getOpts(opt ...Option) (options, error) {
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
// WithID provides an optional ID.
|
||||
func WithID(id string) Option {
|
||||
// withID provides an optional ID.
|
||||
func withID(id string) option {
|
||||
return func(o *options) error {
|
||||
var err error
|
||||
|
||||
@ -67,8 +67,8 @@ func WithID(id string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithNow provides an Option to represent 'now'.
|
||||
func WithNow(now time.Time) Option {
|
||||
// withNow provides an option to represent 'now'.
|
||||
func withNow(now time.Time) option {
|
||||
return func(o *options) error {
|
||||
var err error
|
||||
|
||||
@ -83,8 +83,8 @@ func WithNow(now time.Time) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithSubtype provides an Option to represent the event subtype.
|
||||
func WithSubtype(s string) Option {
|
||||
// withSubtype provides an option to represent the event subtype.
|
||||
func withSubtype(s string) option {
|
||||
return func(o *options) error {
|
||||
s := strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
@ -101,8 +101,8 @@ func WithSubtype(s string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithFormat provides an Option to represent event format.
|
||||
func WithFormat(f string) Option {
|
||||
// withFormat provides an option to represent event format.
|
||||
func withFormat(f string) option {
|
||||
return func(o *options) error {
|
||||
f := strings.TrimSpace(strings.ToLower(f))
|
||||
if f == "" {
|
||||
@ -121,8 +121,8 @@ func WithFormat(f string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithPrefix provides an Option to represent a prefix for a file sink.
|
||||
func WithPrefix(prefix string) Option {
|
||||
// withPrefix provides an option to represent a prefix for a file sink.
|
||||
func withPrefix(prefix string) option {
|
||||
return func(o *options) error {
|
||||
o.withPrefix = prefix
|
||||
|
||||
@ -130,32 +130,32 @@ func WithPrefix(prefix string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithRaw provides an Option to represent whether 'raw' is required.
|
||||
func WithRaw(r bool) Option {
|
||||
// withRaw provides an option to represent whether 'raw' is required.
|
||||
func withRaw(r bool) option {
|
||||
return func(o *options) error {
|
||||
o.withRaw = r
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithElision provides an Option to represent whether elision (...) is required.
|
||||
func WithElision(e bool) Option {
|
||||
// withElision provides an option to represent whether elision (...) is required.
|
||||
func withElision(e bool) option {
|
||||
return func(o *options) error {
|
||||
o.withElision = e
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithOmitTime provides an Option to represent whether to omit time.
|
||||
func WithOmitTime(t bool) Option {
|
||||
// withOmitTime provides an option to represent whether to omit time.
|
||||
func withOmitTime(t bool) option {
|
||||
return func(o *options) error {
|
||||
o.withOmitTime = t
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHMACAccessor provides an Option to represent whether an HMAC accessor is applicable.
|
||||
func WithHMACAccessor(h bool) Option {
|
||||
// withHMACAccessor provides an option to represent whether an HMAC accessor is applicable.
|
||||
func withHMACAccessor(h bool) option {
|
||||
return func(o *options) error {
|
||||
o.withHMACAccessor = h
|
||||
return nil
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestOptions_WithFormat exercises WithFormat Option to ensure it performs as expected.
|
||||
func TestOptions_WithFormat(t *testing.T) {
|
||||
// TestOptions_withFormat exercises withFormat option to ensure it performs as expected.
|
||||
func TestOptions_withFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -38,12 +38,12 @@ func TestOptions_WithFormat(t *testing.T) {
|
||||
"valid-json": {
|
||||
Value: "json",
|
||||
IsErrorExpected: false,
|
||||
ExpectedValue: JSONFormat,
|
||||
ExpectedValue: jsonFormat,
|
||||
},
|
||||
"valid-jsonx": {
|
||||
Value: "jsonx",
|
||||
IsErrorExpected: false,
|
||||
ExpectedValue: JSONxFormat,
|
||||
ExpectedValue: jsonxFormat,
|
||||
},
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ func TestOptions_WithFormat(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithFormat(tc.Value)
|
||||
applyOption := withFormat(tc.Value)
|
||||
err := applyOption(opts)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
@ -67,8 +67,8 @@ func TestOptions_WithFormat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithSubtype exercises WithSubtype Option to ensure it performs as expected.
|
||||
func TestOptions_WithSubtype(t *testing.T) {
|
||||
// TestOptions_withSubtype exercises withSubtype option to ensure it performs as expected.
|
||||
func TestOptions_withSubtype(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -100,7 +100,7 @@ func TestOptions_WithSubtype(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithSubtype(tc.Value)
|
||||
applyOption := withSubtype(tc.Value)
|
||||
err := applyOption(opts)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
@ -114,8 +114,8 @@ func TestOptions_WithSubtype(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithNow exercises WithNow Option to ensure it performs as expected.
|
||||
func TestOptions_WithNow(t *testing.T) {
|
||||
// TestOptions_withNow exercises withNow option to ensure it performs as expected.
|
||||
func TestOptions_withNow(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -143,7 +143,7 @@ func TestOptions_WithNow(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
opts := &options{}
|
||||
applyOption := WithNow(tc.Value)
|
||||
applyOption := withNow(tc.Value)
|
||||
err := applyOption(opts)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
@ -157,8 +157,8 @@ func TestOptions_WithNow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithID exercises WithID Option to ensure it performs as expected.
|
||||
func TestOptions_WithID(t *testing.T) {
|
||||
// TestOptions_withID exercises withID option to ensure it performs as expected.
|
||||
func TestOptions_withID(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -190,7 +190,7 @@ func TestOptions_WithID(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithID(tc.Value)
|
||||
applyOption := withID(tc.Value)
|
||||
err := applyOption(opts)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
@ -204,8 +204,8 @@ func TestOptions_WithID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithPrefix exercises WithPrefix Option to ensure it performs as expected.
|
||||
func TestOptions_WithPrefix(t *testing.T) {
|
||||
// TestOptions_withPrefix exercises withPrefix option to ensure it performs as expected.
|
||||
func TestOptions_withPrefix(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -237,7 +237,7 @@ func TestOptions_WithPrefix(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithPrefix(tc.Value)
|
||||
applyOption := withPrefix(tc.Value)
|
||||
err := applyOption(opts)
|
||||
switch {
|
||||
case tc.IsErrorExpected:
|
||||
@ -251,8 +251,8 @@ func TestOptions_WithPrefix(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithRaw exercises WithRaw Option to ensure it performs as expected.
|
||||
func TestOptions_WithRaw(t *testing.T) {
|
||||
// TestOptions_withRaw exercises withRaw option to ensure it performs as expected.
|
||||
func TestOptions_withRaw(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -275,7 +275,7 @@ func TestOptions_WithRaw(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithRaw(tc.Value)
|
||||
applyOption := withRaw(tc.Value)
|
||||
err := applyOption(opts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.ExpectedValue, opts.withRaw)
|
||||
@ -283,8 +283,8 @@ func TestOptions_WithRaw(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithElision exercises WithElision Option to ensure it performs as expected.
|
||||
func TestOptions_WithElision(t *testing.T) {
|
||||
// TestOptions_withElision exercises withElision option to ensure it performs as expected.
|
||||
func TestOptions_withElision(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -307,7 +307,7 @@ func TestOptions_WithElision(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithElision(tc.Value)
|
||||
applyOption := withElision(tc.Value)
|
||||
err := applyOption(opts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.ExpectedValue, opts.withElision)
|
||||
@ -315,8 +315,8 @@ func TestOptions_WithElision(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithHMACAccessor exercises WithHMACAccessor Option to ensure it performs as expected.
|
||||
func TestOptions_WithHMACAccessor(t *testing.T) {
|
||||
// TestOptions_withHMACAccessor exercises withHMACAccessor option to ensure it performs as expected.
|
||||
func TestOptions_withHMACAccessor(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -339,7 +339,7 @@ func TestOptions_WithHMACAccessor(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithHMACAccessor(tc.Value)
|
||||
applyOption := withHMACAccessor(tc.Value)
|
||||
err := applyOption(opts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.ExpectedValue, opts.withHMACAccessor)
|
||||
@ -347,8 +347,8 @@ func TestOptions_WithHMACAccessor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOptions_WithOmitTime exercises WithOmitTime Option to ensure it performs as expected.
|
||||
func TestOptions_WithOmitTime(t *testing.T) {
|
||||
// TestOptions_withOmitTime exercises withOmitTime option to ensure it performs as expected.
|
||||
func TestOptions_withOmitTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -371,7 +371,7 @@ func TestOptions_WithOmitTime(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := &options{}
|
||||
applyOption := WithOmitTime(tc.Value)
|
||||
applyOption := withOmitTime(tc.Value)
|
||||
err := applyOption(opts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.ExpectedValue, opts.withOmitTime)
|
||||
@ -389,12 +389,12 @@ func TestOptions_Default(t *testing.T) {
|
||||
require.False(t, opts.withNow.IsZero())
|
||||
}
|
||||
|
||||
// TestOptions_Opts exercises GetOpts with various Option values.
|
||||
// TestOptions_Opts exercises GetOpts with various option values.
|
||||
func TestOptions_Opts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
opts []Option
|
||||
opts []option
|
||||
IsErrorExpected bool
|
||||
ExpectedErrorMessage string
|
||||
ExpectedID string
|
||||
@ -407,73 +407,73 @@ func TestOptions_Opts(t *testing.T) {
|
||||
opts: nil,
|
||||
IsErrorExpected: false,
|
||||
IsNowExpected: true,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"empty-options": {
|
||||
opts: []Option{},
|
||||
opts: []option{},
|
||||
IsErrorExpected: false,
|
||||
IsNowExpected: true,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"with-multiple-valid-id": {
|
||||
opts: []Option{
|
||||
WithID("qwerty"),
|
||||
WithID("juan"),
|
||||
opts: []option{
|
||||
withID("qwerty"),
|
||||
withID("juan"),
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedID: "juan",
|
||||
IsNowExpected: true,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"with-multiple-valid-subtype": {
|
||||
opts: []Option{
|
||||
WithSubtype("AuditRequest"),
|
||||
WithSubtype("AuditResponse"),
|
||||
opts: []option{
|
||||
withSubtype("AuditRequest"),
|
||||
withSubtype("AuditResponse"),
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedSubtype: ResponseType,
|
||||
IsNowExpected: true,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"with-multiple-valid-format": {
|
||||
opts: []Option{
|
||||
WithFormat("json"),
|
||||
WithFormat("jsonx"),
|
||||
opts: []option{
|
||||
withFormat("json"),
|
||||
withFormat("jsonx"),
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedFormat: JSONxFormat,
|
||||
ExpectedFormat: jsonxFormat,
|
||||
IsNowExpected: true,
|
||||
},
|
||||
"with-multiple-valid-now": {
|
||||
opts: []Option{
|
||||
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
WithNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
|
||||
opts: []option{
|
||||
withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
withNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedNow: time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local),
|
||||
IsNowExpected: false,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"with-multiple-valid-then-invalid-now": {
|
||||
opts: []Option{
|
||||
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
WithNow(time.Time{}),
|
||||
opts: []option{
|
||||
withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
withNow(time.Time{}),
|
||||
},
|
||||
IsErrorExpected: true,
|
||||
ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant",
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
},
|
||||
"with-multiple-valid-options": {
|
||||
opts: []Option{
|
||||
WithID("qwerty"),
|
||||
WithSubtype("AuditRequest"),
|
||||
WithFormat("json"),
|
||||
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
opts: []option{
|
||||
withID("qwerty"),
|
||||
withSubtype("AuditRequest"),
|
||||
withFormat("json"),
|
||||
withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
|
||||
},
|
||||
IsErrorExpected: false,
|
||||
ExpectedID: "qwerty",
|
||||
ExpectedSubtype: RequestType,
|
||||
ExpectedFormat: JSONFormat,
|
||||
ExpectedFormat: jsonFormat,
|
||||
ExpectedNow: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
|
||||
},
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func newSinkMetricTimer(name string, sink eventlogger.Node) (*sinkMetricTimer, e
|
||||
// 'vault.audit.{DEVICE}.log_response'
|
||||
func (s *sinkMetricTimer) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
|
||||
defer func() {
|
||||
auditEvent, ok := e.Payload.(*AuditEvent)
|
||||
auditEvent, ok := e.Payload.(*Event)
|
||||
if ok {
|
||||
metrics.MeasureSince([]string{"audit", s.name, auditEvent.Subtype.MetricTag()}, e.CreatedAt)
|
||||
}
|
||||
|
@ -7,20 +7,20 @@ import (
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
// Entry represents an audit entry.
|
||||
// entry represents an audit entry.
|
||||
// It could be an entry for a request or response.
|
||||
type Entry struct {
|
||||
Auth *Auth `json:"auth,omitempty"`
|
||||
type entry struct {
|
||||
Auth *auth `json:"auth,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Forwarded bool `json:"forwarded,omitempty"`
|
||||
ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
|
||||
Request *Request `json:"request,omitempty"`
|
||||
Response *Response `json:"response,omitempty"`
|
||||
Request *request `json:"request,omitempty"`
|
||||
Response *response `json:"response,omitempty"`
|
||||
Time string `json:"time,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
type request struct {
|
||||
ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
ClientToken string `json:"client_token,omitempty"`
|
||||
@ -35,7 +35,7 @@ type Request struct {
|
||||
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
|
||||
MountRunningVersion string `json:"mount_running_version,omitempty"`
|
||||
MountType string `json:"mount_type,omitempty"`
|
||||
Namespace *Namespace `json:"namespace,omitempty"`
|
||||
Namespace *namespace `json:"namespace,omitempty"`
|
||||
Operation logical.Operation `json:"operation,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
PolicyOverride bool `json:"policy_override,omitempty"`
|
||||
@ -46,8 +46,8 @@ type Request struct {
|
||||
WrapTTL int `json:"wrap_ttl,omitempty"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Auth *Auth `json:"auth,omitempty"`
|
||||
type response struct {
|
||||
Auth *auth `json:"auth,omitempty"`
|
||||
Data map[string]interface{} `json:"data,omitempty"`
|
||||
Headers map[string][]string `json:"headers,omitempty"`
|
||||
MountAccessor string `json:"mount_accessor,omitempty"`
|
||||
@ -58,12 +58,12 @@ type Response struct {
|
||||
MountRunningVersion string `json:"mount_running_plugin_version,omitempty"`
|
||||
MountType string `json:"mount_type,omitempty"`
|
||||
Redirect string `json:"redirect,omitempty"`
|
||||
Secret *Secret `json:"secret,omitempty"`
|
||||
WrapInfo *ResponseWrapInfo `json:"wrap_info,omitempty"`
|
||||
Secret *secret `json:"secret,omitempty"`
|
||||
WrapInfo *responseWrapInfo `json:"wrap_info,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
type auth struct {
|
||||
Accessor string `json:"accessor,omitempty"`
|
||||
ClientToken string `json:"client_token,omitempty"`
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
@ -75,7 +75,7 @@ type Auth struct {
|
||||
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
||||
NumUses int `json:"num_uses,omitempty"`
|
||||
Policies []string `json:"policies,omitempty"`
|
||||
PolicyResults *PolicyResults `json:"policy_results,omitempty"`
|
||||
PolicyResults *policyResults `json:"policy_results,omitempty"`
|
||||
RemainingUses int `json:"remaining_uses,omitempty"`
|
||||
TokenPolicies []string `json:"token_policies,omitempty"`
|
||||
TokenIssueTime string `json:"token_issue_time,omitempty"`
|
||||
@ -83,23 +83,23 @@ type Auth struct {
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
}
|
||||
|
||||
type PolicyResults struct {
|
||||
type policyResults struct {
|
||||
Allowed bool `json:"allowed"`
|
||||
GrantingPolicies []PolicyInfo `json:"granting_policies,omitempty"`
|
||||
GrantingPolicies []policyInfo `json:"granting_policies,omitempty"`
|
||||
}
|
||||
|
||||
type PolicyInfo struct {
|
||||
type policyInfo struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
NamespaceId string `json:"namespace_id,omitempty"`
|
||||
NamespacePath string `json:"namespace_path,omitempty"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type Secret struct {
|
||||
type secret struct {
|
||||
LeaseID string `json:"lease_id,omitempty"`
|
||||
}
|
||||
|
||||
type ResponseWrapInfo struct {
|
||||
type responseWrapInfo struct {
|
||||
Accessor string `json:"accessor,omitempty"`
|
||||
CreationPath string `json:"creation_path,omitempty"`
|
||||
CreationTime string `json:"creation_time,omitempty"`
|
||||
@ -108,7 +108,7 @@ type ResponseWrapInfo struct {
|
||||
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
|
||||
}
|
||||
|
||||
type Namespace struct {
|
||||
type namespace struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user