mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
* VAULT-22481: Audit filter node (#24465) * Initial commit on adding filter nodes for audit * tests for audit filter * test: longer filter - more conditions * copywrite headers * Check interface for the right type * Add audit filtering feature (#24554) * Support filter nodes in backend factories and add some tests * More tests and cleanup * Attempt to move control of registration for nodes and pipelines to the audit broker (#24505) * invert control of the pipelines/nodes to the audit broker vs. within each backend * update noop audit test code to implement the pipeliner interface * noop mount path has trailing slash * attempting to make NoopAudit more friendly * NoopAudit uses known salt * Refactor audit.ProcessManual to support filter nodes * HasFiltering * rename the pipeliner * use exported AuditEvent in Filter * Add tests for registering and deregistering backends on the audit broker * Add missing licence header to one file, fix a typo in two tests --------- Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com> * Add changelog file * update bexpr datum to use a strong type * go docs updates * test path * PR review comments * handle scenarios/outcomes from broker.send * don't need to re-check the complete sinks * add extra check to deregister to ensure that re-registering non-filtered device sets sink threshold * Ensure that the multierror is appended before attempting to return it --------- Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com>
97 lines
2.6 KiB
Go
97 lines
2.6 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package audit
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/hashicorp/eventlogger"
|
|
"github.com/hashicorp/vault/internal/observability/event"
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
)
|
|
|
|
// ProcessManual will attempt to create an (audit) event with the specified data
|
|
// and manually iterate over the supplied nodes calling Process on each until the
|
|
// event is nil (which indicates the pipeline has completed).
|
|
// Order of IDs in the NodeID slice determines the order they are processed.
|
|
// (Audit) Event will be of RequestType (as opposed to ResponseType).
|
|
// The last node must be a filter node (eventlogger.NodeTypeFilter) or
|
|
// sink node (eventlogger.NodeTypeSink).
|
|
func ProcessManual(ctx context.Context, data *logical.LogInput, ids []eventlogger.NodeID, nodes map[eventlogger.NodeID]eventlogger.Node) error {
|
|
switch {
|
|
case data == nil:
|
|
return errors.New("data cannot be nil")
|
|
case len(ids) < 2:
|
|
return errors.New("minimum of 2 ids are required")
|
|
case nodes == nil:
|
|
return errors.New("nodes cannot be nil")
|
|
case len(nodes) == 0:
|
|
return errors.New("nodes are required")
|
|
}
|
|
|
|
// Create an audit event.
|
|
a, err := NewEvent(RequestType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Insert the data into the audit event.
|
|
a.Data = data
|
|
|
|
// Create an eventlogger event with the audit event as the payload.
|
|
e := &eventlogger.Event{
|
|
Type: eventlogger.EventType(event.AuditType.String()),
|
|
CreatedAt: time.Now(),
|
|
Formatted: make(map[string][]byte),
|
|
Payload: a,
|
|
}
|
|
|
|
var lastSeen eventlogger.NodeType
|
|
|
|
// Process nodes in order, updating the event with the result.
|
|
// This means we *should* do:
|
|
// 1. filter (optional if configured)
|
|
// 2. formatter (temporary)
|
|
// 3. sink
|
|
for _, id := range ids {
|
|
// If the event is nil, we've completed processing the pipeline (hopefully
|
|
// by either a filter node or a sink node).
|
|
if e == nil {
|
|
break
|
|
}
|
|
node, ok := nodes[id]
|
|
if !ok {
|
|
return fmt.Errorf("node not found: %v", id)
|
|
}
|
|
|
|
switch node.Type() {
|
|
case eventlogger.NodeTypeFormatter:
|
|
// Use a temporary formatter node which doesn't persist its salt anywhere.
|
|
if formatNode, ok := node.(*EntryFormatter); ok && formatNode != nil {
|
|
e, err = newTemporaryEntryFormatter(formatNode).Process(ctx, e)
|
|
}
|
|
default:
|
|
e, err = node.Process(ctx, e)
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Track the last node we have processed, as we should end with a filter or sink.
|
|
lastSeen = node.Type()
|
|
}
|
|
|
|
switch lastSeen {
|
|
case eventlogger.NodeTypeSink, eventlogger.NodeTypeFilter:
|
|
default:
|
|
return errors.New("last node must be a filter or sink")
|
|
}
|
|
|
|
return nil
|
|
}
|