vault/audit/backend_syslog.go

110 lines
2.5 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package audit
import (
"fmt"
"reflect"
"github.com/hashicorp/vault/internal/observability/event"
)
const (
optionFacility = "facility"
optionTag = "tag"
)
var _ Backend = (*syslogBackend)(nil)
type syslogBackend struct {
*backend
}
// NewSyslogBackend provides a wrapper to support the expectation elsewhere in Vault that
// all audit backends can be created via a factory that returns an interface (Backend).
func NewSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Backend, err error) {
be, err = newSyslogBackend(conf, headersConfig)
return
}
// newSyslogBackend creates a backend and configures all nodes including a socket sink.
func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*syslogBackend, error) {
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
}
if conf == nil {
return nil, fmt.Errorf("nil config: %w", ErrInvalidParameter)
}
if err := conf.Validate(); err != nil {
return nil, err
}
bec, err := newBackend(headersConfig, conf)
if err != nil {
return nil, err
}
// Get facility or default to AUTH
facility, ok := conf.Config[optionFacility]
if !ok {
facility = "AUTH"
}
// Get tag or default to 'vault'
tag, ok := conf.Config[optionTag]
if !ok {
tag = "vault"
}
sinkOpts := []event.Option{
event.WithFacility(facility),
event.WithTag(tag),
event.WithLogger(conf.Logger),
}
err = event.ValidateOptions(sinkOpts...)
if err != nil {
return nil, err
}
b := &syslogBackend{backend: bec}
// Configure the sink.
cfg, err := newFormatterConfig(headersConfig, conf.Config)
if err != nil {
return nil, err
}
err = b.configureSinkNode(conf.MountPath, cfg.requiredFormat, sinkOpts...)
if err != nil {
return nil, err
}
return b, nil
}
func (b *syslogBackend) configureSinkNode(name string, format format, opts ...event.Option) error {
sinkNodeID, err := event.GenerateNodeID()
if err != nil {
return fmt.Errorf("error generating random NodeID for sink node: %w: %w", ErrInternal, err)
}
n, err := event.NewSyslogSink(format.String(), opts...)
if err != nil {
return fmt.Errorf("error creating syslog sink node: %w", err)
}
err = b.wrapMetrics(name, sinkNodeID, n)
if err != nil {
return err
}
return nil
}
// Reload will trigger the reload action on the sink node for this backend.
func (b *syslogBackend) Reload() error {
return nil
}