<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->
---
name: implementing-api-logging-monitoring
description: >-
  Implement comprehensive API logging and monitoring to detect abuse,
  track anomalous behavior, enforce rate limits, and support incident
  response with structured audit trails and real-time alerting.
domain: cybersecurity
subdomain: api-security
tags:
  - api-logging
  - api-monitoring
  - observability
  - audit-trail
  - owasp-api9
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1530", "T1190"]
  owasp-api: ["API9"]
  cwe: ["CWE-778"]
  tools: ["fluentd", "elasticsearch", "grafana", "vector"]
---

## Overview

Insufficient API logging and monitoring (OWASP API9) leaves organizations
blind to active attacks, abuse patterns, and data exfiltration. Effective
API monitoring requires structured logging of authentication events, access
patterns, error rates, and payload anomalies — with real-time alerting on
suspicious behavior.

## Prerequisites

- Tools: `fluentd`, `elasticsearch`, `grafana`, `vector`, `jq`
- API gateway or reverse proxy with logging capability
- Log aggregation platform (ELK, Loki, Splunk)
- Alerting infrastructure (PagerDuty, Opsgenie, or webhook)

## Key Concepts

- **Structured logging**: JSON-formatted logs with consistent field schema
- **Audit trail**: Immutable record of who accessed what and when
- **Anomaly detection**: Baseline deviation in request rates, error codes, payload sizes
- **Sensitive data masking**: Redact PII/secrets before log storage
- **Correlation ID**: Trace requests across distributed microservices

## Workflow

### Step 1: Define API Log Schema

```json
{
  "timestamp": "2026-01-15T10:30:00Z",
  "correlation_id": "req-abc123",
  "method": "GET",
  "path": "/api/users/42",
  "client_ip": "10.0.1.50",
  "user_id": "usr_789",
  "status_code": 200,
  "response_time_ms": 45,
  "user_agent": "Mozilla/5.0",
  "request_size": 256,
  "response_size": 1024,
  "auth_method": "bearer_jwt",
  "rate_limit_remaining": 95
}
```

### Step 2: Implement Structured Logging Middleware

```python
import json
import logging
import time
import uuid
from functools import wraps

logger = logging.getLogger("api.audit")

SENSITIVE_FIELDS = {"password", "token", "ssn", "credit_card"}

def mask_sensitive(data: dict) -> dict:
    """Redact sensitive fields from log data."""
    masked = {}
    for key, value in data.items():
        if key.lower() in SENSITIVE_FIELDS:
            masked[key] = "***REDACTED***"
        else:
            masked[key] = value
    return masked

def api_audit_log(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        correlation_id = str(uuid.uuid4())
        start = time.monotonic()
        try:
            response = func(request, *args, **kwargs)
            status = response.status_code
        except Exception as exc:
            status = 500
            raise
        finally:
            elapsed = (time.monotonic() - start) * 1000
            log_entry = {
                "correlation_id": correlation_id,
                "method": request.method,
                "path": request.path,
                "client_ip": request.remote_addr,
                "user_id": getattr(request, "user_id", None),
                "status_code": status,
                "response_time_ms": round(elapsed, 2),
            }
            logger.info(json.dumps(mask_sensitive(log_entry)))
        return response
    return wrapper
```

### Step 3: Configure Log Shipping with Vector

```toml
# vector.toml — ship API logs to Elasticsearch
[sources.api_logs]
type = "file"
include = ["/var/log/api/*.json"]
read_from = "beginning"

[transforms.parse_json]
type = "remap"
inputs = ["api_logs"]
source = '''
. = parse_json!(.message)
.@timestamp = .timestamp
del(.timestamp)
'''

[transforms.redact_pii]
type = "remap"
inputs = ["parse_json"]
source = '''
if exists(.client_ip) {
  .client_ip = redact(.client_ip, filters: ["pattern"],
    patterns: [r'\d+\.\d+\.\d+\.\d+'],
    redactor: {"type": "text", "replacement": "[REDACTED_IP]"})
}
'''

[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["redact_pii"]
endpoints = ["https://es.internal:9200"]
index = "api-logs-%Y-%m-%d"
```

### Step 4: Build Monitoring Dashboards

```bash
# Grafana dashboard queries (Elasticsearch datasource)

# Error rate by endpoint (5xx responses)
GET api-logs-*/_search
{
  "query": {"range": {"status_code": {"gte": 500}}},
  "aggs": {"by_path": {"terms": {"field": "path.keyword", "size": 20}}}
}

# P95 latency by endpoint
GET api-logs-*/_search
{
  "aggs": {
    "by_path": {
      "terms": {"field": "path.keyword"},
      "aggs": {"p95_latency": {"percentiles": {"field": "response_time_ms", "percents": [95]}}}
    }
  }
}

# Authentication failure rate
GET api-logs-*/_search
{
  "query": {"term": {"status_code": 401}},
  "aggs": {"by_ip": {"terms": {"field": "client_ip.keyword", "size": 10}}}
}
```

### Step 5: Configure Security Alerts

```yaml
# ElastAlert rule — brute force detection
name: api-brute-force-detection
type: frequency
index: api-logs-*
num_events: 20
timeframe:
  minutes: 5
filter:
  - term:
      status_code: 401
query_key: client_ip
alert:
  - slack
slack_webhook_url: "https://hooks.slack.com/services/XXX"
alert_text: |
  API Brute Force Detected
  IP: {0}
  Failed attempts: {1} in 5 minutes
alert_text_args:
  - client_ip
  - num_hits
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| High 401 rate from single IP | API logs | Credential stuffing or brute force |
| Spike in 4xx errors | API gateway | Fuzzing or enumeration activity |
| Abnormal request volume | Monitoring | API abuse or DDoS |
| Unusual endpoint access pattern | SIEM | Recon or BOLA attempts |

```yaml
title: API Authentication Brute Force Attempt
id: c3d4e5f6-a7b8-9012-cdef-123456789012
status: experimental
description: Detects excessive authentication failures from a single source
logsource:
  category: webserver
detection:
  selection:
    sc-status: 401
  timeframe: 5m
  condition: selection | count() by c-ip > 20
falsepositives:
  - Misconfigured service account with expired credentials
level: high
tags:
  - attack.t1110
  - attack.credential_access
```

## Verification

- [ ] Structured JSON logging implemented on all API endpoints
- [ ] Sensitive data redaction verified in stored logs
- [ ] Correlation IDs propagated across microservices
- [ ] Monitoring dashboards deployed with error rate and latency panels
- [ ] Security alerts configured for brute force and anomalous access
- [ ] Log retention and rotation policies enforced

## References

- [OWASP API9:2023 — Improper Inventory Management](https://owasp.org/API-Security/editions/2023/en/0xa9-improper-inventory-management/)
- [CWE-778: Insufficient Logging](https://cwe.mitre.org/data/definitions/778.html)
- [Vector Documentation](https://vector.dev/docs/)
