mcpField
A
alibabacloud-cfw-internet-firewall-protect

alibabacloud-cfw-internet-firewall-protect

github.com/aliyun安全281129 次安装1 天前更新
代码仓库

关于 alibabacloud-cfw-internet-firewall-protect

用于查询和管理 Alibaba Cloud Cloud Firewall 的公网 IP 防护。支持按范围批量更改、按条件筛选资产及管理自动防护,并在流程中安排确认和状态检查。

主要功能

  1. 01查询防护状态与资产
  2. 02将资产结果导出为 CSV
  3. 03按筛选条件启用或停用防护
  4. 04按条件在本地筛选资产
  5. 05查询或修改自动防护设置

适用场景

  1. 01审计已防护和未防护的 IP
  2. 02导出防护资产清单用于报告
  3. 03更改指定区域或资产的防护
  4. 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.md
cli-installation-guide.md
manifest.json
ram-policies.md
region-ids.md
resource-types.md
scripts/
auto-protect.sh
common.sh
fw-switch.sh
validate-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 的实例启用防护”),应编排多步工作流:

  1. 查询:使用可用筛选条件(状态、区域、资源类型)运行 fw-switch.sh query。获取完整结果集——筛选会在第 2 步本地进行,因此截断分页会导致匹配项被悄然遗漏。请参阅“查询资产”中的分页指南(先使用 --page-size 1000,只有在超出该范围时才使用 --all-pages)。

  2. 筛选:根据用户的条件(实例名称匹配、特定属性等)筛选返回的 Assets 数组。每项资产的关键字段:Name(实例名称)、InternetAddress(公网 IP)、IntranetAddress(内网 IP)、ProtectStatus、ResourceType、RegionID、BindInstanceId、BindInstanceName。

    对于名称条件,应以不区分大小写的子字符串形式同时匹配 Name 和 BindInstanceName:Name 可能为空(例如,某些 NAT 网关资产返回 Name="",而 BindInstanceName 包含真实名称),因此仅依赖其中一个字段会遗漏资产。

  3. 影响预览(阶段 1):向用户展示匹配资产摘要以供确认(遵循“启用/禁用防护工作流”中的摘要格式)。

  4. 执行(阶段 2):将匹配资产的 InternetAddress 值收集为逗号分隔列表,然后调用 fw-switch.sh enable/disable --ips "ip1,ip2,..."。

  5. 验证(阶段 3):轮询状态以确认操作已完成(遵循“启用/禁用防护工作流”中的轮询策略)。

第 2 步(筛选结果)的边缘情况处理:

筛选结果阶段 2 操作
存在匹配资产,部分或全部资产的 ProtectStatus=closedenable --ips "all_matched_ips"(包括开启和关闭的资产——API 具有幂等性)
存在匹配资产,且全部资产的 ProtectStatus=openenable --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 调用因权限错误而失败,请按以下流程处理:

  1. 阅读 references/ram-policies.md,获取此 SKILL 所需的完整权限列表
  2. 使用 ram-permission-diagnose skill 引导用户申请所需权限
  3. 暂停操作,等待用户确认所需权限已授予

参数确认

执行任何命令或 API 调用之前,请确认以下可由用户自定义的参数符合用户的实际意图。不要默默替换默认值,也不要臆造用户未提及的值:

fw-switch.sh enable / disable:

参数必填说明省略时的默认值
--ips以下四项中至少指定一项显式指定的公网 IP 列表不限制 IP——所有符合其他筛选条件的 IP
--regions以下四项中至少指定一项地域筛选条件,例如 cn-hangzhou所有地域——扩大范围
--resource-types以下四项中至少指定一项资产类型筛选条件,例如 EcsPublicIP所有资源类型——扩大范围
--ip-version以下四项中至少指定一项4 或 6IPv4 和 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 阶段:结果验证

执行后,轮询资产状态以验证操作是否生效:

  1. 初始等待:休眠 5 秒

  2. 查询:使用与第 1 阶段相同的范围筛选条件(地域、资源类型、IP 列表、IP 版本、成员 UID)运行 fw-switch.sh query,但移除 --status 筛选条件。然后读取每个资产的 ProtectStatus,统计已达到目标状态的数量,以及仍处于 opening/closing 状态的数量。

    此处保留 --status closed 会导致结果反转:启用成功后,就不再有任何资产处于 closed 状态,因此查询会返回空集——这会被解读为“没有任何状态转换”,但实际上所有资产都已完成转换。保留状态筛选条件时,空结果表示的是成功,而非失败。移除筛选条件即可彻底消除这种歧义。

  3. 自适应轮询:如果并非所有资产都已完成状态转换:

    • 每隔 5 秒轮询一次
    • 预计:每 20 个资产约需 5 秒
    • 轮询总时长最多为 30 秒
  4. 报告结果,使用相同的摘要格式(示例 + 数量):

    • 全部完成转换:“✓ 完成。已为所有 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 中间状态,因此无需轮询。

  1. 预览——运行 auto-protect.sh query,向用户展示请求的类型当前哪些为 true / false,也就是实际会发生哪些变更。
  2. 执行——使用 --yes 运行 auto-protect.sh modify(见下方强制规则)。无论预览显示什么,都始终运行。
  3. 验证——运行一次 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。

评论

支持 Markdown