mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-07 07:07:05 +02:00
unexport as much as possible in the audit package (#28039)
This commit is contained in:
parent
88975a6c24
commit
a19195c901
@ -20,9 +20,9 @@ const (
|
|||||||
optionMode = "mode"
|
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()
|
||||||
|
@ -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())
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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(),
|
||||||
})
|
})
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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...)
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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})
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user