OPA Authorization Policy
Overview
OPA Authorization Policy is an environment-level request authorization capability provided by CloudBase, built on top of the open-source policy engine Open Policy Agent (OPA) and the policy language Rego. By writing a piece of policy code in the CloudBase console, you can define unified access control rules for all HTTP API and HTTP Access Service requests in the entire environment.
CloudBase executes the policy on every incoming request, makes an "allow / deny" decision based on three categories of information — user identity, HTTP request, and environment context — and then forwards the request to the actual target resource.
User request
↓
CloudBase
↓
Build input (subject + request + cloudbase)
↓
Evaluate OPA policy
├─ allow = true and deny = false → allow → access actual resource
└─ deny = true → reject, return 403 + reason
By default, CloudBase ships a platform default policy for HTTP API and HTTP Access Service, covering the default allow / deny rules for various resources under different identities. See Appendix A: Platform Default Policy for the detailed rules.
User policies can be layered on top of the platform default policy:
- An
allowdefined in the user policy can open up requests denied by the platform default - A
denydefined in the user policy can reject requests allowed by the platform default (denytakes precedence overallow)
By tuning the user policy, you can flexibly and granularly define authorization rules based on HTTP requests, user identity, accessed resources, or any combination of conditions, achieving highly customizable permission control. With OPA policies, you can implement requirements such as:
- IP allowlist access control
- Read/write permissions by user identity
- Protection of admin backend APIs
- Different rules per access entry point
- ...
For complete examples, see Practical Cases.
Core Capabilities
| Capability | Description |
|---|---|
| Multi-condition authorization | Flexibly combine multiple dimensions such as user identity, request features, and environment information to achieve fine-grained access control |
| Unified policy entry | A single policy covers both HTTP API and HTTP Access Service (Cloud Function / CloudBase Run / Static Hosting, etc.) entry points, unifying public traffic governance |
| Traceable rejection reasons | When a request is denied, a human-readable reason can be returned to the caller for quick troubleshooting |
| Customize on top of platform defaults | The platform has built-in default allow/deny rules for each resource type; you only need to write rules to override what you want, no need to start from scratch |
| Standard Rego syntax | Built on the OPA open-source policy engine, using the widely adopted Rego policy language with a low learning curve and rich community resources |
Relationship with Other Security Capabilities
CloudBase provides multiple layers of security capabilities. The OPA Authorization Policy sits at the access control layer at the request entry, and works together with other capabilities to form a defense-in-depth system:
| Capability | Scope | Control Dimension | When to Use |
|---|---|---|---|
| OPA Authorization Policy | All HTTP API and HTTP Access Service requests in the environment | User + request + environment context | When you need complex condition combinations, request-level, programmable access control |
| Rate Limiting | Cloud Function, CloudBase Run | QPS (resource dimension / client dimension) | Anti-abuse, anti-overload |
| Static Hosting Security | Static Hosting resources | Referer / IP / QPS | Static resource hotlink protection |
| Trusted Origins | Client SDK calls | Domain allowlist | Restrict the source of SDK calls |
The OPA Authorization Policy and the capabilities above can be enabled simultaneously — a request first passes through trusted-origin checks and OPA policy evaluation, and then enters subsequent stages such as rate limiting.
Quick Start
The following is a minimal usable policy:
package authz.user
# Default deny
default allow := false
# Allow administrators to access /v1/ paths
allow if {
input.subject.auth_type == "administrator"
startswith(input.request.path, "/v1/")
}
# Forbid unauthenticated users from issuing DELETE
deny contains "DELETE requires authentication" if {
input.request.method == "DELETE"
input.subject.auth_type == "unauthenticated"
}
The startswith in the example is a Rego built-in function. For the full syntax and built-in function list, see the Rego language reference and the Rego built-in function reference. For security reasons, CloudBase only enables a whitelisted subset of these. See Appendix B for commonly disabled functions.
The policy input input is constructed by CloudBase on every request. Its full structure is shown below; for detailed field definitions, see Policy Context:
{
"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"
}
}
Decision matrix at a glance:
deny | allow | Final Result |
|---|---|---|
true | any | Deny |
false | true | Allow |
false | false | Deny |
Policy Context (input)
input is the only external data the policy can read. It always contains three top-level fields:
input.subject # Request subject (user)
input.request # Current HTTP request
input.cloudbase # CloudBase environment context
User Information (subject)
| Field | Type | Description |
|---|---|---|
user_id | string | C-end user ID; "" when not logged in |
auth_type | string | Built-in identity authentication type, see the table below; case-sensitive |
groups | []string | User roles associated with the request, corresponding to the groups field in the request JWT |
All possible values of auth_type:
| Value | Meaning |
|---|---|
administrator | Administrator |
internal | Internal user |
external | External user |
anonymous | Anonymously logged-in user |
unauthenticated | Not logged in / no AccessToken |
service_role | (Only present in PostgreSQL environments) service_role, super privileges |
anon | (Only present in PostgreSQL environments) anonymous role |
authenticated | (Only present in PostgreSQL environments) authenticated role |
Request Information (request)
| Field | Type | Description |
|---|---|---|
method | string | HTTP method, normalized to uppercase |
raw_host | string | Original Host header, not normalized |
host | string | Normalized Host (port removed, lower-cased) |
path | string | Request path, URL encoding preserved |
query | object<string, string> | URL query parameters; multi-value parameters joined by & |
client_ip | string | Client IP, may be "" / IPv4 / IPv6 |
header | object<string, array<string>> | Request headers, preserving multiple values |
header_map | object<string, string> | Request headers |
Difference between header and header_map:
header | header_map | |
|---|---|---|
| Value type | array<string> | string |
| Read as | input.request.header["X-Foo"][0] | input.request.header_map["X-Env-Id"] |
Header keys must be in HTTP Canonical form (e.g. X-Env-Id, Content-Type); lower-cased or all-uppercased keys are not readable. Sensitive headers such as Authorization / Cookie have been stripped by CloudBase and cannot be accessed by the policy.
Environment Information (cloudbase)
| Field | Type | Description |
|---|---|---|
env_id | string | Current environment ID |
region | string | Region of the environment, e.g. "ap-shanghai" |
entrypoint_type | string | Entry point type, see below |
resource_type | string | Resource type matched by the current request, see below |
Possible values of entrypoint_type:
| Value | Meaning |
|---|---|
tcbopenapi | HTTP API path, with domain {envid}.api.tcloudbasegateway.com |
tcbgateway | HTTP Access Service / CloudBase Run / Static Hosting / Cloud Storage and other HTTP Access Services. Default domains include .app.tcloudbase.com / .service.tcloudbase.com (HTTP Access Service), .tcloudbaseapp.com (Static Hosting), .tcb.qcloud.la (Cloud Storage), .run.tcloudbase.com (CloudBase Run), etc.; also includes custom domains bound to the above paths |
Possible values of resource_type:
| Resource | Identifier | Description |
|---|---|---|
| Cloud Storage | storages | Object storage operations |
| Cloud Function | functions | Cloud function invocation |
| CloudBase Run | cloudrun | CloudBase Run service access |
| Large Models | ai | AI large model access |
| AI Agent | aibot | AI agent service |
| Data Model | model | Data model management |
| Knowledge Base | knowledge | Knowledge base management |
| MySQL Access | rdb | MySQL database access |
Output: allow / deny
The policy must declare allow or deny (at least one) under package authz.user:
| Rule | Type | Form |
|---|---|---|
allow | bool | default allow := falseallow if { ... } |
deny | bool or set of string | deny if { ... } or deny contains "rejection reason" if { ... } |
deny supports two forms:
- Boolean form
deny if { ... }— block the request without returning a reason. - Set form
deny contains "msg" if { ... }— block the request and surface the message to the end user as:Access denied by policy. Reason: msg.
The engine evaluates each rule independently, and ultimately decides whether to allow the request based on the combined results of allow and deny.
Notes on Writing Policies
- Rego v1 is mandatory: there is no need to write
import rego.v1; deprecated v0 syntax (such asallow { ... }) will be rejected on save. - The package must be exactly
authz.user: any other package name will be rejected on save. - Policy size ≤ 2 KiB (including comments and blank lines).
- No more than 20 non-
defaultrules: eachallow if {...},deny if {...}, anddeny contains "msg" if {...}counts as one;defaultdeclarations do not count. denyreasons should not contain sensitive information: messages in thedenyset are returned to the end user, so avoid concatenating internal userIDs, SQL, tokens, etc.- Strict mode: OPA strict mode is enabled when saving policies; unused
imports and unused function parameters (other than wildcards) will be rejected. - Restricted built-in functions: this engine uses an allowlist; for commonly disabled functions, see Appendix B.
- Requests not evaluated by the OPA policy: internal CloudBase platform requests and Integration Center callback requests are not evaluated by the policy.
Practical Cases
Read/Write Permissions by User Identity
package authz.user
default allow := false
# Unauthenticated users are read-only
allow if {
input.subject.auth_type == "unauthenticated"
input.request.method in {"GET", "HEAD", "OPTIONS"}
}
# Authenticated / anonymous C-end users can read and write
allow if {
input.subject.auth_type in {"internal", "external", "anonymous"}
input.request.method in {"GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"}
}
# Administrators have no method restrictions
allow if input.subject.auth_type == "administrator"
Restrict Admin APIs to Administrators Only
package authz.user
default allow := false
# Non-admin APIs: allow all
allow if not startswith(input.request.path, "/admin/")
# Admin APIs: administrators only
allow if {
startswith(input.request.path, "/admin/")
input.subject.auth_type == "administrator"
}
IP Allowlist
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)
}
Allow HTTP API Access Only
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"
}
Role-based Control via JWT groups
package authz.user
default allow := false
# ops group: no method restrictions
allow if "ops" in input.subject.groups
# dev group: all methods except DELETE
allow if {
"dev" in input.subject.groups
input.request.method != "DELETE"
}
Appendix A: Platform Default Policy
The platform default policy makes decisions along three dimensions: path, resource type, and identity. User policies are layered on top: the user's allow can open up requests denied by default, and the user's deny can reject requests allowed by default (deny takes precedence over allow). In the tables below, ✅ means allowed by default, ❌ means denied by default.
The following identities are allowed by default for all paths and all resources, and are not repeated in the tables below:
- Not logged in (
unauthenticated): you must add adenyin the user policy to block them - PostgreSQL environment identities:
service_role,anon,authenticated
Resource types not listed in the tables below are allowed by default for all four identities: super-admin / internal user / external user / visitor.
HTTP API Default Policy
The HTTP API path is identified by: entrypoint_type == "tcbopenapi"
Module (resource_type) | Super-admin (administrator) | Internal (internal) | External (external) | Visitor (anonymous) |
|---|---|---|---|---|
CloudBase Run (cloudrun), Knowledge Base (knowledge) | ✅ | ❌ | ❌ | ❌ |
Large Models (ai) | ✅ | ✅ | ✅ | ❌ |
HTTP Access Service Default Policy
The HTTP Access Service path is identified by: entrypoint_type == "tcbgateway"
Module (resource_type) | Super-admin (administrator) | Internal (internal) | External (external) | Visitor (anonymous) |
|---|---|---|---|---|
Cloud Function (functions), Cloud Storage (storages), CloudBase Run (cloudrun) | ✅ | ✅ | ✅ | ❌ |
Appendix B: Disabled Built-in Functions
This engine uses an allowlist for built-in functions. Commonly disabled functions are listed below; for functions not in the table, refer to the validation result returned on save.
| Category | Disabled Functions |
|---|---|
| Outbound network | http.send, net.lookup_ip_addr, providers.aws.sign_req |
| Time | time.* |
| Regex | regex.*, re_match (use startswith / endswith / contains / glob.match instead) |
| JWT parsing | io.jwt.* |
| Encoding / decoding | base64.*, base64url.*, hex.*, urlquery.* |
| YAML | yaml.* (use json.* instead) |
| Reflection / metadata | opa.runtime, rego.metadata.*, rego.parse_module |
| Debugging | trace, print |
| Resource consumption | walk, net.cidr_expand, numbers.range, numbers.range_step, graph.*, graphql.*, strings.render_template |
| Certificates / keys | crypto.x509.*, crypto.parse_private_keys |
| Others | uuid.*, rand.intn, semver.*, units.*, json.patch, json.match_schema, json.verify_schema |
Next Steps
- Rate Limiting: QPS rate limiting for Cloud Function and CloudBase Run
- Static Hosting Security: Hotlink protection and IP allow/deny lists