Skip to content

POC - Test if NAP WAF v5 starting up with readOnlyRootFileSystem enabled in NIC container & waf_enforcer & waf_config_mgr #6562

@shaun-nx

Description

@shaun-nx

Context

UPDATE: TL;DR

Users CAN use NIC v3.7.0 + WAF v5 with the readOnlyRootFilesystem
NOTE: Users that install NIC + WAF v5 via Helm needs to be aware about this fixed issue.


NOTE the code snippet below is not relevant for NIC + WAF v5.

Timebox: 2 days

The NAP team set the follow tmp directories in the http context

http {
        ....
        # Temporary directories for kubernetes "readonlyfilesystem"
        client_body_temp_path /tmp/nginx-client-body;
        proxy_temp_path       /tmp/nginx-proxy;
        fastcgi_temp_path     /tmp/nginx-fastcgi;
        uwsgi_temp_path       /tmp/nginx-uwsgi;
        scgi_temp_path        /tmp/nginx-scgi;
}



apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-path-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: policy-file
data:
  policy.json: |
    {
      "policy": {
        "name": "my_policy",
        "template": {
          "name": "POLICY_TEMPLATE_NGINX_BASE"
        },
        "applicationLanguage": "utf-8",
        "enforcementMode": "blocking"
      }
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: waf-nginx-conf
data:
  test_nginx.conf: |
    user nginx;
    worker_processes  4;

    load_module modules/ngx_http_app_protect_module.so;

    error_log /var/log/nginx/error.log debug;
    pid        /tmp/nginx.pid;

    # working_directory /tmp/cores;
    worker_rlimit_core 1000M;

    events {
        worker_connections  65536;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;

        # WAF enforcer address
        app_protect_enforcer_address 127.0.0.1:50000;

        access_log  /var/log/nginx/access.log;

        # Temporary directories for kubernetes "readonlyfilesystem"
        client_body_temp_path /tmp/nginx-client-body;
        proxy_temp_path       /tmp/nginx-proxy;
        fastcgi_temp_path     /tmp/nginx-fastcgi;
        uwsgi_temp_path       /tmp/nginx-uwsgi;
        scgi_temp_path        /tmp/nginx-scgi;

        server {
            listen       80;
            server_name  localhost;
            proxy_http_version 1.1;
            app_protect_enable on;
            app_protect_policy_file "/etc/app_protect/bundles/compiled_policy.tgz";

            app_protect_security_log_enable on;
            app_protect_security_log log_all syslog:server=127.0.0.1:515;

            location / {
                client_max_body_size 0;
                default_type text/html;
                # Pass traffic to testing web server inside the pod
                proxy_pass http://127.0.0.1:8080/$request_uri;
            }
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: compiler-node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: compiler-node
  template:
    metadata:
      labels:
        app: compiler-node
    spec:
      containers:
        ################################## Compiler ##################################
        - name: compiler-node
          image: NAPX_COMPILER_IMAGE:NAPX_COMPILER_TAG
          imagePullPolicy: Always
          command: ["/bin/bash"]
          args:
          - "-c"
          - |
            /opt/app_protect/bin/apcompile -p /src/policy.json -o /dst/compiled_policy.tgz
            tail -f /dev/null
          # args: ["-p" , "/src/policy.json" , "-o" , "/dst/compiled_policy.tgz"]
          volumeMounts:
            - mountPath: /dst # Saves the bundle to be used later in the bundles pvc
              name: nap5-bundles
            - name: policy-file
              mountPath: /src # Mounts the ConfigMap here to access policy.json
      volumes:
        - name: policy-file
          configMap:
            name: policy-file
        - name: nap5-bundles
          persistentVolumeClaim:
            claimName: local-path-pvc
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: waf-nginx
          image: NAPX_IMAGE:NAPX_TAG
          imagePullPolicy: Always
          securityContext:
            readOnlyRootFilesystem: true
          command: ["/bin/bash"]
          args:
          - "-c"
          - |
            mkdir -p /tmp/cores
            until [ -f /etc/app_protect/bundles/compiled_policy.tgz ]; do sleep 1; done
            nginx -c /tmp/policy/test_nginx.conf -g 'daemon off;' &
            ncat -vlkp 515 > /tmp/nclog 2>&1 &
            tail -f /dev/null
          volumeMounts:
            - name: app-protect-bd-config
              mountPath: /opt/app_protect/bd_config
            - name: app-protect-config
              mountPath: /opt/app_protect/config
            - name: tmp-volume
              mountPath: /tmp
            - name: nginx-log
              mountPath: /var/log/nginx
            - name: app-protect-bundles
              mountPath: /etc/app_protect/bundles
            - name: waf-nginx-conf    # Mounting the nginx.conf file, not required as part of the deployment
              mountPath: /tmp/policy
        - name: enforcer
          image: ENFORCER_IMAGE:ENFORCER_TAG
          imagePullPolicy: Always
          securityContext:
            readOnlyRootFilesystem: true
          env:
            - name: ENFORCER_PORT
              value: "50000"
          volumeMounts:
            - name: app-protect-bd-config
              mountPath: /opt/app_protect/bd_config
        - name: config-mgr
          image: CONFIG_MGR_IMAGE:CONFIG_MGR_TAG
          imagePullPolicy: Always
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - all
          volumeMounts:
            - name: app-protect-bd-config
              mountPath: /opt/app_protect/bd_config
            - name: app-protect-config
              mountPath: /opt/app_protect/config
            - name: app-protect-bundles
              mountPath: /etc/app_protect/bundles
        ################################## Backend Server ##################################
        - name: testing-webserver
          image: artifactory.f5net.com/f5-wafqatools-docker/customwebserver
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
      volumes:
        - name: app-protect-bd-config
          emptyDir: {}
        - name: app-protect-config
          emptyDir: {}
        - name: nginx-log
          emptyDir: {}
        - name: tmp-volume
          emptyDir: {}
        - name: app-protect-bundles
          persistentVolumeClaim:
            claimName: local-path-pvc
        - name: waf-nginx-conf
          configMap:
            name: waf-nginx-conf
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
  selector:
    app: nginx


Metadata

Metadata

Assignees

Labels

backlogPull requests/issues that are backlog items

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions