Ingress-nginx: Adding modsecurity-snippet to configmap

Created on 8 Jan 2020  路  14Comments  路  Source: kubernetes/ingress-nginx

NGINX Ingress controller version:
nginx-ingress-1.28.1

Kubernetes version (use kubectl version):
v1.16.1

Environment:
Development

  • Cloud provider or hardware configuration:
    AWS EKS

  • OS (e.g. from /etc/os-release):

  • Kernel (e.g. uname -a):

  • Install tools:
  • Others:

What happened:
Issue 1: What is the configmap equivalent of modsecurity annotations
Ingress Object Annotations:
```apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
cert-manager.io/issuer: letsencrypt-production
ingress.kubernetes.io/force-ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/cors-allow-headers: X-Forwarded-For
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "false"
nginx.ingress.kubernetes.io/modsecurity-snippet: |
SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /var/log/modsec_audit.log
Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
nginx.ingress.kubernetes.io/proxy-body-size: 200m
nginx.ingress.kubernetes.io/session-cookie-hash: sha1
nginx.ingress.kubernetes.io/session-cookie-name: route
creationTimestamp: "2019-12-26T21:16:48Z"
generation: 1
name: mod-sec1
namespace: ww-mod-sec1
resourceVersion: "4619887"
selfLink: /apis/extensions/v1beta1/namespaces/XXXX/ingresses/XXXX
uid: 06fc4c48-2825-11ea-bc57-0a27ef589117
spec:
rules:

  • host: XXXXX
    http:
    paths:

    • backend:

      serviceName: XXXX

      servicePort: 80

      tls:

  • hosts:

    • XXXXXX

      secretName: XXXXXX

      status:

      loadBalancer:

      ingress:

    • {}

ConfigMap Equivalent of below annotations particularly:
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "false"
nginx.ingress.kubernetes.io/modsecurity-snippet: |
  SecRuleEngine On
  SecRequestBodyAccess On
  SecAuditEngine RelevantOnly
  SecAuditLogParts ABIJDEFHZ
  SecAuditLog /var/log/modsec_audit.log
  Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
I have installed ingress-nginx using helm. 

helm ls nginx
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
nginx 3 Wed Jan 8 13:37:33 2020 DEPLOYED nginx-ingress-1.28.1 0.26.2 kube-system

Trying to enable ModSecurity WAF in ingress-nginx controller. I have successfully configured below using the **Ingress Object Annotations**. However, I would like to achieve the same using configmap. 
1. Installing WAF using ModSecurity in ingress-nginx controller.
2. Enable OWASP Rules
3. Turn on the blocking mode for OWASP


Issue 2. Whenever I set `enable-modsecurity: "true"`, nginx.conf includes a modsecurity rule file `modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;`. 
<!-- (please include exact error messages if you can) -->


**What you expected to happen**:
`enable-modsecurity: "true"` should not enable the OWASP by default. 

According to [https://github.com/kubernetes/ingress-nginx/blob/58146c803bff7f56fae358d6ade4529d69314fa3/rootfs/etc/nginx/template/nginx.tmpl#L141](https://github.com/kubernetes/ingress-nginx/blob/58146c803bff7f56fae358d6ade4529d69314fa3/rootfs/etc/nginx/template/nginx.tmpl#L141)

`modsecurity-snippet: "SecRuleEngine On"` in the ConfigMap should add the rules in nginx.conf file as:

modsecurity_rules '
SecRuleEngine On`
';

**There is no change in the nginx.conf file after adding `modsecurity-snippet` to the confimap.**

<!-- What do you think went wrong? -->
Something wrong with the configmap `nginx-nginx-ingress-controller`



**How to reproduce it**:
<!---

As minimally and precisely as possible. Keep in mind we do not have access to your cluster or application.
Help up us (if possible) reproducing the issue using minikube or kind.
-->
## Install the ingress controller
`helm --install --force upgrade nginx --namespace kube-system --set rbac.create=true --version 1.28.1 stable/nginx-ingress`

## Install an application that will act as default backend (is just an echo app)

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/docs/examples/http-svc.yaml

## Create an ConfigMap (please add any additional annotation required)

echo "
apiVersion: v1
data:
enable-modsecurity: "true"
modsecurity-snippet: "SecRuleEngine On"
use-proxy-protocol: "true"
kind: ConfigMap
metadata:
creationTimestamp: null
labels:
app: nginx-ingress
chart: nginx-ingress-1.28.1
component: controller
heritage: Tiller
release: nginx
name: nginx-nginx-ingress-controller
selfLink: /api/v1/namespaces/kube-system/configmaps/nginx-nginx-ingress-controller
" | kubectl apply -f -
```

make a request

POD_NAME=$(k get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -o NAME)
kubectl exec -it -n ingress-nginx $POD_NAME -- curl -H 'Host: foo.bar' localhost

--->

Anything else we need to know:

/kind bug

Most helpful comment

Ah, thanks for finding that, I eventually moved to a similar workaround. That seems like a mistake, as enabling the OWASP ruleset without being able to do SecRuleEngine On seems completely useless. Somebody should probably open a bug about that.

All 14 comments

I have seen this, I have also looked into here how the snippet gets added. (https://github.com/kubernetes/ingress-nginx/pull/4087)

When I add value to that key in the config map, it is not reflected in the nginx.conf file.

Please re-open the issue.

I am sorry. This feature (modsecurity snippet in configmap) is merged but not released yet. https://github.com/kubernetes/ingress-nginx/pull/4087
If you want to check this, please run:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

echo "
apiVersion: v1
data:
  enable-modsecurity: 'true'
  modsecurity-snippet: |
    SecRuleEngine On
    SecRequestBodyAccess On
    SecAuditEngine RelevantOnly
    SecAuditLogParts ABIJDEFHZ
    SecAuditLog /var/log/modsec_audit.log
    Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
kind: ConfigMap
metadata:
  labels:
  name: nginx-configuration
  namespace: ingress-nginx

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mod-sec
spec:
  rules:
  - host: foo.bar
    http:
      paths:
      - backend:
          serviceName: none
          servicePort: 80
" | kubectl apply -f -

POD_NAME=$(k get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -o NAME)
kubectl exec -it -n ingress-nginx $POD_NAME -- cat nginx.conf

That makes sense. Is there any ETA for that feature?

Thank you

@SachinBadgujar next Monday or Tuesday https://github.com/kubernetes/ingress-nginx/pull/4906

@aledbf did this make it into 0.27 or 0.27.1? The release notes seem to indicate it did, but it doesn't work for me:

$ kubectl -n nginx-ingress describe deploy nginx-ingress-controller | grep Image
    Image:       quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.27.1

$ kubectl -n nginx-ingress get -o yaml cm nginx-ingress-controller | egrep "(mod|Sec)"
  enable-modsecurity: "true"
  enable-owasp-modsecurity-crs: "true"
  modsecurity-snippet: |
    SecRuleEngine On

# Inside nginx controller container
bash-5.0$ grep rules nginx.conf
    modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
    modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;

bash-5.0$ grep SecRuleEngine nginx.conf
# (no output)

@ConnorJC3 Are you still having this issue?

Unfortunately the logic for the modsecurity-snippet is only considered when enable-owasp-modsecurity-crs is set to false, as described here.

The workaround I am using in order to keep the owasp rules while having control over secRuleEngine is the following:

enable-modsecurity: "true"
enable-owasp-modsecurity-crs: "false"
modsecurity-snippet: |-
  SecRuleEngine On
  Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf

In this way I can have both helm installs and updates working on the ConfigMap level.

Greping nginx.conf should reflect those changes:

$ kubectl exec -n gitlab-managed-apps ingress-nginx-ingress-controller-79d499b69b-qmlg9 -- grep SecRuleEngine nginx.conf
SecRuleEngine On

Let me know if you have found a better solution.

Ah, thanks for finding that, I eventually moved to a similar workaround. That seems like a mistake, as enabling the OWASP ruleset without being able to do SecRuleEngine On seems completely useless. Somebody should probably open a bug about that.

@aledbf same problem as ConnorJC3 mentioned:

SecRuleEngine On doesn`t work in configMap because works like SecRuleEngine DetectionOnly

Using quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.31.0

apiVersion: v1
data:
  disable-access-log: "true"
  enable-modsecurity: "true"
  modsecurity-snippet: |
    SecRuleEngine On
    SecRequestBodyAccess On
    SecAuditEngine RelevantOnly
    SecAuditLogParts ABIJDEFHZ
    SecAuditLog /dev/stdout
    Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
kind: ConfigMap

grep SecRuleEngine nginx.conf:

$ kubectl exec  nginx-ingress-controller-75f655df49-69xhb -- grep   SecRuleEngine nginx.conf
        SecRuleEngine On
$ kubectl exec  nginx-ingress-controller-75f655df49-6z97j -- grep   SecRuleEngine nginx.conf
        SecRuleEngine On

I don't understand, do you?

@aledbf - same problem as xyzxyxzxzxyz .

Adding "modsecurity-snippet" directive in ConfigMap does not help, it does not start blocking attacks. We have to go to ingress and define the annotations in order to block the traffic.

@PuneeshMotwani @xyzxyxzxzxyz Unfortunately this will only work if you set enable-owasp-modsecurity-crs to false. I added some more details here https://github.com/kubernetes/ingress-nginx/issues/4902#issuecomment-598331053

HI @zamirmf ,

this is my configmap:-

apiVersion: v1
data:
enable-modsecurity: "true"
enable-owasp-modsecurity-crs: "false"
modsecurity-snippet: |
SecRequestBodyAccess On
Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
kind: ConfigMap

I do not have any modsec annotation in ingress. This only works in DetectionOnly mode i.e. I can see the logs in /var/log/modsec_audit.log file. But it does not block the bad request. I will not start blocking until I have "nginx.ingress.kubernetes.io/configuration-snippet:" annotations in the ingress object of kubernetes.

@PuneeshMotwani for blocking you need to add SecRuleEngine On under your snippet.

@zamirmf - Thanks for all your prompt replies. I tried having SecRuleEngine On under my snippet in configmap. Here is what my it looks like:-

apiVersion: v1
data:
  enable-modsecurity: "true"
  enable-owasp-modsecurity-crs: "false"
  modsecurity-snippet: |-
    SecRuleEngine On
    SecRequestBodyAccess On
    SecAuditEngine RelevantOnly
    SecAuditLogParts ABIJDEFHZ
    SecAuditLog /var/log/modsec_audit.log
    SecRule REQUEST_HEADERS:User-Agent \"fern-scanner\" \"log,deny,id:107,status:403,msg:\'Fern Scanner Identified\'\"
    Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
kind: ConfigMap

but this alone does not block the bad traffic. Although it logs the requests in modsec_audit.log file.

Bad traffic is not blocked until I have this in my Ingress resource:-

kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      modsecurity_rules '
        SecRuleEngine On
      ';

from your experience does the modsecurity stops traffic if you do not have this annotation in the ingress resource?

Was this page helpful?
0 / 5 - 0 ratings