This is a preview release. Do not use it in production environments.
Download the release bundle from Download Edge-Native Defender (Preview). New to Edge-Native Defender? Start with Edge-Native Defender overview.
At a glance
| Deployment | One installer command adds two shared flows and attaches them to every proxy in your Apigee X environments with flow hooks. Your proxies, routes and targets do not change. |
| Added latency | About 9 ms at the median with Defender on your GKE cluster over Private Service Connect; about 27 ms with Defender on Cloud Run. |
| Cost | Defender's own service: two small pods on GKE, or one always-on Cloud Run instance. Nothing from Cequence for the infrastructure. |
| If something fails | Your APIs stay up. If Defender cannot be reached, Apigee lets requests through; if Cequence is unreachable, Defender keeps enforcing its last policies. |
| Upgrades |
defenderctl-apigee upgrade deploys new shared-flow revisions; roll back by running it from the previous bundle. |
Deployment architecture
Defender protects Apigee X proxies through Apigee's own ExternalCallout policy. Two shared flows do the work, attached to every proxy in an environment by flow hooks:
- defender-request, on the Pre-proxy hook: sends each request to Defender, and when Defender blocks, answers the client with your policy's status and block page.
- defender-response, on the Post-target hook: sends the response so Defender can complete the request's analytics.
BEFORE
client ---> Apigee proxy ------------------------------> your target
AFTER
client ---> Apigee proxy ------------------------------> your target
| defender-request defender-response
v v
Defender service (GKE over Private Service Connect, or Cloud Run)
|
+---> your Cequence tenant: policies in, analytics out,
in the background
What stays the same. Your proxies, their policies, targets and routes. The flow hooks apply Defender to every proxy in the environments you choose, with nothing to change in each proxy, and removing them takes Defender out at once.
What Defender does with a request. A blocked request is answered by Apigee with your tenant's block page and never reaches your target. An allowed request is forwarded byte for byte, and your client receives the response byte for byte: Defender inspects a copy of each body, up to your tenant's capture settings, and never changes what it forwards.
What is sent to Cequence. For each request: its headers and URL, the response status and headers, and the inspected body copies, masked first with your tenant's Sensitive Data rules. Your traffic filters decide whether a request is reported at all.
Installation
Prerequisites
- Apigee X: an organization and the environments to protect.
- Where Defender runs, one of:
- GKE over Private Service Connect (recommended, fastest): a GKE cluster in the same region as your Apigee instance;
- Cloud Run: a Google Cloud project with the Cloud Run and Secret Manager APIs. Apigee cannot authenticate to Cloud Run, so this service accepts unauthenticated calls.
- The
defender-extprocimage copied into your Artifact Registry. Cequence support gives you access to the image for your release. -
gcloud, signed in with rights to manage Apigee (and GKE or Cloud Run), on the machine you install from. - Your tenant's name, client ID and client secret.
1. Run Defender
On GKE over Private Service Connect. From the unpacked defender-for-apigee
bundle:
- Apply
gke/defender.yamlin namespacedefender, as its header describes (your tenant's configuration, the client secret and a TLS certificate -- self-signed is fine). - Create a Private Service Connect subnet in the cluster's network and region,
then apply
gke/gke-psc.yaml. Its header has the commands. - In your firewall, allow that subnet's range to reach the GKE nodes on port
- Without it every call fails, and because Apigee lets requests through when Defender cannot be reached, nothing else tells you.
- Note the service attachment's path for the next step:
kubectl -n defender get serviceattachment defender-extproc-psc -o jsonpath='{.status.serviceAttachmentURL}'.
On Cloud Run the installer deploys Defender for you in the next step.
2. Install with defenderctl-apigee
Fill in defender.conf from defender.conf.example:
CEQUENCE_TENANT=<your tenant> CEQUENCE_CLIENT_ID=<client id> APIGEE_ORG=<your Apigee organization> APIGEE_ENVS=<environments, comma-separated>
For GKE, add:
APIGEE_CALLOUT=endpoint APIGEE_SERVICE_ATTACHMENT=projects/<project>/regions/<region>/serviceAttachments/<name>
For Cloud Run, add:
APIGEE_CALLOUT=cloudrun APIGEE_CLOUDRUN_PUBLIC=yes GCP_PROJECT=<project> GCP_REGION=<region of your Apigee instance> GCP_IMAGE=<region>-docker.pkg.dev/<project>/<repository>/defender-extproc:<version>
Then:
export CEQUENCE_CLIENT_SECRET=<client secret> ./bin/defenderctl-apigee preflight ./bin/defenderctl-apigee install
The installer creates the target server, imports and deploys the two shared flows, and attaches the flow hooks last, so traffic goes through Defender only once everything is in place. It refuses to replace anything it did not create: if your environment already uses a flow hook, it tells you how to add Defender to your existing shared flow instead.
3. Check it before you go live
- Run
APIGEE_VERIFY_URL=https://<your API host> ./bin/defenderctl-apigee verify. It checks that an ordinary request passes and that a request matching a test policy is blocked. - Send a request that one of your own policies blocks, and check it is blocked.
-
./bin/defenderctl-apigee statusshows the target server, the deployed shared flows and the hooks in each environment.
Upgrades and rollback
./bin/defenderctl-apigee upgrade
from the new bundle imports and deploys new shared-flow revisions, and on Cloud
Run deploys a new service revision. Apigee switches revisions without dropping
requests. To roll back, run upgrade from the previous bundle. On GKE, update
the image in gke/defender.yaml; the pods are replaced one at a time.
Performance and sizing
| GKE over Private Service Connect | Cloud Run | |
| Added latency, median | about 9 ms | about 27 ms |
| Defender service | two pods, 0.5 vCPU and 512 MiB each, scaling to ten | one instance always on |
Measured on an Apigee X organization in us-central1, alternating runs with and without Defender and with each path confirmed in use. Defender's own decision takes about a millisecond; most of the rest is Apigee's call to it. Each request makes two calls, one for the request and one for the response.
Cost
Cequence charges nothing for the infrastructure. On GKE, Defender is two small pods on a cluster you run; on Cloud Run, one instance stays running so policies and analytics keep flowing. Google's usual GKE, Cloud Run and Private Service Connect charges apply.
Availability
- If Cequence is slow or unreachable, your traffic is unaffected. Defender keeps enforcing the policies it last received, and sends the analytics it holds once Cequence is reachable again.
- If Defender is unreachable or slow, Apigee lets requests through to your target after the 500 ms timeout, uninspected. Run at least two pods on GKE.
-
If you need Defender off the path at once, run
./bin/defenderctl-apigee uninstall, or detach the two flow hooks in Apigee. - A fresh install blocks nothing until your tenant's first policy publish arrives.
Known limits
-
blockandadd-headerpolicies are enforced.challenge,rate-limitandredirectpolicies are reported but not applied: the request is forwarded. - Apigee X is supported. Apigee hybrid works through the shared flows, but the installer does not set it up yet.
- On flows with streaming turned on, Apigee does not send bodies, so body policies cannot match there.
If something is wrong
-
Nothing is blocked. The most likely cause is that Apigee cannot reach
Defender: check the firewall rule in step 1, and in an Apigee debug session
look for
externalcallout.EC-Defender-Request.failed.verifypoints to the same. -
The installer refuses to attach. An environment already uses the flow
hook: add a FlowCallout to
defender-requestat the start of your existing hook's shared flow, and install withAPIGEE_ATTACH=none. - No policies loaded. Defender's logs say why it cannot reach your tenant: outbound access, the client ID or the secret.
Removing it
./bin/defenderctl-apigee uninstall
detaches the flow hooks first, so traffic stops going through Defender, then
removes the shared flows, the target server and what it created for the
callout. The client secret is kept unless you add --delete-secret.