Skip to main content

octorules-cloudflare

Cloudflare provider for octorules: manages 23 Cloudflare rule phases, custom rulesets, lists, Cloud Connector rules, Page Shield and alerting policies, and the zone settings sections (bot management, security, SSL/TLS, security.txt, managed transforms, and more) as YAML.

Installation

pip install octorules-cloudflare

This installs octorules (core), octorules-cloudflare, and octorules-wirefilter (Rust FFI bridge to Cloudflare's wirefilter engine for authoritative expression parsing and full linter coverage).

Prebuilt wirefilter wheels are available for Linux (x86_64, aarch64; glibc and musl/Alpine), macOS (x86_64, ARM64), and Windows (x86_64).

Configuration

providers:
  cloudflare:
    token: env/CLOUDFLARE_API_TOKEN
  rules:
    directory: ./rules

zones:
  example.com:
    sources:
      - rules

The env/ prefix resolves values from environment variables at runtime. All keys under the provider section are forwarded to the provider constructor as keyword arguments (octodns-style passthrough).

Authentication

A Cloudflare API token is required. See docs/permissions.md for the full list of required permissions per phase and extension.

Provider settings

All settings below go under the provider section (e.g. providers.cloudflare).

Key Default Description
token (required) Cloudflare API token (env/ prefix supported)
max_retries 2 API retry count (0-10)
timeout 30 API timeout in seconds (max 300)

Safety thresholds are configured under safety: (framework-owned, not forwarded to the provider):

Key Default Description
safety.delete_threshold 30.0 Max % of rules that can be deleted
safety.update_threshold 30.0 Max % of rules that can be updated
safety.min_existing 3 Min rules before thresholds apply

Examples

The examples/ directory contains a working single-provider config.yaml plus rules files: rules/example.com.yaml (zone-level) and rules/example-account.yaml (account-level, including the five Magic Transit / Layer-4 phases, whose packet-level expressions are validated against octorules-wirefilter's L4 scheme). Together they exercise every supported phase and key. Copy them as a starting point.

All Cloudflare sections (phases, settings, lists, and policies) nest under a single cloudflare: block.

Supported features

Feature Status
Phase rules (23 phases) Supported
Custom rulesets (account-level) Supported
Lists (IP, ASN, hostname, redirect) Supported
Page Shield policies (zone-level) Supported
Zone discovery (list_zones) Supported
Account-level scopes Supported
Audit IP extraction (octorules audit) Supported
Bot Management settings (bot_management) Supported
URL normalization settings (url_normalization_settings) Supported
Zone security defaults (zone_security) Supported
SSL/TLS settings (zone_tls) Supported
security.txt (security_txt) Supported
Managed Transforms (managed_transforms) Supported
Cloud Connector rules (cloud_connector_rules) Supported
Alerting / notification policies (alerting_policies) Supported
Leaked Credential Check (leaked_credential_check) Supported
Content Scanning / anti-malware (content_scanning) Supported

Supported phases

23 Cloudflare phases — 18 HTTP request/response phases and 5 network-level (Magic Transit) phases. Phases execute in a fixed order:

Request  -> url_normalization -> redirect_rules -> url_rewrite_rules -> request_header_rules
         -> origin_rules -> config_rules -> cache_rules
         -> waf_custom_rules -> waf_managed_rules -> rate_limiting_rules
         -> bot_fight_rules -> http_ddos_rules
         ->  Origin fetch  <-
         -> custom_error_rules -> response_header_rules -> compression_rules
         -> sensitive_data_detection -> log_custom_fields -> Response

Phases with a default action (e.g., redirect_rules -> redirect) don't need action in the YAML — it's injected automatically. For phases without a default (e.g., waf_custom_rules), you must specify action explicitly.

Phases marked as both Zone and Account work at either scope. Account-only phases are skipped for zone scopes and vice versa, eliminating wasted API calls.

For the full phase reference — execution order diagram, valid actions per phase, field/function availability, and key behaviors — see docs/lint/README.md.

Expression syntax

Rule expressions use Cloudflare's ruleset expression language. Expressions are parsed by Cloudflare's actual wirefilter engine via octorules-wirefilter — a required dependency, installed automatically with octorules-cloudflare — providing authoritative type checking, field validation, and syntax verification.

Rule-level metadata: All Cloudflare rules support the octorules: key for per-rule metadata — ignored: true to skip a rule during plan/sync, and included/excluded to restrict rules to specific providers. See octorules core docs for syntax and examples.

Custom rulesets (account-level)

At the account level, WAF custom rules and rate limiting rules use a two-tier structure: the phase entrypoint contains deploy rules (action: execute) that reference child custom rulesets by ID. The individual blocking/logging rules live inside those child rulesets.

octorules manages both tiers. Deploy rules are managed via the normal phase sections (waf_custom_rules, rate_limiting_rules). The individual rules inside each custom ruleset are managed via a separate custom_rulesets section:

# Account rules file (e.g. rules/my-account.yaml)
cloudflare:
  # Deploy rules (phase entrypoint — references child rulesets by ID)
  waf_custom_rules:
    - ref: deploy-known-attackers
      description: Deploy known attackers ruleset
      action: execute
      action_parameters:
        id: abc12345def67890abc12345def67890
        version: latest
      enabled: true
      expression: (http.host eq "api.example.com")

  # Individual rules inside each custom ruleset
  custom_rulesets:
    - id: abc12345def67890abc12345def67890
      name: Known attackers
      phase: http_request_firewall_custom
      rules:
        - ref: block-bad-asn
          description: Block by AS number
          action: block
          expression: (ip.geoip.asnum in {12345 67890})
        - ref: block-bad-ua
          description: Block by user-agent
          action: block
          expression: (http.user_agent contains "BadBot")

The id field in each custom_rulesets entry links it to the deploy rule's action_parameters.id. Rules inside use ref for identification (same pattern as phase rules). Every rule must specify an action explicitly.

Use octorules dump --scope account to export existing custom rulesets to YAML.

Note: octorules manages rules within existing custom rulesets. Creating or deleting rulesets themselves must be done via the Cloudflare dashboard. Zone-level rulesets do not have kind=custom children — this is account-level only.

Lists (account-level)

Cloudflare account-level Lists (IP lists, ASN lists, hostname lists, redirect lists) can be referenced in rule expressions via $list_name syntax. octorules manages full lifecycle of lists declaratively: create, delete, update metadata, and manage items.

Add a lists key under the cloudflare: block of your account rules file:

# rules/my-account.yaml
cloudflare:
  lists:
    - name: blocked_ips
      kind: ip
      description: "Known bad IPs"
      items:
        - ip: "1.2.3.4"
          comment: "Scanner"
        - ip: "5.6.7.0/24"
          comment: "Botnet range"

    - name: partner_asns
      kind: asn
      description: "Partner AS numbers"
      items:
        - asn: 12345
          comment: "Partner A"
        - asn: 67890
          comment: "Partner B"

Each list entry requires:

Field Description
name List name — matches CF list name and $list_name in expressions
kind One of ip, asn, hostname, redirect
description Optional — updated if changed
items List of items (can be empty [] to clear all items)

How it works:

  • The presence of a lists: key means ALL lists are managed — lists in Cloudflare not in YAML are planned for deletion (subject to safety thresholds).
  • If the lists: key is absent, lists are ignored entirely.
  • Item updates are asynchronous — octorules polls the bulk operation until completion.
  • During sync, lists are applied before rulesets and phases, so newly created lists are available for rule expressions that reference them.
  • Use octorules dump --scope account to export existing lists to YAML. The dump externalizes list items into separate files (referenced via !include tags) under providers.lists.directory (default: {rules_dir}/custom_lists).

Reference lists in rule expressions:

cloudflare:
  waf_custom_rules:
    - ref: block-bad-ips
      description: Block IPs from blocklist
      action: block
      expression: (ip.src in $blocked_ips)

Page Shield policies (zone-level)

Cloudflare Page Shield manages Content Security Policies (CSP) at the zone level. octorules manages full lifecycle of Page Shield policies declaratively: create, update, and delete.

Add a page_shield_policies key under the cloudflare: block of your zone rules file:

# rules/example.com.yaml
cloudflare:
  page_shield_policies:
    - description: "CSP on all example.com"
      action: allow
      expression: "true"
      enabled: true
      value: >-
        script-src 'self' 'unsafe-inline' 'unsafe-eval' https:;
        worker-src 'self' blob:

    - description: "Log CSP on staging"
      action: log
      expression: '(http.host eq "staging.example.com")'
      enabled: true
      value: "default-src 'self'"

Each policy entry requires:

Field Description
description Policy description — used as the identity key for matching
action allow or log
expression Cloudflare filter expression
enabled Boolean
value CSP directive string

How it works:

  • The description field is the identity key (like ref for rules and name for lists). Policies are matched between YAML and Cloudflare by description.
  • The presence of a page_shield_policies: key means ALL policies are managed - policies in Cloudflare not in YAML are planned for deletion.
  • If the page_shield_policies: key is absent, policies are ignored entirely.
  • During sync, policies are applied after lists and before custom rulesets and phases.
  • Use octorules dump to export existing Page Shield policies to YAML.

CSP source normalization: The order of sources within a CSP directive is not significant — script-src 'self' example.com and script-src example.com 'self' are semantically identical. octorules normalizes source order (sorted alphabetically within each directive) before comparing value fields, so reordering sources in your YAML will not trigger an upstream change on Cloudflare. You can freely reorganize sources for readability without causing a sync.

Cloud Connector rules (zone-level)

Cloudflare Cloud Connector routes matching requests directly to an object-storage provider. octorules manages the zone's rule list declaratively.

Add a cloud_connector_rules key under the cloudflare: block of your zone rules file:

# rules/example.com.yaml
cloudflare:
  cloud_connector_rules:
    - description: "Serve /assets from the R2 bucket"
      expression: 'starts_with(http.request.uri.path, "/assets/")'
      provider: cloudflare_r2
      parameters:
        host: assets.account-a.r2.cloudflarestorage.com

Each rule entry:

Field Description
description Rule description, used as the identity key for matching
expression Cloudflare filter expression (request-phase fields)
provider aws_s3, cloudflare_r2, gcp_storage, or azure_storage
parameters Provider parameters (host: the storage endpoint to route to)
enabled Boolean, defaults to true

How it works:

  • The description field is the identity key (like description for Page Shield policies): the Cloud Connector API has no ref field to persist, so plans match YAML rules to live rules by description. Descriptions must be unique.
  • Rule order is part of the desired state: reordering rules in YAML is a planned change.
  • The presence of a cloud_connector_rules: key means ALL rules are managed - the list is replaced wholesale on sync, so rules in Cloudflare not in YAML are planned for deletion. If the key is absent, Cloud Connector is ignored entirely.
  • Use octorules dump to export existing Cloud Connector rules to YAML.

Alerting policies (account-level)

Cloudflare notification policies decide who gets told when something happens: a certificate about to expire, an L7 DDoS event, a Cloudflare incident. They live on the account, so the section belongs in the account-scoped rules file:

# rules/account-a.yaml
cloudflare:
  alerting_policies:
    - name: "Certificate expiring soon"
      alert_type: dedicated_ssl_certificate_event_type
      enabled: true
      mechanisms:
        email: ["security@account-a.example"]
        webhooks: ["$Ops Slack"]

Each policy entry:

Field Description
name Policy name, used as the identity key for matching
alert_type One of the account's available alert types
enabled Boolean
mechanisms Destinations: email (addresses), webhooks ($name references or ids), pagerduty (ids); at least one required
description Optional
alert_interval Optional re-alert interval
filters Optional per-type filters; zones entries are zone names

How it works:

  • The name field is the identity key. Policies are matched between YAML and Cloudflare by name; names must be unique.
  • Webhook destinations are referenced by name with a $ prefix ("$Ops Slack") and resolved against the account's webhook destinations at plan time. Destinations themselves are not managed; create them once in the dashboard.
  • Zone names inside filters.zones are resolved to zone ids on plan and translated back on dump, so the YAML does not need to carry UUIDs.
  • alert_type and each type's required filters are validated at plan time against the account's own available_alerts registry, not a hardcoded table: an alert type this account cannot use, or a missing required filter, fails the plan before the API rejects it.
  • The presence of an alerting_policies: key means ALL policies are managed - policies in Cloudflare not in YAML are planned for deletion. If the key is absent, alerting is ignored entirely.
  • Fields the YAML declares replace the live value; optional fields it omits keep their dashboard-set values.
  • Use octorules dump to export existing policies to YAML.

Linting

168 Cloudflare-specific lint rules (CF prefix) across 6 ranges:

Range Category Rules
CF001–CF027 Structure, parse & phase 25
CF100–CF105 Cross-rule ordering 6
CF200–CF227 Action validation 28
CF300–CF309 Expression, function & type 10
CF400–CF495 Domain-specific (rate limit, cache, config, redirect, transform, origin, page shield, list, cloud connector) 56
CF500–CF550 Plan limits, style & value constraints 43

See docs/lint/README.md for the full rule reference.

Development

git clone git@github.com:doctena-org/octorules-cloudflare.git
cd octorules-cloudflare
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install

The pre-commit hook runs ruff (check + format) and yamllint. See docs/schemas.md for the schema architecture — octorules-wirefilter provides the field/function data and is a required dependency (there is no frozen fallback).

License

octorules-cloudflare is licensed under the Apache License 2.0.

Release files for octorules-cloudflare 0.17.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for octorules-cloudflare 0.17.2
File Size Uploaded
octorules_cloudflare-0.17.2.tar.gz 221.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for octorules-cloudflare 0.17.2
File Interpreter ABI Platform
octorules_cloudflare-0.17.2-py3-none-any.whl Python 3 none any Details

Total release size: 379.8 kB

Release files / octorules_cloudflare-0.17.2.tar.gz

Download URL octorules_cloudflare-0.17.2.tar.gz
Size 221.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2045b1dee56e8ff10c70fb6b7d6ff2aa3fc5a33d68208377aabb6d231ecdf89c
BLAKE2b-256 checksum
How to use checksums
8f9eb009fe1a03a164fcc407d0d1d1f178eeeb930d727a80beae9c20927ad1e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / octorules_cloudflare-0.17.2-py3-none-any.whl

Download URL octorules_cloudflare-0.17.2-py3-none-any.whl
Size 158.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6a24b974f528796be22bf64e80751c7d0b7b137519a7c39c816f856eb5de8e52
BLAKE2b-256 checksum
How to use checksums
4794d803ad5625578b979520be1f5f7df8154b75154831f8acfaeccd1c834bc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.17.2 This release

2 release files

0.16.0

2 release files

0.15.0

2 release files

0.13.0

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.9

2 release files

0.8.8

2 release files

0.8.7

2 release files

0.8.6

2 release files

0.8.5

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.12

2 release files

0.7.11

2 release files

0.7.10

2 release files

0.7.9

2 release files

0.7.8

2 release files

0.7.7

2 release files

0.7.6

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page