在软件开发中,API Token 经常被当作一项简单的配置。

开发者需要调用云服务接口时,进入控制台创建一个 Token,把它放进环境变量,再通过 HTTP 请求发送给服务端。只要接口能够正常返回结果,这项配置似乎就完成了。

但随着自动化部署、CI/CD 和 AI Agent 的广泛使用,API Token 已经不只是开发者偶尔使用的访问凭据。

它可能长期保存在部署环境中,被定时任务调用,也可能交给具有自主规划能力的 Agent,用于创建云资源、修改配置或读取业务数据。

如果权限设置过宽,一次凭据泄漏就可能影响大量资源。即使没有发生泄漏,自动化程序自身的错误也可能导致超出预期的操作。

2026 年 11 月 6 日,Cloudflare 更新了 User API Token 的创建流程。

此次更新主要集中在管理界面:权限策略编辑更加直观,有效期预设和客户端 IP 地址限制被整合进创建流程,同时使 User API Token 与 Account API Token 的操作体验更加一致。

这并不是一项全新的身份认证协议,也没有改变 User API Token 的基本身份语义。

不过,它提供了一个很好的切入点,让我们重新审视一个经常被忽略的问题:

当越来越多的程序和 Agent 需要调用云服务时,应该如何设计 API 凭据的权限范围、使用期限和安全边界?

一、User API Token 与 Account API Token 的区别

理解 Cloudflare 此次更新,需要先明确两类凭据的身份模型。

User API Token 代表创建它的用户执行操作。

Account API Token 则属于账户级凭据,适合在支持的场景中为自动化工作负载提供独立于个人用户的身份。

这两类凭据虽然都可以用于 API 请求,但它们的管理主体和生命周期并不相同。

假设一个团队使用 Cloudflare Workers 部署应用。

开发者 A 负责日常开发,开发者 B 负责生产环境维护,CI/CD 系统负责在代码合并后自动部署。

如果部署流水线直接使用开发者 A 的 User API Token,那么这套自动化系统的访问能力就与 A 的用户身份关联起来。

这种方式在个人项目或短期测试中可能比较方便,但对于长期运行的团队自动化任务,需要考虑人员变动、权限调整和凭据管理责任。

如果 A 离开团队,或者管理员调整了他的权限,依赖该用户身份的自动化流程就可能受到影响。

相反,使用适合该场景的账户级凭据,可以使自动化身份与具体开发者分离。

不过,Account API Token 并不天然更加安全。

如果账户级凭据拥有过宽权限,泄漏后仍然可能造成严重影响。

真正重要的是让凭据身份与任务责任相匹配,并严格限制它能够访问的资源和操作。

可以将两类凭据的典型使用场景概括如下:

维度User API TokenAccount API Token
身份主体创建 Token 的用户所属账户
典型用途用户授权的 API 操作、个人自动化账户级自动化、团队工作负载
生命周期与用户身份及相关管理策略关联由账户管理流程控制
权限设计根据用户可执行的操作设置根据工作负载所需操作设置
主要风险个人身份与自动化流程耦合账户级凭据权限过宽

这里的表格用于说明身份设计上的区别,具体可用权限仍应以 Cloudflare 当前 API 文档和账户角色配置为准。

Cloudflare 在 11 月 6 日的公告中特别强调,User API Token 即使采用了与 Account API Token 更一致的创建界面,仍然代表创建它的用户。

这个细节非常重要。

界面统一并不意味着身份模型统一。

如果开发者仅根据控制台外观判断 Token 的权限性质,就可能误解其实际授权范围。

二、最小权限为什么是凭据安全的核心

API Token 的安全性通常涉及三个问题:

它能够执行什么操作?

它能够访问哪些资源?

它可以在什么条件下使用?

这三个问题分别对应操作权限、资源范围和访问约束。

例如,一个用于部署 Workers 的自动化任务,可能只需要修改指定应用的部署配置。

如果为它分配了整个账户的广泛管理权限,那么自动化程序就拥有了远超实际任务所需的能力。

这种设计在功能测试时通常不会暴露问题。

因为权限过宽往往不会阻止程序正常运行,反而可能让开发过程更加顺利。

真正的问题会在凭据泄漏、脚本错误或自动化程序被错误引导时出现。

假设一个部署 Agent 的目标只是更新测试环境中的 Worker。

如果它使用的 Token 同时拥有修改生产环境配置的权限,那么一次错误的资源选择就可能影响线上服务。

如果 Token 只能访问测试环境所需的资源,即使 Agent 出现操作错误,潜在影响也会受到限制。

这就是最小权限原则的实际意义。

它并不要求系统完全消除错误,而是尽量减少错误发生后能够影响的范围。

Cloudflare 此次更新使权限策略的创建和检查更加直观。

管理员可以在创建 Token 的过程中添加、编辑和删除权限策略块,并在提交前集中检查相关配置。

但管理界面的改善只是降低了配置难度。

最终是否符合最小权限原则,仍然取决于开发者是否准确理解任务需要哪些 API 操作。

对于复杂的自动化流程,可以先列出实际调用的 API,再根据每个接口的权限要求设计 Token。

例如,一个部署流程可能包含读取现有配置、上传新版本和查询部署状态三个步骤。

这些操作对应的权限未必完全相同。

如果系统还需要读取日志或修改路由,就应当明确这些能力是否属于同一个自动化任务。

不建议为了避免权限错误而直接赋予所有相关资源的最高权限。

更稳妥的方式是让不同职责使用不同凭据。

例如,部署任务使用部署凭据,监控任务使用只读凭据,涉及生产配置修改的操作则通过独立的审批流程执行。

这样做会增加一定的配置工作,但可以让凭据的用途更加明确。

对于 AI Agent,这一点尤其重要。

Agent 可以根据任务目标自主选择工具,并连续执行多个操作。

如果它能够调用的所有工具都共享一个高权限 Token,那么提示词中的错误理解、工具参数错误或不可信内容的干扰,都可能转化为真实的资源修改。

因此,Agent 的工具调用权限应当受到服务端约束,而不能只依赖自然语言指令。

三、有效期与 IP 限制如何影响实际安全性

除了权限范围,Cloudflare 此次还改进了 Token 创建过程中的有效期和客户端 IP 限制设置。

这两项功能看起来比较简单,但在实际工程中具有明确的作用。

有效期限制的是凭据可以持续使用的时间。

假设一个 Token 在创建后长期有效。如果它被意外写入日志、上传到公开仓库,或者保存在已经不再使用的开发设备中,潜在风险就可能长期存在。

如果 Token 设置了合理的到期时间,即使凭据没有及时撤销,其可使用时间也会受到限制。

不过,较短的有效期并不意味着越短越好。

对于人工操作,短期凭据通常比较容易管理。

但对于无人值守的定时任务,如果 Token 在没有轮换机制的情况下到期,就可能导致自动化流程突然失败。

因此,凭据有效期应当与轮换能力共同设计。

例如,一个每天执行的自动化任务,可以使用受控的凭据管理流程,在旧 Token 到期前完成新 Token 的创建、部署和验证。

轮换完成后,再撤销不再使用的旧凭据。

如果新凭据部署失败,系统还需要有明确的恢复方法,避免为了紧急修复而重新使用长期有效的高权限 Token。

客户端 IP 地址限制则提供了另一层约束。

例如,一个内部自动化服务只会从固定的出口 IP 地址访问 Cloudflare API。

管理员可以考虑将 Token 的使用范围限制在这些可信出口地址。

这样,即使 Token 被复制到其他网络环境中,也可能因为来源地址不符合限制而无法正常使用。

但 IP 限制不能替代身份认证。

如果攻击者已经控制了允许访问的主机,或者能够通过该主机发起请求,IP 限制就无法阻止相应操作。

此外,对于运行在动态网络环境中的任务,出口 IP 地址可能发生变化。

如果没有稳定的网络出口,过于严格的 IP 限制可能导致正常任务间歇性失败。

因此,IP 限制更适合具有明确网络边界的工作负载。

在设计凭据时,可以将这几项条件组合考虑:

API Token
    |
    +-- Identity
    |     User / Account
    |
    +-- Permissions
    |     Allowed operations
    |
    +-- Resources
    |     Allowed scope
    |
    +-- Expiration
    |     Valid time window
    |
    +-- Network restrictions
          Allowed client IPs

这是一张用于说明凭据约束关系的概念示意,并非 Cloudflare 内部权限计算流程图。

它强调的是:一个 Token 的实际访问能力不应仅由“是否持有正确字符串”决定。

即使凭据有效,也需要检查当前请求是否符合相应权限和使用条件。

四、实操:用 Python 验证最小权限策略

为了理解权限范围、有效期和来源地址限制之间的关系,可以编写一个独立的策略验证程序。

这个实验不需要 Cloudflare 账号,也不会调用真实 Cloudflare API。

我们将使用 Python 标准库建立一个简化模型,模拟不同自动化任务使用 Token 访问资源时的授权判断。

需要说明,这不是 Cloudflare 权限引擎的复现,也不代表其正式 API Token 配置格式。

实验只用于观察最小权限策略如何影响访问结果。

建议使用 Python 3.10 或更新版本。

创建文件 token_policy.py:

from dataclasses import dataclass
from datetime import datetime, timezone
from ipaddress import ip_address, ip_network


@dataclass(frozen=True)
class TokenPolicy:
    identity: str
    permissions: frozenset[str]
    resources: frozenset[str]
    expires_at: datetime
    allowed_networks: tuple[str, ...]


def authorize(
    policy: TokenPolicy,
    permission: str,
    resource: str,
    client_ip: str,
    now: datetime,
) -> bool:

    if now.tzinfo is None:
        raise ValueError(
            "now must be timezone-aware"
        )

    if policy.expires_at.tzinfo is None:
        raise ValueError(
            "expires_at must be timezone-aware"
        )

    if now >= policy.expires_at:
        return False

    if permission not in policy.permissions:
        return False

    if resource not in policy.resources:
        return False

    address = ip_address(client_ip)

    network_allowed = any(
        address in ip_network(network)
        for network in policy.allowed_networks
    )

    if not network_allowed:
        return False

    return True


if __name__ == "__main__":

    policy = TokenPolicy(
        identity="ci-deploy",
        permissions=frozenset({
            "worker:read",
            "worker:deploy",
        }),
        resources=frozenset({
            "staging-worker",
        }),
        expires_at=datetime(
            2026, 12, 1,
            tzinfo=timezone.utc,
        ),
        allowed_networks=(
            "192.0.2.0/24",
        ),
    )

    now = datetime(
        2026, 11, 6,
        tzinfo=timezone.utc,
    )

    cases = [
        (
            "worker:deploy",
            "staging-worker",
            "192.0.2.10",
        ),
        (
            "worker:deploy",
            "production-worker",
            "192.0.2.10",
        ),
        (
            "worker:delete",
            "staging-worker",
            "192.0.2.10",
        ),
        (
            "worker:deploy",
            "staging-worker",
            "198.51.100.10",
        ),
    ]

    for permission, resource, client_ip in cases:

        result = authorize(
            policy,
            permission,
            resource,
            client_ip,
            now,
        )

        print(
            permission,
            resource,
            client_ip,
            result,
        )

这里定义了一个名为 ci-deploy 的自动化身份。

它拥有两个教学用权限标识:

worker:read
worker:deploy

能够访问的资源只有:

staging-worker

并且要求请求来自 192.0.2.0/24 网络范围。

该网段属于文档示例地址范围,不代表真实生产网络。

执行:

python token_policy.py

根据程序逻辑,预期结果为:

worker:deploy staging-worker 192.0.2.10 True
worker:deploy production-worker 192.0.2.10 False
worker:delete staging-worker 192.0.2.10 False
worker:deploy staging-worker 198.51.100.10 False

第一组请求满足全部条件,因此允许访问。

第二组请求虽然使用了允许的操作,但目标资源是生产环境,不在授权范围内。

第三组请求访问了允许的资源,却使用了未授权的删除操作。

第四组请求的操作和资源均符合要求,但来源 IP 地址不在允许范围内。

这个实验展示了一个重要原则:

凭据是否有效,与某次具体操作是否获得授权,是两个不同的问题。

接下来可以使用 Python 标准库的 unittest 为它编写测试。

创建 test_token_policy.py:

import unittest

from datetime import datetime, timezone

from token_policy import TokenPolicy, authorize


class TokenPolicyTests(unittest.TestCase):

    def setUp(self):

        self.policy = TokenPolicy(
            identity="ci-deploy",
            permissions=frozenset({
                "worker:deploy",
            }),
            resources=frozenset({
                "staging-worker",
            }),
            expires_at=datetime(
                2026, 12, 1,
                tzinfo=timezone.utc,
            ),
            allowed_networks=(
                "192.0.2.0/24",
            ),
        )

        self.now = datetime(
            2026, 11, 6,
            tzinfo=timezone.utc,
        )

    def check(
        self,
        permission,
        resource,
        client_ip,
        now=None,
    ):

        return authorize(
            self.policy,
            permission,
            resource,
            client_ip,
            now or self.now,
        )

    def test_allowed(self):

        self.assertTrue(
            self.check(
                "worker:deploy",
                "staging-worker",
                "192.0.2.10",
            )
        )

    def test_wrong_resource(self):

        self.assertFalse(
            self.check(
                "worker:deploy",
                "production-worker",
                "192.0.2.10",
            )
        )

    def test_wrong_permission(self):

        self.assertFalse(
            self.check(
                "worker:delete",
                "staging-worker",
                "192.0.2.10",
            )
        )

    def test_wrong_network(self):

        self.assertFalse(
            self.check(
                "worker:deploy",
                "staging-worker",
                "198.51.100.10",
            )
        )

    def test_expired(self):

        expired_time = datetime(
            2026, 12, 2,
            tzinfo=timezone.utc,
        )

        self.assertFalse(
            self.check(
                "worker:deploy",
                "staging-worker",
                "192.0.2.10",
                expired_time,
            )
        )


if __name__ == "__main__":
    unittest.main()

执行:

python -m unittest -v

预期应当运行五项测试,分别检查正常授权、资源越界、操作越权、来源地址不匹配和凭据过期。

如果全部通过,测试结果会包含:

Ran 5 tests

OK

本次示例依据 Python 标准库接口编写,但没有在真实 Cloudflare 环境中执行,也没有完成本次独立代码运行验证。因此,上述输出属于根据代码逻辑推导的预期结果。

这个模型可以帮助开发者理解权限设计,但不能直接作为生产系统的鉴权组件。

真实系统还需要考虑 Token 的真实性验证、签名或凭据校验、资源层级关系、策略冲突以及并发配置更新。

尤其不能让客户端自行声明自己的权限集合,再把这些字段直接交给 authorize()。

权限信息必须来自可信的服务端配置或已经完成验证的身份系统。

五、AI Agent 接入云服务时,Token 应该怎样管理

随着 AI Agent 开始承担部署、测试和资源管理任务,API Token 的使用方式正在发生变化。

过去,开发者通常会明确编写每一个 API 调用。

例如,部署脚本可能只包含上传构建产物、更新 Worker 和检查状态三个固定步骤。

Agent 则可能根据任务目标动态决定调用顺序。

如果任务执行失败,它可能重新检查配置、修改参数或尝试其他工具。

这种灵活性有助于完成复杂任务,但也使权限边界更加重要。

假设一个 Agent 被要求修复测试环境中的部署失败。

如果它只能访问测试环境,即使推理过程出现偏差,也无法直接修改生产资源。

但如果它持有具有广泛管理权限的 Token,就可能在错误判断下修改不相关的配置。

因此,Agent 的权限设计不应以模型能力为依据,而应以具体任务需要执行的操作为依据。

对于具有明确职责的 Agent,可以为其分配独立凭据。

例如,代码分析 Agent 使用只读权限,部署 Agent 使用指定环境的部署权限,监控 Agent 使用日志读取权限。

如果某项操作需要更高权限,可以通过独立审批流程完成授权,而不是让所有 Agent 长期共享一个高权限 Token。

另外,还需要考虑凭据是否应该直接暴露给 Agent。

一种更稳妥的设计是让 Agent 调用受控工具,由工具服务在后端持有真正的 API Token。

Agent 只能提交经过约束的操作参数,工具服务负责执行权限检查。

例如:

AI Agent
    |
    | Request:
    | Deploy staging-worker
    |
    v
Controlled Tool Service
    |
    | Validate:
    | - allowed operation
    | - allowed resource
    | - approval state
    |
    v
Cloudflare API

这种结构能够减少模型直接接触原始凭据的机会。

但它并不自动消除所有风险。

如果工具服务没有严格验证参数,或者允许 Agent 自由指定任意资源,那么权限问题仍然存在。

工具接口应当尽量提供明确的操作,而不是将完整的高权限 API 请求能力直接暴露给 Agent。

例如,与其提供一个可以发送任意 Cloudflare API 请求的工具,不如提供一个只允许部署指定测试 Worker 的接口。

这类设计通常会牺牲一定的灵活性,但能够显著降低权限误用的范围。

对于需要长期运行的 Agent,还应当考虑凭据轮换和任务恢复。

如果 Token 在任务执行期间到期,Agent 应当能够识别授权失败,并通过受控流程恢复,而不是反复使用已经失效的凭据。

同时,系统需要保留必要的审计记录,记录哪个 Agent、通过哪个工具、在什么时间请求了什么操作。

这些记录应避免包含完整 Token、敏感请求头或不必要的私人数据。

六、从创建 Token 到管理自动化身份

Cloudflare 11 月 6 日的更新主要改善了 User API Token 的创建体验。

它没有引入新的凭据类型,也没有改变用户级 Token 的身份归属。

但对于开发者而言,这次更新值得关注的原因,是它把权限编辑、有效期和来源地址限制放到了更加明确的位置。

API Token 的安全管理不应该只发生在凭据泄漏之后。

在创建凭据时,就需要明确它代表谁、用于什么任务、能够访问哪些资源,以及应该在什么时候失效。

当 Token 被用于 CI/CD、定时任务或 AI Agent 时,还需要进一步考虑自动化身份与个人身份的分离、凭据轮换、权限审计和错误恢复。

如果一个自动化任务只需要读取数据,就不应长期持有写入权限。

如果一个 Agent 只负责测试环境,就不应因为部署方便而获得生产环境的管理能力。

如果凭据可以通过受控工具间接使用,就没有必要让模型直接读取原始密钥。

这些原则并不依赖某一家云服务提供商。

无论使用 Cloudflare、其他云平台还是自建 API 服务,最小权限、有限有效期和清楚的授权边界都是值得坚持的工程实践。

随着自动化程序承担越来越多真实操作,凭据管理也需要从简单的配置工作,逐步转变为软件系统安全设计的一部分。


参考资料

[1] Cloudflare Developers. User API tokens have a redesigned creation experience. 2026-11-06.

https://developers.cloudflare.com/changelog/post/2026-11-06-user-api-token-redesign/

[2] Cloudflare Developers. Create API tokens.

https://developers.cloudflare.com/fundamentals/api/get-started/create-token/

[3] Cloudflare Developers. API token permissions.

https://developers.cloudflare.com/fundamentals/api/reference/permissions/

[4] Python Documentation. ipaddress — IPv4/IPv6 manipulation library.

https://docs.python.org/3/library/ipaddress.html

[5] Python Documentation. unittest — Unit testing framework.

https://docs.python.org/3/library/unittest.html


附录:实验适用范围

本文中的 Python 程序用于演示最小权限策略的基本判断过程。

建议使用 Python 3.10 或更新版本,不需要安装第三方依赖。

程序使用文档示例 IP 地址,不包含真实凭据,也不会连接 Cloudflare API。

实验没有实现真实 Token 认证、密钥存储、撤销检查、权限继承或并发策略管理。

所有运行结果均为根据代码逻辑给出的预期输出,不应当视为已经完成的 Cloudflare 平台验证。

实际配置 Cloudflare User API Token 时,应根据官方文档选择所需权限、资源范围、有效期和客户端 IP 限制,并在测试环境中确认访问结果。

Logo

更多推荐