From 0ade6b1a529828c72d68ae2c42d17a33dd61586e Mon Sep 17 00:00:00 2001 From: JingLu5 Date: Fri, 7 Sep 2018 16:18:15 +0800 Subject: Add ModSecurity config guide This patch adds ModSecurity config guide. This patch also deploy the modsecurity and ext_authz filter to clover-gateway namespace. Change-Id: I5ab21e6337b8f8b839ddd028370df378686bd017 Signed-off-by: JingLu5 --- docs/release/configguide/imgs/istio_gateway.png | Bin 0 -> 3985370 bytes .../configguide/modsecurity_config_guide.rst | 294 +++++++++++++++++++++ .../scenarios/ingressgateway_ext_authz_filter.yaml | 24 ++ .../istio_ingressgateway_envoyfilter.yaml | 24 -- samples/scenarios/modsecurity_all_in_one.yaml | 65 +++++ .../services/modsecurity/yaml/manifest.template | 2 + .../modsecurity/yaml/modsecurity-deployment.yaml | 1 + .../modsecurity/yaml/modsecurity-service.yaml | 1 + samples/services/modsecurity/yaml/render_yaml.py | 4 + 9 files changed, 391 insertions(+), 24 deletions(-) create mode 100644 docs/release/configguide/imgs/istio_gateway.png create mode 100644 docs/release/configguide/modsecurity_config_guide.rst create mode 100644 samples/scenarios/ingressgateway_ext_authz_filter.yaml delete mode 100644 samples/scenarios/istio_ingressgateway_envoyfilter.yaml create mode 100644 samples/scenarios/modsecurity_all_in_one.yaml diff --git a/docs/release/configguide/imgs/istio_gateway.png b/docs/release/configguide/imgs/istio_gateway.png new file mode 100644 index 0000000..f96212e Binary files /dev/null and b/docs/release/configguide/imgs/istio_gateway.png differ diff --git a/docs/release/configguide/modsecurity_config_guide.rst b/docs/release/configguide/modsecurity_config_guide.rst new file mode 100644 index 0000000..7b1c6cf --- /dev/null +++ b/docs/release/configguide/modsecurity_config_guide.rst @@ -0,0 +1,294 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. SPDX-License-Identifier CC-BY-4.0 +.. (c) Authors of Clover + +.. _modsecurity_config_guide: + +========================================= +ModSecurity Configuration Guide +========================================= + +This document provides a guide to setup the ModSecurity web application firewall +as a security enhancement for the Istio ingressgateway. + + +ModSecurity Overview +===================== + +ModSecurity is an open source web application firewall. Essentially, ModSecurity +is an Apache module that can be added to any compatible version of Apache. To +detect threats, the ModSecurity engine is usually deployed embedded within the +webserver or as a proxy server in front of a web application. This allows the +engine to scan incoming and outgoing HTTP communications to the endpoint. + +In Clover, we deploy ModSecurity on an Apache server and running it as a +Kubernetes service that reside in "clover-gateway" namespace. + +ModSecurity provides very little protection on its own. In order to become +useful, ModSecurity must be configured with rules. Dependent on the rule +configuration the engine will decide how communications should be handled which +includes the capability to pass, drop, redirect, return a given status code, +execute a user script, and more. + +In Clover, we choose the OWASP ModSecurity Core Rule Set (CRS) for use with +ModSecurity. + +The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack detection +rules. The CRS aims to protect web applications from a wide range of attacks, +including the OWASP Top Ten, with a minimum of false alerts. + + +Ingress traffic security enhancement +====================================== + +In a typical Istio service mesh, ingressgateway terminates TLS from external +networks and allows traffic into the mesh. + +.. image:: imgs/istio_gateway.png + :align: center + :scale: 100% + +Clover enhances the security aspect of ingressgateway by redirecting all incoming +HTTP requests through the ModSecurity WAF. To redirect HTTP traffic to the ModSecurity, +Clover enables ext_authz (external authorization) Envoy filter on the ingressgateway. + +For all incoming HTTP traffic, the ext_authz filter will authenticate each ingress +request with the ModSecurity service. To perform authentication, an HTTP subrequest +is sent from ingressgateway to ModSecurity where the subrequest is verified. If +the subrequest is clean, ModSecurity will return a 2xx response code, access is +allowed; If it returns 401 or 403, access is denied. + + +Deploying the ModSecurity WAF +============================== + +.. _modsecurity_prerequisites: + +Prerequisites +------------- + +The following assumptions must be met before continuing on to deployment: + + * Installation of Kubernetes has already been performed. + * Installation of Istio and Istio client (istioctl) is in your PATH. + +Deploy from source +------------------ + +Clone the Clover git repository and navigate within the samples directory as +shown below: + +.. code-block:: bash + + $ git clone https://gerrit.opnfv.org/gerrit/clover + $ cd clover/samples/scenarios + $ git checkout stable/gambia + +To deploy the ModSecurity WAF in the "clover-gateway" Kubernetes namespace, use +the following command: + +.. code-block:: bash + + $ kubectl create namespace clover-gateway + $ kubectl apply -n clover-gateway -f modsecurity_all_in_one.yaml + +Verifying the deployment +------------------------ + +To verify the ModSecurity pod is deployed, executing the command below: + +.. code-block:: bash + + $ kubectl get pod -n clover-gateway + +The listing below must include the following ModSecurity pod: + +.. code-block:: bash + + $ NAME READY STATUS RESTARTS AGE + modsecurity-crs-cf5fffcc-whwqm 1/1 Running 0 1d + +To verify the ModSecurity service is created, executing the command below: + +.. code-block:: bash + + $ kubectl get svc -n clover-gateway + +The listing below must include the following ModSecurity service: + +.. code-block:: bash + + $ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + modsecurity-crs NodePort 10.233.11.72 80:31346/TCP 1d + +To verify the ext-authz Envoy filter is created, executing the command below: + +.. code-block:: bash + + $ istioctl get envoyfilter -n clover-gateway + +The listing below must include the following Envoy filter: + +.. code-block:: bash + + $ NAME KIND NAMESPACE AGE + ext-authz EnvoyFilter.networking.istio.io.v1alpha3 istio-system 1d + + +ModSecurity configuration +========================== + +OWASP ModSecurity CRS mode +--------------------------- + +The OWASP ModSecurity CRS can run in two modes: + +* **Anomaly Scoring Mode** - In this mode, each matching rule increases an +'anomaly score'. At the conclusion of the inbound rules, and again at the +conclusion of the outbound rules, the anomaly score is checked, and the blocking +evaluation rules apply a disruptive action, by default returning an error 403. + +* **Self-Contained Mode** - In this mode, rules apply an action instantly. Rules +inherit the disruptive action that you specify (i.e. deny, drop, etc). The first +rule that matches will execute this action. In most cases this will cause evaluation +to stop after the first rule has matched, similar to how many IDSs function. + +By default, the CRS runs in Anomally scoring mode. + +You can configurate CRS mode by editing the **crs-setup.conf** in the modsecurity-crs +container: + +.. code-block:: bash + + $ kubectl exec -t -i -n clover-gateway [modsecurity-crs-pod-name] -c modsecurity-crs -- bash + $ vi /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf + +Alert logging +------------- + +By default, CRS enables all detailed logging to the ModSecurity audit log. +You can check the audit log using the command below: + +.. code-block:: bash + + $ kubectl exec -t -i -n clover-gateway [modsecurity-crs-pod-name] -c modsecurity-crs -- cat /var/log/modsec_audit.log + +CRS Rules +--------- + +By default, Clover enables all OWASP CRS rules. Below is a short description of all enabled rules: + +* **REQUEST-905-COMMON-EXCEPTIONS** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf + +Some rules are quite prone to causing false positives in well established software, +such as Apache callbacks or Google Analytics tracking cookie. This file offers +rules that will allow the transactions to avoid triggering these false positives. + +* **REQUEST-910-IP-REPUTATION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-910-IP-REPUTATION.conf + +These rules deal with detecting traffic from IPs that have previously been involved +with malicious activity, either on our local site or globally. + +* **REQUEST-912-DOS-PROTECTION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-912-DOS-PROTECTION.conf + +The rules in this file will attempt to detect some level 7 DoS (Denial of Service) +attacks against your server. + +* **REQUEST-913-SCANNER-DETECTION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-913-SCANNER-DETECTION.conf + +These rules are concentrated around detecting security tools and scanners. + + +* **REQUEST-920-PROTOCOL-ENFORCEMENT** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf + +The rules in this file center around detecting requests that either violate HTTP +or represent a request that no modern browser would generate, for instance missing +a user-agent. + +* **REQUEST-921-PROTOCOL-ATTACK** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf + +The rules in this file focus on specific attacks against the HTTP protocol itself +such as HTTP Request Smuggling and Response Splitting. + +* **REQUEST-930-APPLICATION-ATTACK-LFI** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf + +These rules attempt to detect when a user is trying to include a file that would +be local to the webserver that they should not have access to. Exploiting this type +of attack can lead to the web application or server being compromised. + +* **REQUEST-931-APPLICATION-ATTACK-RFI** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf + +These rules attempt to detect when a user is trying to include a remote resource +into the web application that will be executed. Exploiting this type of attack can +lead to the web application or server being compromised. + + +* **REQUEST-941-APPLICATION-ATTACK-SQLI** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-SQLI.conf + +Within this configuration file we provide rules that protect against SQL injection +attacks. SQL attackers occur when an attacker passes crafted control characters +to parameters to an area of the application that is expecting only data. The +application will then pass the control characters to the database. This will end +up changing the meaning of the expected SQL query. + +* **REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf + +These rules focus around providing protection against Session Fixation attacks. + +* **REQUEST-949-BLOCKING-EVALUATION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf + +These rules provide the anomaly based blocking for a given request. If you are in +anomaly detection mode this file must not be deleted. + +* **RESPONSE-954-DATA-LEAKAGES-IIS** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf + +These rules provide protection against data leakages that may occur because of Microsoft IIS + + +* **RESPONSE-952-DATA-LEAKAGES-JAVA** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf + +These rules provide protection against data leakages that may occur because of Java + + +* **RESPONSE-953-DATA-LEAKAGES-PHP** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf + +These rules provide protection against data leakages that may occur because of PHP + + +* **RESPONSE-950-DATA-LEAKAGES** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf + +These rules provide protection against data leakages that may occur genericly + +* **RESPONSE-951-DATA-LEAKAGES-SQL** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf + +These rules provide protection against data leakages that may occur from backend +SQL servers. Often these are indicative of SQL injection issues being present. + +* **RESPONSE-959-BLOCKING-EVALUATION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf + +These rules provide the anomaly based blocking for a given response. If you are +in anomaly detection mode this file must not be deleted. + +* **RESPONSE-980-CORRELATION** +Configuration Path: /etc/apache2/modsecurity.d/owasp-crs/rules/RESPONSE-980-CORRELATION.conf + +The rules in this configuration file facilitate the gathering of data about +successful and unsuccessful attacks on the server. diff --git a/samples/scenarios/ingressgateway_ext_authz_filter.yaml b/samples/scenarios/ingressgateway_ext_authz_filter.yaml new file mode 100644 index 0000000..0960a50 --- /dev/null +++ b/samples/scenarios/ingressgateway_ext_authz_filter.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz + namespace: clover-gateway +spec: + workloadLabels: + app: istio-ingressgateway + filters: + - insertPosition: + index: FIRST + listenerMatch: + portNumber: 80 + listenerType: GATEWAY + listenerProtocol: HTTP + filterType: HTTP + filterName: "envoy.ext_authz" + filterConfig: + http_service: + server_uri: + uri: "http://modsecurity-crs.clover-gateway.svc.cluster.local" + cluster: "outbound|80||modsecurity-crs.clover-gateway.svc.cluster.local" + timeout: 0.5s + failure_mode_allow: false diff --git a/samples/scenarios/istio_ingressgateway_envoyfilter.yaml b/samples/scenarios/istio_ingressgateway_envoyfilter.yaml deleted file mode 100644 index 46f730c..0000000 --- a/samples/scenarios/istio_ingressgateway_envoyfilter.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: networking.istio.io/v1alpha3 -kind: EnvoyFilter -metadata: - name: ext-authz - namespace: istio-system -spec: - workloadLabels: - app: istio-ingressgateway - filters: - - insertPosition: - index: FIRST - listenerMatch: - portNumber: 80 - listenerType: GATEWAY - listenerProtocol: HTTP - filterType: HTTP - filterName: "envoy.ext_authz" - filterConfig: - http_service: - server_uri: - uri: "http://modsecurity-crs.istio-system.svc.cluster.local" - cluster: "outbound|80||modsecurity-crs.istio-system.svc.cluster.local" - timeout: 0.5s - failure_mode_allow: false diff --git a/samples/scenarios/modsecurity_all_in_one.yaml b/samples/scenarios/modsecurity_all_in_one.yaml new file mode 100644 index 0000000..aa92b13 --- /dev/null +++ b/samples/scenarios/modsecurity_all_in_one.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: modsecurity-crs + namespace: clover-gateway +spec: + replicas: 1 + selector: + matchLabels: + app: modsecurity-crs + template: + metadata: + labels: + app: modsecurity-crs + spec: + containers: + - name: modsecurity-crs + image: clover/clover-ns-modsecurity-crs + ports: + - containerPort: 80 + env: + - name: PARANOIA + value: '1' +--- +apiVersion: v1 +kind: Service +metadata: + name: modsecurity-crs + namespace: clover-gateway +spec: + type: NodePort + ports: + - port: 80 + name: http-modsecurity-crs + protocol: TCP + targetPort: 80 + selector: + app: modsecurity-crs +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz + namespace: clover-gateway +spec: + workloadLabels: + app: istio-ingressgateway + filters: + - insertPosition: + index: FIRST + listenerMatch: + portNumber: 80 + listenerType: GATEWAY + listenerProtocol: HTTP + filterType: HTTP + filterName: "envoy.ext_authz" + filterConfig: + http_service: + server_uri: + uri: "http://modsecurity-crs.clover-gateway.svc.cluster.local" + cluster: "outbound|80||modsecurity-crs.clover-gateway.svc.cluster.local" + timeout: 0.5s + failure_mode_allow: false +--- diff --git a/samples/services/modsecurity/yaml/manifest.template b/samples/services/modsecurity/yaml/manifest.template index afeb9dc..2206e6d 100644 --- a/samples/services/modsecurity/yaml/manifest.template +++ b/samples/services/modsecurity/yaml/manifest.template @@ -3,6 +3,7 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: name: {{ deploy_name }} + namespace: {{ deploy_namespace }} labels: app: {{ deploy_name }} spec: @@ -26,6 +27,7 @@ apiVersion: v1 kind: Service metadata: name: {{ deploy_name }} + namespace: {{ deploy_namespace }} labels: app: {{ deploy_name }} spec: diff --git a/samples/services/modsecurity/yaml/modsecurity-deployment.yaml b/samples/services/modsecurity/yaml/modsecurity-deployment.yaml index 450ede5..1e88f30 100644 --- a/samples/services/modsecurity/yaml/modsecurity-deployment.yaml +++ b/samples/services/modsecurity/yaml/modsecurity-deployment.yaml @@ -2,6 +2,7 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: name: modsecurity-crs + namespace: clover-gateway spec: replicas: 1 selector: diff --git a/samples/services/modsecurity/yaml/modsecurity-service.yaml b/samples/services/modsecurity/yaml/modsecurity-service.yaml index 8548dca..7432630 100644 --- a/samples/services/modsecurity/yaml/modsecurity-service.yaml +++ b/samples/services/modsecurity/yaml/modsecurity-service.yaml @@ -2,6 +2,7 @@ apiVersion: v1 kind: Service metadata: name: modsecurity-crs + namespace: clover-gateway spec: type: NodePort ports: diff --git a/samples/services/modsecurity/yaml/render_yaml.py b/samples/services/modsecurity/yaml/render_yaml.py index 54f8069..67622d6 100644 --- a/samples/services/modsecurity/yaml/render_yaml.py +++ b/samples/services/modsecurity/yaml/render_yaml.py @@ -22,6 +22,7 @@ def render_yaml(args): image_name=args['image_name'], image_tag=args['image_tag'], deploy_name=args['deploy_name'], + deploy_namespace=args['deploy_namespace'], http_port=args['http_port'], paranoia_level=args['paranoia_level'] ) @@ -48,6 +49,9 @@ if __name__ == '__main__': parser.add_argument( '--deploy_name', default='modsecurity-crs', help='The k8s deploy name to use') + parser.add_argument( + '--deploy_namespace', default='clover-gateway', + help='The k8s namespace to deploy pod and service') parser.add_argument( '--http_port', default='80', help='Analyze http traffic on this port') -- cgit 1.2.3-korg