github.com/hernad/nomad@v1.6.112/nomad/structs/config/audit.go (about)

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