关于 alibabacloud-cfw-internet-firewall-protect
用于查询和管理 Alibaba Cloud Cloud Firewall 的公网 IP 防护。支持按范围批量更改、按条件筛选资产及管理自动防护,并在流程中安排确认和状态检查。
主要功能
- 01查询防护状态与资产
- 02将资产结果导出为 CSV
- 03按筛选条件启用或停用防护
- 04按条件在本地筛选资产
- 05查询或修改自动防护设置
适用场景
- 01审计已防护和未防护的 IP
- 02导出防护资产清单用于报告
- 03更改指定区域或资产的防护
- 04为名称符合条件的资产启用防护
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aliyun/ alibabacloud-aiops-skills --skill alibabacloud-cfw-internet-firewall-protect安装后在 Claude Code 中输入/alibabacloud-cfw-internet-firewall-protect确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-errors.mdcli-installation-guide.mdmanifest.jsonram-policies.mdregion-ids.mdresource-types.mdscripts/auto-protect.shcommon.shfw-switch.shvalidate-cli.sh详细介绍
操作路由
识别用户意图,然后路由到匹配的执行路径:
| 用户意图 | 执行路径 |
|---|---|
| 查询资产防护状态、列出资产、查看哪些 IP 已受保护/未受保护 | fw-switch.sh query,并使用筛选条件 |
| 将资产防护状态导出为 CSV/Excel,以供审计或报告使用 | fw-switch.sh query --all-pages --export-csv <file> |
| 列出新发现的资产(最近 1 小时/1 天/7 天) | fw-switch.sh query --new-resource-tag "discovered in 7 days" |
| 为特定 IP 启用/停用防护 | fw-switch.sh enable/disable --ips "ip1,ip2,..." |
| 为某个区域启用/停用防护 | fw-switch.sh enable/disable --regions "cn-hangzhou,..." |
| 为某种资源类型启用/停用防护(例如,所有 ECS 公网 IP) | fw-switch.sh enable/disable --resource-types "EcsPublicIP,..." |
| 为所有 IPv4 或 IPv6 资产启用/停用防护 | fw-switch.sh enable/disable --ip-version 4 或 6 |
| 组合筛选条件(例如,北京区域 + ECS 公网 IP + IPv4) | fw-switch.sh enable/disable --regions cn-beijing --resource-types EcsPublicIP --ip-version 4 |
| 一次性为所有公网 IP 启用/停用防护 | fw-switch.sh enable-all/disable-all --yes |
| 为符合某项条件(名称、标签等)的资产启用防护 | 多步操作:查询 → 筛选 → 按 IP 列表启用(见下文) |
| 查询新资产的自动防护设置 | auto-protect.sh query |
| 修改自动防护设置 | auto-protect.sh modify --enable/--disable <types> --yes |
参数可以自由组合。--ips、--regions、--resource-types 和 --ip-version 选项可以配合使用——至少提供其中一项。
条件式多步工作流
当用户的筛选条件无法直接传递给 API 时(例如,“为所有名称包含 Dify 的实例启用防护”),应编排多步工作流:
-
查询:使用可用筛选条件(状态、区域、资源类型)运行
fw-switch.sh query。获取完整结果集——筛选会在第 2 步本地进行,因此截断分页会导致匹配项被悄然遗漏。请参阅“查询资产”中的分页指南(先使用--page-size 1000,只有在超出该范围时才使用--all-pages)。 -
筛选:根据用户的条件(实例名称匹配、特定属性等)筛选返回的
Assets数组。每项资产的关键字段:Name(实例名称)、InternetAddress(公网 IP)、IntranetAddress(内网 IP)、ProtectStatus、ResourceType、RegionID、BindInstanceId、BindInstanceName。对于名称条件,应以不区分大小写的子字符串形式同时匹配
Name和BindInstanceName:Name可能为空(例如,某些 NAT 网关资产返回Name="",而BindInstanceName包含真实名称),因此仅依赖其中一个字段会遗漏资产。 -
影响预览(阶段 1):向用户展示匹配资产摘要以供确认(遵循“启用/禁用防护工作流”中的摘要格式)。
-
执行(阶段 2):将匹配资产的
InternetAddress值收集为逗号分隔列表,然后调用fw-switch.sh enable/disable --ips "ip1,ip2,..."。 -
验证(阶段 3):轮询状态以确认操作已完成(遵循“启用/禁用防护工作流”中的轮询策略)。
第 2 步(筛选结果)的边缘情况处理:
| 筛选结果 | 阶段 2 操作 |
|---|---|
| 存在匹配资产,部分或全部资产的 ProtectStatus=closed | enable --ips "all_matched_ips"(包括开启和关闭的资产——API 具有幂等性) |
| 存在匹配资产,且全部资产的 ProtectStatus=open | enable --ips "all_matched_ips"(仍需调用——遵循幂等规则) |
| 没有资产符合筛选条件 | 仅当用户自己的请求提供了更宽泛的维度(例如其指定的区域、资源类型或 IP 版本)时,才回退到该维度——例如 enable --regions <region> --resource-types <type>。如果用户没有提供任何此类维度,则报告零匹配结果,并说明没有进行任何更改:这就是已完成的工作流,而不是跳过了阶段 2。绝不能为了弥补零匹配结果而升级为 enable-all/disable-all——用户的条件是范围限制,扩大范围会影响他们明确排除的资产。 |
此模式适用于任何基于条件的操作——名称匹配、标签筛选、基于状态的批量操作等。
检查 CLI 环境
在运行此处的任何内容之前,请生成下文“可观测性”中所述的 session-id——validate-cli.sh --check-permission 已经会调用真实的 CFW API,因此也需要 session-id。通过 SKILL_SESSION_ID={session-id} bash scripts/validate-cli.sh --check-permission 传入它,可以确保从第一次调用开始,每次调用都能归因于此会话。
预检查:需要 Aliyun CLI >= 3.3.3。 使用 aliyun version 验证。3.3.3 是插件生态系统的最低版本——较旧版本无法加载 Cloudfw 插件,因此此 Skill 中的每条命令都会失败。如果版本低于此版本,请先安装或升级:
# First install, or major upgrade
/bin/bash -c "$(curl -fsSL --connect-timeout 10 --max-time 120 https://aliyuncli.alicdn.com/setup.sh)"
# Routine self-update (supported from CLI 3.3.5)
aliyun upgrade --yes
# Alternative on macOS
brew install aliyun-cli # or: brew upgrade aliyun-cli
aliyun upgrade 会写入 CLI 的安装目录,因此当二进制文件位于 /usr/local/bin 等系统路径时,需要提升权限。完整的安装和故障排查说明请参阅 references/cli-installation-guide.md。
CLI 版本符合要求后,验证环境的其余部分:
bash scripts/validate-cli.sh --check-permission
检查结果并采取相应措施:
cli_installed= false → 使用上述某条命令安装 CLI,或运行--install-guide查看完整指南cli_version_ok= false → CLI 版本低于 3.3.3,使用aliyun upgrade --yes升级auto_plugin_install=unknown(通常如此)→ CLI 未提供读取此设置的方式,因此脚本会将其报告为 unknown,而不进行猜测。这是本地便利开关,并非前置条件:如果希望自动安装缺失的插件,可运行一次aliyun configure set --auto-plugin-install true;不要在每次运行时都将unknown视为需要处理的故障。credential_valid= false → 未配置配置文件;请在此会话之外使用aliyun configure配置一个,然后重新运行。CLI 会从默认凭证链解析凭证——此 Skill 本身不会读取或处理凭证。permission_check= false → 凭证无效或已过期,或该身份缺少yundun-cloudfirewall:DescribeAssetList权限;请在 RAM 控制台中检查凭证状态,并参阅references/ram-policies.md
注意:credential_valid 仅表示 aliyun configure list 中是否存在配置文件。凭证的实际有效性由 permission_check 验证,该检查会调用真实的 CFW 业务 API——无效或已过期的凭证会在此处验证失败。
显示完整安装指南:
bash scripts/validate-cli.sh --install-guide
环境检查通过后,请确保插件为最新版本:
aliyun plugin update
API 版本说明: Cloudfw 使用 CLI 插件模式(
aliyun-cli-cloudfw)。API 版本由插件内部管理(实际版本:2017-12-07)。调用 CFW 命令时请使用默认调用方式,不要传入--version。插件会拒绝任何外部版本覆盖,并报错unchecked version。common.sh中的call_cfw_api函数已按此要求设计,不会包含--version。
可观测性
此 Skill 发出的每次云 API 调用都应归属于一个 Agent 会话,以便云端日志能将所有操作关联到单次执行。为每次调用添加会话范围的 User-Agent。
UA 模板:
--user-agent "AlibabaCloud-Agent-Skills/alibabacloud-cfw-internet-firewall-protect/{session-id} skill-version/{skill-version}"
- Skill 的
name字段固定为:alibabacloud-cfw-internet-firewall-protect。 {session-id}是占位符——运行命令前,请将其替换为当前会话标识符;切勿发送字面文本{session-id}。{skill-version}是references/manifest.json中version字符串的占位符,这是唯一可接受的来源。请在首次云调用前读取该值:如果文件不存在、JSON 无效,或version为空或不是字符串,请停止并报告错误,不要猜测。编造或借用的版本会错误标记云端遥测数据;并且由于同一会话中的每次调用都共用一个版本,错误读取一次就会破坏整个会话的关联性。
session-id 生成规则:
- 每个会话只生成一次,在首次 CLI 调用时生成;后续调用中不要重新生成。
- 格式:32 个字符的小写十六进制字符串(128 位),例如
3f2a9c1b4d5e6f708192a3b4c5d6e7f8。一种可移植的生成方式是python3 -c "import uuid; print(uuid.uuid4().hex)"。 - 在整个会话的每次调用中重复使用同一个 session-id,以便所有操作共用一个可关联的标识符。
标志如何传递到 API:
脚本会从 SKILL_SESSION_ID 读取 session-id,从 references/manifest.json 获取 {skill-version},并自行在每次云 API 调用中追加 --user-agent,因此调用脚本时请传入 session-id:
SKILL_SESSION_ID={session-id} bash scripts/fw-switch.sh query --region cn-hangzhou
SKILL_SESSION_ID={session-id} bash scripts/auto-protect.sh modify --enable "EIP" --yes
SKILL_SESSION_ID 是必填项:不带会话归属信息的调用无法追溯到此会话,因此脚本会拒绝该调用,并在联系任何 API 之前以状态码 1 退出,报错 SKILL_SESSION_ID is not set。无法读取清单中的版本时也一样。请在首次调用此 Skill 时设置 session-id,不要在未设置的情况下重试。
如果你直接调用 aliyun CLI,而不是通过这些脚本调用云 API,则必须在每条云 API 命令中自行添加该标志。本地 CLI 命令(configure、plugin、version、upgrade、help)不接受 --user-agent——不要为这些命令添加该标志。
RAM 策略与权限处理
Cloud Firewall 的 RAM Action 前缀是 yundun-cloudfirewall,不是 cloudfw。请阅读 references/ram-policies.md 获取完整权限列表。
[MUST] 权限失败处理: 执行期间的任何时候,如果任何命令或 API 调用因权限错误而失败,请按以下流程处理:
- 阅读
references/ram-policies.md,获取此 SKILL 所需的完整权限列表- 使用
ram-permission-diagnoseskill 引导用户申请所需权限- 暂停操作,等待用户确认所需权限已授予
参数确认
执行任何命令或 API 调用之前,请确认以下可由用户自定义的参数符合用户的实际意图。不要默默替换默认值,也不要臆造用户未提及的值:
fw-switch.sh enable / disable:
| 参数 | 必填 | 说明 | 省略时的默认值 |
|---|---|---|---|
--ips | 以下四项中至少指定一项 | 显式指定的公网 IP 列表 | 不限制 IP——所有符合其他筛选条件的 IP |
--regions | 以下四项中至少指定一项 | 地域筛选条件,例如 cn-hangzhou | 所有地域——扩大范围 |
--resource-types | 以下四项中至少指定一项 | 资产类型筛选条件,例如 EcsPublicIP | 所有资源类型——扩大范围 |
--ip-version | 以下四项中至少指定一项 | 4 或 6 | IPv4 和 IPv6 |
--member-uid | 可选 | 成员账号 UID | 管理账号本身 |
enable / disable 在四个范围维度都未指定时会拒绝调用 — 脚本会在本地检查,并以退出码 1 退出,显示 At least one of --ips, --regions, --resource-types, --ip-version is required,不会调用任何 API。因此,空筛选条件并不等同于“全部”。 |
fw-switch.sh enable-all / disable-all:
| 参数 | 必填 | 描述 | 省略时的默认值 |
|---|---|---|---|
--instance-id | 可选 | CFW 实例 ID | 账户的默认实例 |
这两个命令不接受任何范围参数:--ips、--regions、--resource-types、--ip-version 和 --member-uid 都会被拒绝,并显示 Unknown option(退出码为 1)。按设计,其范围是整个账户 — 这是唯一需要向用户确认的事项。如果用户想要更窄的范围,请改用带筛选条件的 enable / disable。
auto-protect.sh modify:
| 参数 | 必填 | 描述 | 省略时的默认值 |
|---|---|---|---|
--enable / --disable | 必须指定其中一个,或指定 --config | 要开启 / 关闭的资源类型,以逗号分隔 | 不更改这些类型 |
--config | 与上述参数互斥 | 用于完整替换自动防护映射的 JSON | — |
--config 会在一次提交中替换整个映射:JSON 中未出现的资源类型会被设置为不启用自动防护。对于要求启用 EIP 和 NAT 自动防护的用户,传入 --config '{"EIP":true,"NatEIP":true}' 会悄无声息地关闭其他约 26 种类型。用户只指定部分类型时,不要直接将其部分列表传给 --config — 应先运行 auto-protect.sh query,将用户的请求合并到返回的映射中,再提交完整 JSON;或者使用增量模式(--enable / --disable),由其自行执行读取、合并和写入。无论采用哪种方式,都要在报告中说明提交的映射中哪些类型仍为 false。
用户 JSON 中非正式的类型名称(eip、ecs、slb)不是 API 值。将每个键传给命令前,都要通过 references/resource-types.md 确认其对应值:映射键区分大小写,而且 API 不会将无法识别的键作为错误返回 — 它只会导致无法保护任何资源。
自动防护在账户的默认范围内配置,且不接受区域参数 — 没有需要向用户确认的按区域配置选项。如果用户要求将自动防护限制在某个区域,请告知他们 API 不支持可读取的区域级配置,并提供 fw-switch.sh enable --regions <region>,以启用该区域内现有资产的防护。
fw-switch.sh query(只读,因此无需确认):
| 参数 | 必填 | 描述 | 省略时的默认值 |
|---|---|---|---|
--region / --status / --resource-type / --ip-version / --member-uid | 可选 | 单值筛选条件 | 此维度不应用筛选 |
--search | 可选 | IP 或实例 ID 子字符串 | 无 |
--new-resource-tag | 可选 | 资产发现时间范围:discovered in 1 hour / 1 day / 7 days | 无 |
--page / --page-size | 可选 | 仅用于分页,绝不影响更改范围 | 第 1 页,每页 10 条 |
只确认确实尚未确定的事项。用户已在请求中明确说明的参数,按定义即已确认 — 应在第 1 阶段的影响预览中重述,而不是再次询问。
需要用户决定的参数,是用户未指定且会扩大范围的参数 — 对于 enable / disable,省略区域或资源类型意味着“匹配其余筛选条件的全部”。不要暂停并询问,而要在第 1 阶段的预览中明确说明这一解释(资产数量及区域分布),让用户了解实际影响范围,并由“确认与 --yes 标志”中所述的确认流程处理决策。enable-all / disable-all 没有需要确定的此类参数:其范围始终是整个账户,因此预览本身就是范围说明。
参数确认绝不会覆盖非交互式执行规则。在 Agent 模式下,Phase 1 预览仅供参考,
--yes即为确认——不要与用户额外进行一轮往返确认,也绝不要在 Phase 2 和 Phase 3 完成前停止。
查询资产
bash scripts/fw-switch.sh query [options]
可用筛选条件:--region、--status(open/closed/opening/closing)、--resource-type、--search(IP 或实例 ID)、--ip-version(4/6)、--member-uid、--new-resource-tag。每个筛选条件仅接受一个值。
--new-resource-tag 根据资产发现时间筛选,而非用户定义的标签。它仅接受三个值:discovered in 1 hour、discovered in 1 day、discovered in 7 days。当用户询问新发现或最近添加的资产时使用此筛选条件。
对于多地域或多资源类型查询,DescribeAssetList API 仅支持单值筛选。请按地域或资源类型分别并行调用,然后合并结果。例如:若要查询 cn-hangzhou 和 cn-beijing 的 EcsPublicIP 资产,请分别调用 fw-switch.sh query --region cn-hangzhou --resource-type EcsPublicIP 和 fw-switch.sh query --region cn-beijing --resource-type EcsPublicIP。
分页:--page(默认值为 1)、--page-size(默认值为 10)。检查响应中的 TotalCount,以确定是否还有更多页面。API 接受较大的 --page-size(已知 1000 可用),因此最多约有一千个公网 IP 的账户可以通过单次调用完整获取——请先尝试 --page-size 1000,因为这样可以完全避免分页。仅当 TotalCount 超过单页容量时才使用 --all-pages;--all-pages 会遍历所有页面并返回合并后的单个结果,且需要 python3 来合并结果。
响应会返回包含 Assets 数组的原始 API JSON。每项资产包含:InternetAddress、IntranetAddress、ProtectStatus、ResourceType、RegionID、Name、BindInstanceId、BindInstanceName、ResourceInstanceId、IpVersion、MemberUid。
请以易读的格式向用户呈现结果。对于 ProtectStatus:open = 受保护,closed = 未受保护,opening = 正在启用,closing = 正在停用。
导出查询结果
对于用户需要资产保护状态电子表格的安全审计或报告场景:
bash scripts/fw-switch.sh query --status open --all-pages --export-csv ./protected-assets.csv
--export-csv <file> 会为每项资产写入一行,包含上述所有字段。文件采用带 BOM 的 UTF-8 编码,因此可直接在 Excel 中打开,并正确显示中文实例名称——无需单独转换为 .xlsx。请将其与 --all-pages 结合使用,否则只会导出当前页面。
使用 --export-csv 时,stdout 会输出导出摘要(exported_file、row_count),而非完整资产 JSON。请向用户报告文件路径和行数;只有在需要内容进行进一步分析时才读取 CSV。
目标目录必须已存在——脚本不会创建目录,且路径不可写时会以状态码 1 退出。
启用 / 禁用保护工作流
所有启用 / 禁用 / 全部启用 / 全部禁用操作都遵循三阶段工作流:阶段 1 影响预览 → 阶段 2 执行 → 阶段 3 结果验证。确认是阶段 1 中的一个关卡,如何通过该关卡取决于执行模式 — 请参阅下文的“确认与 --yes 标志”。跳过任何阶段都可能导致意外更改或未经验证的结果。
此工作流仅适用于 fw-switch.sh 保护开关。auto-protect.sh modify 有自己的三步工作流,且不包含轮询 — 请参阅“自动保护设置 → 修改设置”。
⚠️ 强制要求:非交互式执行规则 以 Agent(非交互模式)运行时,
--yes表示用户已明确确认。你必须无条件完成全部三个阶段:
- 阶段 1 显示受影响资产数为 0 → 仍须执行阶段 2 和阶段 3。不要停止。
- 阶段 1 显示所有资产都已处于期望状态 → 仍须执行阶段 2 和阶段 3。不要停止。
- 绝不要仅在阶段 1 后终止工作流。完成阶段 2 和阶段 3 之前,绝不要输出“无需操作”。
- 无论阶段 1 的结果如何,在所有执行路径中,阶段 1 → 阶段 2 → 阶段 3 的顺序都必须无条件执行。
**范围边界:**此规则禁止跳过用户所要求范围内的阶段 2 — 它绝不授权扩大该范围。当目标集来自用户提供的条件(实例名称、标签等),且没有任何匹配项时,就没有范围内的目标可供操作;报告未匹配到目标是正确的终止状态。请参阅“条件式多步工作流”中的零匹配行。
确认机制和 --yes 标志
--yes 是脚本级安全联锁,不是面向用户的提示。这里涉及两件不同的事,切勿混为一谈:
- Phase 1 中的确认门槛:交互模式下由用户满足,非交互模式下由 Agent 自行满足。
--yes标志:调用方必须在具有破坏性的命令中传入的 CLI 参数。脚本不会提示,也不会读取标准输入。
具体哪些命令接受 --yes——该标志仅适用于标记为 Required 的两行:
| 命令 | --yes | 原因 |
|---|---|---|
fw-switch.sh query、auto-protect.sh query | 不接受 | 只读 |
fw-switch.sh enable / disable | 不接受 | 限定于明确指定的 IP/区域/类型/版本筛选条件 |
fw-switch.sh enable-all / disable-all | 必需 | 会影响账户中的所有公网 IP |
auto-protect.sh modify | 必需 | 会更改账户范围的自动防护策略 |
“不接受”比“可选”更严格:向这些命令传入 --yes 会中止执行,并显示 [ERROR] Unknown option: --yes,退出码为 1,且不会调用任何 API。因此,只有两条 Required 命令需要传入 --yes,不要出于防范而在其他命令中添加它。
需要 --yes 却未传入时,脚本会输出 {"success": false, "error_code": "NotConfirmed", ...},并以退出码 1 退出,且不会执行任何写入操作——不会更改任何内容。(auto-protect.sh modify 会先读取当前配置,因此停止前可能会发起一次只读 API 调用。)这是预期的安全行为,但也意味着非交互运行时如果忘记传入 --yes,将不会完成任何操作。作为 Agent,请在正常执行 Required 命令时传入 --yes,不要将其视为需要等用户再次确认后才传入的参数。
预览时有一点需要注意:--dry-run 的处理先于安全联锁,因此即使没有 --yes,enable-all --dry-run 也会打印命令预览并以 0 退出。成功的 dry-run 无法证明 --yes 有效——实际调用时仍需传入它。
另一个注意事项仅适用于 auto-protect.sh modify:其增量形式(--enable / --disable)无法在读取当前配置前显示合并后的配置,因此该命令的 --dry-run 确实会实际调用 DescribeResourceTypeAutoEnable。因此,与其他云调用一样,它需要 SKILL_SESSION_ID;如果未设置,就会在打印任何预览前以退出码 1 退出,并显示 SKILL_SESSION_ID is not set。只有 --config --dry-run 是纯本地操作,因为完整替换无需读取当前配置。每次调用(包括 dry-run)都传入 session-id,即可避免纠结这一区别。
阶段 1:影响预览
执行前,查询将受影响的资产,并以便于用户理解的方式进行摘要:
- enable 操作:查询
--status closed,并使用相同的筛选维度,显示将获得防护的资产 - disable 操作:查询
--status open,并使用相同的筛选维度,显示将失去防护的资产 - enable-all:查询
--status closed,显示所有当前未受防护的资产 - disable-all:查询
--status open,显示所有当前受防护的资产
预览查询采用与“查询资产”相同的单次获取方式:--page-size 1000 可通过一次调用获取完整结果集,从而准确统计数量和区域分布。只有当 TotalCount 超过单页返回的数量时,才进行分页(或使用 --all-pages)。
向用户总结结果:
- 如果资产总数 ≤ 5:列出全部资产(IP、实例名称、区域、资源类型)
- 如果资产总数 > 5:列出 3 个代表性示例,再按区域分布总结其余资产
示例格式:
This operation will enable firewall protection for the following 45 unprotected public IPs:
1. 47.96.xx.xx (ECS instance web-server-01, cn-hangzhou, EcsPublicIP)
2. 120.55.xx.xx (NAT gateway nat-prod, cn-hangzhou, NatEIP)
3. 39.108.xx.xx (ECS instance api-gateway, cn-beijing, EcsPublicIP)
...and 42 more public IPs across cn-hangzhou(25), cn-beijing(12), cn-shanghai(5).
Confirm execution?
对于 disable 和 disable-all,还要额外警告:关闭防护意味着流量将不再经过 Cloud Firewall,访问控制策略和入侵检测将停止工作。
三种操作具有较大的影响范围,预览是唯一能揭示影响范围的机会——enable-all、disable-all 以及任何 disable 操作。因此,对于这些操作,必须在 内容中披露阶段 1 的信息,而不能只在表单中披露。请在阶段 2 之前的消息中包含全部内容:
- 用文字说明范围:对于
enable-all/disable-all,说明“此账户下的每个公网 IP”;对于disable,说明确切的筛选条件; - 说明预览查询得到的受影响资产数量;如果数量超过 5,还要说明区域分布;
- 对于两种
disable操作,明确说明上述失去防护的后果。
在 Agent 模式下,这项披露相当于交互式确认提示——它会让操作过程在对话记录中可供审查。完成披露后继续执行;不要将其改成问题并等待回复。
然后根据执行模式满足确认要求:
- 交互模式(由人类回复):继续阶段 2 之前,等待用户明确确认。
- 非交互模式 / Agent 模式:上述预览仅供参考。不要等待输入——直接进入阶段 2,并在需要确认的命令中传入
--yes。
在 Agent 模式下,用户说“先看看有哪些,确认没问题再开启”不会改变这一要求。用户想要的是在任何内容发生变化之前查看受影响的资产,而阶段 1 预览正是为此准备的——提供预览,说明接下来将执行什么,然后执行。若将其理解为“停下来等我回复”,任务就会无法完成,而这恰恰不是用户要求的结果。
有两种情况例外,此时你必须停下来询问:
- 用户明确指定了交互环节。“如果有多个候选,请先列出并让我确认后再继续”、“先问我再改”、“列出来我看过再执行”——这不是常规的确认流程,而是关于如何执行任务的指示。列出候选项、提出问题,然后等待回复。
- 请求中缺少关键值,且无法安全推断。“帮我关闭几个公网 IP 的防护”没有说明 IP、区域、资源类型或 IP 版本,因此无法预览操作范围,也没有安全的默认假设。应询问目标是什么,而不是自行选择范围;在这里猜测,可能会导致关闭用户从未提及的资产的防护。
与上一段的区别在于是谁要求暂停:用户想查看预览,并不等于提出问题;而明确要求“先问我”或缺少操作范围,则意味着需要暂停。
第 2 阶段:执行
确认条件满足后,运行实际的启用/禁用命令。如果使用基于条件的 IP 列表进行预览查询,请通过 --ips 传入收集到的 IP。
⚠️ 强制要求:幂等执行规则 即使第 1 阶段显示所有目标资产都已处于所需状态(例如,启用时全部为
open,或找到 0 个未受保护的资产),你仍必须执行启用/禁用命令。该 API 具有幂等性,对已受保护的资产调用是安全的,并会返回成功。请勿根据当前状态或零计数结果跳过第 2 阶段。错误行为示例:
- “所有资产都已受保护,无需操作” → 错误,仍必须调用 API
- “未找到未受保护的资产,跳过执行” → 错误,仍必须调用 API
第 3 阶段:结果验证
执行后,轮询资产状态以验证操作是否生效:
-
初始等待:休眠 5 秒
-
查询:使用与第 1 阶段相同的范围筛选条件(地域、资源类型、IP 列表、IP 版本、成员 UID)运行
fw-switch.sh query,但移除--status筛选条件。然后读取每个资产的ProtectStatus,统计已达到目标状态的数量,以及仍处于opening/closing状态的数量。此处保留
--status closed会导致结果反转:启用成功后,就不再有任何资产处于closed状态,因此查询会返回空集——这会被解读为“没有任何状态转换”,但实际上所有资产都已完成转换。保留状态筛选条件时,空结果表示的是成功,而非失败。移除筛选条件即可彻底消除这种歧义。 -
自适应轮询:如果并非所有资产都已完成状态转换:
- 每隔 5 秒轮询一次
- 预计:每 20 个资产约需 5 秒
- 轮询总时长最多为 30 秒
-
报告结果,使用相同的摘要格式(示例 + 数量):
- 全部完成转换:“✓ 完成。已为所有 45 个公网 IP 启用防火墙防护。”
- 30 秒内部分完成:“38/45 个资产已完成。7 个仍在进行中(状态:opening)。请查看云防火墙控制台以确认最终状态。”
- 超时:“已等待 30 秒。12 个资产尚未完成状态转换。大规模变更可能需要更长时间——请查看云防火墙控制台以确认。”
预期状态转换:
- 启用 →
closed→opening→open - 禁用 →
open→closing→closed
将 opening/closing 视为“进行中”——操作已被接受,但尚未完成。
启用 / 禁用防护
按 IP、地域、资源类型或 IP 版本筛选
bash scripts/fw-switch.sh enable [options]
bash scripts/fw-switch.sh disable [options]
选项:--ips、--regions、--resource-types、--ip-version、--member-uid、--dry-run。
至少需要一个筛选维度。传入的维度将按 AND 关系组合,省略的维度则不受限制——因此,单独使用 --regions cn-hangzhou 会涵盖该地域内的所有资源类型和两个 IP 版本,而 --regions cn-hangzhou --resource-types EcsPublicIP 则会将范围缩小到该地域内的 ECS 公网 IP。各维度可以自由组合:
# Single dimension
bash scripts/fw-switch.sh enable --ips "1.2.3.4,5.6.7.8"
bash scripts/fw-switch.sh enable --ip-version 6
# Combined dimensions
bash scripts/fw-switch.sh enable --regions "cn-beijing" --resource-types "EcsPublicIP" --ip-version 4
使用 --dry-run 在执行前预览 CLI 命令。用户提供了多个 IP 或组合筛选条件时,建议使用此选项,以便核对参数。
references/resource-types.md 将用户实际使用的产品名称(例如 负载均衡)映射为准确的 API 值;references/region-ids.md 将地域名称(例如 华北2)映射为地域 ID。传入筛选条件前请查阅这两个文件,因为看似合理但实际不存在的值会被拒绝,而不会自动更正。
所有公网 IP
bash scripts/fw-switch.sh enable-all --yes [--instance-id <id>]
bash scripts/fw-switch.sh disable-all --yes [--instance-id <id>]
这些操作会影响账户下的所有公网 IP。必须传入 --yes:否则脚本会以 NotConfirmed(退出代码 1)退出,且不会调用任何 API。在非交互式(Agent)模式下,--yes 视为用户已默认确认——传入该参数前不要等待用户明确输入。
对于这些操作,影响预览尤为重要——继续操作前,务必始终运行阶段 1,向用户准确展示将影响多少资产。
⚠️ 强制要求:enable-all / disable-all 的幂等执行规则 即使阶段 1 显示没有未受保护的资产(enable-all 时所有资产都已为
open),或没有受保护的资产(disable-all 时所有资产都已为closed),你仍必须执行该命令。不要输出“所有资产均已处于目标状态,无需操作”后就停止——这样会跳过阶段 2 和阶段 3。
自动保护设置
查询当前设置
bash scripts/auto-protect.sh query
返回一个 ResourceTypeAutoEnable 映射,显示哪些资源类型已启用自动保护(此类新资产将自动受到保护)。
修改设置
自动保护设置变更遵循独立的三步工作流。它不是用于保护开关的轮询工作流:配置变更没有 opening / closing 中间状态,因此无需轮询。
- 预览——运行
auto-protect.sh query,向用户展示请求的类型当前哪些为true/false,也就是实际会发生哪些变更。 - 执行——使用
--yes运行auto-protect.sh modify(见下方强制规则)。无论预览显示什么,都始终运行。 - 验证——运行一次
auto-protect.sh query,并报告请求类型的最终状态。不要使用sleep,也不要循环轮询。如果某个类型尚未显示为请求的状态,请报告观察到的值,而不是盲目重试——重复写入不会改变结果。
增量模式(推荐):
bash scripts/auto-protect.sh modify --enable "EIP,NatEIP" --disable "SlbEIP" --yes
脚本会读取当前配置,合并变更,然后提交完整配置。这样可以避免意外覆盖其他设置。
⚠️ 强制要求:auto-protect modify 的幂等执行规则 当用户请求启用某些资源类型时,无论当前配置显示什么,你都必须调用
auto-protect.sh modify --enable <types> --yes。
- 即使
auto-protect.sh query显示请求的类型已经为true,也仍要执行 modify 命令。该 API 调用具有幂等性且安全。- 不要仅根据查询结果就断定“无需修改”或跳过 modify。
- 错误行为示例:
- 查询显示
EcsPublicIP: true→“已启用,无需操作”→ 错误,仍必须调用 modify- 查询显示所有请求的类型都已启用 →“配置已处于目标状态,跳过”→ 错误,仍必须调用 modify
完整配置模式:
bash scripts/auto-protect.sh modify --config '{"EIP":true,"NatEIP":false,...}' --yes
使用 --dry-run 可在应用前预览合并后的配置——使用 --enable / --disable 时,此预览会从 API 读取当前配置,因此需要 SKILL_SESSION_ID(参见“确认和 --yes 标志”中的第二条注意事项)。执行时必须使用 --yes——否则脚本会以 NotConfirmed(退出代码 1)退出,且配置保持不变。在非交互式(Agent)模式下,将其作为常规执行的一部分传入。
多账号操作
--member-uid <uid> 用于操作成员账号的资产,但只有针对资产的命令接受此参数:
| 命令 | --member-uid |
|---|---|
fw-switch.sh query | 支持 |
fw-switch.sh enable / disable | 支持 |
fw-switch.sh enable-all / disable-all | 不接受(Unknown option,退出码为 1) |
auto-protect.sh query / modify | 不接受(Unknown option,退出码为 1) |
当用户在管理账号下管理多个账号时,请询问他们要操作哪个账号,并在接受此参数的命令中传入成员 UID。对于成员账号的资产,要实现整账号范围的效果,请使用 enable --regions ... --member-uid <uid>,而不是无法指定成员账号的 enable-all。自动防护设置按账号配置——请切换配置文件或凭据,为成员账号配置自动防护。
处理错误
API 调用失败时,脚本会输出包含 error_code 和 error_message 的 JSON 错误,并在 stderr 中提供诊断建议。常见情况:
ErrorInstanceOpenIpNumExceed/ErrorGeneralInstanceSpecFull:防护配额或实例规格已达到上限——建议升级 CFW 版本。ErrorBandwidthPenalty:因带宽超量触发限制——建议等待或联系支持团队。ErrorInstanceStatusNotNormal:实例可能未付费或处于异常状态——请检查 CFW 控制台。ErrorParamsNotEnough:启用/禁用至少需要一个筛选维度。脚本会先在本地进行检查(退出码为 1,不会调用 API),因此如果遇到此错误,说明检查被绕过了——请重新检查传入的筛选条件。ErrorAuthentication/NoPermission:凭据或权限问题——请运行validate-cli.sh并检查references/ram-policies.md。
完整错误代码参考请参阅 references/api-errors.md。
脚本参考
| 脚本 | 用途 | 关键参数 |
|---|---|---|
fw-switch.sh query | 查询资产和防护状态 | --region、--status、--resource-type、--search、--ip-version、--member-uid、--new-resource-tag、--page、--page-size、--all-pages、--export-csv |
fw-switch.sh enable | 启用防护(灵活筛选) | --ips、--regions、--resource-types、--ip-version、--member-uid |
fw-switch.sh disable | 禁用防护(灵活筛选) | 同 enable |
fw-switch.sh enable-all | 启用所有公网 IP 防护 | --instance-id、--yes |
fw-switch.sh disable-all | 禁用所有公网 IP 防护 | --instance-id、--yes |
auto-protect.sh query | 查询自动防护配置 | (无) |
auto-protect.sh modify | 修改自动防护配置 | --enable、--disable、--config、--yes |
validate-cli.sh | 检查 CLI 和凭据 | --check-permission |
所有脚本都支持 --dry-run 和 --help。退出码:0 = 成功,1 = 参数错误,2 = API 错误。
--dry-run 会预览功能性参数(API 操作,以及决定要更改哪些内容的筛选条件)。执行时,call_cfw_api 还会附加每次调用都相同、无需审核的基础设施标志——请求/连接超时设置,以及上文所述的 --user-agent 可观测性标签。
底层切换 API 还支持自己的服务端 DryRun 预检查标志,以及用于保证幂等性的 ClientToken。这些脚本有意不提供这两项功能:--dry-run 始终是本地命令预览(上文提到的只读例外除外);启用/禁用失败后重试是安全的,无需令牌,因为切换 API 按目标状态保证幂等。请勿尝试通过脚本传入 --DryRun 或 --ClientToken——它们会被拒绝,并返回 Unknown option。