Skip to content

Commit

Permalink
CBG-3924: Add mocked config and API for audit logging (#6874)
Browse files Browse the repository at this point in the history
* Add config fields for audit logging

* Support all flag types and pointers in fillConfigWithFlags

* tweak comment

* wip

* rebase fix for rotation_interval

* Move uint map key to string for JSON

* Add API specs

* make GET API actually return the data...

* Add placeholder audit log config for runtime server config

* Add db/global audit log API changes

* unindent
  • Loading branch information
bbrks committed Jun 14, 2024
1 parent d5b463d commit 7b7bd6b
Show file tree
Hide file tree
Showing 15 changed files with 398 additions and 69 deletions.
4 changes: 2 additions & 2 deletions base/audit/auditd_descriptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (
"github.com/stretchr/testify/require"
)

// TestGenerateAuditdModuleDescriptor outputs a generated auditd module descriptor for sgAuditEvents.
// TestGenerateAuditdModuleDescriptor outputs a generated auditd module descriptor for SGAuditEvents.
func TestGenerateAuditdModuleDescriptor(t *testing.T) {
b, err := generateAuditdModuleDescriptor(sgAuditEvents)
b, err := generateAuditdModuleDescriptor(SGAuditEvents)
require.NoError(t, err)
t.Log(string(b))
}
16 changes: 8 additions & 8 deletions base/audit/auditd_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ type auditdEventDescriptor struct {
OptionalFields map[string]any `json:"optional_fields,omitempty"`
}

// toAuditdEventDescriptor converts an eventDescriptor to an auditdEventDescriptor.
// toAuditdEventDescriptor converts an EventDescriptor to an auditdEventDescriptor.
// These are _mostly_ the same, but each event holds its own ID in an array in the JSON format.
func toAuditdEventDescriptor(id ID, e eventDescriptor) auditdEventDescriptor {
func toAuditdEventDescriptor(id ID, e EventDescriptor) auditdEventDescriptor {
return auditdEventDescriptor{
ID: id,
Name: e.name,
Description: e.description,
Enabled: e.enabledByDefault,
FilteringPermitted: e.filteringPermitted,
MandatoryFields: toAuditdFieldType(e.mandatoryFields),
OptionalFields: toAuditdFieldType(e.optionalFields),
Name: e.Name,
Description: e.Description,
Enabled: e.EnabledByDefault,
FilteringPermitted: e.FilteringPermitted,
MandatoryFields: toAuditdFieldType(e.MandatoryFields),
OptionalFields: toAuditdFieldType(e.OptionalFields),
}
}

Expand Down
14 changes: 7 additions & 7 deletions base/audit/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ const (
IDPlaceholder ID = 54000
)

var sgAuditEvents = events{
var SGAuditEvents = events{
IDPlaceholder: {
name: "Placeholder audit event",
description: "This is a placeholder.",
mandatoryFields: map[string]any{
Name: "Placeholder audit event",
Description: "This is a placeholder.",
MandatoryFields: map[string]any{
"context": map[string]any{
"provider": "example provider",
"username": "alice",
},
},
optionalFields: map[string]any{
OptionalFields: map[string]any{
"operationID": 123,
"isSomething": false,
},
filteringPermitted: false,
eventType: eventTypeAdmin,
FilteringPermitted: false,
EventType: eventTypeAdmin,
},
}
4 changes: 2 additions & 2 deletions base/audit/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ const (

func TestValidateAuditEvents(t *testing.T) {
// Ensures that the above audit event IDs are within the allocated range and are valid.
require.NoError(t, validateAuditEvents(sgAuditEvents))
require.NoError(t, validateAuditEvents(SGAuditEvents))
}

func validateAuditEvents(e events) error {
for id, descriptor := range e {
if id < auditdSyncGatewayStartID || id > auditdSyncGatewayEndID {
return fmt.Errorf("invalid audit event ID: %d %q (allowed range: %d-%d)",
id, descriptor.name, auditdSyncGatewayStartID, auditdSyncGatewayEndID)
id, descriptor.Name, auditdSyncGatewayStartID, auditdSyncGatewayEndID)
}
}
return nil
Expand Down
43 changes: 25 additions & 18 deletions base/audit/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,35 @@

package audit

import "strconv"

// ID is a unique identifier for an audit event.
type ID uint

// String implements Stringer
func (i ID) String() string {
return strconv.FormatUint(uint64(i), 10)
}

// events is a map of audit event IDs to event descriptors.
type events map[ID]eventDescriptor

// eventDescriptor is an audit event. The fields closely (but not exactly) follows kv_engine's auditd descriptor implementation.
type eventDescriptor struct {
// name is a short textual name of the event
name string
// description is a longer name / description of the event
description string
// enabledByDefault indicates whether the event should be enabled by default
enabledByDefault bool
// filteringPermitted indicates whether the event can be filtered or not
filteringPermitted bool
// mandatoryFields describe field(s) required for a valid instance of the event
mandatoryFields map[string]any
// optionalFields describe optional field(s) valid in an instance of the event
optionalFields map[string]any
// eventType represents a type of event. Used only for documentation categorization.
eventType eventType
type events map[ID]EventDescriptor

// EventDescriptor is an audit event. The fields closely (but not exactly) follows kv_engine's auditd descriptor implementation.
type EventDescriptor struct {
// Name is a short textual Name of the event
Name string
// Description is a longer Name / Description of the event
Description string
// EnabledByDefault indicates whether the event should be enabled by default
EnabledByDefault bool
// FilteringPermitted indicates whether the event can be filtered or not
FilteringPermitted bool
// MandatoryFields describe field(s) required for a valid instance of the event
MandatoryFields map[string]any
// OptionalFields describe optional field(s) valid in an instance of the event
OptionalFields map[string]any
// EventType represents a type of event. Used only for documentation categorization.
EventType eventType
}

const (
Expand Down
8 changes: 8 additions & 0 deletions base/logging_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ type LoggingConfig struct {
Debug *FileLoggerConfig `json:"debug,omitempty"`
Trace *FileLoggerConfig `json:"trace,omitempty"`
Stats *FileLoggerConfig `json:"stats,omitempty"`
Audit *AuditLoggerConfig `json:"audit,omitempty"`
}

type AuditLoggerConfig struct {
FileLoggerConfig
AuditLogFilePath *string `json:"audit_log_file_path,omitempty"` // If set, overrides the output path for the audit log files
}

func BuildLoggingConfigFromLoggers(redactionLevel RedactionLevel, LogFilePath string) *LoggingConfig {
Expand All @@ -256,6 +262,8 @@ func BuildLoggingConfigFromLoggers(redactionLevel RedactionLevel, LogFilePath st
config.Debug = debugLogger.getFileLoggerConfig()
config.Trace = traceLogger.getFileLoggerConfig()
config.Stats = statsLogger.getFileLoggerConfig()
// FIXME(bbrks): Once AuditLogger is implemented
config.Audit = &AuditLoggerConfig{}

return &config
}
Expand Down
2 changes: 2 additions & 0 deletions docs/api/admin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ paths:
$ref: ./paths/admin/_post_upgrade.yaml
'/{db}/_config':
$ref: './paths/admin/db-_config.yaml'
'/{db}/_config/audit':
$ref: './paths/admin/db-_config-audit.yaml'
'/{keyspace}/_config/sync':
$ref: './paths/admin/keyspace-_config-sync.yaml'
'/{keyspace}/_config/import_filter':
Expand Down
95 changes: 95 additions & 0 deletions docs/api/components/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1835,7 +1835,81 @@ Database:
items:
type: string
example: ["CRUD", "HTTP", "Query"]
audit:
description: Audit logging configuration.
type: object
properties:
enabled:
description: Whether audit logging is enabled.
type: boolean
default: false
enabled_events:
description: List of enabled audit events
type: array
items:
type: number
example: [1234, 5678]
disabled_users:
description: List of users for which audit logging is disabled
type: array
items:
type: object
properties:
domain:
description: The domain of the user for which audit logging is disabled.
type: string
name:
description: The name of the user for which audit logging is disabled.
type: string
disabled_roles:
description: List of roles for which audit logging is disabled
type: array
items:
type: object
properties:
domain:
description: The domain of the role for which audit logging is disabled.
type: string
name:
description: The name of the role for which audit logging is disabled.
type: string
title: Database-config
Database-audit:
title: Database-audit
description: A map of audit events and whether they are enabled or not.
type: object
additionalProperties:
x-additionalPropertiesName: audit_id
description: The audit event ID and whether it is enabled or not.
type: boolean
Database-audit-verbose:
title: Database-audit-verbose
description: A map of detailed audit events.
type: object
additionalProperties:
x-additionalPropertiesName: audit_id
description: The audit event ID and whether it is enabled or not.
$ref: '#/AuditEventVerbose'
AuditEventVerbose:
title: audit-event-verbose
description: Detailed information about an audit event.
type: object
properties:
name:
type: string
description: "The name of the audit event."
readOnly: true
description:
type: string
description: "The description of the audit event."
readOnly: true
enabled:
type: boolean
description: "Whether this audit event is currently enabled or not."
filterable:
type: boolean
description: "Whether this audit event can be disabled. Some audit events are always on."
readOnly: true
Event-config:
type: object
properties:
Expand Down Expand Up @@ -2162,6 +2236,8 @@ Startup-config:
$ref: '#/File-logging-config'
stats:
$ref: '#/File-logging-config'
audit:
$ref: '#/File-logging-config'
auth:
type: object
properties:
Expand Down Expand Up @@ -2284,6 +2360,8 @@ Runtime-config:
$ref: '#/File-logging-config'
stats:
$ref: '#/File-logging-config'
audit:
$ref: '#/Audit-logging-config'
max_concurrent_replications:
description: Maximum number of concurrent replication connections allowed. If set to 0 this limit will be ignored.
type: integer
Expand All @@ -2302,6 +2380,23 @@ File-logging-config:
type: integer
readOnly: true
title: File-logging-config
Audit-logging-config:
type: object
properties:
enabled:
description: Toggle for this log output
type: boolean
rotation:
$ref: '#/Log-rotation-config-readonly'
audit_log_file_path:
description: The path to write audit log files to
type: string
readOnly: true
collation_buffer_size:
description: The size of the log collation buffer
type: integer
readOnly: true
title: File-logging-config
Log-rotation-config-readonly:
type: object
properties:
Expand Down
Loading

0 comments on commit 7b7bd6b

Please sign in to comment.