Audit Logging

May 18, 2026 · View on GitHub

Comprehensive audit trails for compliance and security monitoring.

Overview

NornicDB provides immutable audit logging required by major regulatory frameworks:

  • GDPR Art.30 - Records of processing activities
  • HIPAA §164.312(b) - Audit controls
  • SOC2 CC7.2 - System monitoring
  • FISMA AU-2 - Audit events

Features

  • ✅ Immutable append-only logs
  • ✅ Structured JSON format
  • ✅ Real-time security alerting
  • ✅ Compliance reporting
  • ✅ Configurable retention (7+ years)
  • ✅ User activity tracking
  • ✅ Data access logging

Configuration

Enable Audit Logging

Audit settings live under compliance::

# nornicdb.yaml
compliance:
  audit_enabled: true
  audit_log_path: "/var/log/nornicdb/audit.log"
  audit_retention_days: 2555  # ~7 years (covers SOC2 7-year requirement)

NornicDB does not expose per-event-class toggles (log_queries, log_data_access, etc.) or declarative alerting thresholds in configuration. The audit logger emits structured JSONL for every relevant event; route the file into your existing SIEM/detection pipeline if you need alerting on patterns like repeated failed logins.

Code Example

// Initialize audit logger
config := audit.DefaultConfig()
config.LogPath = "/var/log/nornicdb/audit.log"
config.RetentionDays = 2555

logger, err := audit.NewLogger(config)
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

// Set up security alerting
logger.SetAlertCallback(func(event audit.Event) {
    if event.Type == audit.EventSecurityAlert {
        sendSecurityAlert(event)
    }
})

// Attach to server
server.SetAuditLogger(logger)

Event Types

Authentication Events

Event TypeDescription
LOGINSuccessful login
LOGIN_FAILEDFailed login attempt
LOGOUTUser logout
PASSWORD_CHANGEPassword changed
ACCESS_DENIEDAuthorization failure

Data Events (GDPR Art.15)

Event TypeDescription
DATA_READData accessed
DATA_CREATEData created
DATA_UPDATEData modified
DATA_DELETEData deleted
DATA_EXPORTData exported

GDPR Rights Events

Event TypeDescription
ERASURE_REQUESTRight to be forgotten request
ERASURE_COMPLETEErasure completed
EXPORT_REQUESTData portability request
CONSENT_GIVENConsent recorded
CONSENT_REVOKEDConsent withdrawn

System Events

Event TypeDescription
CONFIG_CHANGEConfiguration modified
BACKUPBackup created
RESTOREBackup restored
SECURITY_ALERTSecurity event detected

Log Format

JSON Structure

{
  "id": "evt_abc123xyz",
  "timestamp": "2024-12-01T10:30:00.123Z",
  "type": "DATA_READ",
  "user_id": "usr_123",
  "username": "alice",
  "ip_address": "192.168.1.100",
  "user_agent": "Mozilla/5.0...",
  "resource": "node",
  "resource_id": "patient-456",
  "action": "READ",
  "success": true,
  "details": "PHI access",
  "session_id": "sess_789"
}

Fields

FieldDescriptionRequired
idUnique event IDYes
timestampISO 8601 timestampYes
typeEvent typeYes
user_idUser identifierYes
usernameHuman-readable nameNo
ip_addressClient IPYes
resourceObject type accessedFor data events
resource_idObject identifierFor data events
actionOperation performedFor data events
successOperation resultYes
detailsAdditional contextNo

Compliance Reporting

Generate Reports

// Create audit reader
reader := audit.NewReader(config.LogPath)

// Generate compliance report
report, err := reader.GenerateComplianceReport(
    time.Now().AddDate(0, -1, 0), // Start: 1 month ago
    time.Now(),                    // End: now
    "Monthly Compliance Report",
)

fmt.Printf("Total events: %d\n", report.TotalEvents)
fmt.Printf("Failed logins: %d\n", report.FailedLogins)
fmt.Printf("Data accesses: %d\n", report.DataAccesses)
fmt.Printf("GDPR requests: %d\n", report.GDPRRequests)

Searching Audit Logs

NornicDB writes audit events as JSON Lines to the configured log_path (default /var/log/nornicdb/audit.log). Use standard tooling such as jq, grep, or your log-aggregation pipeline to query them:

# Generate compliance report (last month)
jq -c 'select(.timestamp >= "2024-11-01" and .timestamp < "2024-12-01")' \
  /var/log/nornicdb/audit.log

# Export for external analysis (CSV)
jq -r '[.timestamp, .event_type, .username, .ip_address, .success] | @csv' \
  /var/log/nornicdb/audit.log > audit-november.csv

# Search for specific events
jq -c 'select(.username == "alice" and .event_type == "LOGIN_FAILED")' \
  /var/log/nornicdb/audit.log

Security Alerting

Configure Alerts

logger.SetAlertCallback(func(event audit.Event) {
    switch event.Type {
    case audit.EventLoginFailed:
        if getFailedLoginCount(event.IPAddress) >= 5 {
            sendSlackAlert("Multiple failed logins from " + event.IPAddress)
        }
    case audit.EventSecurityAlert:
        sendPagerDutyAlert(event)
    case audit.EventErasureRequest:
        notifyDPO(event) // Notify Data Protection Officer
    }
})

Alert Conditions

ConditionDefault ThresholdAction
Failed logins5 in 15 minutesAlert + lockout
Unusual data accessN/AAlert
Config changesAnyAlert
GDPR requestsAnyNotify DPO

Log Rotation

Automatic Rotation

The audit logger rotates automatically based on file size and elapsed time. Defaults: 100 MB rotation size, 24-hour rotation interval. These are configurable through the embedded Go API on audit.Config:

config := audit.DefaultConfig()
config.RotationSize = 100 * 1024 * 1024 // 100 MB
config.RotationInterval = 24 * time.Hour
config.RetentionDays = 2555
config.SyncWrites = true

There is no public YAML for rotation today; the file-size and interval values come from the embedded defaults unless your application code overrides them.

Manual Rotation

Audit log rotation is handled by the configured rotation policy (max_size, max_age, max_backups, compress under the audit: block). For ad-hoc archival, use standard log tooling:

# Archive logs older than a date
find /var/log/nornicdb -name 'audit.log.*' -newermt "2023-01-01" ! -newermt "2024-01-01" \
  -print0 | tar -czvf archive-2023.tar.gz --null -T -

Retention Management

GDPR Requirements

  • Keep logs as long as necessary for purpose
  • Delete when no longer needed

HIPAA Requirements

  • Minimum 6 years retention
  • Recommend 7+ years

SOC2 Requirements

  • 7 years recommended
# Configure retention
audit:
  retention_days: 2555  # 7 years
  auto_purge: true      # Delete expired logs

Integration

Syslog

audit:
  syslog:
    enabled: true
    address: "syslog.example.com:514"
    facility: local0

Elasticsearch

audit:
  elasticsearch:
    enabled: true
    urls: ["https://es.example.com:9200"]
    index: "nornicdb-audit"

Splunk

audit:
  splunk:
    enabled: true
    hec_url: "https://splunk.example.com:8088"
    token: "${SPLUNK_HEC_TOKEN}"

Best Practices

DO:

  • Enable audit logging in production
  • Set up alerting for security events
  • Regularly review audit logs
  • Keep logs for compliance period
  • Encrypt log files at rest

DON'T:

  • Disable audit logging
  • Delete logs before retention period
  • Log sensitive data in details field
  • Ignore security alerts

See Also