Skip to content

Commit

Permalink
NGINX Ingress Controller Configuration guide update (#2864)
Browse files Browse the repository at this point in the history
* Missing_Documentation_for_Use_Cases_for_NAP_within_NIC
  • Loading branch information
rranghar authored and ciarams87 committed Aug 22, 2022
1 parent b64cb1e commit fde2ede
Showing 1 changed file with 292 additions and 6 deletions.
298 changes: 292 additions & 6 deletions docs/content/app-protect/configuration.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
---
title: Configuration

description: "This document describes how to configure the NGINX App Protect module"
description: "This document describes how to configure the NGINX App Protect module."
weight: 1900
doctypes: [""]
toc: true
docs: "DOCS-578"
---

This document describes how to configure the NGINX App Protect module
> Check out the complete [NGINX Ingress Controller with App Protect example resources on GitHub](https://github.com/nginxinc/kubernetes-ingress/tree/v2.3.0/examples/appprotect).
> Check out the complete NGINX Ingress Controller with App Protect example resources on GitHub for [VirtualServer resources](https://github.com/nginxinc/kubernetes-ingress/tree/main/examples/custom-resources/waf) and for [Ingress resources](https://github.com/nginxinc/kubernetes-ingress/tree/v2.3.0/examples/appprotect).
## Global Configuration

The NGINX Ingress Controller has a set of global configuration parameters that align with those available in the NGINX App Protect module. See [ConfigMap keys](/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#modules) for the complete list. The App Protect parameters use the `app-protect*` prefix.

> Check out the complete [NGINX Ingress Controller with App Protect example resources on GitHub](https://github.com/nginxinc/kubernetes-ingress/tree/v2.3.0/examples/appprotect).
## Enable App Protect for an Ingress Resource
## Enabling App Protect

You can enable and configure NGINX App Protect on the Custom Resources (VirtualServer, VirtualServerRoute) or on the Ingress-resource basis.

To configure NGINX App Protect on a VirtualServer resource, you would create a Policy Custom Resource referencing the APPolicy Custom Resource, and add this to the VirtualServer definition. See the documentation on the [App Protect WAF Policy](/nginx-ingress-controller/configuration/policy-resource/#waf).

To configure NGINX App Protect on an Ingress resource, you would apply the [App Protect annotations](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations/#app-protect) to each desired resource.

You can enable and configure NGINX App Protect on a per-Ingress-resource basis. To do so, you can apply the [App Protect annotations](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations/#app-protect) to each desired resource.

## App Protect Policies

You can define App Protect policies for your Ingress resources by creating an `APPolicy` [Custom Resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
You can define App Protect policies for your VirtualServer, VirtualServerRoute, or Ingress resources by creating an `APPolicy` [Custom Resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).

> **Note**: The fields `policy.signature-requirements[].minRevisionDatetime` and `policy.signature-requirements[].maxRevisionDatetime` are not currently supported.
Expand Down Expand Up @@ -98,6 +102,7 @@ To add any [App Protect policy](/nginx-app-protect/declarative-policy/policy/) t
```

> Notice how the fields match exactly in name and level. The Ingress Controller will transform the YAML into a valid JSON App Protect policy config.
<br>
## App Protect Logs

Expand Down Expand Up @@ -203,3 +208,284 @@ spec:
softwareVersion: 15.1.0
tag: Fruits
```

## OpenAPI Specification in NGINX Ingress Controller

The OpenAPI Specification defines the spec file format needed to describe RESTful APIs. The spec file can be written either in JSON or YAML. Using a spec file simplifies the work of implementing API protection. Refer to the [OpenAPI Specification](#https://github.com/OAI/OpenAPI-Specification) (formerly called Swagger) for details.

NGINX Ingress Controller supports OpenAPI Specification versions 2.0 and 3.0.

The simplest way to create an API protection policy is using an OpenAPI Specification file to import the details of the APIs. If you use an OpenAPI Specification file, NGINX App Protect WAF will automatically create a policy for the following properties (depending on what's included in the spec file):
* Methods
* URLs
* Parameters
* JSON profiles

An OpenAPI-ready policy template is provided with the NGINX App Protect WAF packages and is located in: `/etc/app_protect/conf/NginxApiSecurityPolicy.json`

It contains violations related to OpenAPI set to blocking (enforced).

### Types of OpenAPI References

There are different ways of referencing OpenAPI Specification files. The configuration is similar to [External References](#external-references).

**Note**: Any update of an OpenAPI Specification file referenced in the policy will not trigger a policy compilation. This action needs to be done actively by reloading the NGINX configuration.

#### URL Reference

URL reference is the method of referencing an external source by providing its full URL.

Make sure to configure certificates prior to using the HTTPS protocol - see the [External References](#https-reference) for details.

## Configuration in NGINX Ingress Controller

These are the typical steps to deploy an OpenAPI protection Policy in NGINX Ingress Controller:

1. Copy the API security policy `/etc/app_protect/conf/NginxApiSecurityPolicy.json` to a different file so that it can be edited.
2. Add the reference to the desired OpenAPI file.
3. Make other custom changes if needed (e.g. enable Data Guard protection).
4. Use a tool to convert the result to YAML. There are many, for example: [`yq` utility](https://github.com/mikefarah/yq).
5. Add the YAML properties to create an `APPolicy` Custom Resource putting the policy itself (as in step 4) within the `spec` property of the Custom Resource. Refer to [App Protect Policies](#app-protect-policies) section above.
6. Create a `Policy` object which references the `APPolicy` Custom Resource as in [this example](https://github.com/nginxinc/kubernetes-ingress/blob/main/examples/custom-resources/waf/waf.yaml).
7. Finally, attach the `Policy` object to a `VirtualServer` resource as in [this example](https://github.com/nginxinc/kubernetes-ingress/blob/main/examples/custom-resources/waf/virtual-server.yaml).

**Note**: You need to make sure that the server where the resource files are located is always available when you are compiling your policy.

##### Example Configuration

In this example, we are adding an OpenAPI Specification file reference to `/etc/app_protect/conf/NginxApiSecurityPolicy.yaml` using the [link](https://raw.githubusercontent.com/aws-samples/api-gateway-secure-pet-store/master/src/main/resources/swagger.yaml). This will configure allowed data types for `query_int` and `query_str` parameters values.

**Policy configuration:**

~~~yaml
---
apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
name: petstore_api_security_policy
spec:
policy:
name: petstore_api_security_policy
description: NGINX App Protect WAF API Security Policy for the Petstore API
template:
name: POLICY_TEMPLATE_NGINX_BASE
open-api-files:
- link: https://raw.githubusercontent.com/aws-samples/api-gateway-secure-pet-store/master/src/main/resources/swagger.yaml
blocking-settings:
violations:
- block: true
description: Disallowed file upload content detected in body
name: VIOL_FILE_UPLOAD_IN_BODY
- block: true
description: Mandatory request body is missing
name: VIOL_MANDATORY_REQUEST_BODY
- block: true
description: Illegal parameter location
name: VIOL_PARAMETER_LOCATION
- block: true
description: Mandatory parameter is missing
name: VIOL_MANDATORY_PARAMETER
- block: true
description: JSON data does not comply with JSON schema
name: VIOL_JSON_SCHEMA
- block: true
description: Illegal parameter array value
name: VIOL_PARAMETER_ARRAY_VALUE
- block: true
description: Illegal Base64 value
name: VIOL_PARAMETER_VALUE_BASE64
- block: true
description: Disallowed file upload content detected
name: VIOL_FILE_UPLOAD
- block: true
description: Illegal request content type
name: VIOL_URL_CONTENT_TYPE
- block: true
description: Illegal static parameter value
name: VIOL_PARAMETER_STATIC_VALUE
- block: true
description: Illegal parameter value length
name: VIOL_PARAMETER_VALUE_LENGTH
- block: true
description: Illegal parameter data type
name: VIOL_PARAMETER_DATA_TYPE
- block: true
description: Illegal parameter numeric value
name: VIOL_PARAMETER_NUMERIC_VALUE
- block: true
description: Parameter value does not comply with regular expression
name: VIOL_PARAMETER_VALUE_REGEXP
- block: true
description: Illegal URL
name: VIOL_URL
- block: true
description: Illegal parameter
name: VIOL_PARAMETER
- block: true
description: Illegal empty parameter value
name: VIOL_PARAMETER_EMPTY_VALUE
- block: true
description: Illegal repeated parameter name
name: VIOL_PARAMETER_REPEATED

~~~

Content of the referenced file `myapi.yaml`:

~~~yaml
openapi: 3.0.1
info:
title: 'Primitive data types'
description: 'Primitive data types.'
version: '2.5.0'
servers:
- url: http://localhost
paths:
/query:
get:
tags:
- query_int_str
description: query_int_str
operationId: query_int_str
parameters:
- name: query_int
in: query
required: false
allowEmptyValue: false
schema:
type: integer
- name: query_str
in: query
required: false
allowEmptyValue: true
schema:
type: string
responses:
200:
description: OK
404:
description: NotFound
~~~

In this case, the following request will trigger an `Illegal parameter data type` violation, as we expect to have an integer value in the `query_int` parameter:

```
http://localhost/query?query_int=abc
```

The request will be blocked.

The `link` option is also available in the `openApiFileReference` property and is synonymous with the `open-api-files` property as seen in the App Protect policy example above.

**Note**: `openApiFileReference` is not an array.


## Configuration in NGINX Plus Ingress Controller using Virtual Server Resource
In this example we deploy the NGINX Plus Ingress Controller with NGINX App Protect, a simple web application and then configure load balancing and WAF protection for that application using the VirtualServer resource.

**Note:** This example, and the files referenced, can be found [here](https://github.com/nginxinc/kubernetes-ingress/tree/main/examples/custom-resources/waf).

You can find the [Virtual Server example](https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/webapp.yaml) here.

## Prerequisites

1. Follow the installation [instructions](https://docs.nginx.com/nginx-ingress-controller/installation) to deploy the Ingress Controller with NGINX App Protect.
2. Save the public IP address of the Ingress Controller into a shell variable:
```
$ IC_IP=XXX.YYY.ZZZ.III
```

3. Save the HTTP port of the Ingress Controller into a shell variable:
```
$ IC_HTTP_PORT=<port number>
```

### Step 1. Deploy a Web Application

Create the application deployment and service:
```
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/webapp.yaml
```

### Step 2. Deploy the AP Policy

1. Create the syslog service and pod for the App Protect security logs:
```
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/syslog.yaml
```

2. Create the User Defined Signature, App Protect policy and log configuration:

```
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/ap-apple-uds.yaml
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/ap-dataguard-alarm-policy.yaml
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/ap-logconf.yaml
```

### Step 3 - Deploy the WAF Policy

Create the WAF policy
```
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/waf.yaml
```
Note the App Protect configuration settings in the Policy resource. They enable WAF protection by configuring App Protect with the policy and log configuration created in the previous step.

### Step 4 - Configure Load Balancing

1. Create the VirtualServer Resource:
```
$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/virtual-server.yaml
```
Note that the VirtualServer references the policy waf-policy created in Step 3.

### Step 5 - Test the Application

To access the application, curl the coffee and the tea services. We'll use the --resolve option to set the Host header of a request with `webapp.example.com`

1. Send a request to the application:
```
$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT/
Server address: 10.12.0.18:80
Server name: webapp-7586895968-r26zn
```

2. Now, let's try to send a request with a suspicious URL:
```
$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP "http://webapp.example.com:$IC_HTTP_PORT/<script>"
<html><head><title>Request Rejected</title></head><body>
```

3. Lastly, let's try to send some suspicious data that matches the user defined signature.
```
$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP -X POST -d "apple" http://webapp.example.com:$IC_HTTP_PORT/
<html><head><title>Request Rejected</title></head><body>
```
As you can see, the suspicious requests were blocked by App Protect

4. To check the security logs in the syslog pod:
```
$ kubectl exec -it <SYSLOG_POD> -- cat /var/log/messages
```

### Configuration Example of Virtual Server:

Refer to github repo for [Virtual Server example](https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.3.0/examples/custom-resources/waf/webapp.yaml).

```yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: webapp
spec:
host: webapp.example.com
policies:
- name: waf-policy
upstreams:
- name: webapp
service: webapp-svc
port: 80
routes:
- path: /
action:
pass: webapp
```

0 comments on commit fde2ede

Please sign in to comment.