跳到主要内容

OPA 鉴权策略


概述

OPA 鉴权策略是云开发提供的 环境级请求鉴权能力,基于开源策略引擎 Open Policy Agent (OPA) 和策略语言 Rego 构建。通过在云开发控制台编写一段策略代码,可以为整个环境的 HTTP APIHTTP 访问服务 请求定义统一的访问控制规则。

云开发会在每次收到请求时执行策略,根据 用户身份、HTTP 请求、环境上下文 三类信息做出"放行 / 拦截"决策,再将请求转发到实际调用的资源。

用户请求

云开发

构造 input(subject + request + cloudbase)

执行 OPA 策略评估
├─ allow = true 且 deny = false → 放行 → 访问实际资源
└─ deny = true → 拒绝,返回 403 + 原因

默认情况下,云开发为 HTTP API 和 HTTP 访问服务内置一套平台默认策略,覆盖各类资源在不同身份下的默认放通与拒绝规则,具体策略规则见 附录 A:平台默认策略

用户策略可在平台默认策略之上进行追加调整:

  • 用户策略中定义的 allow(放通)可放开被平台默认拒绝的请求
  • 用户策略中定义的 deny (拒绝)可拒绝被平台默认放通的请求(deny 优先级高于 allow)

通过用户策略的调整,可灵活、细粒度地定义基于 HTTP 请求、用户身份、访问资源或多种条件组合的鉴权规则,实现高度可定制的权限管控。通过编写 OPA 策略,可实现下列需求:

  • IP 白名单访问控制
  • 按用户身份控制读写权限
  • 保护管理后台接口
  • 按访问入口执行不同规则
  • ...

关于完整实现示例,请参考 实战案例

核心能力

能力说明
多条件组合鉴权可基于用户身份、请求特征、环境信息等多维度条件灵活组合鉴权规则,实现细粒度访问控制
统一策略入口同一份策略同时覆盖 HTTP API 和 HTTP 访问服务(云函数/云托管/静态托管等)入口,统一管控公网流量
拒绝原因可溯源拒绝请求时可向调用方返回可读的拒绝原因,便于快速排查权限问题
在平台默认策略基础上定制平台已内置各资源类型的默认放通/拒绝规则,你只需编写策略调整需要覆盖的规则,无需从零开始
支持标准 Rego 语法基于 OPA 开源策略引擎,使用通用的 Rego 策略语言,学习成本低,社区资源丰富

与其他安全能力的关系

云开发提供了多层安全能力,OPA 鉴权策略位于请求入口的 访问控制 层,与其他能力协作形成防护体系:

能力作用域控制维度何时选用
OPA 鉴权策略环境内所有 HTTP APIHTTP 访问服务 请求用户 + 请求 + 环境上下文需要复杂条件组合、基于请求级别、可编程的访问控制
限频设置云函数、云托管QPS(资源维度 / 客户端维度)防刷、防过载
静态托管安全配置静态托管资源Referer / IP / QPS静态资源防盗链
安全来源客户端 SDK 调用域名白名单限制 SDK 调用来源
提示

OPA 鉴权策略与上述能力可同时启用——请求会先通过安全来源校验与 OPA 策略评估,再进入限频等后续环节。

快速开始

以下为一段最小可用策略:

package authz.user

# 默认拒绝
default allow := false

# 管理员访问 /v1/ 路径放行
allow if {
input.subject.auth_type == "administrator"
startswith(input.request.path, "/v1/")
}

# 未认证用户禁止 DELETE
deny contains "DELETE requires authentication" if {
input.request.method == "DELETE"
input.subject.auth_type == "unauthenticated"
}

示例中的 startswith 是 Rego 内建函数。完整语法与内建函数清单见 Rego 语言参考Rego 内建函数列表;出于安全考虑,CloudBase 仅启用其中的一个白名单子集,常见禁用函数见附录 B

策略输入 input 由云开发在每次请求时构造,完整结构如下,字段详细定义请参考 策略上下文:

{
"subject": {
"user_id": "c-user-123",
"auth_type": "administrator",
"groups": ["developer"]
},
"request": {
"method": "GET",
"raw_host": "env-xxx.api.tcloudbasegateway.com",
"host": "env-xxx.api.tcloudbasegateway.com",
"path": "/v1/functions/foo",
"query": {"page": "1"},
"client_ip": "10.1.2.3",
"header": {"X-Env-Id": ["env-xxx"]},
"header_map": {"X-Env-Id": "env-xxx"}
},
"cloudbase": {
"env_id": "env-xxx",
"region": "ap-shanghai",
"entrypoint_type": "tcbopenapi",
"resource_type": "functions"
}
}

决策矩阵速查:

denyallow最终结果
true任意拒绝
falsetrue允许
falsefalse拒绝

策略上下文(input)

input 是策略可读取的唯一外部数据,固定包含三个顶层字段:

input.subject # 请求主体(用户)
input.request # 当前 HTTP 请求
input.cloudbase # CloudBase 环境上下文

用户信息(subject)

字段类型说明
user_idstringC 端用户 ID;未登录为 ""
auth_typestring内置身份认证类型,见下表;区分大小写
groups[]string请求关联的用户角色,对应请求 JWT 中的 groups 字段

auth_type 的全部取值:

含义
administrator管理员
internal内部用户
external外部用户
anonymous匿名登录用户
unauthenticated未登录 / 无 AccessToken
service_role(仅使用 PostgreSQL 环境存在)service_role,超级权限
anon(仅使用 PostgreSQL 环境存在)匿名角色
authenticated(仅使用 PostgreSQL 环境存在)已认证角色

请求信息(request)

字段类型说明
methodstringHTTP 方法,已统一为大写
raw_hoststring原始 Host 请求头,未经规整
hoststring规整后的 Host(去除端口、统一小写)
pathstring请求路径,保留 URL 编码
queryobject<string,string>URL query 参数;多值参数以 & 拼接
client_ipstring客户端 IP,可能为 "" / IPv4 / IPv6
headerobject<string,array<string>>请求头,保留多值
header_mapobject<string,string>请求头

headerheader_map 的差别:

headerheader_map
值类型array<string>string
读法input.request.header["X-Foo"][0]input.request.header_map["X-Env-Id"]

Header key 必须使用 HTTP Canonical 形式(如 X-Env-IdContent-Type),小写或全大写均无法读取。Authorization / Cookie 等敏感头已被云开发剔除,策略无法访问。

环境信息(cloudbase)

字段类型说明
env_idstring当前环境 ID
regionstring环境所属地域,如 "ap-shanghai"
entrypoint_typestring接入入口类型,见下
resource_typestring当前请求命中的资源类型,见下

entrypoint_type 取值:

含义
tcbopenapiHTTP API 链路,域名为 {envid}.api.tcloudbasegateway.com
tcbgatewayHTTP 访问服务 / 云托管 / 静态托管 / 云存储等 HTTP 访问服务,默认域名包括 .app.tcloudbase.com / .service.tcloudbase.com(HTTP 访问服务)、.tcloudbaseapp.com(静态托管)、.tcb.qcloud.la(云存储)、.run.tcloudbase.com(云托管) 等;也包括为上述链路绑定的自定义域名

resource_type 取值:

资源标识标识说明
云存储storages对象存储操作
云函数functions云函数调用
云托管cloudrun云托管服务访问
大模型aiAI 大模型接入
AI 智能体aibotAI 智能体服务
数据模型model数据模型管理
知识库knowledge知识库管理
MySQL 访问rdbMySQL 数据库访问

输出:allow / deny

策略需在 package authz.user 下声明 allowdeny,至少其一:

规则类型写法
allowbooldefault allow := false
allow if { ... }
denyboolset of stringdeny if { ... }deny contains "拒绝原因" if { ... }

deny 支持两种写法:

  • 布尔模式 deny if { ... } — 拦截,不返回原因。
  • 集合模式 deny contains "msg" if { ... }— 拦截,并把消息回显给终端用户:Access denied by policy. Reason: msg

引擎独立求值每条规则,最终根据 allowdeny 的结果决定是否放行。


策略编写注意点

  • 强制 Rego v1:无需写 import rego.v1;v0 已废弃语法(如 allow { ... })在保存时会被拒绝。
  • package 必须精确为 authz.user:不符合要求的包名在保存时均会被拒绝。
  • 策略大小 ≤ 2 KiB(含注释和空行)。
  • default 规则数 ≤ 20 条:每个 allow if {...}deny if {...}deny contains "msg" if {...} 各算一条;default 声明不计入。
  • deny 原因不应包含敏感信息deny 集合中的消息会回显给终端用户,避免拼接内部 userID、SQL、token 等内容。
  • 严格模式:保存策略时启用 OPA strict mode,未使用的 import 与未使用的函数参数(非通配符)会被拒绝。
  • 可用的内建函数受限:本引擎采用白名单机制,常见的被禁用函数见附录 B
  • 不会经过 OPA 策略评估的请求:云开发平台内部请求和集成中心回调请求不会经过策略评估。

实战案例

按用户身份控制读写权限

package authz.user

default allow := false

# 未认证用户只能读
allow if {
input.subject.auth_type == "unauthenticated"
input.request.method in {"GET", "HEAD", "OPTIONS"}
}

# 已认证 / 匿名 C 端用户可读写
allow if {
input.subject.auth_type in {"internal", "external", "anonymous"}
input.request.method in {"GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"}
}

# 管理员不限方法
allow if input.subject.auth_type == "administrator"

管理接口仅限管理员调用

package authz.user

default allow := false

# 非管理接口:全部放行
allow if not startswith(input.request.path, "/admin/")

# 管理接口:仅管理员
allow if {
startswith(input.request.path, "/admin/")
input.subject.auth_type == "administrator"
}

IP 白名单

package authz.user

default allow := false

office_cidrs := ["10.0.0.0/8", "192.168.0.0/16"]

allow if {
some cidr in office_cidrs
net.cidr_contains(cidr, input.request.client_ip)
}

仅允许 HTTP API 访问

package authz.user

default allow := false

allow if input.cloudbase.entrypoint_type == "tcbopenapi"

deny contains "this env only accepts openapi traffic" if {
input.cloudbase.entrypoint_type == "tcbgateway"
}

按 JWT groups 做角色控制

package authz.user

default allow := false

# ops 组:不限方法
allow if "ops" in input.subject.groups

# dev 组:除 DELETE 外允许
allow if {
"dev" in input.subject.groups
input.request.method != "DELETE"
}

附录 A:平台默认策略

平台默认策略基于链路资源类型身份三个维度做出决策。用户策略在此基础上追加调整:用户的 allow 可放开被默认拒绝的请求,用户的 deny 可拒绝被默认放通的请求(deny 优先于 allow)。下表中,✅ 表示平台默认放通,❌ 表示平台默认拒绝。

以下身份在所有链路、所有资源下平台均默认放通,不在下表中重复列出:

  • 未登录(unauthenticated):需在用户策略中追加 deny 才会被拦截
  • PostgreSQL 环境身份:service_roleanonauthenticated
信息

下表中未列出的资源类型,代表平台对超管 / 内部用户 / 外部用户 / 访客四类身份均默认放通

HTTP API 默认策略

提示

HTTP API 链路标识为:entrypoint_type == "tcbopenapi"

业务模块(resource_type)超管(administrator)内部用户(internal)外部用户(external)访客(anonymous)
云托管(cloudrun)、知识库(knowledge)
大模型(ai)

HTTP 访问服务默认策略

提示

HTTP 访问服务链路标识为:entrypoint_type == "tcbgateway"

业务模块(resource_type)超管(administrator)内部用户(internal)外部用户(external)访客(anonymous)
云函数(functions)、云存储(storages)、云托管(cloudrun)

附录 B:被禁用的内建函数

本引擎对内建函数采用白名单机制,常见的被禁用函数如下;不在表内的函数请以保存时的校验结果为准。

类别被禁用的函数
网络外联http.sendnet.lookup_ip_addrproviders.aws.sign_req
时间time.*
正则regex.*re_match(改用 startswith / endswith / contains / glob.match)
JWT 解析io.jwt.*
编解码base64.*base64url.*hex.*urlquery.*
YAMLyaml.*(改用 json.*)
反射 / 元数据opa.runtimerego.metadata.*rego.parse_module
调试traceprint
资源消耗walknet.cidr_expandnumbers.rangenumbers.range_stepgraph.*graphql.*strings.render_template
证书 / 密钥crypto.x509.*crypto.parse_private_keys
其他uuid.*rand.intnsemver.*units.*json.patchjson.match_schemajson.verify_schema

下一步