{"id":22790381,"url":"https://github.com/fabriziosalmi/wafcontrol","last_synced_at":"2026-04-30T01:38:56.285Z","repository":{"id":266812143,"uuid":"867033824","full_name":"fabriziosalmi/wafcontrol","owner":"fabriziosalmi","description":"Cloudflare WAF Settings Automation using GitHub Actions","archived":false,"fork":false,"pushed_at":"2026-02-20T07:16:29.000Z","size":113,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-20T11:17:52.066Z","etag":null,"topics":["cloudflare","cloudflare-api","cybersecurity","firewall-rules","rules","security","settings","waf","web-application-firewall","workflow","zones"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fabriziosalmi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["fabriziosalmi"]}},"created_at":"2024-10-03T10:32:51.000Z","updated_at":"2026-02-20T07:16:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"f2ebd000-5a83-45f6-a667-97aa6b7cd18c","html_url":"https://github.com/fabriziosalmi/wafcontrol","commit_stats":null,"previous_names":["fabriziosalmi/wafcontrol"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fabriziosalmi/wafcontrol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabriziosalmi%2Fwafcontrol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabriziosalmi%2Fwafcontrol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabriziosalmi%2Fwafcontrol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabriziosalmi%2Fwafcontrol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabriziosalmi","download_url":"https://codeload.github.com/fabriziosalmi/wafcontrol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabriziosalmi%2Fwafcontrol/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32451481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"ssl_error","status_checked_at":"2026-04-29T22:10:49.234Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare","cloudflare-api","cybersecurity","firewall-rules","rules","security","settings","waf","web-application-firewall","workflow","zones"],"created_at":"2024-12-12T02:26:22.668Z","updated_at":"2026-04-30T01:38:56.280Z","avatar_url":"https://github.com/fabriziosalmi.png","language":"Python","funding_links":["https://github.com/sponsors/fabriziosalmi"],"categories":[],"sub_categories":[],"readme":"# WAFcontrol\n\nWAFcontrol applies Cloudflare zone security settings and custom WAF rules across multiple domains using a YAML configuration file and the Cloudflare API. It is designed to run as a GitHub Actions workflow.\n\n## What it does\n\nThe script `scripts/apply_cloudflare.py` reads `config/cloudflare.yaml`, validates the configuration, and calls Cloudflare's API to set the following per-zone settings:\n\n- **Security Level** — `off`, `essentially_off`, `low`, `medium`, `high`, or `under_attack`\n- **Browser Integrity Check** — `on` or `off`\n- **Automatic HTTPS Rewrites** — `on` or `off`\n- **Custom WAF Rules** — create or update rules in the zone's `http_request_firewall_custom` ruleset (actions: `block`, `challenge`, `allow`, `log`, `bypass`)\n\nA `default` section in the config applies to all zones. Settings in a zone's own block override the defaults.\n\n\u003e **Note:** Custom WAF rules (rulesets) require a Cloudflare paid plan. Zone-level firewall settings (security level, browser integrity check, automatic HTTPS rewrites) are available on all plans.\n\n## Prerequisites\n\n- Python 3.9 or higher\n- A Cloudflare API token with **Zone Settings: Edit** permission\n- A GitHub repository secret named `CLOUDFLARE_API_TOKEN`\n\nInstall dependencies:\n\n```bash\npip install pydantic requests PyYAML tenacity\n```\n\n## Configuration\n\nEdit `config/cloudflare.yaml`. Settings defined under `default` apply to every zone unless overridden.\n\n```yaml\ncloudflare:\n  waf:\n    default:\n      firewall_settings:\n        security_level: \"high\"\n        browser_integrity_check: \"on\"\n        automatic_https_rewrites: \"on\"\n      rules:\n        - description: \"Block bad user agents\"\n          expression: '(http.user_agent contains \"bad-bot\")'\n          action: \"block\"\n    zones:\n      - id: \"your-zone-id\"\n        domain: \"your-domain.com\"\n        waf:\n          firewall_settings:\n            security_level: \"under_attack\"\n            browser_integrity_check: \"off\"   # overrides default\n            automatic_https_rewrites: \"on\"\n          rules:\n            - description: \"Challenge suspicious requests\"\n              expression: '(ip.geoip.country eq \"RU\")'\n              action: \"challenge\"\n```\n\n## Running manually\n\n```bash\nexport CLOUDFLARE_API_TOKEN=your-token-here\npython scripts/apply_cloudflare.py --config config/cloudflare.yaml\n```\n\n## GitHub Actions\n\nThe workflow at `.github/workflows/cloudflare_deploy.yml` runs on:\n\n- Push to `main` (when `config/`, `scripts/`, or `.github/workflows/` files change)\n- Pull requests to `main` (same path filter)\n- A daily schedule at midnight UTC\n- Manual dispatch via the GitHub Actions UI\n\nThe workflow verifies the API token before applying settings and requires a `CLOUDFLARE_API_TOKEN` repository secret and a `production` environment configured in the repository settings.\n\n## Example output\n\n```\n2024-01-01 00:00:00 - INFO - Processing zone example.com (zone-id)...\n2024-01-01 00:00:00 - INFO - Applying WAF settings for zone zone-id...\n2024-01-01 00:00:00 - INFO - Successfully updated security level to under_attack\n2024-01-01 00:00:00 - INFO - Successfully updated browser integrity check to off\n2024-01-01 00:00:00 - INFO - Successfully updated automatic https rewrites to on\n```\n\nWhen run inside GitHub Actions, log lines use the `::INFO ::` prefix format instead.\n\n## Security\n\n- Store your API token in GitHub Secrets, never in the repository.\n- Use a GitHub environment protection rule to restrict production deployments.\n- Verify zone IDs before applying settings.\n\n## Troubleshooting\n\n**API token errors**\n- Confirm the token has `Zone Settings: Edit` permission.\n- Check the token has not expired.\n- Confirm the secret name in the repository matches `CLOUDFLARE_API_TOKEN`.\n\n**Configuration errors**\n- Verify zone IDs are correct (found in the Cloudflare dashboard overview page for each domain).\n- Confirm YAML syntax is valid.\n- Check that `security_level` is one of the accepted values listed above.\n\n## Contributing\n\nOpen an issue to discuss significant changes before submitting a pull request.\n\n## License\n\nMIT — see the [LICENSE](LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabriziosalmi%2Fwafcontrol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffabriziosalmi%2Fwafcontrol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabriziosalmi%2Fwafcontrol/lists"}