github.com/hashicorp/vault/sdk@v0.13.0/logical/audit.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package logical
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/mitchellh/copystructure"
    10  )
    11  
    12  // LogInput is used as the input to the audit system on which audit entries are based.
    13  type LogInput struct {
    14  	Type                string
    15  	Auth                *Auth
    16  	Request             *Request
    17  	Response            *Response
    18  	OuterErr            error
    19  	NonHMACReqDataKeys  []string
    20  	NonHMACRespDataKeys []string
    21  }
    22  
    23  type MarshalOptions struct {
    24  	ValueHasher func(string) string
    25  }
    26  
    27  type OptMarshaler interface {
    28  	MarshalJSONWithOptions(*MarshalOptions) ([]byte, error)
    29  }
    30  
    31  // LogInputBexpr is used for evaluating boolean expressions with go-bexpr.
    32  type LogInputBexpr struct {
    33  	MountPoint string `bexpr:"mount_point"`
    34  	MountType  string `bexpr:"mount_type"`
    35  	Namespace  string `bexpr:"namespace"`
    36  	Operation  string `bexpr:"operation"`
    37  	Path       string `bexpr:"path"`
    38  }
    39  
    40  // BexprDatum returns values from a LogInput formatted for use in evaluating go-bexpr boolean expressions.
    41  // The namespace should be supplied from the current request's context.
    42  func (l *LogInput) BexprDatum(namespace string) *LogInputBexpr {
    43  	var mountPoint string
    44  	var mountType string
    45  	var operation string
    46  	var path string
    47  
    48  	if l.Request != nil {
    49  		mountPoint = l.Request.MountPoint
    50  		mountType = l.Request.MountType
    51  		operation = string(l.Request.Operation)
    52  		path = l.Request.Path
    53  	}
    54  
    55  	return &LogInputBexpr{
    56  		MountPoint: mountPoint,
    57  		MountType:  mountType,
    58  		Namespace:  namespace,
    59  		Operation:  operation,
    60  		Path:       path,
    61  	}
    62  }
    63  
    64  // Clone will attempt to create a deep copy (almost) of the LogInput.
    65  // If the LogInput type or any of the subtypes referenced by LogInput fields are
    66  // changed, then the Clone methods will need to be updated.
    67  // NOTE: Does not deep clone the LogInput.OuterError field as it represents an
    68  // error interface.
    69  // NOTE: LogInput.Request.Connection (at the time of writing) is also not deep-copied
    70  // and remains a pointer, see Request.Clone for more information.
    71  func (l *LogInput) Clone() (*LogInput, error) {
    72  	// Clone Auth
    73  	auth, err := cloneAuth(l.Auth)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	// Clone Request
    79  	var req *Request
    80  	if l.Request != nil {
    81  		req, err = l.Request.Clone()
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  	}
    86  
    87  	// Clone Response
    88  	resp, err := cloneResponse(l.Response)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	// Copy HMAC keys
    94  	reqDataKeys := make([]string, len(l.NonHMACReqDataKeys))
    95  	copy(reqDataKeys, l.NonHMACReqDataKeys)
    96  	respDataKeys := make([]string, len(l.NonHMACRespDataKeys))
    97  	copy(respDataKeys, l.NonHMACRespDataKeys)
    98  
    99  	// OuterErr is just linked in a non-deep way as it's an interface, and we
   100  	// don't know for sure which type this might actually be.
   101  	// At the time of writing this code, OuterErr isn't modified by anything,
   102  	// so we shouldn't get any race issues.
   103  	cloned := &LogInput{
   104  		Type:                l.Type,
   105  		Auth:                auth,
   106  		Request:             req,
   107  		Response:            resp,
   108  		OuterErr:            l.OuterErr,
   109  		NonHMACReqDataKeys:  reqDataKeys,
   110  		NonHMACRespDataKeys: respDataKeys,
   111  	}
   112  
   113  	return cloned, nil
   114  }
   115  
   116  // clone will deep-copy the supplied struct.
   117  // However, it cannot copy unexported fields or evaluate methods.
   118  func clone[V any](s V) (V, error) {
   119  	var result V
   120  
   121  	data, err := copystructure.Copy(s)
   122  	if err != nil {
   123  		return result, err
   124  	}
   125  
   126  	result = data.(V)
   127  
   128  	return result, err
   129  }
   130  
   131  // cloneAuth deep copies an Auth struct.
   132  func cloneAuth(auth *Auth) (*Auth, error) {
   133  	// If auth is nil, there's nothing to clone.
   134  	if auth == nil {
   135  		return nil, nil
   136  	}
   137  
   138  	auth, err := clone[*Auth](auth)
   139  	if err != nil {
   140  		return nil, fmt.Errorf("unable to clone auth: %w", err)
   141  	}
   142  
   143  	return auth, nil
   144  }
   145  
   146  // cloneResponse deep copies a Response struct.
   147  func cloneResponse(response *Response) (*Response, error) {
   148  	// If response is nil, there's nothing to clone.
   149  	if response == nil {
   150  		return nil, nil
   151  	}
   152  
   153  	resp, err := clone[*Response](response)
   154  	if err != nil {
   155  		return nil, fmt.Errorf("unable to clone response: %w", err)
   156  	}
   157  
   158  	return resp, nil
   159  }