---
title: "Implementing workload-centric Web Application Firewall (WAF) using Calico"
source: "https://www.tigera.io/blog/implementing-workload-centric-web-application-firewall-waf-using-calico/"
---

[Technical Blog](https://www.tigera.io/category/technical-blog/)

# Implementing workload-centric Web Application Firewall (WAF) using Calico

By [Faisal Naseem](https://www.tigera.io/blog/author/faisal-naseem/) on Jul 18, 2023 • 9 min read

[Microservices security](https://www.tigera.io/learn/guides/microservices-security/microservices-kubernetes/) is a growing concern for businesses in the face of increasing cyber threats. With application layer attacks being a leading cause of breaches, it’s more important than ever to safeguard the HTTP-based communication between microservices within a Kubernetes cluster. Traditional web application firewalls (WAFs) are not designed to address this specific challenge, but Calico WAF offers a unique solution.

## What is a workload-centric WAF?

Calico WAF, a workload-centric web application firewall, brings a fresh, cloud-native approach to securing microservices communication. Unlike traditional [WAF](https://www.tigera.io/learn/guides/kubernetes-security/kubernetes-waf/)s deployed at the edge of a Kubernetes cluster, Calico WAF focuses on protecting the intra-cluster traffic and applies zero-trust rules specifically designed for microservices within your cluster.

This innovative solution defends against common HTTP-layer attacks, such as server-side request forgery (SSRF), improper HTTP header type, occurring within the cluster. It seamlessly integrates with Calico Cloud network policies, enabling the enforcement of security controls at the host level for selected pods.

Calico WAF ensures the secure communication between microservices within your Kubernetes cluster, reducing the risk of vulnerabilities and threats. By adopting Calico WAF, businesses can confidently fortify the HTTP-based communication channels within their microservices architecture. This comprehensive approach enhances the overall security posture of the Kubernetes cluster, allowing for secure and reliable operation of microservices.

## Deploying and Leveraging Calico Cloud WAF

Calico Cloud’s WAF is architecturally deployed as an Envoy DaemonSet within the Kubernetes cluster. By proxying selected service traffic through Envoy, HTTP requests are evaluated based on the industry-standard open-source ModSecurity WAF module. This rule set that comes bundled with Calico WAF, can be found here.

WAF can be enabled via the Manager UI, allowing you to specify the services requiring WAF protection. To facilitate real-time tracking and response, WAF events are logged as HTTP logs and can be accessed via the Dynamic Service and Threat Graph, and Kibana. Global alerts can be configured to trigger notifications based on these logs.

Below we will go step-by-step through deploying the Calico Cloud workload-centric WAF.

### Prerequisites

1. Install Calico Cloud and verify that all components are running.

 

2. Enable the Policy Sync API in Felix. To do this cluster-wide, modify the `default` FelixConfiguration to set the field `policySyncPathPrefix` to `/var/run/nodeagent`:

```
`[ec2-user@ip-172-31-20-71 ~]$ kubectl patch felixconfiguration default --type='merge' -p '{"spec":{"policySyncPathPrefix":"/var/run/nodeagent"}}' felixconfiguration.projectcalico.org/default patched`
```

### Configure the cluster for WAF​

**Step 1: Configure ApplicationLayer CRD​**

Create or update the [ApplicationLayer](https://docs.tigera.io/calico-enterprise/latest/reference/installation/api) resource to include the webApplicationFirewall section of the file. Ensure the value of the field is set to Enabled.

```
`apiVersion: operator.tigera.io/v1 kind: ApplicationLayer metadata: name: tigera-secure spec: webApplicationFirewall: Enabled`
```

Apply the manifest: `kubectl apply -f application.yaml`

You will see new pods spinning up in the clusters in the calico-system namespace:

![Screenshot showing new 'l7-log-collector' pods in the 'calico-system' namespace, highlighted to indicate recent startup](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-2.png)

Optional: Launch a sample application using the following commands (we will test the WAF functionality on this):

```
`kubectl apply -f -<<EOF apiVersion: v1 kind: Namespace metadata: name: yaobank labels: istio-injection: disabled tenant: tenant1 --- apiVersion: v1 kind: Service metadata: name: database namespace: yaobank labels: app: database tenant: tenant1 spec: ports: - port: 2379 name: http selector: app: database --- apiVersion: v1 kind: ServiceAccount metadata: name: database namespace: yaobank labels: app: yaobank tenant: tenant1 --- apiVersion: apps/v1 kind: Deployment metadata: name: database namespace: yaobank spec: selector: matchLabels: app: database version: v1 tenant: tenant1 replicas: 1 template: metadata: labels: app: database version: v1 tenant: tenant1 spec: serviceAccountName: database containers: - name: database image: calico/yaobank-database:certification imagePullPolicy: IfNotPresent ports: - containerPort: 2379 command: ["etcd"] args: - "-advertise-client-urls" - "http://database:2379" - "-listen-client-urls" - "http://0.0.0.0:2379" --- apiVersion: v1 kind: Service metadata: name: summary namespace: yaobank labels: app: summary tenant: tenant1 spec: ports: - port: 80 name: http selector: app: summary --- apiVersion: v1 kind: ServiceAccount metadata: name: summary namespace: yaobank labels: app: yaobank database: reader tenant: tenant1 --- apiVersion: apps/v1 kind: Deployment metadata: name: summary namespace: yaobank spec: replicas: 2 selector: matchLabels: app: summary version: v1 tenant: tenant1 template: metadata: labels: app: summary version: v1 tenant: tenant1 spec: serviceAccountName: summary containers: - name: summary image: calico/yaobank-summary:certification imagePullPolicy: Always ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: labels: app: customer tenant: tenant1 name: customer namespace: yaobank spec: ports: - name: http port: 80 selector: app: customer --- apiVersion: v1 kind: ServiceAccount metadata: name: customer namespace: yaobank labels: app: yaobank summary: reader tenant: tenant1 --- apiVersion: apps/v1 kind: Deployment metadata: name: customer namespace: yaobank spec: replicas: 1 selector: matchLabels: app: customer version: v1 tenant: tenant1 ingress: "true" template: metadata: labels: app: customer version: v1 tenant: tenant1 ingress: "true" spec: serviceAccountName: customer containers: - name: customer image: calico/yaobank-customer:certification imagePullPolicy: Always ports: - containerPort: 80 EOF`
```

Optional: Expose the svc customer as a LoadBalancer service to quickly access it using the browser. You can use any other service you may like to expose and test.

![Screenshot shows 'customer' service exposed as LoadBalancer with an external IP, confirming quick browser access for testing](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-3.png)

**Step 2: Select traffic for WAF**

Annotate the services you wish to enable WAF for as shown.

`kubectl annotate svc <service-name> -n <service-namespace> projectcalico.org/l7-logging=true`

```
`[ec2-user@ip-172-31-20-71 WAF]$ kubectl annotate svc customer -n yaobank projectcalico.org/l7-logging=true service/customer annotated`
```

Note: In case you want to disable WAF on the service, remove the annotation likewise:

`kubectl annotate svc <service-name> -n <service-namespace> projectcalico.org/l7-logging-`

**Step 3: Test your installation​**

To test your installation, you must first know the URL to access services. The URL can be either of the following:

- The external address of your cluster/service

- The cluster IP of your application’s service (if testing within the cluster).

After identifying the URL, `curl` your service with a command to trigger an OWASP rule. This is a simple example of potential SQL Injection attack:

`curl<http://<host>//test/artists.php?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user>`

```
`curl http://af7ad88cf23b34ed084cb75b28e330ea-1400749873.ca-central-1.elb.amazonaws.com//test/artists.php?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user`
```

In the l7-log-collector pods, you should notice a **warning** log when the attack triggered (dikastes container)

```
`[ec2-user@ip-172-31-20-71 WAF]$ k logs l7-log-collector-2fgrg -n calico-system -c dikastes | grep SQL time="2023-03-21T18:25:30Z" level=info msg="WAF Found Rules File[8]('/etc/modsecurity-ruleset/RESPONSE-951-DATA-LEAKAGES-SQL.conf')" time="2023-03-21T18:25:30Z" level=info msg="WAF Found Rules File[13]('/etc/modsecurity-ruleset/REQUEST-942-APPLICATION-ATTACK-SQLI.conf')" time="2023-03-21T19:17:42Z" level=warning msg="WAF Process Http Request [eabbf6c3-7964-4063-81be-c2abb8c66740] URL '//test/artists.php?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user' OWASP Warning'[2] Host:'192.168.60.185' File:'/etc/modsecurity-ruleset/REQUEST-942-APPLICATION-ATTACK-SQLI.conf' Line:'45' ID:'942100' Data:'' Severity:'0' Version:'OWASP_CRS/3.3.2' Message:'Warning. detected SQLi using libinjection.''"`
```

![Terminal output showing WAF logs filtered for SQL, indicating SQL rule files and detected SQL injection attempts](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-4.png)

#### Add or edit a rule set​

Create a directory, and download the core rules set files that you want to use, for example:

```
`mkdir my-ruleset && cd my-ruleset curl -O https://raw.githubusercontent.com/coreruleset/coreruleset/v3.3/dev/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf`
```

Note: Download the following required bootstrapping configuration files ([Reference](https://medium.com/lightbaseio/web-application-firewall-in-go-feat-owasp-modsecurity-core-rule-set-3f97a26e3311)).

ModSecurity is a popular open-source module for web application firewalls (WAF). It is used by Tigera-Operator. ModSecurity helps protect web applications from various attacks and exploits by monitoring HTTP traffic in real-time. It uses a set of rule configurations to filter and log activity, allowing it to prevent attacks categorized as SQL injection, cross-site scripting (XSS), and others.

```
`curl -O https://raw.githubusercontent.com/lsgroup/SmartReverseProxy/master/modsecdefault.conf curl https://raw.githubusercontent.com/coreruleset/coreruleset/v3.3/dev/crs-setup.conf.example > crs-setup.conf`
```

**NOTE**

The two bootstrapping files modsecdefault.conf and crs-setup.conf MUST be named lowercase i.e. lowercase “m” and lowercase “c” respectively in order to ensure they are loaded into ModSec before any REQUST-*.conf Core Rules Set files. Presence of these two files is required and enforced by the operator. Change your current directory to the my-ruleset folder where your core rules set files live. Create a configMap containing all the files downloaded into your new directory and replace the existing rule set with it

Have a look at the configmap for modsecurity in namespace calico-system:

![CLI output showing configmaps in the calico-system namespace, highlighting 'modsecurity-ruleset' with 55 data entries](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-5.png)

```
`kubectl create cm --dry-run=client --from-file=. -o yaml -n tigera-operator modsecurity-ruleset > ../my-ruleset.yaml kubectl replace -f ../my-ruleset.yaml`
```

Check the config map created above using the following command:

`Kubectl describe cm modsecurity-ruleset -n calico-system | grep SQL`

![Terminal output showing ModSecurity ruleset configuration related to SQL injection attacks, filtered by 'SQL](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-6.png)

To add more rulesets, we can include them in the same directory and replace the configmap accordingly.

We can download the extensive rulesets from:

`wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.4.tar.gz` (change versions as required)

![Terminal output showing the contents of the 'rules' directory after downloading and extracting the Core Rule Set](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-7.png)

 

### Viewing WAF events in Kibana and Manager UI

In order for logs to be pushed and seen in Kibana and Manager UI, core rulesets have to be modified to **deny** or **drop** traffic. When WAF is configured in the cluster by default, modsecurity rules are programmed in the l7-log-collector to log a warning but not deny or drop the traffic.

For example, modify the modsecurity core rulesets’ `SecDefaultAction` to **deny** rules by commenting and uncommenting these sections in the `crs-setup.conf`, which will change the `SecDefaultAction` from `pass` to `deny` with a `403` response.

Comment

```
`SecDefaultAction "phase:1,log,auditlog,pass" SecDefaultAction "phase:2,log,auditlog,pass"`
```

Uncomment

```
`SecDefaultAction "phase:1,log,auditlog,deny,status:403" SecDefaultAction "phase:2,log,auditlog,deny,status:403"`
```

 

Before updating the config map it was returning 404 as shown below:

![Terminal output showing a '404 Not Found' error after running the provided curl command](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-10.png)

After replacing the configmap it should return 403 forbidden (we will need to run the above command to replace the configmap with the new rulesets again to take effect)

NOTE: Switching to deny means it will stop processing the request and return a 403 forbidden error when a rule is triggered. All denied traffic in this case means any HTTP request will return HTTP 403 Response Code from Envoy to the originating service like below:

```
`curl http://af7ad88cf23b34ed084cb75b28e330ea-1400749873.ca-central-1.elb.amazonaws.com//test/artists.php?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user -v`
```

![Terminal output showing a 'curl' command resulting in a 'HTTP/1.1 403 Forbidden' error. This indicates the request was](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-11.png)

### Viewing logs in Kibana

In Kibana you will have to create `tigera_secure_ee_waf*` index pattern. Instructions on how to create an index pattern can be found [here](https://www.elastic.co/guide/en/kibana/7.17/index-patterns.html).

Now view the WAF logs in Kibana by selecting the `tigera_secure_ee_waf*` index pattern. You should see the relevant WAF assessment from your request recorded.

Go into Stack Management in Kibana and create the index pattern:

![Kibana's navigation menu, with 'Stack Management' under 'Management' highlighted](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-12.png)

![Kibana's Index Patterns page, highlighting the 'tigera_secure_ee_waf' pattern](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-13.png)

Now view the WAF logs in Kibana by selecting the `tigera_secure_ee_waf*` index pattern. You should see the relevant WAF assessment from your request recorded:

Now if we go into discover and filter with the above index pattern, we should see the flow.

### Calico Manager UI Set-up​

Create a new Global Alert for WAF using Calico Manager UI, or using standard YAML. For example, we would like to trigger a Global Alert for SQL Injection attack specifically Rule ID 942100 as per custom version of Core Rule Set file that will “deny” all traffic instead of “block”.

```
`apiVersion: projectcalico.org/v3 kind: GlobalAlert metadata: name: waf-new-alert-rule-info spec: summary: 'WAF new waf-alert-942100' description: 'Test WAF Global Alert' severity: 1 dataSet: waf period: 1m lookback: 1h query: '"rule_info" IN {"*942100*"}' threshold: 0 condition: gt`
```

 

Once the file is applied, if a SQL Injection attack is detected for rule ID 942100, you will see the global alert in Manager UI, Activity, Alerts.

 

![Manager UI showing navigation to Activity, Alerts, and the global alert for SQL Injection attacks](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-15.png)

 

![Screenshot of a Calico WAF Global Alert, showing details like source/destination IPs, ports, and a record of the failed WAF](https://www.tigera.io/app/uploads/2023/07/Calico-WAF-17.png)

 

## Considerations and Caveats

While Calico Cloud WAF offers a novel approach to web security, it is crucial to acknowledge the associated limitations. This solution currently does not extend support to Windows, eBPF data plane, RKE, and RKE2 clusters. Additionally, WAF is not applicable for host-networked client pods, and the selection and deselection of traffic for WAF may disrupt active connections.

Particular caution should be exercised while enabling WAF for system services as it may lead to undesirable cluster states. Avoid enabling WAF for system services prefixed with “tigera-“, “calico-“, or “kube-system”.

Prior to enabling Calico Cloud WAF, Felix must be configured for syncing WAF policy. If L7 logs have already been configured, this step can be bypassed. It is also crucial to enable the Policy Sync API in Felix cluster-wide by setting the `policySyncPathPrefix` field to `/var/run/nodeagent`.

## Looking Ahead

Calico Cloud’s Workload-based WAF represents an evolutionary step in microservices security. By operating at the workload level within the cluster, it provides more refined and targeted security measures that align with the dynamics of cloud-native applications. As we navigate the landscape dominated by microservices, leveraging tools such as Calico Cloud’s WAF is integral to maintaining the integrity and reliability of valuable data exchanged between microservices against an ever-evolving threat landscape. Embracing this innovative solution allows businesses to ensure the security of their microservices and confidently adapt to the changing security landscape.

Ready to try Calico for yourself? Get started with a [free Calico Cloud trial](https://link.tigera.io/ueOp4).

[How-To](https://www.tigera.io/tags/how-to/)[Products](https://www.tigera.io/tags/products/)

## Related posts

[![Meet Mylo: An AI-native way to work with Calico](https://www.tigera.io/app/uploads/2026/09/Meet-Mylo-An-AI-native-way-to-work-with-Calico.png)](https://www.tigera.io/blog/meet-mylo-an-ai-native-way-to-work-with-calico/)

#### [Meet Mylo: An AI-native way to work with Calico](https://www.tigera.io/blog/meet-mylo-an-ai-native-way-to-work-with-calico/)

By [Phil DiCorpo](https://www.tigera.io/blog/author/phil-dicorpo/)
on Sep 3, 2026

A library of Calico tools and skills — delivered through the Calico MCP Server What if your hardest network question took ten minutes instead of ten days? Anyone who has operated Kubernetes networking at scale...

[Read more](https://www.tigera.io/blog/meet-mylo-an-ai-native-way-to-work-with-calico/)

[![The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It](https://www.tigera.io/app/uploads/2026/08/The-Safest-Place-to-Run-an-AI-Agent-Is-On-a-Cluster-That-Doesnt-Trust-It.png)](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

#### [The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/)
on Aug 27, 2026

Every organization running AI agents has already made a hosting decision. Most made it by accident. The sales team switched on the agent built into their CRM. Engineering is piloting a coding agent in a...

[Read more](https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/)

[![AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.](https://www.tigera.io/app/uploads/2026/08/AI-Red-Team-Agents-Automate-Attacks-on-your-AI-Agents.-Runtime-Policies-Automate-their-Defense.png)](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

#### [AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

By [Alister Baroi](https://www.tigera.io/blog/author/alister-baroi/)
on Aug 24, 2026

The AI red teaming market grew up fast this year. OpenAI bought Promptfoo, Cisco and Microsoft shipped automated attack suites, and a seed-stage startup publicly compromised 50 of 55 live customer service bots. These platforms...

[Read more](https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=3279 metric#misses=34 metric#hit-ratio=99.0 metric#bytes=1596875 metric#prefetches=0 metric#store-reads=176 metric#store-writes=13 metric#store-hits=190 metric#store-misses=23 metric#sql-queries=30 metric#ms-total=1318.40 metric#ms-cache=78.83 metric#ms-cache-avg=0.4193 metric#ms-cache-ratio=6.0 sample#redis-hits=5232070 sample#redis-misses=2100548 sample#redis-hit-ratio=71.3 sample#redis-ops-per-sec=204 sample#redis-evicted-keys=0 sample#redis-used-memory=99698184 sample#redis-used-memory-rss=94814208 sample#redis-memory-fragmentation-ratio=0.9 sample#redis-connected-clients=2 sample#redis-tracking-clients=0 sample#redis-rejected-connections=0 sample#redis-keys=55910 -->
