doctena-org/octorules-sync
GitHub: doctena-org/octorules-sync
一个用于在 GitHub Actions 中自动规划、审计并同步 WAF 及安全规则配置到多家云提供商的自动化部署组件。
Stars: 1 | Forks: 0
# octorules-sync
此 action 运行来自 [doctena-org/octorules](https://github.com/doctena-org/octorules) 的 `octorules` 来部署您的 WAF 规则配置。
octorules 允许您将 WAF 和安全规则(重定向、重写、标头、缓存、WAF、速率限制等)作为 YAML 文件进行管理,并通过您的提供商 API 发布更改。支持的提供商:[Cloudflare](https://github.com/doctena-org/octorules-cloudflare)、[AWS WAF](https://github.com/doctena-org/octorules-aws)、[Google Cloud Armor](https://github.com/doctena-org/octorules-google)、[Azure WAF](https://github.com/doctena-org/octorules-azure)、[Bunny.net](https://github.com/doctena-org/octorules-bunny)。
当您在 GitHub 仓库中管理 octorules 配置时,此 [GitHub Action](https://help.github.com/actions/getting-started-with-github-actions/about-github-actions) 允许您使用自定义的 [workflow](https://help.github.com/actions/configuring-and-managing-workflows) 自动测试并发布更改。
## 示例 workflow
### Cloudflare
```
name: octorules-sync
on:
push:
branches:
- main
paths:
- 'rules/**'
- 'config.yaml'
jobs:
publish:
name: Publish rules from main
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install octorules-cloudflare
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
```
### AWS WAF
```
- run: pip install octorules-aws
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: eu-central-1
```
### Google Cloud Armor
```
- run: pip install octorules-google
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
```
### Azure WAF
```
- run: pip install octorules-azure
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
```
### Bunny.net
```
- run: pip install octorules-bunny
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
BUNNY_API_KEY: ${{ secrets.BUNNY_API_KEY }}
```
### 多提供商
安装您的配置中使用的所有提供商包:
```
- run: pip install octorules-cloudflare octorules-aws octorules-google octorules-azure octorules-bunny
```
## 输入
### Secrets
提供商凭证通过环境变量传递,使用的是
[encrypted secrets](https://help.github.com/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#about-encrypted-secrets)。
Secret 名称和配置语法取决于您的提供商:
| 提供商 | Secret 示例 | 配置语法 |
|----------|---------------|---------------|
| [Cloudflare](https://github.com/doctena-org/octorules-cloudflare) | `CLOUDFLARE_API_TOKEN` | `token: env/CLOUDFLARE_API_TOKEN` |
| [AWS WAF](https://github.com/doctena-org/octorules-aws) | 标准 boto3 凭证 (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) 或 IAM role | 不需要 `token` — 使用 boto3 凭证链 |
| [Google Cloud Armor](https://github.com/doctena-org/octorules-google) | `GOOGLE_APPLICATION_CREDENTIALS` 或 Workload Identity | 不需要 `token` — 使用 Application Default Credentials |
| [Azure WAF](https://github.com/doctena-org/octorules-azure) | `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET` | 不需要 `token` — 使用 Azure SDK 凭证链 |
| [Bunny.net](https://github.com/doctena-org/octorules-bunny) | `BUNNY_API_KEY` | `token: env/BUNNY_API_KEY` |
配置值中的 `env/` 前缀会在运行时解析环境变量。有关完整的身份验证详细信息,请参阅各个提供商的 README。
### `config_path`
您希望 octorules 使用的配置文件相对于仓库根目录的路径。
默认 `"config.yaml"`。
### `doit`
设置为 `"--doit"` 以应用更改,留空则仅执行计划。仅接受 `""` 和
`"--doit"` — 任何其他值都会立即失败。
默认 `""`(仅计划)。
### `force`
设置为 `"Yes"` 以绕过安全阈值,留空则强制执行它们。仅接受 `""`
和 `"Yes"`。
默认 `""`(强制执行阈值)。
### `checksum`
将计划校验和传递给 `octorules sync` 以进行漂移保护。workflow
如下:
1. `octorules plan` 计算计划更改的 SHA-256 哈希值,并在其日志输出中
打印 `checksum=`。
2. 在计划 (plan) 和同步 (sync) 之间,远程状态可能会发生变化(另一次部署、
手动编辑、API 端更新)。这就是“漂移”。
3. `octorules sync --checksum ` 会在内部重新计划,并将新的
哈希值与提供的哈希值进行比较。如果它们不同,同步将报错并中止,
而不是应用过期的更改。
仅在 `doit` 为 `"--doit"` 时使用。默认 `""`(空字符串,无
校验和验证)。
示例 workflow:
```
- uses: doctena-org/octorules-sync@v1
id: plan
with:
config_path: config.yaml
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: "--doit"
checksum: ${{ steps.plan.outputs.checksum }}
```
### `phases`
以空格分隔的要同步的规则阶段列表。留空则同步配置文件中的所有阶段。用于针对特定的规则类型。
可用的阶段取决于配置的提供商。有关完整列表,请参阅每个提供商的 README:
[Cloudflare](https://github.com/doctena-org/octorules-cloudflare) (23 个阶段) |
[AWS WAF](https://github.com/doctena-org/octorules-aws) (4 个阶段) |
[Google Cloud Armor](https://github.com/doctena-org/octorules-google) (4 个阶段) |
[Azure WAF](https://github.com/doctena-org/octorules-azure) (3 个阶段) |
[Bunny.net](https://github.com/doctena-org/octorules-bunny) (4 个阶段)
默认 `""`(空字符串,所有阶段)。
### `zones`
以空格分隔的要同步的 zone 列表,留空则同步配置文件中的所有 zone。
默认 `""`(空字符串,所有 zone)。
### `lint`
在计划/同步之前运行 `octorules lint`?设置为 `"Yes"` 以启用。启用后,linter 将在计划/同步步骤之前运行。Lint 错误(退出代码 1)会阻止同步模式应用更改;警告则不会。
默认 `"No"`。
### `lint_severity`
要报告的最低 lint 严重级别:`"error"`、`"warning"` 或 `"info"`。
默认 `"warning"`。
### `lint_plan`
用于 Cloudflare lint 权限检查的 Plan 层级覆盖:`"free"`、`"pro"`、`"business"`、`"enterprise"`。非 Cloudflare 提供商会忽略此设置。
默认 `""`(默认为 `"enterprise"`)。
### `add_pr_comment`
当由 pull request 触发时,是否将计划作为评论添加?设置为 `"Yes"` 以启用。
启用后,此 action 将创建一个包含计划输出的单一 PR 评论,并在后续运行时**就地更新**(而不是每次都创建新评论)。
默认 `"No"`。
### `pr_comment_token`
如果您将 `add_pr_comment` 设置为 `"Yes"`,请提供一个要使用的 token。
**重要提示:** 不会自动注入任何 token — 您必须显式传递一个 token(例如 `${{ github.token }}`)。默认的 `github.token` 对于同仓库 PR 具有足够的权限。对于跨仓库或 fork PR,请使用具有 `pull_requests: write` scope 的 token。
默认 `""`(空字符串,当 `add_pr_comment` 为 `"Yes"` 时必须提供)。
### `audit`
在计划/同步之前运行 `octorules audit`(IP 重叠、IP 遮蔽、CDN 范围、zone 漂移分析)?设置为 `"Yes"` 以启用。启用后,审计结果将在 action 输出中报告。只有错误(退出代码 1)会阻止同步;警告(退出代码 2)会被报告,但不会阻止部署。
默认 `"No"`。
### `audit_checks`
要运行的以空格分隔的审计检查列表:`ip-overlap`、`ip-shadow`、`cdn-ranges`、`zone-drift`。留空则执行所有检查。
默认 `""`(所有检查)。
### `audit_severity`
最低审计严重级别:`"error"`、`"warning"` 或 `"info"`。控制显示哪些结果。默认值:`"warning"`。
### `audit_log`
写入同步结果的 JSON-lines 审计日志的路径。仅在 `doit` 为 `"--doit"`(同步模式)时使用。每一行都是一个包含同步操作详细信息的 JSON 对象(zone、阶段、action、结果)。可用于合规性和同步后分析。
默认 `""`(禁用)。
## 输出
### `plan`
来自 `octorules` 的计划更改输出。输出格式通过您的 octorules 配置文件中的 `manager.plan_outputs` 控制。同时也会写入到 `$GITHUB_WORKSPACE/octorules-sync.plan`。
### `log`
`octorules` 命令的日志输出。同时也会写入到 `$GITHUB_WORKSPACE/octorules-sync.log`。
### `exit_code`
`octorules` 命令的原始退出代码。可用于在后续步骤中进行分支控制:
| 模式 | 代码 | 含义 |
|------|------|---------|
| plan | `0` | 未检测到更改 |
| plan | `2` | 检测到更改 |
| plan | `1` | 错误 |
| sync | `0` | 成功应用 |
| sync | `1` | 错误 |
在后续步骤中使用的示例:
```
- name: Notify on changes
if: steps.octorules.outputs.exit_code == '2'
run: echo "Changes were detected"
```
### `checksum`
用于漂移保护的 SHA-256 计划校验和(仅限计划模式)。将此值通过 `checksum` 输入传递给后续的同步步骤,以确保状态在计划和应用之间没有发生漂移。在同步模式下运行或未发出校验和时为空。
### `lint_exit_code`
`octorules lint` 的退出代码:`0` = 干净,`1` = 错误,`2` = 仅有警告,空 = lint 已禁用。
### `lint_results`
Lint 结果文本。当 lint 被禁用或结果干净时为空。
### `audit_exit_code`
`octorules audit` 的退出代码:`0` = 干净,`1` = 错误,`2` = 仅有警告,空 = audit 已禁用。只有退出代码 `1`(错误)会阻止同步;警告会被报告,但不会阻止部署。
### `audit_results`
Audit 结果文本。当 audit 被禁用或结果干净时为空。
## 审计
当 `audit` 设置为 `"Yes"` 时,action 会在计划/同步步骤之前运行 `octorules audit`。审计结果将包含在 PR 评论中(如果已启用),并通过 `audit_exit_code` 和 `audit_results` 输出暴露出来。
- **计划模式**:会报告审计错误,但计划仍会运行,因此您可以同时看到审计结果和计划更改。如果审计发现错误,action 将在最后失败。
- **同步模式**:审计错误会**完全阻止**同步步骤 — 更改不会被应用。警告不会阻止同步。
## Linting
当 `lint` 设置为 `"Yes"` 时,action 会在计划/同步步骤之前运行 `octorules lint --exit-code`。Lint 结果将包含在 PR 评论中(如果已启用),并通过 `lint_exit_code` 和 `lint_results` 输出暴露出来。
- **计划模式**:会报告 lint 错误,但计划仍会运行,因此您可以同时看到 lint 问题和计划更改。如果 lint 发现错误,action 将在最后失败。
- **同步模式**:lint 错误会**完全阻止**同步步骤 — 更改不会被应用。警告不会阻止同步。
### Wirefilter 支持
在 lint Cloudflare 规则时,表达式由 Cloudflare 真正的 [wirefilter](https://github.com/cloudflare/wirefilter) 引擎解析,该引擎作为 `octorules-cloudflare` 的必需依赖项发布 — 无需额外的安装步骤。这可以捕获语法错误、未知或拼写的字段、类型不匹配、无效的运算符使用以及未知的函数名,而这些是仅靠名称启发式方法无法发现的。
非 Cloudflare 提供商(AWS WAF、Google Cloud Armor、Azure WAF、Bunny.net)包含其各自的表达式验证,不需要 wirefilter。
## Pull request 计划评论
要让此 action 将计划作为 PR 评论发布,请将您的 workflow 配置为:
1. 在 `pull_request` 事件上运行
2. 将 `add_pr_comment` 设置为 `"Yes"`
3. 提供一个 `pr_comment_token`
该 action 将创建一条评论,并在对同一个 PR 的后续推送中对其进行就地更新。评论去重使用一个隐藏的 HTML 标记 (``) 来查找和更新现有评论。
```
name: octorules-plan
on:
pull_request:
jobs:
plan:
name: Plan WAF rules changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
lint: 'Yes'
audit: 'Yes'
add_pr_comment: 'Yes'
pr_comment_token: '${{ github.token }}'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
```
## 完整 workflow 示例
一种常见的模式是在 pull request 时进行计划 (plan),并在合并到 main 分支时进行应用 (apply):
```
name: octorules-sync
on:
pull_request:
paths:
- 'rules/**'
- 'config.yaml'
push:
branches:
- main
paths:
- 'rules/**'
- 'config.yaml'
jobs:
plan:
if: github.event_name == 'pull_request'
name: Plan changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- uses: doctena-org/octorules-sync@v1
id: octorules
with:
config_path: config.yaml
lint: 'Yes'
audit: 'Yes'
add_pr_comment: 'Yes'
pr_comment_token: '${{ github.token }}'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
deploy:
if: github.event_name == 'push'
name: Deploy changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
```
## 高级:阶段过滤
要仅同步特定的规则阶段,请使用 `phases` 输入:
```
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
phases: 'cache_rules redirect_rules'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
```
## 高级:校验和漂移保护
该 action 会从 `octorules plan --checksum` 输出一个 `checksum`。将其传递给
后续的同步步骤,以确保状态在计划和应用之间没有发生漂移:
```
jobs:
plan:
name: Plan
runs-on: ubuntu-latest
outputs:
checksum: ${{ steps.plan.outputs.checksum }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- uses: doctena-org/octorules-sync@v1
id: plan
with:
config_path: config.yaml
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
deploy:
needs: plan
name: Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pip install -r requirements.txt
- uses: doctena-org/octorules-sync@v1
with:
config_path: config.yaml
doit: '--doit'
checksum: '${{ needs.plan.outputs.checksum }}'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
```
## 故障排除
### 在 PATH 上找不到 octorules
该 action 要求在运行之前安装 `octorules` 和提供商包。请在您的 workflow 中添加一个安装步骤:
```
# Cloudflare
- run: pip install octorules-cloudflare
# AWS WAF
- run: pip install octorules-aws
# Google Cloud Armor
- run: pip install octorules-google
# Azure WAF
- run: pip install octorules-azure
# Bunny.net
- run: pip install octorules-bunny
# 多个 providers
- run: pip install octorules-cloudflare octorules-aws
# 或使用 requirements.txt
- run: pip install -r requirements.txt
```
### 提供商 token / 无效 token 错误
确保您已为提供商凭证创建了仓库 secret,并将其作为环境变量传递。有关特定于提供商的示例,请参阅上面的 [Secrets](#secrets) 部分。引用环境变量的配置值必须使用 `env/` 前缀(例如 `token: env/CLOUDFLARE_API_TOKEN`)。
### 未找到配置文件
`config_path` 输入默认为仓库根目录中的 `config.yaml`。如果您的配置位于其他位置,请相应地设置 `config_path`。该路径是相对于仓库根目录(工作区的。
### PR 评论权限错误
如果 action 未能创建或更新 PR 评论,请检查:
1. 您是否通过 `pr_comment_token` 传递了有效的 token(例如 `${{ github.token }}`)。
2. 该 token 是否具有 `pull_requests: write` 权限。对于同仓库 PR,默认的 `github.token` 即可满足要求。
3. 对于 fork PR 或跨仓库 workflow,请使用具有适当 scope 的 Personal Access Token 或 GitHub App token。
## 贡献
欢迎贡献!
### 开发设置
1. Fork 并克隆仓库。
2. 安装开发依赖项:
# macOS
brew install shellcheck yamllint bats-core
# Debian / Ubuntu
apt-get install shellcheck yamllint bats
3. 运行完整的检查套件:
make
### 进行更改
1. 从 `main` 创建一个分支。
2. 进行更改。如果您修改了 `scripts/*.sh`,请在 `tests/` 中添加或更新相应的测试。
3. 在提交之前运行 linting 和测试:
make lint # yamllint + shellcheck
make test # bats tests/
4. 发起一个针对 `main` 的 pull request。
### 代码风格
- Shell 脚本遵循 [ShellCheck](https://www.shellcheck.net/) 建议。
- YAML 文件必须通过 `yamllint --no-warnings`。
- 在新脚本中使用 `set -euo pipefail`。
- 优先使用数组来构建命令(有关模式,请参见 `scripts/run.sh`)。
### 发布
发布过程是自动化的。推送一个 semver 标签 (`v1.2.3`) 以创建 GitHub Release。发布该 Release 会自动更新主版本标签 (`v1`)。
在打标签之前,请在 `[Unreleased]` 部分下使用您的更改更新 `CHANGELOG.md`。
## 许可证
octorules-sync 采用 [Apache License 2.0](LICENSE) 许可证。
标签:CDN, GitHub Actions, WAF, 自动化运维, 自动笔记, 逆向工具