mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
VAULT-24452: audit refactor (#26460)
* Refactor audit code into audit package * remove builtin/audit * removed unrequired files
This commit is contained in:
154
audit/backend_file.go
Normal file
154
audit/backend_file.go
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package audit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/eventlogger"
|
||||
"github.com/hashicorp/vault/internal/observability/event"
|
||||
)
|
||||
|
||||
const (
|
||||
stdout = "stdout"
|
||||
discard = "discard"
|
||||
|
||||
optionFilePath = "file_path"
|
||||
optionMode = "mode"
|
||||
)
|
||||
|
||||
var _ Backend = (*FileBackend)(nil)
|
||||
|
||||
type FileBackend struct {
|
||||
*backend
|
||||
}
|
||||
|
||||
// NewFileBackend 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 NewFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Backend, err error) {
|
||||
be, err = newFileBackend(conf, headersConfig)
|
||||
return
|
||||
}
|
||||
|
||||
// newFileBackend creates a backend and configures all nodes including a file sink.
|
||||
func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBackend, 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
|
||||
}
|
||||
|
||||
// Get file path from config or fall back to the old option ('path') for compatibility
|
||||
// (see commit bac4fe0799a372ba1245db642f3f6cd1f1d02669).
|
||||
var filePath string
|
||||
if p, ok := conf.Config[optionFilePath]; ok {
|
||||
filePath = p
|
||||
} else if p, ok = conf.Config["path"]; ok {
|
||||
filePath = p
|
||||
} else {
|
||||
return nil, fmt.Errorf("%q is required: %w", optionFilePath, ErrExternalOptions)
|
||||
}
|
||||
|
||||
bec, err := newBackend(headersConfig, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := &FileBackend{backend: bec}
|
||||
|
||||
// normalize file path if configured for stdout
|
||||
if strings.EqualFold(filePath, stdout) {
|
||||
filePath = stdout
|
||||
}
|
||||
if strings.EqualFold(filePath, discard) {
|
||||
filePath = discard
|
||||
}
|
||||
|
||||
// Configure the sink.
|
||||
cfg, err := newFormatterConfig(headersConfig, conf.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var opt []event.Option
|
||||
if mode, ok := conf.Config[optionMode]; ok {
|
||||
opt = append(opt, event.WithFileMode(mode))
|
||||
}
|
||||
|
||||
err = b.configureSinkNode(conf.MountPath, filePath, cfg.requiredFormat, opt...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// configureSinkNode is used internally by FileBackend to create and configure the
|
||||
// sink node on the backend.
|
||||
func (b *FileBackend) configureSinkNode(name string, filePath string, format format, opt ...event.Option) error {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return fmt.Errorf("name is required: %w", ErrExternalOptions)
|
||||
}
|
||||
|
||||
filePath = strings.TrimSpace(filePath)
|
||||
if filePath == "" {
|
||||
return fmt.Errorf("file path is required: %w", ErrExternalOptions)
|
||||
}
|
||||
|
||||
sinkNodeID, err := event.GenerateNodeID()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating random NodeID for sink node: %w: %w", ErrInternal, err)
|
||||
}
|
||||
|
||||
// normalize file path if configured for stdout or discard
|
||||
if strings.EqualFold(filePath, stdout) {
|
||||
filePath = stdout
|
||||
} else if strings.EqualFold(filePath, discard) {
|
||||
filePath = discard
|
||||
}
|
||||
|
||||
var sinkNode eventlogger.Node
|
||||
var sinkName string
|
||||
|
||||
switch filePath {
|
||||
case stdout:
|
||||
sinkName = stdout
|
||||
sinkNode, err = event.NewStdoutSinkNode(format.String())
|
||||
case discard:
|
||||
sinkName = discard
|
||||
sinkNode = event.NewNoopSink()
|
||||
default:
|
||||
// The NewFileSink function attempts to open the file and will return an error if it can't.
|
||||
sinkName = name
|
||||
sinkNode, err = event.NewFileSink(filePath, format.String(), opt...)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("file sink creation failed for path %q: %w", filePath, err)
|
||||
}
|
||||
|
||||
// Wrap the sink node with metrics middleware
|
||||
err = b.wrapMetrics(sinkName, sinkNodeID, sinkNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reload will trigger the reload action on the sink node for this backend.
|
||||
func (b *FileBackend) Reload() error {
|
||||
for _, n := range b.nodeMap {
|
||||
if n.Type() == eventlogger.NodeTypeSink {
|
||||
return n.Reopen()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user