mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			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:      event.AuditType.AsEventType(),
 | |
| 		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
 | |
| }
 | 
