# Centralized log aggregation configured with timestamps, severity, and trace IDs

- **Pattern:** `ab-001653` (`infrastructure-hardening.monitoring-incident-response.centralized-logging`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001653
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001653)

## Why it matters

Logs written only to stdout and discarded when a pod restarts leave no forensic trail for incidents — there is no record of which requests preceded a data breach, no timestamp evidence for compliance audits, and no visibility into error patterns that precede outages (NIST 800-53 AU-3, AU-9). CIS Kubernetes 3.2.2 requires log aggregation and forwarding. Missing trace IDs means individual requests cannot be correlated across service boundaries, turning a multi-service investigation into manual log grep archaeology. 30-day retention is the minimum threshold for detecting slow-burn attacks that unfold over weeks.

## Severity rationale

Info because absent centralized logging does not directly expose data, but makes post-incident forensics and compliance audit responses impossible.

## Remediation

Deploy a log aggregation sidecar or DaemonSet. For Fluent Bit to CloudWatch, add to `k8s/logging/fluent-bit.yaml`:

```yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluent-bit
  namespace: logging
spec:
  template:
    spec:
      containers:
        - name: fluent-bit
          image: fluent/fluent-bit:2.2
          volumeMounts:
            - name: varlog
              mountPath: /var/log
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
```

Structure application logs as JSON with three required fields: `timestamp` (ISO 8601), `level` (severity), and `traceId` (propagated from the incoming `X-Request-ID` or `traceparent` header). Set log retention to 30 days minimum in your aggregation target — CloudWatch log groups default to `Never expire` which costs more; set explicitly to `30` days.

## Detection

- **ID:** `centralized-logging`
- **Severity:** `info`
- **What to look for:** List all logging configuration files and sidecar containers (Fluent Bit, Filebeat, Fluentd). Check for log aggregation targets (ELK Stack, Splunk, Datadog, CloudWatch, Stackdriver). Count the required structured fields present in log output: timestamp, severity level, and request trace ID. All 3 fields must be present.
- **Pass criteria:** Centralized logging is configured with log aggregation to at least 1 external system (ELK, Splunk, Datadog, CloudWatch, or equivalent). Every log entry includes all 3 required structured fields: timestamp, severity level, and request trace ID. Logs are retained for at least 30 days. Report even on pass: "Logging aggregated to X, retention Y days, 3 of 3 structured fields present."
- **Fail criteria:** No centralized logging configured (logs only written to stdout), or logs are missing any of the 3 required structured fields (timestamp, severity, trace ID).
- **Skip (N/A) when:** Logging is managed externally or application is stateless with no relevant logs.
- **Detail on fail:** Quote the logging config. Example: `"Application logs are written to stdout only. No Fluent Bit or Filebeat sidecar configured."` or `"Logs include timestamp and severity but lack request trace IDs — 2 of 3 structured fields"`
- **Remediation:** Set up centralized logging. Example with Fluent Bit → CloudWatch:

  ```yaml
  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: fluent-bit-config
  data:
    fluent-bit.conf: |
      [SERVICE]
          Flush        5
          Daemon       Off
          Log_Level    info

      [INPUT]
          Name              tail
          Path              /var/log/containers/*.log
          Parser            json
          Tag               kube.*

      [OUTPUT]
          Name   cloudwatch_logs
          Match  kube.*
          region us-east-1
          log_group_name /ecs/my-app
          log_stream_prefix from-fluent-bit-
          auto_create_group true
  ```

## External references

- nist AU-3
- nist AU-9
- external CIS-Kubernetes-3.2.2 — https://www.cisecurity.org/benchmark/kubernetes

Taxons: observability, operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-001653
