Skip to content

[design-spec] cloudflare-zone-waf-report #112

@rw-codebundle-agent

Description

@rw-codebundle-agent

Design Spec: cloudflare-zone-waf-report

Parent: #111
Target: runwhen-contrib/rw-cli-codecollection

Spec

codebundle_name: "cloudflare-zone-waf-report"
target_collection: "runwhen-contrib/rw-cli-codecollection"
display_name: "Cloudflare Zone WAF & Security Events Report"
author: "rw-codebundle-agent"

purpose: |
  Pulls Cloudflare WAF and security-adjacent firewall events for a zone, correlates them
  by rule, action, client IP, geography, host, and path, and raises issues when volumes
  exceed operator-defined thresholds. Intended for proactive abuse detection and tuning.

tasks:
  - name: "Fetch Firewall and WAF Events for Zone `${CLOUDFLARE_ZONE_ID}`"
    description: |
      Queries the Cloudflare GraphQL Analytics API (firewall/security event datasets)
      for the configured lookback window and persists normalized JSON for downstream tasks.
    script_name: "fetch-cloudflare-firewall-events.sh"
    expected_issue_severity: [1, 2]
    access_level: "read-only"
    data_type: "metrics"

  - name: "Aggregate WAF Events by Rule, Action, and Service"
    description: |
      Groups events by rule ID, action (block, challenge, jschallenge, etc.), and
      source service to show which protections are firing most often.
    script_name: "aggregate-waf-by-rule.sh"
    expected_issue_severity: [2, 2]
    access_level: "read-only"
    data_type: "metrics"

  - name: "Correlate WAF Events by Source IP and Country"
    description: |
      Identifies top client IPs, ASNs, and countries to highlight concentrated attacks
      versus distributed noise.
    script_name: "correlate-waf-by-source.sh"
    expected_issue_severity: [2, 3]
    access_level: "read-only"
    data_type: "metrics"

  - name: "Break Down WAF Activity by Hostname and Request Path"
    description: |
      Surfaces which hosts and URL paths draw the most security actions for targeted
      investigation and rule tuning.
    script_name: "aggregate-waf-by-path.sh"
    expected_issue_severity: [2, 2]
    access_level: "read-only"
    data_type: "metrics"

  - name: "Evaluate WAF Volume and Spike Thresholds"
    description: |
      Compares totals and top-segment counts to configurable thresholds (absolute counts
      and optional ratio versus prior window) and emits structured issues with expected vs
      actual and remediation hints.
    script_name: "evaluate-waf-thresholds.sh"
    expected_issue_severity: [3, 4]
    access_level: "read-only"
    data_type: "metrics"

  - name: "Produce Consolidated WAF Correlation Report"
    description: |
      Renders a single human-readable summary referencing the aggregations above and
      attaches key metrics to the RunWhen report for on-call handoff.
    script_name: "report-waf-correlation-summary.sh"
    expected_issue_severity: [2, 3]
    access_level: "read-only"
    data_type: "metrics"

scope:
  level: "Resource"
  qualifiers:
    - CLOUDFLARE_ZONE_ID
    - CLOUDFLARE_ACCOUNT_ID
  iteration_pattern: |
    One SLX per Cloudflare zone. Operators supply CLOUDFLARE_ZONE_ID (and optionally
    account context). Future generation rules may discover zones via the Accounts API
    when an account-level token is available.

resource_types:
  - "cloudflare_zone"

generation_strategy: |
  Target resource type cloudflare_zone with qualifier zone identifier. Match RunWhen
  resources representing monitored Cloudflare zones (manual registration or future
  discovery from Cloudflare Accounts/Zones list APIs).

env_vars:
  - name: CLOUDFLARE_ZONE_ID
    description: "Cloudflare zone identifier (zone tag) to scope analytics queries"
    required: true

  - name: CLOUDFLARE_ACCOUNT_ID
    description: "Cloudflare account identifier when required by GraphQL dataset filters"
    required: false

  - name: WAF_LOOKBACK_MINUTES
    description: "Length of the primary analytics window in minutes"
    required: false
    default: "60"

  - name: WAF_COMPARE_LOOKBACK_MINUTES
    description: "Optional prior window for simple spike/baseline comparison (0 disables)"
    required: false
    default: "60"

  - name: WAF_TOTAL_EVENTS_ISSUE_THRESHOLD
    description: "Raise an issue when total WAF/security actions in the window exceed this count"
    required: false
    default: "500"

  - name: WAF_TOP_ENTITY_ISSUE_THRESHOLD
    description: "Raise when any single IP, rule ID, or path bucket exceeds this count"
    required: false
    default: "100"

  - name: WAF_SPIKE_RATIO_THRESHOLD
    description: "Optional ratio (e.g. 2.0) of primary window to prior window; issue if exceeded"
    required: false
    default: "0"

  - name: WAF_REPORT_TOP_N
    description: "Number of top entities to include in tables (IPs, rules, paths)"
    required: false
    default: "15"

secrets:
  - name: cloudflare_api_token
    description: "Cloudflare API token with Analytics read and Zone/WAF appropriate scopes"
    format: |
      Plain text token or RunWhen secret; HTTP Authorization Bearer to api.cloudflare.com
      and the GraphQL Analytics endpoint. Minimum scopes: Zone Analytics read and Zone
      Firewall Services read (exact names per Cloudflare token templates).

platform:
  name: "cloudflare"
  cli_tools:
    - "curl"
    - "jq"
  auth_methods:
    - "API Token (cloudflare_api_token Bearer auth)"
  api_docs: "https://developers.cloudflare.com/analytics/graphql-api/"

related_bundles:
  - name: "gcp-project-cost-health"
    relationship: "complements"
    notes: |
      Establishes the same multi-task reporting + JSON issue pattern with configurable
      thresholds; reuse bash+json issue emission and Robot task structure.

  - name: "gcloud-log-inspection"
    relationship: "complements"
    notes: |
      Similar log aggregation and “top N” correlation story on a different platform;
      applicable for jq patterns and issue text quality.

  - name: "vercel-project-health"
    relationship: "overlaps"
    notes: |
      Edge traffic health on another provider; does not query Cloudflare WAF—different
      data plane but adjacent operational concerns.

test_scenarios:
  - name: "quiet_zone"
    description: "Zone with no or minimal firewall events below all thresholds"
    expected_issues: 0

  - name: "concentrated_block_spike"
    description: "Synthetic fixture with one rule ID and one IP exceeding top-entity threshold"
    expected_issues: 2
    expected_severities: [3, 3]

  - name: "high_volume_distributed"
    description: "Many low-volume sources that sum above total threshold"
    expected_issues: 1
    expected_severities: [3]

notes: |
  Use the GraphQL Analytics API firewall/security event fields documented by Cloudflare;
  dataset names and filters evolve—implementations should pin to the documented schema for
  firewallEventsAdaptive / security event equivalents and degrade gracefully on empty
  result sets. Prefer read-only Analytics and Zone APIs only; no configuration changes.
  If GraphQL quota or sampling limits apply, document effective limits in the README.

Metadata

Metadata

Assignees

No one assigned

    Labels

    completedAgent work completeddesign-specArchitect has produced a design specnew-codebundleScoped issue for SRE to implement a new CodeBundle

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions