github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/structs/config/audit.go (about) 1 package config 2 3 import ( 4 "time" 5 6 "github.com/hashicorp/nomad/helper/pointer" 7 "golang.org/x/exp/slices" 8 ) 9 10 // AuditConfig is the configuration specific to Audit Logging 11 type AuditConfig struct { 12 // Enabled controls the Audit Logging mode 13 Enabled *bool `hcl:"enabled"` 14 15 // Sinks configure output sinks for audit logs 16 Sinks []*AuditSink `hcl:"sink"` 17 18 // Filters configure audit event filters to filter out certain eevents 19 // from being written to a sink. 20 Filters []*AuditFilter `hcl:"filter"` 21 22 // ExtraKeysHCL is used by hcl to surface unexpected keys 23 ExtraKeysHCL []string `hcl:",unusedKeys" json:"-"` 24 } 25 26 type AuditSink struct { 27 // Name is a unique name given to the filter 28 Name string `hcl:",key"` 29 30 // DeliveryGuarantee is the level at which delivery of logs must 31 // be met in order to successfully make requests 32 DeliveryGuarantee string `hcl:"delivery_guarantee"` 33 34 // Type is the sink type to configure. (file) 35 Type string `hcl:"type"` 36 37 // Format is the sink output format. (json) 38 Format string `hcl:"format"` 39 40 // FileName is the name that the audit log should follow. 41 // If rotation is enabled the pattern will be name-timestamp.log 42 Path string `hcl:"path"` 43 44 // RotateDuration is the time period that logs should be rotated in 45 RotateDuration time.Duration 46 RotateDurationHCL string `hcl:"rotate_duration" json:"-"` 47 48 // RotateBytes is the max number of bytes that should be written to a file 49 RotateBytes int `hcl:"rotate_bytes"` 50 51 // RotateMaxFiles is the max number of log files to keep 52 RotateMaxFiles int `hcl:"rotate_max_files"` 53 54 // Mode is the octal formatted permissions for the audit log files. 55 Mode string `hcl:"mode"` 56 } 57 58 // AuditFilter is the configuration for a Audit Log Filter 59 type AuditFilter struct { 60 // Name is a unique name given to the filter 61 Name string `hcl:",key"` 62 63 // Type of auditing event to filter, such as HTTPEvent 64 Type string `hcl:"type"` 65 66 // Endpoints is the list of endpoints to include in the filter 67 Endpoints []string `hcl:"endpoints"` 68 69 // State is the auditing request lifecycle stage to filter 70 Stages []string `hcl:"stages"` 71 72 // Operations is the type of operation to filter, such as GET, DELETE 73 Operations []string `hcl:"operations"` 74 } 75 76 // Copy returns a new copy of an AuditConfig 77 func (a *AuditConfig) Copy() *AuditConfig { 78 if a == nil { 79 return nil 80 } 81 82 nc := new(AuditConfig) 83 *nc = *a 84 85 // Copy bool pointers 86 if a.Enabled != nil { 87 nc.Enabled = pointer.Of(*a.Enabled) 88 } 89 90 // Copy Sinks and Filters 91 nc.Sinks = copySliceAuditSink(nc.Sinks) 92 nc.Filters = copySliceAuditFilter(nc.Filters) 93 94 return nc 95 } 96 97 // Merge is used to merge two Audit Configs together. Settings from the input take precedence. 98 func (a *AuditConfig) Merge(b *AuditConfig) *AuditConfig { 99 result := a.Copy() 100 101 if b.Enabled != nil { 102 result.Enabled = pointer.Of(*b.Enabled) 103 } 104 105 // Merge Sinks 106 if len(a.Sinks) == 0 && len(b.Sinks) != 0 { 107 result.Sinks = copySliceAuditSink(b.Sinks) 108 } else if len(b.Sinks) != 0 { 109 result.Sinks = auditSinkSliceMerge(a.Sinks, b.Sinks) 110 } 111 112 // Merge Filters 113 if len(a.Filters) == 0 && len(b.Filters) != 0 { 114 result.Filters = copySliceAuditFilter(b.Filters) 115 } else if len(b.Filters) != 0 { 116 result.Filters = auditFilterSliceMerge(a.Filters, b.Filters) 117 } 118 119 return result 120 } 121 122 func (a *AuditSink) Copy() *AuditSink { 123 if a == nil { 124 return nil 125 } 126 127 nc := new(AuditSink) 128 *nc = *a 129 130 return nc 131 } 132 133 func (a *AuditFilter) Copy() *AuditFilter { 134 if a == nil { 135 return nil 136 } 137 138 nc := new(AuditFilter) 139 *nc = *a 140 141 // Copy slices 142 nc.Endpoints = slices.Clone(nc.Endpoints) 143 nc.Stages = slices.Clone(nc.Stages) 144 nc.Operations = slices.Clone(nc.Operations) 145 146 return nc 147 } 148 149 func copySliceAuditFilter(a []*AuditFilter) []*AuditFilter { 150 l := len(a) 151 if l == 0 { 152 return nil 153 } 154 155 ns := make([]*AuditFilter, l) 156 for idx, cfg := range a { 157 ns[idx] = cfg.Copy() 158 } 159 160 return ns 161 } 162 163 func auditFilterSliceMerge(a, b []*AuditFilter) []*AuditFilter { 164 n := make([]*AuditFilter, len(a)) 165 seenKeys := make(map[string]int, len(a)) 166 167 for i, config := range a { 168 n[i] = config.Copy() 169 seenKeys[config.Name] = i 170 } 171 172 for _, config := range b { 173 if fIndex, ok := seenKeys[config.Name]; ok { 174 n[fIndex] = config.Copy() 175 continue 176 } 177 178 n = append(n, config.Copy()) 179 } 180 181 return n 182 } 183 184 func copySliceAuditSink(a []*AuditSink) []*AuditSink { 185 l := len(a) 186 if l == 0 { 187 return nil 188 } 189 190 ns := make([]*AuditSink, l) 191 for idx, cfg := range a { 192 ns[idx] = cfg.Copy() 193 } 194 195 return ns 196 } 197 198 func auditSinkSliceMerge(a, b []*AuditSink) []*AuditSink { 199 n := make([]*AuditSink, len(a)) 200 seenKeys := make(map[string]int, len(a)) 201 202 for i, config := range a { 203 n[i] = config.Copy() 204 seenKeys[config.Name] = i 205 } 206 207 for _, config := range b { 208 if fIndex, ok := seenKeys[config.Name]; ok { 209 n[fIndex] = config.Copy() 210 continue 211 } 212 213 n = append(n, config.Copy()) 214 } 215 216 return n 217 }