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 }