unexport as much as possible in the audit package (#28039)

This commit is contained in:
Peter Wilson 2024-08-09 17:03:29 +01:00 committed by GitHub
parent 88975a6c24
commit a19195c901
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 429 additions and 419 deletions

View File

@ -20,9 +20,9 @@ const (
optionMode = "mode" optionMode = "mode"
) )
var _ Backend = (*FileBackend)(nil) var _ Backend = (*fileBackend)(nil)
type FileBackend struct { type fileBackend struct {
*backend *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. // 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() { if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter) return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
} }
@ -60,7 +60,7 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
if err != nil { if err != nil {
return nil, err return nil, err
} }
b := &FileBackend{backend: bec} b := &fileBackend{backend: bec}
// normalize file path if configured for stdout // normalize file path if configured for stdout
if strings.EqualFold(filePath, stdout) { if strings.EqualFold(filePath, stdout) {
@ -89,9 +89,9 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
return b, nil 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. // 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) name = strings.TrimSpace(name)
if name == "" { if name == "" {
return fmt.Errorf("name is required: %w", ErrExternalOptions) 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. // 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 { for _, n := range b.nodeMap {
if n.Type() == eventlogger.NodeTypeSink { if n.Type() == eventlogger.NodeTypeSink {
return n.Reopen() return n.Reopen()

View File

@ -16,7 +16,7 @@ import (
) )
// TestFileBackend_newFileBackend_fallback ensures that we get the correct errors // 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. // and filter.
func TestFileBackend_newFileBackend_fallback(t *testing.T) { func TestFileBackend_newFileBackend_fallback(t *testing.T) {
t.Parallel() t.Parallel()
@ -62,7 +62,7 @@ func TestFileBackend_newFileBackend_fallback(t *testing.T) {
name := name name := name
tc := tc tc := tc
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
be, err := newFileBackend(tc.backendConfig, &NoopHeaderFormatter{}) be, err := newFileBackend(tc.backendConfig, &noopHeaderFormatter{})
if tc.isErrorExpected { if tc.isErrorExpected {
require.Error(t, err) require.Error(t, err)
@ -97,13 +97,13 @@ func TestFileBackend_newFileBackend_FilterFormatterSink(t *testing.T) {
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
} }
b, err := newFileBackend(backendConfig, &NoopHeaderFormatter{}) b, err := newFileBackend(backendConfig, &noopHeaderFormatter{})
require.Error(t, err) require.Error(t, err)
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration") require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
// Try without filter option // Try without filter option
delete(cfg, "filter") delete(cfg, "filter")
b, err = newFileBackend(backendConfig, &NoopHeaderFormatter{}) b, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
require.Len(t, b.nodeIDList, 2) 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.Error(t, err)
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration") require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
// Remove the option and try again // Remove the option and try again
delete(cfg.Config, "fallback") delete(cfg.Config, "fallback")
be, err = newFileBackend(cfg, &NoopHeaderFormatter{}) be, err = newFileBackend(cfg, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, be) require.NotNil(t, be)
require.Equal(t, false, be.IsFallback()) require.Equal(t, false, be.IsFallback())

View File

@ -38,7 +38,7 @@ func TestAuditFile_fileModeNew(t *testing.T) {
SaltView: &logical.InmemStorage{}, SaltView: &logical.InmemStorage{},
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
} }
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{}) _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
info, err := os.Stat(file) info, err := os.Stat(file)
@ -71,7 +71,7 @@ func TestAuditFile_fileModeExisting(t *testing.T) {
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
} }
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{}) _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
info, err := os.Stat(f.Name()) info, err := os.Stat(f.Name())
@ -105,7 +105,7 @@ func TestAuditFile_fileMode0000(t *testing.T) {
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
} }
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{}) _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
info, err := os.Stat(f.Name()) info, err := os.Stat(f.Name())
@ -134,7 +134,7 @@ func TestAuditFile_EventLogger_fileModeNew(t *testing.T) {
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
} }
_, err = newFileBackend(backendConfig, &NoopHeaderFormatter{}) _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err) require.NoError(t, err)
info, err := os.Stat(file) info, err := os.Stat(file)
@ -267,7 +267,7 @@ func TestFileBackend_newFileBackend(t *testing.T) {
}, },
MountPath: tc.mountPath, MountPath: tc.mountPath,
} }
b, err := newFileBackend(cfg, &NoopHeaderFormatter{}) b, err := newFileBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr { if tc.wantErr {
require.Error(t, err) require.Error(t, err)

View File

@ -35,14 +35,17 @@ type noopWrapper struct {
backend *NoopAudit backend *NoopAudit
} }
// NoopAuditEventListener is a callback used by noopWrapper.Process() to notify // SetListener provides a callback func to the NoopAudit which can be invoked
// of each received audit event. // during processing of the Event.
type NoopAuditEventListener func(*AuditEvent) //
// Deprecated: SetListener should not be used in new tests.
func (n *NoopAudit) SetListener(listener NoopAuditEventListener) { func (n *NoopAudit) SetListener(listener func(event *Event)) {
n.listener = listener 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 { type NoopAudit struct {
Config *BackendConfig Config *BackendConfig
@ -68,16 +71,16 @@ type NoopAudit struct {
nodeIDList []eventlogger.NodeID nodeIDList []eventlogger.NodeID
nodeMap map[eventlogger.NodeID]eventlogger.Node 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. // 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. // 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. // 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) { func (f *noopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string][]string, _ Salter) (result map[string][]string, retErr error) {
if len(headers) < 1 { if len(headers) < 1 {
return map[string][]string{}, nil 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 // 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 // predictable salt and wraps eventlogger nodes so information can be retrieved on
// what they've seen or formatted. // what they've seen or formatted.
//
// Deprecated: NewNoopAudit only exists to allow legacy tests to continue working.
func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) { func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
view := &logical.InmemStorage{} view := &logical.InmemStorage{}
@ -122,7 +127,7 @@ func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
nodeMap: make(map[eventlogger.NodeID]eventlogger.Node, 2), nodeMap: make(map[eventlogger.NodeID]eventlogger.Node, 2),
} }
cfg, err := newFormatterConfig(&NoopHeaderFormatter{}, nil) cfg, err := newFormatterConfig(&noopHeaderFormatter{}, nil)
if err != nil { if err != nil {
return nil, err 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 // NoopAuditFactory should be used when the test needs a way to access bytes that
// have been formatted by the pipeline during audit requests. // have been formatted by the pipeline during audit requests.
// The records parameter will be repointed to the one used within the pipeline. // 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 { func NoopAuditFactory(records **[][]byte) Factory {
return func(config *BackendConfig, _ HeaderFormatter) (Backend, error) { return func(config *BackendConfig, _ HeaderFormatter) (Backend, error) {
n, err := NewNoopAudit(config) n, err := NewNoopAudit(config)
@ -184,7 +191,7 @@ func (n *noopWrapper) Process(ctx context.Context, e *eventlogger.Event) (*event
var err error var err error
// We're expecting audit events since this is an audit device. // We're expecting audit events since this is an audit device.
a, ok := e.Payload.(*AuditEvent) a, ok := e.Payload.(*Event)
if !ok { if !ok {
return nil, errors.New("cannot parse payload as an audit event") 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. // formatted headers that would have made it to the logs via the sink node.
// They only appear in requests. // They only appear in requests.
if a.Subtype == RequestType { if a.Subtype == RequestType {
reqEntry := &Entry{} reqEntry := &entry{}
err = json.Unmarshal(b, &reqEntry) err = json.Unmarshal(b, &reqEntry)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to parse formatted audit entry data: %w", err) return nil, fmt.Errorf("unable to parse formatted audit entry data: %w", err)
@ -336,6 +343,7 @@ func (n *NoopAudit) IsFallback() bool {
return false 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 { func TestNoopAudit(t *testing.T, path string, config map[string]string) *NoopAudit {
cfg := &BackendConfig{ cfg := &BackendConfig{
Config: config, Config: config,

View File

@ -18,9 +18,9 @@ const (
optionWriteTimeout = "write_timeout" optionWriteTimeout = "write_timeout"
) )
var _ Backend = (*SocketBackend)(nil) var _ Backend = (*socketBackend)(nil)
type SocketBackend struct { type socketBackend struct {
*backend *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. // 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() { if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter) return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
} }
@ -78,7 +78,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
return nil, err return nil, err
} }
b := &SocketBackend{backend: bec} b := &socketBackend{backend: bec}
// Configure the sink. // Configure the sink.
cfg, err := newFormatterConfig(headersConfig, conf.Config) cfg, err := newFormatterConfig(headersConfig, conf.Config)
@ -94,7 +94,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
return b, nil 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() sinkNodeID, err := event.GenerateNodeID()
if err != nil { if err != nil {
return fmt.Errorf("error generating random NodeID for sink node: %w", err) 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. // 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 { for _, n := range b.nodeMap {
if n.Type() == eventlogger.NodeTypeSink { if n.Type() == eventlogger.NodeTypeSink {
return n.Reopen() return n.Reopen()

View File

@ -114,7 +114,7 @@ func TestSocketBackend_newSocketBackend(t *testing.T) {
}, },
MountPath: tc.mountPath, MountPath: tc.mountPath,
} }
b, err := newSocketBackend(cfg, &NoopHeaderFormatter{}) b, err := newSocketBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr { if tc.wantErr {
require.Error(t, err) require.Error(t, err)

View File

@ -15,9 +15,9 @@ const (
optionTag = "tag" optionTag = "tag"
) )
var _ Backend = (*SyslogBackend)(nil) var _ Backend = (*syslogBackend)(nil)
type SyslogBackend struct { type syslogBackend struct {
*backend *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. // 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() { if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter) return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
} }
@ -68,7 +68,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
return nil, err return nil, err
} }
b := &SyslogBackend{backend: bec} b := &syslogBackend{backend: bec}
// Configure the sink. // Configure the sink.
cfg, err := newFormatterConfig(headersConfig, conf.Config) cfg, err := newFormatterConfig(headersConfig, conf.Config)
@ -84,7 +84,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
return b, nil 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() sinkNodeID, err := event.GenerateNodeID()
if err != nil { if err != nil {
return fmt.Errorf("error generating random NodeID for sink node: %w: %w", ErrInternal, err) 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. // 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 return nil
} }

View File

@ -97,7 +97,7 @@ func TestSyslogBackend_newSyslogBackend(t *testing.T) {
}, },
MountPath: tc.mountPath, MountPath: tc.mountPath,
} }
b, err := newSyslogBackend(cfg, &NoopHeaderFormatter{}) b, err := newSyslogBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr { if tc.wantErr {
require.Error(t, err) require.Error(t, err)

View File

@ -25,7 +25,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}{ }{
"happy-path-json": { "happy-path-json": {
config: map[string]string{ config: map[string]string{
"format": JSONFormat.String(), "format": jsonFormat.String(),
"hmac_accessor": "true", "hmac_accessor": "true",
"log_raw": "true", "log_raw": "true",
"elide_list_responses": "true", "elide_list_responses": "true",
@ -39,7 +39,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}, },
"happy-path-jsonx": { "happy-path-jsonx": {
config: map[string]string{ config: map[string]string{
"format": JSONxFormat.String(), "format": jsonxFormat.String(),
"hmac_accessor": "true", "hmac_accessor": "true",
"log_raw": "true", "log_raw": "true",
"elide_list_responses": "true", "elide_list_responses": "true",
@ -65,7 +65,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}, },
"invalid-hmac-accessor": { "invalid-hmac-accessor": {
config: map[string]string{ config: map[string]string{
"format": JSONFormat.String(), "format": jsonFormat.String(),
"hmac_accessor": "maybe", "hmac_accessor": "maybe",
}, },
want: formatterConfig{}, want: formatterConfig{},
@ -74,7 +74,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}, },
"invalid-log-raw": { "invalid-log-raw": {
config: map[string]string{ config: map[string]string{
"format": JSONFormat.String(), "format": jsonFormat.String(),
"hmac_accessor": "true", "hmac_accessor": "true",
"log_raw": "maybe", "log_raw": "maybe",
}, },
@ -84,7 +84,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}, },
"invalid-elide-bool": { "invalid-elide-bool": {
config: map[string]string{ config: map[string]string{
"format": JSONFormat.String(), "format": jsonFormat.String(),
"hmac_accessor": "true", "hmac_accessor": "true",
"log_raw": "true", "log_raw": "true",
"elide_list_responses": "maybe", "elide_list_responses": "maybe",
@ -95,11 +95,11 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}, },
"prefix": { "prefix": {
config: map[string]string{ config: map[string]string{
"format": JSONFormat.String(), "format": jsonFormat.String(),
"prefix": "foo", "prefix": "foo",
}, },
want: formatterConfig{ want: formatterConfig{
requiredFormat: JSONFormat, requiredFormat: jsonFormat,
prefix: "foo", prefix: "foo",
hmacAccessor: true, hmacAccessor: true,
}, },
@ -111,7 +111,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
got, err := newFormatterConfig(&NoopHeaderFormatter{}, tc.config) got, err := newFormatterConfig(&noopHeaderFormatter{}, tc.config)
if tc.wantErr { if tc.wantErr {
require.Error(t, err) require.Error(t, err)
require.EqualError(t, err, tc.expectedMessage) require.EqualError(t, err, tc.expectedMessage)
@ -133,7 +133,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
func TestBackend_configureFormatterNode(t *testing.T) { func TestBackend_configureFormatterNode(t *testing.T) {
t.Parallel() t.Parallel()
b, err := newBackend(&NoopHeaderFormatter{}, &BackendConfig{ b, err := newBackend(&noopHeaderFormatter{}, &BackendConfig{
MountPath: "foo", MountPath: "foo",
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
}) })

View File

@ -15,7 +15,7 @@ import (
"github.com/armon/go-metrics" "github.com/armon/go-metrics"
"github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog" "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/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical" "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) metrics.IncrCounter([]string{"audit", "log_request_failure"}, metricVal)
}() }()
e, err := NewEvent(RequestType) e, err := newEvent(RequestType)
if err != nil { if err != nil {
return err 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) // 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 // is triggered. Pipeline nodes and the eventlogger.Broker may check for a
// cancelled context and refuse to process the nodes further. // cancelled context and refuse to process the nodes further.
ns, err := namespace.FromContext(ctx) ns, err := nshelper.FromContext(ctx)
if err != nil { if err != nil {
return fmt.Errorf("namespace missing from context: %w", err) return fmt.Errorf("namespace missing from context: %w", err)
} }
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout) tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
defer auditCancel() defer auditCancel()
auditContext = namespace.ContextWithNamespace(tempContext, ns) auditContext = nshelper.ContextWithNamespace(tempContext, ns)
} }
var status eventlogger.Status 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) metrics.IncrCounter([]string{"audit", "log_response_failure"}, metricVal)
}() }()
e, err := NewEvent(ResponseType) e, err := newEvent(ResponseType)
if err != nil { if err != nil {
return err 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) // 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 // is triggered. Pipeline nodes and the eventlogger.Broker may check for a
// cancelled context and refuse to process the nodes further. // cancelled context and refuse to process the nodes further.
ns, err := namespace.FromContext(ctx) ns, err := nshelper.FromContext(ctx)
if err != nil { if err != nil {
return fmt.Errorf("namespace missing from context: %w", err) return fmt.Errorf("namespace missing from context: %w", err)
} }
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout) tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
defer auditCancel() defer auditCancel()
auditContext = namespace.ContextWithNamespace(tempContext, ns) auditContext = nshelper.ContextWithNamespace(tempContext, ns)
} }
var status eventlogger.Status var status eventlogger.Status

View File

@ -44,6 +44,6 @@ func (b *Broker) requiredSuccessThresholdSinks() int {
return 0 return 0
} }
func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *AuditEvent) error { func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *Event) error {
return nil return nil
} }

View File

@ -10,7 +10,7 @@ import (
"time" "time"
"github.com/hashicorp/go-hclog" "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/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
@ -23,7 +23,7 @@ func testAuditBackend(t *testing.T, path string, config map[string]string) Backe
t.Helper() t.Helper()
headersCfg := &HeadersConfig{ headersCfg := &HeadersConfig{
headerSettings: make(map[string]*HeaderSettings), headerSettings: make(map[string]*headerSettings),
view: nil, 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.ResetTimer()
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -10,7 +10,7 @@ import (
"github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-bexpr"
"github.com/hashicorp/vault/helper/namespace" nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/logical" "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) return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
} }
a, ok := e.Payload.(*AuditEvent) a, ok := e.Payload.(*Event)
if !ok { if !ok {
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter) 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 return nil, nil
} }
ns, err := namespace.FromContext(ctx) ns, err := nshelper.FromContext(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot obtain namespace: %w", err) return nil, fmt.Errorf("cannot obtain namespace: %w", err)
} }

View File

@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/hashicorp/eventlogger" "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/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -117,7 +117,7 @@ func TestEntryFilter_Process_ContextDone(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Fake audit event // Fake audit event
a, err := NewEvent(RequestType) a, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
// Fake event logger event // Fake event logger event
@ -184,7 +184,7 @@ func TestEntryFilter_Process_NoAuditDataInPayload(t *testing.T) {
l, err := newEntryFilter("operation == foo") l, err := newEntryFilter("operation == foo")
require.NoError(t, err) require.NoError(t, err)
a, err := NewEvent(RequestType) a, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
// Ensure audit data is nil // Ensure audit data is nil
@ -212,7 +212,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
l, err := newEntryFilter("mount_type == juan") l, err := newEntryFilter("mount_type == juan")
require.NoError(t, err) require.NoError(t, err)
a, err := NewEvent(RequestType) a, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
a.Data = &logical.LogInput{ a.Data = &logical.LogInput{
@ -229,7 +229,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
Payload: a, Payload: a,
} }
ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace) ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
e2, err := l.Process(ctx, e) 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") l, err := newEntryFilter("mount_type == john and operation == create and namespace == root")
require.NoError(t, err) require.NoError(t, err)
a, err := NewEvent(RequestType) a, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
a.Data = &logical.LogInput{ a.Data = &logical.LogInput{
@ -262,7 +262,7 @@ func TestEntryFilter_Process_FilterFail(t *testing.T) {
Payload: a, Payload: a,
} }
ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace) ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
e2, err := l.Process(ctx, e) e2, err := l.Process(ctx, e)

View File

@ -15,7 +15,7 @@ import (
"github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror" "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/jsonutil"
"github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical" "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 // 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) { 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 // 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. // 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) return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
} }
a, ok := e.Payload.(*AuditEvent) a, ok := e.Payload.(*Event)
if !ok { if !ok {
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter) 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) 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 var err error
result, err = jsonx.EncodeJSONBytes(result) result, err = jsonx.EncodeJSONBytes(result)
if err != nil { 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 // 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 // (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. // tokenRemainingUses should be the client token remaining uses to include in auth.
// This usually can be found in logical.Request.ClientTokenRemainingUses. // This usually can be found in logical.Request.ClientTokenRemainingUses.
// NOTE: supplying a nil value for auth will result in a nil return value and // 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. // (nil) error. The caller should check the return value before attempting to use it.
func newAuth(auth *logical.Auth, tokenRemainingUses int) (*Auth, error) { // ignore-nil-nil-function-check.
if auth == nil { func newAuth(input *logical.Auth, tokenRemainingUses int) (*auth, error) {
if input == nil {
return nil, nil return nil, nil
} }
extNSPolicies, err := clone(auth.ExternalNamespacePolicies) extNSPolicies, err := clone(input.ExternalNamespacePolicies)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to clone logical auth: external namespace policies: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("unable to clone logical auth: identity policies: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("unable to clone logical auth: metadata: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("unable to clone logical auth: policies: %w", err) return nil, fmt.Errorf("unable to clone logical auth: policies: %w", err)
} }
var policyResults *PolicyResults var polRes *policyResults
if auth.PolicyResults != nil { if input.PolicyResults != nil {
policyResults = &PolicyResults{ polRes = &policyResults{
Allowed: auth.PolicyResults.Allowed, Allowed: input.PolicyResults.Allowed,
GrantingPolicies: make([]PolicyInfo, len(auth.PolicyResults.GrantingPolicies)), GrantingPolicies: make([]policyInfo, len(input.PolicyResults.GrantingPolicies)),
} }
for _, p := range auth.PolicyResults.GrantingPolicies { for _, p := range input.PolicyResults.GrantingPolicies {
policyResults.GrantingPolicies = append(policyResults.GrantingPolicies, PolicyInfo{ polRes.GrantingPolicies = append(polRes.GrantingPolicies, policyInfo{
Name: p.Name, Name: p.Name,
NamespaceId: p.NamespaceId, NamespaceId: p.NamespaceId,
NamespacePath: p.NamespacePath, 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 { if err != nil {
return nil, fmt.Errorf("unable to clone logical auth: token policies: %w", err) return nil, fmt.Errorf("unable to clone logical auth: token policies: %w", err)
} }
var tokenIssueTime string var tokenIssueTime string
if !auth.IssueTime.IsZero() { if !input.IssueTime.IsZero() {
tokenIssueTime = auth.IssueTime.Format(time.RFC3339) tokenIssueTime = input.IssueTime.Format(time.RFC3339)
} }
return &Auth{ return &auth{
Accessor: auth.Accessor, Accessor: input.Accessor,
ClientToken: auth.ClientToken, ClientToken: input.ClientToken,
DisplayName: auth.DisplayName, DisplayName: input.DisplayName,
EntityCreated: auth.EntityCreated, EntityCreated: input.EntityCreated,
EntityID: auth.EntityID, EntityID: input.EntityID,
ExternalNamespacePolicies: extNSPolicies, ExternalNamespacePolicies: extNSPolicies,
IdentityPolicies: identityPolicies, IdentityPolicies: identityPolicies,
Metadata: metadata, Metadata: metadata,
NoDefaultPolicy: auth.NoDefaultPolicy, NoDefaultPolicy: input.NoDefaultPolicy,
NumUses: auth.NumUses, NumUses: input.NumUses,
Policies: policies, Policies: policies,
PolicyResults: policyResults, PolicyResults: polRes,
RemainingUses: tokenRemainingUses, RemainingUses: tokenRemainingUses,
TokenPolicies: tokenPolicies, TokenPolicies: tokenPolicies,
TokenIssueTime: tokenIssueTime, TokenIssueTime: tokenIssueTime,
TokenTTL: int64(auth.TTL.Seconds()), TokenTTL: int64(input.TTL.Seconds()),
TokenType: auth.TokenType.String(), TokenType: input.TokenType.String(),
}, nil }, nil
} }
// newRequest takes a logical.Request and namespace.Namespace, transforms and // newRequest takes a logical.Request and namespace.Namespace, transforms and
// aggregates them into an audit Request. // aggregates them into an audit request.
func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error) { func newRequest(req *logical.Request, ns *nshelper.Namespace) (*request, error) {
if req == nil { if req == nil {
return nil, fmt.Errorf("request cannot be 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) wrapTTL = int(req.WrapInfo.TTL / time.Second)
} }
return &Request{ return &request{
ClientCertificateSerialNumber: clientCertSerial, ClientCertificateSerialNumber: clientCertSerial,
ClientID: req.ClientID, ClientID: req.ClientID,
ClientToken: req.ClientToken, ClientToken: req.ClientToken,
@ -377,7 +378,7 @@ func newRequest(req *logical.Request, ns *namespace.Namespace) (*Request, error)
MountRunningSha256: req.MountRunningSha256(), MountRunningSha256: req.MountRunningSha256(),
MountRunningVersion: req.MountRunningVersion(), MountRunningVersion: req.MountRunningVersion(),
MountType: req.MountType, MountType: req.MountType,
Namespace: &Namespace{ Namespace: &namespace{
ID: ns.ID, ID: ns.ID,
Path: ns.Path, 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 // 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. // 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 // 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. // (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 { if resp == nil {
return nil, 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) return nil, fmt.Errorf("unable to clone logical response: headers: %w", err)
} }
var secret *Secret var s *secret
if resp.Secret != nil { 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 { if resp.WrapInfo != nil {
token := resp.WrapInfo.Token token := resp.WrapInfo.Token
if jwtToken := parseVaultTokenFromJWT(token); jwtToken != nil { 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) ttl := int(resp.WrapInfo.TTL / time.Second)
wrapInfo = &ResponseWrapInfo{ wrapInfo = &responseWrapInfo{
TTL: ttl, TTL: ttl,
Token: token, Token: token,
Accessor: resp.WrapInfo.Accessor, 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 nil, fmt.Errorf("unable to clone logical response: warnings: %w", err)
} }
return &Response{ return &response{
Auth: auth, Auth: auth,
Data: data, Data: data,
Headers: headers, Headers: headers,
@ -498,15 +500,15 @@ func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired
MountRunningVersion: req.MountRunningVersion(), MountRunningVersion: req.MountRunningVersion(),
MountType: req.MountType, MountType: req.MountType,
Redirect: resp.Redirect, Redirect: resp.Redirect,
Secret: secret, Secret: s,
WrapInfo: wrapInfo, WrapInfo: wrapInfo,
Warnings: warnings, Warnings: warnings,
}, nil }, nil
} }
// createEntry takes the AuditEvent and builds an audit Entry. // createEntry takes the AuditEvent and builds an audit entry.
// The Entry will be HMAC'd and elided where required. // The entry will be HMAC'd and elided where required.
func (f *entryFormatter) createEntry(ctx context.Context, a *AuditEvent) (*Entry, error) { func (f *entryFormatter) createEntry(ctx context.Context, a *Event) (*entry, error) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() 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) 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 { if err != nil {
return nil, fmt.Errorf("unable to retrieve namespace from context: %w", err) 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) return nil, fmt.Errorf("cannot convert request: %w", err)
} }
var resp *Response var resp *response
if a.Subtype == ResponseType { if a.Subtype == ResponseType {
shouldElide := f.config.elideListResponses && req.Operation == logical.ListOperation shouldElide := f.config.elideListResponses && req.Operation == logical.ListOperation
resp, err = newResponse(data.Response, data.Request, shouldElide) 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() entryType = a.Subtype.String()
} }
entry := &Entry{ entry := &entry{
Auth: auth, Auth: auth,
Error: outerErr, Error: outerErr,
Forwarded: false, Forwarded: false,

View File

@ -42,7 +42,7 @@ type formatterConfig struct {
// This should only ever be used in a testing context // This should only ever be used in a testing context
omitTime bool 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 requiredFormat format
// headerFormatter specifies the formatter used for headers that existing in any incoming audit request. // 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) return formatterConfig{}, fmt.Errorf("header formatter is required: %w", ErrInvalidParameter)
} }
var opt []Option var opt []option
if format, ok := config[optionFormat]; ok { if format, ok := config[optionFormat]; ok {
if !IsValidFormat(format) { if !isValidFormat(format) {
return formatterConfig{}, fmt.Errorf("unsupported %q: %w", optionFormat, ErrExternalOptions) 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 // Check if hashing of accessor is disabled
@ -74,7 +74,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil { if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionHMACAccessor, ErrExternalOptions) 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 // Check if raw logging is enabled
@ -83,7 +83,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil { if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionLogRaw, ErrExternalOptions) 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 { if elideListResponsesRaw, ok := config[optionElideListResponses]; ok {
@ -91,11 +91,11 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil { if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionElideListResponses, ErrExternalOptions) 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 { if prefix, ok := config[optionPrefix]; ok {
opt = append(opt, WithPrefix(prefix)) opt = append(opt, withPrefix(prefix))
} }
opts, err := getOpts(opt...) opts, err := getOpts(opt...)

View File

@ -15,7 +15,7 @@ import (
"github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-sockaddr" "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/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/internal/observability/event" "github.com/hashicorp/vault/internal/observability/event"
"github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/helper/jsonutil"
@ -132,14 +132,14 @@ func TestNewEntryFormatter(t *testing.T) {
Options: map[string]string{ Options: map[string]string{
"format": "json", "format": "json",
}, },
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"default": { "default": {
Name: "juan", Name: "juan",
UseStaticSalt: true, UseStaticSalt: true,
Logger: hclog.NewNullLogger(), Logger: hclog.NewNullLogger(),
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"config-json": { "config-json": {
Name: "juan", Name: "juan",
@ -149,7 +149,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "json", "format": "json",
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"config-jsonx": { "config-jsonx": {
Name: "juan", Name: "juan",
@ -159,7 +159,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "jsonx", "format": "jsonx",
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONxFormat, ExpectedFormat: jsonxFormat,
}, },
"config-json-prefix": { "config-json-prefix": {
Name: "juan", Name: "juan",
@ -170,7 +170,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "json", "format": "json",
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
ExpectedPrefix: "foo", ExpectedPrefix: "foo",
}, },
"config-jsonx-prefix": { "config-jsonx-prefix": {
@ -182,7 +182,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "jsonx", "format": "jsonx",
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONxFormat, ExpectedFormat: jsonxFormat,
ExpectedPrefix: "foo", ExpectedPrefix: "foo",
}, },
} }
@ -245,7 +245,7 @@ func TestEntryFormatter_Type(t *testing.T) {
} }
// TestEntryFormatter_Process attempts to run the Process method to convert the // 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) { func TestEntryFormatter_Process(t *testing.T) {
t.Parallel() t.Parallel()
@ -261,21 +261,21 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter", ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: nil, Data: nil,
}, },
"json-response-no-data": { "json-response-no-data": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter", ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: nil, Data: nil,
}, },
"json-request-basic-input": { "json-request-basic-input": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil", ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{Type: "magic"}, Data: &logical.LogInput{Type: "magic"},
RootNamespace: true, RootNamespace: true,
}, },
@ -283,34 +283,34 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil", ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{Type: "magic"}, Data: &logical.LogInput{Type: "magic"},
}, },
"json-request-basic-input-and-request-no-ns": { "json-request-basic-input-and-request-no-ns": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace", ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
}, },
"json-response-basic-input-and-request-no-ns": { "json-response-basic-input-and-request-no-ns": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace", ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
}, },
"json-request-basic-input-and-request-with-ns": { "json-request-basic-input-and-request-with-ns": {
IsErrorExpected: false, IsErrorExpected: false,
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
RootNamespace: true, RootNamespace: true,
}, },
"json-response-basic-input-and-request-with-ns": { "json-response-basic-input-and-request-with-ns": {
IsErrorExpected: false, IsErrorExpected: false,
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONFormat, RequiredFormat: jsonFormat,
Data: &logical.LogInput{ Data: &logical.LogInput{
Request: &logical.Request{ID: "123"}, Request: &logical.Request{ID: "123"},
Response: &logical.Response{}, Response: &logical.Response{},
@ -321,21 +321,21 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter", ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: nil, Data: nil,
}, },
"jsonx-response-no-data": { "jsonx-response-no-data": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter", ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: nil, Data: nil,
}, },
"jsonx-request-basic-input": { "jsonx-request-basic-input": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil", ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Type: "magic"}, Data: &logical.LogInput{Type: "magic"},
RootNamespace: true, RootNamespace: true,
}, },
@ -343,7 +343,7 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil", ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Type: "magic"}, Data: &logical.LogInput{Type: "magic"},
RootNamespace: true, RootNamespace: true,
}, },
@ -351,27 +351,27 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace", ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
}, },
"jsonx-response-basic-input-and-request-no-ns": { "jsonx-response-basic-input-and-request-no-ns": {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace", ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
}, },
"jsonx-request-basic-input-and-request-with-ns": { "jsonx-request-basic-input-and-request-with-ns": {
IsErrorExpected: false, IsErrorExpected: false,
Subtype: RequestType, Subtype: RequestType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}}, Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
RootNamespace: true, RootNamespace: true,
}, },
"jsonx-response-basic-input-and-request-with-ns": { "jsonx-response-basic-input-and-request-with-ns": {
IsErrorExpected: false, IsErrorExpected: false,
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{ Data: &logical.LogInput{
Request: &logical.Request{ID: "123"}, Request: &logical.Request{ID: "123"},
Response: &logical.Response{}, Response: &logical.Response{},
@ -382,7 +382,7 @@ func TestEntryFormatter_Process(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil", ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
Subtype: ResponseType, Subtype: ResponseType,
RequiredFormat: JSONxFormat, RequiredFormat: jsonxFormat,
Data: &logical.LogInput{ Data: &logical.LogInput{
Auth: &logical.Auth{}, Auth: &logical.Auth{},
}, },
@ -409,7 +409,7 @@ func TestEntryFormatter_Process(t *testing.T) {
var ctx context.Context var ctx context.Context
switch { switch {
case tc.RootNamespace: case tc.RootNamespace:
ctx = namespace.RootContext(context.Background()) ctx = nshelper.RootContext(context.Background())
default: default:
ctx = context.Background() 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. // Create the formatter node.
cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil) cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil)
@ -472,7 +472,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
require.NotNil(b, formatter) require.NotNil(b, formatter)
// Create the sink node. // 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.NoError(b, err)
require.NotNil(b, sink) require.NotNil(b, sink)
@ -551,12 +551,12 @@ func TestEntryFormatter_Process_Request(t *testing.T) {
var ctx context.Context var ctx context.Context
switch { switch {
case tc.RootNamespace: case tc.RootNamespace:
ctx = namespace.RootContext(context.Background()) ctx = nshelper.RootContext(context.Background())
default: default:
ctx = context.Background() ctx = context.Background()
} }
auditEvent, err := NewEvent(RequestType) auditEvent, err := newEvent(RequestType)
auditEvent.setTimeProvider(&testTimeProvider{}) auditEvent.setTimeProvider(&testTimeProvider{})
require.NoError(t, err) require.NoError(t, err)
auditEvent.Data = tc.Input auditEvent.Data = tc.Input
@ -577,18 +577,18 @@ func TestEntryFormatter_Process_Request(t *testing.T) {
case tc.ShouldOmitTime: case tc.ShouldOmitTime:
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
b, ok := e2.Format(JSONFormat.String()) b, ok := e2.Format(jsonFormat.String())
require.True(t, ok) require.True(t, ok)
var entry *Entry var entry *entry
err = json.Unmarshal(b, &entry) err = json.Unmarshal(b, &entry)
require.NoError(t, err) require.NoError(t, err)
require.Zero(t, entry.Time) require.Zero(t, entry.Time)
default: default:
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
b, ok := e2.Format(JSONFormat.String()) b, ok := e2.Format(jsonFormat.String())
require.True(t, ok) require.True(t, ok)
var entry *Entry var entry *entry
err = json.Unmarshal(b, &entry) err = json.Unmarshal(b, &entry)
require.NoError(t, err) require.NoError(t, err)
require.NotZero(t, entry.Time) require.NotZero(t, entry.Time)
@ -661,12 +661,12 @@ func TestEntryFormatter_Process_ResponseType(t *testing.T) {
var ctx context.Context var ctx context.Context
switch { switch {
case tc.RootNamespace: case tc.RootNamespace:
ctx = namespace.RootContext(context.Background()) ctx = nshelper.RootContext(context.Background())
default: default:
ctx = context.Background() ctx = context.Background()
} }
auditEvent, err := NewEvent(ResponseType) auditEvent, err := newEvent(ResponseType)
auditEvent.setTimeProvider(&testTimeProvider{}) auditEvent.setTimeProvider(&testTimeProvider{})
require.NoError(t, err) require.NoError(t, err)
auditEvent.Data = tc.Input auditEvent.Data = tc.Input
@ -688,18 +688,18 @@ func TestEntryFormatter_Process_ResponseType(t *testing.T) {
case tc.ShouldOmitTime: case tc.ShouldOmitTime:
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
b, ok := e2.Format(JSONFormat.String()) b, ok := e2.Format(jsonFormat.String())
require.True(t, ok) require.True(t, ok)
var entry *Entry var entry *entry
err = json.Unmarshal(b, &entry) err = json.Unmarshal(b, &entry)
require.NoError(t, err) require.NoError(t, err)
require.Zero(t, entry.Time) require.Zero(t, entry.Time)
default: default:
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
b, ok := e2.Format(JSONFormat.String()) b, ok := e2.Format(jsonFormat.String())
require.True(t, ok) require.True(t, ok)
var entry *Entry var entry *entry
err = json.Unmarshal(b, &entry) err = json.Unmarshal(b, &entry)
require.NoError(t, err) require.NoError(t, err)
require.NotZero(t, entry.Time) 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 // Create an audit event and more generic eventlogger.event to allow us
// to process (format). // to process (format).
auditEvent, err := NewEvent(RequestType) auditEvent, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
auditEvent.Data = in auditEvent.Data = in
@ -818,10 +818,10 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
Payload: auditEvent, 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) 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.True(t, ok)
require.Positive(t, len(jsonBytes)) 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) 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 { if err := jsonutil.DecodeJSON([]byte(expectedResultStr), &expectedJSON); err != nil {
t.Fatalf("bad json: %s", err) 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 { if err := jsonutil.DecodeJSON(jsonBytes[len(tc.Prefix):], &actualJSON); err != nil {
t.Fatalf("bad json: %s", err) 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 // Create an audit event and more generic eventlogger.event to allow us
// to process (format). // to process (format).
auditEvent, err := NewEvent(RequestType) auditEvent, err := newEvent(RequestType)
require.NoError(t, err) require.NoError(t, err)
auditEvent.Data = in auditEvent.Data = in
@ -983,10 +983,10 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
Payload: auditEvent, 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) 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.True(t, ok)
require.Positive(t, len(jsonxBytes)) require.Positive(t, len(jsonxBytes))
@ -1071,11 +1071,11 @@ func TestEntryFormatter_ElideListResponses(t *testing.T) {
oneInterestingTestCase := tests["Enhanced list (has key_info)"] oneInterestingTestCase := tests["Enhanced list (has key_info)"]
ss := newStaticSalt(t) ss := newStaticSalt(t)
ctx := namespace.RootContext(context.Background()) ctx := nshelper.RootContext(context.Background())
var formatter *entryFormatter var formatter *entryFormatter
var err error 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()) formatter, err = newEntryFormatter("juan", config, ss, hclog.NewNullLogger())
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, formatter) require.NotNil(t, formatter)
@ -1085,7 +1085,7 @@ func TestEntryFormatter_ElideListResponses(t *testing.T) {
Response: &logical.Response{Data: inputData}, Response: &logical.Response{Data: inputData},
} }
auditEvent, err := NewEvent(ResponseType) auditEvent, err := newEvent(ResponseType)
require.NoError(t, err) require.NoError(t, err)
auditEvent.Data = in auditEvent.Data = in
@ -1182,7 +1182,7 @@ func TestEntryFormatter_Process_NoMutation(t *testing.T) {
e := fakeEvent(t, RequestType, in) 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.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
@ -1245,7 +1245,7 @@ func TestEntryFormatter_Process_Panic(t *testing.T) {
e := fakeEvent(t, ResponseType, in) 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.Error(t, err)
require.Contains(t, err.Error(), "panic generating audit log: \"juan\"") require.Contains(t, err.Error(), "panic generating audit log: \"juan\"")
require.Nil(t, e2) require.Nil(t, e2)
@ -1282,13 +1282,13 @@ func TestEntryFormatter_Process_NeverLeaksHeaders(t *testing.T) {
e := fakeEvent(t, RequestType, input) e := fakeEvent(t, RequestType, input)
// Process the node. // Process the node.
ctx := namespace.RootContext(context.Background()) ctx := nshelper.RootContext(context.Background())
e2, err := formatter.Process(ctx, e) e2, err := formatter.Process(ctx, e)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, e2) require.NotNil(t, e2)
// Now check we can retrieve the formatted JSON. // 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.True(t, b2)
require.NotNil(t, jsonFormatted) require.NotNil(t, jsonFormatted)
var input2 *logical.LogInput 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) date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local)
auditEvent, err := NewEvent(subtype, auditEvent, err := newEvent(subtype,
WithID("123"), withID("123"),
WithNow(date), withNow(date),
) )
require.NoError(tb, err) require.NoError(tb, err)
require.NotNil(tb, auditEvent) require.NotNil(tb, auditEvent)

View File

@ -20,9 +20,9 @@ var (
ErrExternalOptions = errors.New("invalid configuration") ErrExternalOptions = errors.New("invalid configuration")
) )
// ConvertToExternalError handles converting an error that was generated in Vault // ConvertToExternalError handles converting an audit related error that was generated
// and should appear as-is in the server logs, to an error that can be returned to // in Vault and should appear as-is in the server logs, to an error that can be
// calling clients (via the API/CLI). // returned to calling clients (via the API/CLI).
func ConvertToExternalError(err error) error { func ConvertToExternalError(err error) error {
// If the error is an internal error, the contents will have been logged, and // If the error is an internal error, the contents will have been logged, and
// we should probably shield the caller from the details. // we should probably shield the caller from the details.

View File

@ -23,15 +23,15 @@ const (
// Audit formats. // Audit formats.
const ( const (
JSONFormat format = "json" jsonFormat format = "json"
JSONxFormat format = "jsonx" jsonxFormat format = "jsonx"
) )
// Check AuditEvent implements the timeProvider at compile time. // Check AuditEvent implements the timeProvider at compile time.
var _ timeProvider = (*AuditEvent)(nil) var _ timeProvider = (*Event)(nil)
// AuditEvent is the audit event. // Event is the audit event.
type AuditEvent struct { type Event struct {
ID string `json:"id"` ID string `json:"id"`
Version string `json:"version"` Version string `json:"version"`
Subtype subtype `json:"subtype"` // the subtype of the audit event. 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 // 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. // 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 a.prov = t
} }
// timeProvider returns a configured time provider, or the default if not set. // 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 { if a.prov == nil {
return a return a
} }
@ -62,10 +62,10 @@ type format string
// subtype defines the type of audit event. // subtype defines the type of audit event.
type subtype string 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 // for audit events. It will generate an ID if no ID is supplied. Supported
// options: WithID, WithNow. // options: withID, withNow.
func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) { func newEvent(s subtype, opt ...option) (*Event, error) {
// Get the default options // Get the default options
opts, err := getOpts(opt...) opts, err := getOpts(opt...)
if err != nil { if err != nil {
@ -81,7 +81,7 @@ func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
} }
} }
audit := &AuditEvent{ audit := &Event{
ID: opts.withID, ID: opts.withID,
Timestamp: opts.withNow, Timestamp: opts.withNow,
Version: version, 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. // 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 { if a == nil {
return fmt.Errorf("event is nil: %w", ErrInvalidParameter) 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. // validate ensures that format is one of the set of allowed event formats.
func (f format) validate() error { func (f format) validate() error {
switch f { switch f {
case JSONFormat, JSONxFormat: case jsonFormat, jsonxFormat:
return nil return nil
default: default:
return fmt.Errorf("invalid format %q: %w", f, ErrInvalidParameter) 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 // formattedTime returns the UTC time the AuditEvent was created in the RFC3339Nano
// format (which removes trailing zeros from the seconds field). // 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) 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. // 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() err := format(strings.TrimSpace(strings.ToLower(v))).validate()
return err == nil return err == nil
} }

View File

@ -15,7 +15,7 @@ func TestAuditEvent_new(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
Options []Option Options []option
Subtype subtype Subtype subtype
Format format Format format
IsErrorExpected bool IsErrorExpected bool
@ -33,47 +33,47 @@ func TestAuditEvent_new(t *testing.T) {
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter", ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
}, },
"empty-Option": { "empty-option": {
Options: []Option{}, Options: []option{},
Subtype: subtype(""), Subtype: subtype(""),
Format: format(""), Format: format(""),
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter", ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
}, },
"bad-id": { "bad-id": {
Options: []Option{WithID("")}, Options: []option{withID("")},
Subtype: ResponseType, Subtype: ResponseType,
Format: JSONFormat, Format: jsonFormat,
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "id cannot be empty", ExpectedErrorMessage: "id cannot be empty",
}, },
"good": { "good": {
Options: []Option{ Options: []option{
WithID("audit_123"), withID("audit_123"),
WithFormat(string(JSONFormat)), withFormat(string(jsonFormat)),
WithSubtype(string(ResponseType)), withSubtype(string(ResponseType)),
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)), withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
}, },
Subtype: RequestType, Subtype: RequestType,
Format: JSONxFormat, Format: jsonxFormat,
IsErrorExpected: false, IsErrorExpected: false,
ExpectedID: "audit_123", ExpectedID: "audit_123",
ExpectedTimestamp: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local), ExpectedTimestamp: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
ExpectedSubtype: RequestType, ExpectedSubtype: RequestType,
ExpectedFormat: JSONxFormat, ExpectedFormat: jsonxFormat,
}, },
"good-no-time": { "good-no-time": {
Options: []Option{ Options: []option{
WithID("audit_123"), withID("audit_123"),
WithFormat(string(JSONFormat)), withFormat(string(jsonFormat)),
WithSubtype(string(ResponseType)), withSubtype(string(ResponseType)),
}, },
Subtype: RequestType, Subtype: RequestType,
Format: JSONxFormat, Format: jsonxFormat,
IsErrorExpected: false, IsErrorExpected: false,
ExpectedID: "audit_123", ExpectedID: "audit_123",
ExpectedSubtype: RequestType, ExpectedSubtype: RequestType,
ExpectedFormat: JSONxFormat, ExpectedFormat: jsonxFormat,
IsNowExpected: true, IsNowExpected: true,
}, },
} }
@ -84,7 +84,7 @@ func TestAuditEvent_new(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
audit, err := NewEvent(tc.Subtype, tc.Options...) audit, err := newEvent(tc.Subtype, tc.Options...)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
require.Error(t, err) require.Error(t, err)
@ -112,7 +112,7 @@ func TestAuditEvent_Validate(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
Value *AuditEvent Value *Event
IsErrorExpected bool IsErrorExpected bool
ExpectedErrorMessage string ExpectedErrorMessage string
}{ }{
@ -122,12 +122,12 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event is nil: invalid internal parameter", ExpectedErrorMessage: "event is nil: invalid internal parameter",
}, },
"default": { "default": {
Value: &AuditEvent{}, Value: &Event{},
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "missing ID: invalid internal parameter", ExpectedErrorMessage: "missing ID: invalid internal parameter",
}, },
"id-empty": { "id-empty": {
Value: &AuditEvent{ Value: &Event{
ID: "", ID: "",
Version: version, Version: version,
Subtype: RequestType, Subtype: RequestType,
@ -138,7 +138,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "missing ID: invalid internal parameter", ExpectedErrorMessage: "missing ID: invalid internal parameter",
}, },
"version-fiddled": { "version-fiddled": {
Value: &AuditEvent{ Value: &Event{
ID: "audit_123", ID: "audit_123",
Version: "magic-v2", Version: "magic-v2",
Subtype: RequestType, Subtype: RequestType,
@ -149,7 +149,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event version unsupported: invalid internal parameter", ExpectedErrorMessage: "event version unsupported: invalid internal parameter",
}, },
"subtype-fiddled": { "subtype-fiddled": {
Value: &AuditEvent{ Value: &Event{
ID: "audit_123", ID: "audit_123",
Version: version, Version: version,
Subtype: subtype("moon"), Subtype: subtype("moon"),
@ -160,7 +160,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "invalid event subtype \"moon\": invalid internal parameter", ExpectedErrorMessage: "invalid event subtype \"moon\": invalid internal parameter",
}, },
"default-time": { "default-time": {
Value: &AuditEvent{ Value: &Event{
ID: "audit_123", ID: "audit_123",
Version: version, Version: version,
Subtype: ResponseType, Subtype: ResponseType,
@ -171,7 +171,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event timestamp cannot be the zero time instant: invalid internal parameter", ExpectedErrorMessage: "event timestamp cannot be the zero time instant: invalid internal parameter",
}, },
"valid": { "valid": {
Value: &AuditEvent{ Value: &Event{
ID: "audit_123", ID: "audit_123",
Version: version, Version: version,
Subtype: ResponseType, Subtype: ResponseType,
@ -373,7 +373,7 @@ func TestAuditEvent_Subtype_String(t *testing.T) {
// method returns the correct format. // method returns the correct format.
func TestAuditEvent_formattedTime(t *testing.T) { func TestAuditEvent_formattedTime(t *testing.T) {
theTime := time.Date(2024, time.March, 22, 10, 0o0, 5, 10, time.UTC) 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.NoError(t, err)
require.NotNil(t, a) require.NotNil(t, a)
require.Equal(t, "2024-03-22T10:00:05.00000001Z", a.formattedTime()) require.Equal(t, "2024-03-22T10:00:05.00000001Z", a.formattedTime())
@ -439,7 +439,7 @@ func TestEvent_IsValidFormat(t *testing.T) {
tc := tc tc := tc
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
res := IsValidFormat(tc.input) res := isValidFormat(tc.input)
require.Equal(t, tc.expected, res) require.Equal(t, tc.expected, res)
}) })
} }

View File

@ -25,10 +25,10 @@ func hashString(ctx context.Context, salter Salter, data string) (string, error)
return salt.GetIdentifiedHMAC(data), nil 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 // hmacAccessor is used to indicate whether the accessor should also be HMAC'd
// when present. // 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 { if auth == nil {
return nil return nil
} }
@ -50,14 +50,14 @@ func hashAuth(ctx context.Context, salter Salter, auth *Auth, hmacAccessor bool)
return nil return nil
} }
// hashRequest uses the Salter to hash the supplied Request (modifying it). // hashRequest uses the Salter to hash the supplied request (modifying it).
// 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. // prevents those specific keys from HMAC'd.
// hmacAccessor is used to indicate whether some accessors should also be HMAC'd // hmacAccessor is used to indicate whether some accessors should also be HMAC'd
// when present. // 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. // 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 { if req == nil {
return nil return nil
} }
@ -102,13 +102,13 @@ func hashMap(hashFunc hashCallback, data map[string]interface{}, nonHMACDataKeys
return hashStructure(data, hashFunc, 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 // hmacAccessor is used to indicate whether some accessors should also be HMAC'd
// when present. // 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. // prevents those specific keys from HMAC'd.
// See: /vault/docs/audit#eliding-list-response-bodies // 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 { if resp == nil {
return nil return nil
} }
@ -142,10 +142,10 @@ func hashResponse(ctx context.Context, salter Salter, resp *Response, hmacAccess
return nil 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 // hmacAccessor is used to indicate whether some accessors should also be HMAC'd
// when present. // when present.
func hashWrapInfo(hashFunc hashCallback, wrapInfo *ResponseWrapInfo, hmacAccessor bool) error { func hashWrapInfo(hashFunc hashCallback, wrapInfo *responseWrapInfo, hmacAccessor bool) error {
if wrapInfo == nil { if wrapInfo == nil {
return nil return nil
} }

View File

@ -11,7 +11,7 @@ import (
"testing" "testing"
"time" "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/certutil"
"github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/helper/wrapping" "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. // manner.
type TestSalter struct{} type testSalter struct{}
// Salt returns a salt.Salt pointer based on dummy data stored in an in-memory // Salt returns a salt.Salt pointer based on dummy data stored in an in-memory
// storage instance. // storage instance.
func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) { func (*testSalter) Salt(ctx context.Context) (*salt.Salt, error) {
inmemStorage := &logical.InmemStorage{} inmemStorage := &logical.InmemStorage{}
err := inmemStorage.Put(context.Background(), &logical.StorageEntry{ err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
Key: "salt", Key: "salt",
@ -120,7 +120,7 @@ func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) {
} }
func TestHashString(t *testing.T) { func TestHashString(t *testing.T) {
salter := &TestSalter{} salter := &testSalter{}
out, err := hashString(context.Background(), salter, "foo") out, err := hashString(context.Background(), salter, "foo")
if err != nil { if err != nil {
@ -134,7 +134,7 @@ func TestHashString(t *testing.T) {
func TestHashAuth(t *testing.T) { func TestHashAuth(t *testing.T) {
cases := map[string]struct { cases := map[string]struct {
Input *logical.Auth Input *logical.Auth
Output *Auth Output *auth
HMACAccessor bool HMACAccessor bool
}{ }{
"no-accessor-hmac": { "no-accessor-hmac": {
@ -146,7 +146,7 @@ func TestHashAuth(t *testing.T) {
}, },
TokenType: logical.TokenTypeService, TokenType: logical.TokenTypeService,
}, },
&Auth{ &auth{
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a", ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
Accessor: "very-accessible", Accessor: "very-accessible",
TokenTTL: 3600, TokenTTL: 3600,
@ -164,7 +164,7 @@ func TestHashAuth(t *testing.T) {
}, },
TokenType: logical.TokenTypeBatch, TokenType: logical.TokenTypeBatch,
}, },
&Auth{ &auth{
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a", ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
Accessor: "hmac-sha256:5d6d7c8da5b699ace193ea453bbf77082a8aaca42a474436509487d646a7c0af", Accessor: "hmac-sha256:5d6d7c8da5b699ace193ea453bbf77082a8aaca42a474436509487d646a7c0af",
TokenTTL: 3600, TokenTTL: 3600,
@ -181,7 +181,7 @@ func TestHashAuth(t *testing.T) {
Value: []byte("foo"), Value: []byte("foo"),
}) })
require.NoError(t, err) require.NoError(t, err)
salter := &TestSalter{} salter := &testSalter{}
for _, tc := range cases { for _, tc := range cases {
auditAuth, err := newAuth(tc.Input, 5) auditAuth, err := newAuth(tc.Input, 5)
require.NoError(t, err) require.NoError(t, err)
@ -205,7 +205,7 @@ var _ logical.OptMarshaler = &testOptMarshaler{}
func TestHashRequest(t *testing.T) { func TestHashRequest(t *testing.T) {
cases := []struct { cases := []struct {
Input *logical.Request Input *logical.Request
Output *Request Output *request
NonHMACDataKeys []string NonHMACDataKeys []string
HMACAccessor bool HMACAccessor bool
}{ }{
@ -218,16 +218,16 @@ func TestHashRequest(t *testing.T) {
"om": &testOptMarshaler{S: "bar", I: 1}, "om": &testOptMarshaler{S: "bar", I: 1},
}, },
}, },
&Request{ &request{
Data: map[string]interface{}{ Data: map[string]interface{}{
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", "foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
"baz": "foobar", "baz": "foobar",
"private_key_type": "hmac-sha256:995230dca56fffd310ff591aa404aab52b2abb41703c787cfa829eceb4595bf1", "private_key_type": "hmac-sha256:995230dca56fffd310ff591aa404aab52b2abb41703c787cfa829eceb4595bf1",
"om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`), "om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
}, },
Namespace: &Namespace{ Namespace: &namespace{
ID: namespace.RootNamespace.ID, ID: nshelper.RootNamespace.ID,
Path: namespace.RootNamespace.Path, Path: nshelper.RootNamespace.Path,
}, },
}, },
[]string{"baz"}, []string{"baz"},
@ -241,9 +241,9 @@ func TestHashRequest(t *testing.T) {
Value: []byte("foo"), Value: []byte("foo"),
}) })
require.NoError(t, err) require.NoError(t, err)
salter := &TestSalter{} salter := &testSalter{}
for _, tc := range cases { for _, tc := range cases {
auditReq, err := newRequest(tc.Input, namespace.RootNamespace) auditReq, err := newRequest(tc.Input, nshelper.RootNamespace)
require.NoError(t, err) require.NoError(t, err)
err = hashRequest(context.Background(), salter, auditReq, tc.HMACAccessor, tc.NonHMACDataKeys) err = hashRequest(context.Background(), salter, auditReq, tc.HMACAccessor, tc.NonHMACDataKeys)
require.NoError(t, err) require.NoError(t, err)
@ -279,14 +279,14 @@ func TestHashResponse(t *testing.T) {
nonHMACDataKeys := []string{"baz"} nonHMACDataKeys := []string{"baz"}
expected := &Response{ expected := &response{
Data: map[string]interface{}{ Data: map[string]interface{}{
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", "foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
"baz": "foobar", "baz": "foobar",
"bar": now.Format(time.RFC3339Nano), "bar": now.Format(time.RFC3339Nano),
"om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`), "om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
}, },
WrapInfo: &ResponseWrapInfo{ WrapInfo: &responseWrapInfo{
TTL: 60, TTL: 60,
Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317", Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
Accessor: "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390", Accessor: "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390",
@ -306,7 +306,7 @@ func TestHashResponse(t *testing.T) {
Value: []byte("foo"), Value: []byte("foo"),
}) })
require.NoError(t, err) require.NoError(t, err)
salter := &TestSalter{} salter := &testSalter{}
auditResp, err := newResponse(resp, req, false) auditResp, err := newResponse(resp, req, false)
require.NoError(t, err) require.NoError(t, err)
err = hashResponse(context.Background(), salter, auditResp, true, nonHMACDataKeys) err = hashResponse(context.Background(), salter, auditResp, true, nonHMACDataKeys)

View File

@ -42,7 +42,7 @@ func AuditedHeadersKey() string {
return AuditedHeadersSubPath + auditedHeadersEntry 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 is used to indicate whether the value of the header should be HMAC'd.
HMAC bool `json:"hmac"` HMAC bool `json:"hmac"`
} }
@ -51,7 +51,7 @@ type HeaderSettings struct {
// headers to the audit logs. It uses a BarrierView to persist the settings. // headers to the audit logs. It uses a BarrierView to persist the settings.
type HeadersConfig struct { type HeadersConfig struct {
// headerSettings stores the current headers that should be audited, and their settings. // 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 is the barrier view which should be used to access underlying audit header config data.
view durableStorer view durableStorer
@ -69,18 +69,18 @@ func NewHeadersConfig(view durableStorer) (*HeadersConfig, error) {
// Store the view so that we can reload headers when we 'Invalidate'. // Store the view so that we can reload headers when we 'Invalidate'.
return &HeadersConfig{ return &HeadersConfig{
view: view, view: view,
headerSettings: make(map[string]*HeaderSettings), headerSettings: make(map[string]*headerSettings),
}, nil }, nil
} }
// Header attempts to retrieve a copy of the settings associated with the specified header. // 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, // 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. // 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() a.RLock()
defer a.RUnlock() defer a.RUnlock()
var s HeaderSettings var s headerSettings
v, ok := a.headerSettings[strings.ToLower(name)] v, ok := a.headerSettings[strings.ToLower(name)]
if ok { 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. // 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() a.RLock()
defer a.RUnlock() defer a.RUnlock()
// We know how many entries the map should have. // 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 // Clone the headers
for name, setting := range a.headerSettings { for name, setting := range a.headerSettings {
headers[name] = HeaderSettings{HMAC: setting.HMAC} headers[name] = headerSettings{HMAC: setting.HMAC}
} }
return headers return headers
@ -118,10 +118,10 @@ func (a *HeadersConfig) Add(ctx context.Context, header string, hmac bool) error
defer a.Unlock() defer a.Unlock()
if a.headerSettings == nil { 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) entry, err := logical.StorageEntryJSON(auditedHeadersEntry, a.headerSettings)
if err != nil { if err != nil {
return fmt.Errorf("failed to persist audited headers config: %w", err) 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 // 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, // format. If the Vault Operator adds their own setting for any of the defaults,
// their setting will be honored. // 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) // Support deprecated 'x-' prefix (https://datatracker.ietf.org/doc/html/rfc6648)
const correlationID = "correlation-id" const correlationID = "correlation-id"
xCorrelationID := fmt.Sprintf("x-%s", correlationID) xCorrelationID := fmt.Sprintf("x-%s", correlationID)
return map[string]*HeaderSettings{ return map[string]*headerSettings{
correlationID: {}, correlationID: {},
xCorrelationID: {}, 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 // If we cannot update the stored 'new' headers, we will clear the existing
// ones as part of invalidation. // ones as part of invalidation.
headers := make(map[string]*HeaderSettings) headers := make(map[string]*headerSettings)
if out != nil { if out != nil {
err = out.DecodeJSON(&headers) err = out.DecodeJSON(&headers)
if err != nil { 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; // Ensure that we are able to case-sensitively access the headers;
// necessary for the upgrade case // necessary for the upgrade case
lowerHeaders := make(map[string]*HeaderSettings, len(headers)) lowerHeaders := make(map[string]*headerSettings, len(headers))
for k, v := range headers { for k, v := range headers {
lowerHeaders[strings.ToLower(k)] = v lowerHeaders[strings.ToLower(k)] = v
} }

View File

@ -71,7 +71,7 @@ func newMockStorage(t *testing.T) *mockStorage {
func mockAuditedHeadersConfig(t *testing.T) *HeadersConfig { func mockAuditedHeadersConfig(t *testing.T) *HeadersConfig {
return &HeadersConfig{ return &HeadersConfig{
headerSettings: make(map[string]*HeaderSettings), headerSettings: make(map[string]*headerSettings),
view: newMockStorage(t), view: newMockStorage(t),
} }
} }
@ -110,13 +110,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value") t.Fatal("nil value")
} }
headers := make(map[string]*HeaderSettings) headers := make(map[string]*headerSettings)
err = out.DecodeJSON(&headers) err = out.DecodeJSON(&headers)
if err != nil { if err != nil {
t.Fatalf("Error decoding header view: %s", err) t.Fatalf("Error decoding header view: %s", err)
} }
expected := map[string]*HeaderSettings{ expected := map[string]*headerSettings{
"x-test-header": { "x-test-header": {
HMAC: false, HMAC: false,
}, },
@ -148,13 +148,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value") t.Fatal("nil value")
} }
headers = make(map[string]*HeaderSettings) headers = make(map[string]*headerSettings)
err = out.DecodeJSON(&headers) err = out.DecodeJSON(&headers)
if err != nil { if err != nil {
t.Fatalf("Error decoding header view: %s", err) t.Fatalf("Error decoding header view: %s", err)
} }
expected["x-vault-header"] = &HeaderSettings{ expected["x-vault-header"] = &headerSettings{
HMAC: true, HMAC: true,
} }
@ -184,13 +184,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value") t.Fatal("nil value")
} }
headers := make(map[string]*HeaderSettings) headers := make(map[string]*headerSettings)
err = out.DecodeJSON(&headers) err = out.DecodeJSON(&headers)
if err != nil { if err != nil {
t.Fatalf("Error decoding header view: %s", err) t.Fatalf("Error decoding header view: %s", err)
} }
expected := map[string]*HeaderSettings{ expected := map[string]*headerSettings{
"x-vault-header": { "x-vault-header": {
HMAC: true, HMAC: true,
}, },
@ -218,13 +218,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value") t.Fatal("nil value")
} }
headers = make(map[string]*HeaderSettings) headers = make(map[string]*headerSettings)
err = out.DecodeJSON(&headers) err = out.DecodeJSON(&headers)
if err != nil { if err != nil {
t.Fatalf("Error decoding header view: %s", err) t.Fatalf("Error decoding header view: %s", err)
} }
expected = make(map[string]*HeaderSettings) expected = make(map[string]*headerSettings)
if !reflect.DeepEqual(headers, expected) { if !reflect.DeepEqual(headers, expected) {
t.Fatalf("Expected config didn't match actual. Expected: %#v, Got: %#v", expected, headers) 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"}, "Content-Type": {"json"},
} }
salter := &TestSalter{} salter := &testSalter{}
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter) result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
if err != nil { if err != nil {
@ -307,7 +307,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoRequestHeaders(t *testing.T) {
err = conf.Add(context.Background(), "X-Vault-HeAdEr", true) err = conf.Add(context.Background(), "X-Vault-HeAdEr", true)
require.NoError(t, err) require.NoError(t, err)
salter := &TestSalter{} salter := &testSalter{}
// Test sending in nil headers first. // Test sending in nil headers first.
result, err := conf.ApplyConfig(context.Background(), nil, salter) result, err := conf.ApplyConfig(context.Background(), nil, salter)
@ -331,7 +331,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoConfiguredHeaders(t *testing.T) {
"Content-Type": {"json"}, "Content-Type": {"json"},
} }
salter := &TestSalter{} salter := &testSalter{}
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter) result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
if err != nil { if err != nil {
@ -391,11 +391,11 @@ func TestAuditedHeadersConfig_ApplyConfig_HashStringError(t *testing.T) {
func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) { func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
conf := &HeadersConfig{ conf := &HeadersConfig{
headerSettings: make(map[string]*HeaderSettings), headerSettings: make(map[string]*headerSettings),
view: nil, view: nil,
} }
conf.headerSettings = map[string]*HeaderSettings{ conf.headerSettings = map[string]*headerSettings{
"X-Test-Header": {false}, "X-Test-Header": {false},
"X-Vault-Header": {true}, "X-Vault-Header": {true},
} }
@ -406,7 +406,7 @@ func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
"Content-Type": {"json"}, "Content-Type": {"json"},
} }
salter := &TestSalter{} salter := &testSalter{}
// Reset the timer since we did a lot above // Reset the timer since we did a lot above
b.ResetTimer() b.ResetTimer()
@ -449,7 +449,7 @@ func TestAuditedHeaders_invalidate(t *testing.T) {
require.Len(t, ahc.headerSettings, 0) require.Len(t, ahc.headerSettings, 0)
// Store some data using the view. // 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) fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err) require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1}) 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) require.True(t, ok)
// Do it again with more headers and random casing. // Do it again with more headers and random casing.
fakeHeaders2 := map[string]*HeaderSettings{ fakeHeaders2 := map[string]*headerSettings{
"x-magic-header": {}, "x-magic-header": {},
"x-even-MORE-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) require.Len(t, ahc.headerSettings, 0)
// Store some data using the view. // 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) fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err) require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1}) 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) require.Len(t, ahc.headerSettings, 0)
// Store some data using the view. // 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) fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err) require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1}) 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) require.False(t, s.HMAC)
// Add correlation ID specifically with HMAC and make sure it doesn't get blasted away. // 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) fakeBytes1, err = json.Marshal(fakeHeaders1)
require.NoError(t, err) require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1}) err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})

View File

@ -34,7 +34,7 @@ func processManual(ctx context.Context, data *logical.LogInput, ids []eventlogge
} }
// Create an audit event. // Create an audit event.
a, err := NewEvent(RequestType) a, err := newEvent(RequestType)
if err != nil { if err != nil {
return err return err
} }

View File

@ -9,7 +9,7 @@ import (
"github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-uuid" "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/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -32,7 +32,7 @@ func TestProcessManual_NilData(t *testing.T) {
ids = append(ids, sinkId) ids = append(ids, sinkId)
nodes[sinkId] = sinkNode 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.Error(t, err)
require.EqualError(t, err, "data cannot be nil") require.EqualError(t, err, "data cannot be nil")
} }
@ -76,7 +76,7 @@ func TestProcessManual_BadIDs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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.Error(t, err)
require.EqualError(t, err, tc.ExpectedErrorMessage) require.EqualError(t, err, tc.ExpectedErrorMessage)
}) })
@ -103,7 +103,7 @@ func TestProcessManual_NoNodes(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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.Error(t, err)
require.EqualError(t, err, "nodes are required") require.EqualError(t, err, "nodes are required")
} }
@ -130,7 +130,7 @@ func TestProcessManual_IdNodeMismatch(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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.Error(t, err)
require.ErrorContains(t, err, "node not found: ") require.ErrorContains(t, err, "node not found: ")
} }
@ -153,7 +153,7 @@ func TestProcessManual_NotEnoughNodes(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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.Error(t, err)
require.EqualError(t, err, "minimum of 2 ids are required") require.EqualError(t, err, "minimum of 2 ids are required")
} }
@ -181,7 +181,7 @@ func TestProcessManual_LastNodeNotSink(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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.Error(t, err)
require.EqualError(t, err, "last node must be a filter or sink") 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) require.NoError(t, err)
data := newData(requestId) 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) require.NoError(t, err)
} }
@ -243,7 +243,7 @@ func TestProcessManual_EndWithFilter(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) 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) require.NoError(t, err)
} }

View File

@ -9,8 +9,8 @@ import (
"time" "time"
) )
// Option is how options are passed as arguments. // option is how options are passed as arguments.
type Option func(*options) error type option func(*options) error
// options are used to represent configuration for a audit related nodes. // options are used to represent configuration for a audit related nodes.
type options struct { type options struct {
@ -29,15 +29,15 @@ type options struct {
func getDefaultOptions() options { func getDefaultOptions() options {
return options{ return options{
withNow: time.Now(), withNow: time.Now(),
withFormat: JSONFormat, withFormat: jsonFormat,
withHMACAccessor: true, withHMACAccessor: true,
} }
} }
// getOpts applies each supplied Option and returns the fully configured options. // 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 // 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'. // possible to supply the same option numerous times and the 'last write wins'.
func getOpts(opt ...Option) (options, error) { func getOpts(opt ...option) (options, error) {
opts := getDefaultOptions() opts := getDefaultOptions()
for _, o := range opt { for _, o := range opt {
if o == nil { if o == nil {
@ -50,8 +50,8 @@ func getOpts(opt ...Option) (options, error) {
return opts, nil return opts, nil
} }
// WithID provides an optional ID. // withID provides an optional ID.
func WithID(id string) Option { func withID(id string) option {
return func(o *options) error { return func(o *options) error {
var err error var err error
@ -67,8 +67,8 @@ func WithID(id string) Option {
} }
} }
// WithNow provides an Option to represent 'now'. // withNow provides an option to represent 'now'.
func WithNow(now time.Time) Option { func withNow(now time.Time) option {
return func(o *options) error { return func(o *options) error {
var err error var err error
@ -83,8 +83,8 @@ func WithNow(now time.Time) Option {
} }
} }
// WithSubtype provides an Option to represent the event subtype. // withSubtype provides an option to represent the event subtype.
func WithSubtype(s string) Option { func withSubtype(s string) option {
return func(o *options) error { return func(o *options) error {
s := strings.TrimSpace(s) s := strings.TrimSpace(s)
if s == "" { if s == "" {
@ -101,8 +101,8 @@ func WithSubtype(s string) Option {
} }
} }
// WithFormat provides an Option to represent event format. // withFormat provides an option to represent event format.
func WithFormat(f string) Option { func withFormat(f string) option {
return func(o *options) error { return func(o *options) error {
f := strings.TrimSpace(strings.ToLower(f)) f := strings.TrimSpace(strings.ToLower(f))
if f == "" { if f == "" {
@ -121,8 +121,8 @@ func WithFormat(f string) Option {
} }
} }
// WithPrefix provides an Option to represent a prefix for a file sink. // withPrefix provides an option to represent a prefix for a file sink.
func WithPrefix(prefix string) Option { func withPrefix(prefix string) option {
return func(o *options) error { return func(o *options) error {
o.withPrefix = prefix o.withPrefix = prefix
@ -130,32 +130,32 @@ func WithPrefix(prefix string) Option {
} }
} }
// WithRaw provides an Option to represent whether 'raw' is required. // withRaw provides an option to represent whether 'raw' is required.
func WithRaw(r bool) Option { func withRaw(r bool) option {
return func(o *options) error { return func(o *options) error {
o.withRaw = r o.withRaw = r
return nil return nil
} }
} }
// WithElision provides an Option to represent whether elision (...) is required. // withElision provides an option to represent whether elision (...) is required.
func WithElision(e bool) Option { func withElision(e bool) option {
return func(o *options) error { return func(o *options) error {
o.withElision = e o.withElision = e
return nil return nil
} }
} }
// WithOmitTime provides an Option to represent whether to omit time. // withOmitTime provides an option to represent whether to omit time.
func WithOmitTime(t bool) Option { func withOmitTime(t bool) option {
return func(o *options) error { return func(o *options) error {
o.withOmitTime = t o.withOmitTime = t
return nil return nil
} }
} }
// WithHMACAccessor provides an Option to represent whether an HMAC accessor is applicable. // withHMACAccessor provides an option to represent whether an HMAC accessor is applicable.
func WithHMACAccessor(h bool) Option { func withHMACAccessor(h bool) option {
return func(o *options) error { return func(o *options) error {
o.withHMACAccessor = h o.withHMACAccessor = h
return nil return nil

View File

@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// TestOptions_WithFormat exercises WithFormat Option to ensure it performs as expected. // TestOptions_withFormat exercises withFormat option to ensure it performs as expected.
func TestOptions_WithFormat(t *testing.T) { func TestOptions_withFormat(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -38,12 +38,12 @@ func TestOptions_WithFormat(t *testing.T) {
"valid-json": { "valid-json": {
Value: "json", Value: "json",
IsErrorExpected: false, IsErrorExpected: false,
ExpectedValue: JSONFormat, ExpectedValue: jsonFormat,
}, },
"valid-jsonx": { "valid-jsonx": {
Value: "jsonx", Value: "jsonx",
IsErrorExpected: false, IsErrorExpected: false,
ExpectedValue: JSONxFormat, ExpectedValue: jsonxFormat,
}, },
} }
@ -53,7 +53,7 @@ func TestOptions_WithFormat(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithFormat(tc.Value) applyOption := withFormat(tc.Value)
err := applyOption(opts) err := applyOption(opts)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
@ -67,8 +67,8 @@ func TestOptions_WithFormat(t *testing.T) {
} }
} }
// TestOptions_WithSubtype exercises WithSubtype Option to ensure it performs as expected. // TestOptions_withSubtype exercises withSubtype option to ensure it performs as expected.
func TestOptions_WithSubtype(t *testing.T) { func TestOptions_withSubtype(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -100,7 +100,7 @@ func TestOptions_WithSubtype(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithSubtype(tc.Value) applyOption := withSubtype(tc.Value)
err := applyOption(opts) err := applyOption(opts)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
@ -114,8 +114,8 @@ func TestOptions_WithSubtype(t *testing.T) {
} }
} }
// TestOptions_WithNow exercises WithNow Option to ensure it performs as expected. // TestOptions_withNow exercises withNow option to ensure it performs as expected.
func TestOptions_WithNow(t *testing.T) { func TestOptions_withNow(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -143,7 +143,7 @@ func TestOptions_WithNow(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithNow(tc.Value) applyOption := withNow(tc.Value)
err := applyOption(opts) err := applyOption(opts)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
@ -157,8 +157,8 @@ func TestOptions_WithNow(t *testing.T) {
} }
} }
// TestOptions_WithID exercises WithID Option to ensure it performs as expected. // TestOptions_withID exercises withID option to ensure it performs as expected.
func TestOptions_WithID(t *testing.T) { func TestOptions_withID(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -190,7 +190,7 @@ func TestOptions_WithID(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithID(tc.Value) applyOption := withID(tc.Value)
err := applyOption(opts) err := applyOption(opts)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
@ -204,8 +204,8 @@ func TestOptions_WithID(t *testing.T) {
} }
} }
// TestOptions_WithPrefix exercises WithPrefix Option to ensure it performs as expected. // TestOptions_withPrefix exercises withPrefix option to ensure it performs as expected.
func TestOptions_WithPrefix(t *testing.T) { func TestOptions_withPrefix(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -237,7 +237,7 @@ func TestOptions_WithPrefix(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithPrefix(tc.Value) applyOption := withPrefix(tc.Value)
err := applyOption(opts) err := applyOption(opts)
switch { switch {
case tc.IsErrorExpected: case tc.IsErrorExpected:
@ -251,8 +251,8 @@ func TestOptions_WithPrefix(t *testing.T) {
} }
} }
// TestOptions_WithRaw exercises WithRaw Option to ensure it performs as expected. // TestOptions_withRaw exercises withRaw option to ensure it performs as expected.
func TestOptions_WithRaw(t *testing.T) { func TestOptions_withRaw(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -275,7 +275,7 @@ func TestOptions_WithRaw(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithRaw(tc.Value) applyOption := withRaw(tc.Value)
err := applyOption(opts) err := applyOption(opts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withRaw) 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. // TestOptions_withElision exercises withElision option to ensure it performs as expected.
func TestOptions_WithElision(t *testing.T) { func TestOptions_withElision(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -307,7 +307,7 @@ func TestOptions_WithElision(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithElision(tc.Value) applyOption := withElision(tc.Value)
err := applyOption(opts) err := applyOption(opts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withElision) 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. // TestOptions_withHMACAccessor exercises withHMACAccessor option to ensure it performs as expected.
func TestOptions_WithHMACAccessor(t *testing.T) { func TestOptions_withHMACAccessor(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -339,7 +339,7 @@ func TestOptions_WithHMACAccessor(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithHMACAccessor(tc.Value) applyOption := withHMACAccessor(tc.Value)
err := applyOption(opts) err := applyOption(opts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withHMACAccessor) 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. // TestOptions_withOmitTime exercises withOmitTime option to ensure it performs as expected.
func TestOptions_WithOmitTime(t *testing.T) { func TestOptions_withOmitTime(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
@ -371,7 +371,7 @@ func TestOptions_WithOmitTime(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := &options{} opts := &options{}
applyOption := WithOmitTime(tc.Value) applyOption := withOmitTime(tc.Value)
err := applyOption(opts) err := applyOption(opts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withOmitTime) require.Equal(t, tc.ExpectedValue, opts.withOmitTime)
@ -389,12 +389,12 @@ func TestOptions_Default(t *testing.T) {
require.False(t, opts.withNow.IsZero()) 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) { func TestOptions_Opts(t *testing.T) {
t.Parallel() t.Parallel()
tests := map[string]struct { tests := map[string]struct {
opts []Option opts []option
IsErrorExpected bool IsErrorExpected bool
ExpectedErrorMessage string ExpectedErrorMessage string
ExpectedID string ExpectedID string
@ -407,73 +407,73 @@ func TestOptions_Opts(t *testing.T) {
opts: nil, opts: nil,
IsErrorExpected: false, IsErrorExpected: false,
IsNowExpected: true, IsNowExpected: true,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"empty-options": { "empty-options": {
opts: []Option{}, opts: []option{},
IsErrorExpected: false, IsErrorExpected: false,
IsNowExpected: true, IsNowExpected: true,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"with-multiple-valid-id": { "with-multiple-valid-id": {
opts: []Option{ opts: []option{
WithID("qwerty"), withID("qwerty"),
WithID("juan"), withID("juan"),
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedID: "juan", ExpectedID: "juan",
IsNowExpected: true, IsNowExpected: true,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"with-multiple-valid-subtype": { "with-multiple-valid-subtype": {
opts: []Option{ opts: []option{
WithSubtype("AuditRequest"), withSubtype("AuditRequest"),
WithSubtype("AuditResponse"), withSubtype("AuditResponse"),
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedSubtype: ResponseType, ExpectedSubtype: ResponseType,
IsNowExpected: true, IsNowExpected: true,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"with-multiple-valid-format": { "with-multiple-valid-format": {
opts: []Option{ opts: []option{
WithFormat("json"), withFormat("json"),
WithFormat("jsonx"), withFormat("jsonx"),
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedFormat: JSONxFormat, ExpectedFormat: jsonxFormat,
IsNowExpected: true, IsNowExpected: true,
}, },
"with-multiple-valid-now": { "with-multiple-valid-now": {
opts: []Option{ opts: []option{
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)), 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)), withNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedNow: time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local), ExpectedNow: time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local),
IsNowExpected: false, IsNowExpected: false,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"with-multiple-valid-then-invalid-now": { "with-multiple-valid-then-invalid-now": {
opts: []Option{ opts: []option{
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)), withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
WithNow(time.Time{}), withNow(time.Time{}),
}, },
IsErrorExpected: true, IsErrorExpected: true,
ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant", ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant",
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
}, },
"with-multiple-valid-options": { "with-multiple-valid-options": {
opts: []Option{ opts: []option{
WithID("qwerty"), withID("qwerty"),
WithSubtype("AuditRequest"), withSubtype("AuditRequest"),
WithFormat("json"), withFormat("json"),
WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)), withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
}, },
IsErrorExpected: false, IsErrorExpected: false,
ExpectedID: "qwerty", ExpectedID: "qwerty",
ExpectedSubtype: RequestType, ExpectedSubtype: RequestType,
ExpectedFormat: JSONFormat, ExpectedFormat: jsonFormat,
ExpectedNow: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local), ExpectedNow: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
}, },
} }

View File

@ -56,7 +56,7 @@ func newSinkMetricTimer(name string, sink eventlogger.Node) (*sinkMetricTimer, e
// 'vault.audit.{DEVICE}.log_response' // 'vault.audit.{DEVICE}.log_response'
func (s *sinkMetricTimer) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) { func (s *sinkMetricTimer) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
defer func() { defer func() {
auditEvent, ok := e.Payload.(*AuditEvent) auditEvent, ok := e.Payload.(*Event)
if ok { if ok {
metrics.MeasureSince([]string{"audit", s.name, auditEvent.Subtype.MetricTag()}, e.CreatedAt) metrics.MeasureSince([]string{"audit", s.name, auditEvent.Subtype.MetricTag()}, e.CreatedAt)
} }

View File

@ -7,20 +7,20 @@ import (
"github.com/hashicorp/vault/sdk/logical" "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. // It could be an entry for a request or response.
type Entry struct { type entry struct {
Auth *Auth `json:"auth,omitempty"` Auth *auth `json:"auth,omitempty"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
Forwarded bool `json:"forwarded,omitempty"` Forwarded bool `json:"forwarded,omitempty"`
ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
Request *Request `json:"request,omitempty"` Request *request `json:"request,omitempty"`
Response *Response `json:"response,omitempty"` Response *response `json:"response,omitempty"`
Time string `json:"time,omitempty"` Time string `json:"time,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
} }
type Request struct { type request struct {
ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"` ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"`
ClientID string `json:"client_id,omitempty"` ClientID string `json:"client_id,omitempty"`
ClientToken string `json:"client_token,omitempty"` ClientToken string `json:"client_token,omitempty"`
@ -35,7 +35,7 @@ type Request struct {
MountRunningSha256 string `json:"mount_running_sha256,omitempty"` MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
MountRunningVersion string `json:"mount_running_version,omitempty"` MountRunningVersion string `json:"mount_running_version,omitempty"`
MountType string `json:"mount_type,omitempty"` MountType string `json:"mount_type,omitempty"`
Namespace *Namespace `json:"namespace,omitempty"` Namespace *namespace `json:"namespace,omitempty"`
Operation logical.Operation `json:"operation,omitempty"` Operation logical.Operation `json:"operation,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
PolicyOverride bool `json:"policy_override,omitempty"` PolicyOverride bool `json:"policy_override,omitempty"`
@ -46,8 +46,8 @@ type Request struct {
WrapTTL int `json:"wrap_ttl,omitempty"` WrapTTL int `json:"wrap_ttl,omitempty"`
} }
type Response struct { type response struct {
Auth *Auth `json:"auth,omitempty"` Auth *auth `json:"auth,omitempty"`
Data map[string]interface{} `json:"data,omitempty"` Data map[string]interface{} `json:"data,omitempty"`
Headers map[string][]string `json:"headers,omitempty"` Headers map[string][]string `json:"headers,omitempty"`
MountAccessor string `json:"mount_accessor,omitempty"` MountAccessor string `json:"mount_accessor,omitempty"`
@ -58,12 +58,12 @@ type Response struct {
MountRunningVersion string `json:"mount_running_plugin_version,omitempty"` MountRunningVersion string `json:"mount_running_plugin_version,omitempty"`
MountType string `json:"mount_type,omitempty"` MountType string `json:"mount_type,omitempty"`
Redirect string `json:"redirect,omitempty"` Redirect string `json:"redirect,omitempty"`
Secret *Secret `json:"secret,omitempty"` Secret *secret `json:"secret,omitempty"`
WrapInfo *ResponseWrapInfo `json:"wrap_info,omitempty"` WrapInfo *responseWrapInfo `json:"wrap_info,omitempty"`
Warnings []string `json:"warnings,omitempty"` Warnings []string `json:"warnings,omitempty"`
} }
type Auth struct { type auth struct {
Accessor string `json:"accessor,omitempty"` Accessor string `json:"accessor,omitempty"`
ClientToken string `json:"client_token,omitempty"` ClientToken string `json:"client_token,omitempty"`
DisplayName string `json:"display_name,omitempty"` DisplayName string `json:"display_name,omitempty"`
@ -75,7 +75,7 @@ type Auth struct {
NoDefaultPolicy bool `json:"no_default_policy,omitempty"` NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
NumUses int `json:"num_uses,omitempty"` NumUses int `json:"num_uses,omitempty"`
Policies []string `json:"policies,omitempty"` Policies []string `json:"policies,omitempty"`
PolicyResults *PolicyResults `json:"policy_results,omitempty"` PolicyResults *policyResults `json:"policy_results,omitempty"`
RemainingUses int `json:"remaining_uses,omitempty"` RemainingUses int `json:"remaining_uses,omitempty"`
TokenPolicies []string `json:"token_policies,omitempty"` TokenPolicies []string `json:"token_policies,omitempty"`
TokenIssueTime string `json:"token_issue_time,omitempty"` TokenIssueTime string `json:"token_issue_time,omitempty"`
@ -83,23 +83,23 @@ type Auth struct {
TokenType string `json:"token_type,omitempty"` TokenType string `json:"token_type,omitempty"`
} }
type PolicyResults struct { type policyResults struct {
Allowed bool `json:"allowed"` 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"` Name string `json:"name,omitempty"`
NamespaceId string `json:"namespace_id,omitempty"` NamespaceId string `json:"namespace_id,omitempty"`
NamespacePath string `json:"namespace_path,omitempty"` NamespacePath string `json:"namespace_path,omitempty"`
Type string `json:"type"` Type string `json:"type"`
} }
type Secret struct { type secret struct {
LeaseID string `json:"lease_id,omitempty"` LeaseID string `json:"lease_id,omitempty"`
} }
type ResponseWrapInfo struct { type responseWrapInfo struct {
Accessor string `json:"accessor,omitempty"` Accessor string `json:"accessor,omitempty"`
CreationPath string `json:"creation_path,omitempty"` CreationPath string `json:"creation_path,omitempty"`
CreationTime string `json:"creation_time,omitempty"` CreationTime string `json:"creation_time,omitempty"`
@ -108,7 +108,7 @@ type ResponseWrapInfo struct {
WrappedAccessor string `json:"wrapped_accessor,omitempty"` WrappedAccessor string `json:"wrapped_accessor,omitempty"`
} }
type Namespace struct { type namespace struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
} }