b09abef332
allow oss to parse sink duration clean up audit sink parsing ent eventer config reload fix typo SetEnabled to eventer interface client acl test rm dead code fix failing test
214 lines
4.6 KiB
Go
214 lines
4.6 KiB
Go
package config
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/helper"
|
|
)
|
|
|
|
// AuditConfig is the configuration specific to Audit Logging
|
|
type AuditConfig struct {
|
|
// Enabled controls the Audit Logging mode
|
|
Enabled *bool `hcl:"enabled"`
|
|
|
|
// Sinks configure output sinks for audit logs
|
|
Sinks []*AuditSink `hcl:"sink"`
|
|
|
|
// Filters configure audit event filters to filter out certain eevents
|
|
// from being written to a sink.
|
|
Filters []*AuditFilter `hcl:"filter"`
|
|
|
|
// ExtraKeysHCL is used by hcl to surface unexpected keys
|
|
ExtraKeysHCL []string `hcl:",unusedKeys" json:"-"`
|
|
}
|
|
|
|
type AuditSink struct {
|
|
// Name is a unique name given to the filter
|
|
Name string `hcl:",key"`
|
|
|
|
// DeliveryGuarantee is the level at which delivery of logs must
|
|
// be met in order to successfully make requests
|
|
DeliveryGuarantee string `hcl:"delivery_guarantee"`
|
|
|
|
// Type is the sink type to configure. (file)
|
|
Type string `hcl:"type"`
|
|
|
|
// Format is the sink output format. (json)
|
|
Format string `hcl:"format"`
|
|
|
|
// FileName is the name that the audit log should follow.
|
|
// If rotation is enabled the pattern will be name-timestamp.log
|
|
Path string `hcl:"path"`
|
|
|
|
// RotateDuration is the time period that logs should be rotated in
|
|
RotateDuration time.Duration
|
|
RotateDurationHCL string `hcl:"rotate_duration" json:"-"`
|
|
|
|
// RotateBytes is the max number of bytes that should be written to a file
|
|
RotateBytes int `hcl:"rotate_bytes"`
|
|
|
|
// RotateMaxFiles is the max number of log files to keep
|
|
RotateMaxFiles int `hcl:"rotate_max_files"`
|
|
}
|
|
|
|
// AuditFilter is the configuration for a Audit Log Filter
|
|
type AuditFilter struct {
|
|
// Name is a unique name given to the filter
|
|
Name string `hcl:",key"`
|
|
|
|
// Type of auditing event to filter, such as HTTPEvent
|
|
Type string `hcl:"type"`
|
|
|
|
// Endpoints is the list of endpoints to include in the filter
|
|
Endpoints []string `hcl:"endpoints"`
|
|
|
|
// State is the auditing request lifecycle stage to filter
|
|
Stages []string `hcl:"stages"`
|
|
|
|
// Operations is the type of operation to filter, such as GET, DELETE
|
|
Operations []string `hcl:"operations"`
|
|
}
|
|
|
|
// Copy returns a new copy of an AuditConfig
|
|
func (a *AuditConfig) Copy() *AuditConfig {
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
|
|
nc := new(AuditConfig)
|
|
*nc = *a
|
|
|
|
// Copy bool pointers
|
|
if a.Enabled != nil {
|
|
nc.Enabled = helper.BoolToPtr(*a.Enabled)
|
|
}
|
|
|
|
// Copy Sinks and Filters
|
|
nc.Sinks = copySliceAuditSink(nc.Sinks)
|
|
nc.Filters = copySliceAuditFilter(nc.Filters)
|
|
|
|
return nc
|
|
}
|
|
|
|
// Merge is used to merge two Audit Configs together. Settings from the input take precedence.
|
|
func (a *AuditConfig) Merge(b *AuditConfig) *AuditConfig {
|
|
result := a.Copy()
|
|
|
|
if b.Enabled != nil {
|
|
result.Enabled = helper.BoolToPtr(*b.Enabled)
|
|
}
|
|
|
|
// Merge Sinks
|
|
if len(a.Sinks) == 0 && len(b.Sinks) != 0 {
|
|
result.Sinks = copySliceAuditSink(b.Sinks)
|
|
} else if len(b.Sinks) != 0 {
|
|
result.Sinks = auditSinkSliceMerge(a.Sinks, b.Sinks)
|
|
}
|
|
|
|
// Merge Filters
|
|
if len(a.Filters) == 0 && len(b.Filters) != 0 {
|
|
result.Filters = copySliceAuditFilter(b.Filters)
|
|
} else if len(b.Filters) != 0 {
|
|
result.Filters = auditFilterSliceMerge(a.Filters, b.Filters)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (a *AuditSink) Copy() *AuditSink {
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
|
|
nc := new(AuditSink)
|
|
*nc = *a
|
|
|
|
return nc
|
|
}
|
|
|
|
func (a *AuditFilter) Copy() *AuditFilter {
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
|
|
nc := new(AuditFilter)
|
|
*nc = *a
|
|
|
|
// Copy slices
|
|
nc.Endpoints = helper.CopySliceString(nc.Endpoints)
|
|
nc.Stages = helper.CopySliceString(nc.Stages)
|
|
nc.Operations = helper.CopySliceString(nc.Operations)
|
|
|
|
return nc
|
|
}
|
|
|
|
func copySliceAuditFilter(a []*AuditFilter) []*AuditFilter {
|
|
l := len(a)
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
|
|
ns := make([]*AuditFilter, l)
|
|
for idx, cfg := range a {
|
|
ns[idx] = cfg.Copy()
|
|
}
|
|
|
|
return ns
|
|
}
|
|
|
|
func auditFilterSliceMerge(a, b []*AuditFilter) []*AuditFilter {
|
|
n := make([]*AuditFilter, len(a))
|
|
seenKeys := make(map[string]int, len(a))
|
|
|
|
for i, config := range a {
|
|
n[i] = config.Copy()
|
|
seenKeys[config.Name] = i
|
|
}
|
|
|
|
for _, config := range b {
|
|
if fIndex, ok := seenKeys[config.Name]; ok {
|
|
n[fIndex] = config.Copy()
|
|
continue
|
|
}
|
|
|
|
n = append(n, config.Copy())
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func copySliceAuditSink(a []*AuditSink) []*AuditSink {
|
|
l := len(a)
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
|
|
ns := make([]*AuditSink, l)
|
|
for idx, cfg := range a {
|
|
ns[idx] = cfg.Copy()
|
|
}
|
|
|
|
return ns
|
|
}
|
|
|
|
func auditSinkSliceMerge(a, b []*AuditSink) []*AuditSink {
|
|
n := make([]*AuditSink, len(a))
|
|
seenKeys := make(map[string]int, len(a))
|
|
|
|
for i, config := range a {
|
|
n[i] = config.Copy()
|
|
seenKeys[config.Name] = i
|
|
}
|
|
|
|
for _, config := range b {
|
|
if fIndex, ok := seenKeys[config.Name]; ok {
|
|
n[fIndex] = config.Copy()
|
|
continue
|
|
}
|
|
|
|
n = append(n, config.Copy())
|
|
}
|
|
|
|
return n
|
|
}
|