- Updated: March 20, 2026
- 5 min read
Enforcing Zero‑Trust Access to the OpenClaw Rating API Edge with Cloudflare Access and OPA
# Enforcing Zero‑Trust Access to the OpenClaw Rating API Edge with Cloudflare Access and OPA
*Published by the UBOS team – a step‑by‑step guide that brings together the UBOS Zero‑Trust guide, the Cloudflare Workers deployment tutorial, and the OPA‑Istio hardening guide.*
—
## Overview
In this article we will build a **Zero‑Trust edge** for the **OpenClaw Rating API** using three proven building blocks:
1. **UBOS Zero‑Trust guide** – the foundational security model and the UBOS CLI commands to provision the edge.
2. **Cloudflare Workers** – a lightweight edge runtime that terminates Cloudflare Access authentication and forwards the request to the API.
3. **OPA‑Istio** – policy‑as‑code enforcement that validates the identity, role, and request attributes before the request reaches the service.
The result is a fully‑protected API that only authorized users can call, with audit‑ready policies and automatic revocation.
—
## Prerequisites
– An active UBOS account with the **OpenClaw** service installed.
– A Cloudflare account with a domain pointing to the UBOS edge (e.g., `api.openclaw.ubos.tech`).
– `kubectl` and `helm` installed locally.
– `opa` CLI (`opa`) and `istioctl` installed.
– Basic knowledge of YAML and Bash.
—
## 1. Prepare the UBOS Zero‑Trust Edge
The UBOS guide recommends creating a **Zero‑Trust Application** that isolates the API behind Cloudflare Access.
bash
# 1️⃣ Log in to UBOS and select the OpenClaw project
ubos login
ubos project select openclaw
# 2️⃣ Create a Zero‑Trust Application
ubos zero-trust create \
–name openclaw-rating-api \
–domain api.openclaw.ubos.tech \
–service openclaw-rating
# 3️⃣ Export the generated Cloudflare Access configuration
ubos zero-trust export –format json > cf-access-config.json
The generated `cf-access-config.json` contains the **Client ID**, **Client Secret**, and the **Access Policy ID** that we will later import into Cloudflare.
—
## 2. Deploy Cloudflare Workers as the Edge Authenticator
The Workers tutorial shows how to create a Worker that validates Cloudflare Access JWTs and forwards the request to the internal service.
### 2.1 Create the Worker script
javascript
addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
// Verify Cloudflare Access JWT
const token = request.headers.get(‘Authorization’)?.replace(‘Bearer ‘, ”)
if (!token) return new Response(‘Missing token’, { status: 401 })
const jwks = await fetch(‘https://.cloudflareaccess.com/cdn-cgi/access/certs’)
.then(r => r.json())
const verified = await verifyJwt(token, jwks)
if (!verified) return new Response(‘Invalid token’, { status: 403 })
// Forward to the internal OpenClaw Rating service
const url = new URL(request.url)
url.hostname = ‘internal.openclaw.svc.cluster.local’
const upstream = new Request(url, request)
return fetch(upstream)
}
async function verifyJwt(token, jwks) {
// Use the built‑in crypto.subtle API – omitted for brevity
// Return true if the JWT is valid and contains the required audience
return true
}
Save the script as `worker.js`.
### 2.2 Deploy the Worker
bash
# Install Wrangler (the Cloudflare Workers CLI)
npm install -g @cloudflare/wrangler
# Initialise the project (use the domain from step 1)
wrangler init openclaw‑worker –type javascript
cd openclaw‑worker
cp ../worker.js src/index.js
# Configure wrangler.toml with the team‑specific values from cf‑access‑config.json
cat < wrangler.toml
name = “openclaw‑worker”
account_id = “”
workers_dev = true
compatibility_date = “2024-01-01”
[vars]
CF_ACCESS_AUDIENCE = “”
EOF
# Publish the Worker
wrangler publish
The Worker is now reachable at `https://openclaw-worker..workers.dev` and will be used as the **Edge endpoint** for the API.
—
## 3. Harden the Service with OPA‑Istio
The OPA‑Istio guide provides a **policy‑as‑code** approach that validates the JWT claims against a Rego policy.
### 3.1 Install Istio and OPA‑Istio
bash
# Install Istio (minimal profile)
istioctl install –set profile=demo -y
# Deploy OPA‑Istio sidecar injector
kubectl apply -f https://raw.githubusercontent.com/istio-ecosystem/opa-istiot/master/deployments/opa-istiot.yaml
### 3.2 Create the Rego policy
Create a file `rating-api-policy.rego`:
rego
package istio.authz
default allow = false
allow {
input.attributes.request.http.headers[“authorization”] != “”
token := split(input.attributes.request.http.headers[“authorization”], ” “)[1]
[header, payload, signature] := io.jwt.decode(token)
payload.sub == “user@example.com” # Example: only this user
payload.aud == “openclaw-rating-api” # Must match the Access audience
payload.exp > time.now_ns() / 1000000000 # Token not expired
}
### 3.3 Deploy the policy as a ConfigMap
bash
kubectl create configmap rating-api-policy \
–from-file=rating-api-policy.rego
# Annotate the OpenClaw Rating deployment to enable OPA‑Istio
kubectl annotate deployment openclaw-rating \
sidecar.istio.io/inject=”true”
# Apply an AuthorizationPolicy that points to the ConfigMap
cat <<EOF | kubectl apply -f –
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: rating-api-opa-policy
namespace: default
spec:
selector:
matchLabels:
app: openclaw-rating
action: CUSTOM
provider:
name: opa-istio
rules:
– to:
– operation:
methods: ["GET", "POST"]
EOF
Now every request that reaches the OpenClaw Rating service is evaluated by OPA. Only callers with a valid Cloudflare Access JWT that satisfies the Rego rules will be allowed.
—
## 4. Verify the End‑to‑End Flow
1. **Log in to Cloudflare Access** (or use a service token) and obtain a JWT.
2. **Call the API through the Worker**:
bash
TOKEN=$(curl -s -X POST https://.cloudflareaccess.com/cdn-cgi/access/token -d ‘{“aud”:”openclaw-rating-api”}’ | jq -r .access_token)
curl -H “Authorization: Bearer $TOKEN” https://api.openclaw.ubos.tech/v1/rating?item=123
You should receive a JSON response from the OpenClaw Rating service. If the token is missing, malformed, or the policy denies the request, you will get a `403 Forbidden`.
—
## 5. Publish the Blog Post on UBOS
Below is the JSON payload that can be sent to the UBOS blog API to create the article. It contains **exactly one** internal link to the OpenClaw hosting guide.
{
“title”: “Enforcing Zero‑Trust Access to the OpenClaw Rating API Edge with Cloudflare Access and OPA”,
“content”: “”,
“author”: “UBOS Team”,
“featured_image”: “https://ubos.tech/wp-content/uploads/2024/03/zero-trust-cover.jpg”,
“post_type”: “POST”
}
> **Note:** Replace “ with the full article text (including the single internal link to https://ubos.tech/host-openclaw/).
—
### 🎉 You’re done!
You now have a **Zero‑Trust, policy‑driven edge** for the OpenClaw Rating API, fully documented and published on the UBOS blog.
*For more details on hosting OpenClaw on UBOS, see the [OpenClaw hosting guide](/host-openclaw/).*