Skip to content

Commit 90eba20

Browse files
committed
Update PLM Installation Section
1 parent 0fb248d commit 90eba20

File tree

1 file changed

+253
-61
lines changed

1 file changed

+253
-61
lines changed

content/nap-waf/v5/admin-guide/policy-lifecycle-management.md

Lines changed: 253 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ product: NAP-WAF
88

99
## Overview
1010

11-
Policy Lifecycle Management (PLM) provides a comprehensive solution for automating the management, compilation, and deployment of security policies within Kubernetes environments. PLM extends the WAF compiler capabilities by providing a native Kubernetes operator-based approach to policy orchestration.
11+
Policy Lifecycle Management (PLM) is an integrated feature of NGINX App Protect WAF that provides a comprehensive solution for automating the management, compilation, and deployment of security policies within Kubernetes environments. PLM extends the WAF compiler capabilities by providing a native Kubernetes operator-based approach to policy orchestration.
1212

1313
The Policy Lifecycle Management system is architected around a **Policy Controller** that implements the Kubernetes operator pattern to manage the complete lifecycle of WAF security artifacts. The system addresses the fundamental challenge of policy distribution at scale by eliminating manual intervention points and providing a declarative configuration model through Custom Resource Definitions (CRDs) for policies, logging profiles, signatures, and user-defined signatures.
1414

@@ -18,10 +18,9 @@ Before deploying Policy Lifecycle Management, ensure you have the following prer
1818

1919
### System Requirements
2020

21-
- Kubernetes cluster (tested with k3s)
2221
- Helm 3 installed
2322
- Docker installed and configured
24-
- NGINX Docker Image
23+
- [NGINX Docker Image]({{< ref "/nap-waf/v5/admin-guide/deploy-on-docker.md#build-the-nginx-app-protect-waf-docker-image" >}})
2524
- NGINX JWT License
2625
- Docker registry credentials for private-registry.nginx.com
2726

@@ -35,16 +34,52 @@ Policy Lifecycle Management requires specific Custom Resource Definitions to be
3534
- `apusersigs.appprotect.f5.com` - Handles user-defined signatures
3635
- `apsignatures.appprotect.f5.com` - Manages signature updates and collections
3736

38-
Apply the CRDs using the following command:
39-
```bash
40-
kubectl apply -f crds/
41-
```
4237

43-
### NGINX Configuration
38+
## Configuration
39+
40+
Policy Lifecycle Management is deployed as part of the NGINX App Protect Helm chart and requires configuration in both the Helm `values.yaml` file and the NGINX configuration.
41+
42+
### Policy Controller Configuration
43+
44+
#### Enable/Disable the Policy Controller
45+
46+
The Policy Controller option is enabled by default (`appprotect.policyController.enable: true`). Helm will also install the required custom resource definitions (CRDs) required by the policy controller pod.
47+
48+
**Important**: Before applying the Policy Controller, the required Custom Resource Definitions (CRDs) must be installed first. If the CRDs are not installed, the Policy Controller pod will fail to start and show CRD-related errors in the logs.
49+
50+
If you do not use the custom resources that require those CRDs (with `appprotect.policyController.enable` set to false), the installation of the CRDs can be skipped by specifying `--skip-crds` in your helm install command. Please also note that when upgrading helm charts, the current CRDs will need to be deleted and the new ones will be created as part of the helm install of the new version.
51+
52+
If you wish to pull security updates from the NGINX repository (with APSignatures CRD), you should set the `appprotect.nginxRepo` value in values.yaml file.
53+
54+
**Helm Configuration (values.yaml):**
55+
56+
```yaml
57+
appprotect:
58+
policyController:
59+
enable: true # Set to false to disable Policy Controller
60+
replicas: 1
61+
image:
62+
repository: private-registry.nginx.com/nap/waf-policy-controller
63+
tag: 5.8.0
64+
imagePullPolicy: IfNotPresent
65+
wafCompiler:
66+
image:
67+
repository: private-registry.nginx.com/nap/waf-compiler
68+
tag: 5.8.0
69+
enableJobLogSaving: false
70+
resources:
71+
requests:
72+
cpu: 100m
73+
memory: 128Mi
74+
# Optional: Configure NGINX repository for signature updates
75+
nginxRepo:
76+
nginxCrt: <base64-encoded-cert>
77+
nginxKey: <base64-encoded-key>
78+
```
4479
45-
Policy Lifecycle Management requires specific NGINX configuration to integrate with the Policy Controller. The key directive `app_protect_default_config_source` must be set to `"custom-resource"` to enable PLM integration.
80+
**NGINX Configuration:**
4681
47-
**Required NGINX Configuration:**
82+
When Policy Controller is enabled in Helm, you must also enable it in your NGINX configuration using the `app_protect_default_config_source` directive:
4883

4984
```nginx
5085
user nginx;
@@ -110,46 +145,18 @@ http {
110145
- `app_protect_policy_file my-policy-cr` - References the Custom Resource policy name instead of bundle file paths
111146
- `app_protect_security_log my-logging-cr` - References the Custom Resource logging configuration name
112147

113-
## Helm Chart Configuration
114-
115-
Policy Lifecycle Management is deployed as part of the NGINX App Protect Helm chart. To enable PLM, you must configure the Policy Controller settings in your `values.yaml` file.
116-
117-
### Enabling Policy Controller
118-
119-
Set the following configuration in your `values.yaml`:
120-
121-
```yaml
122-
appprotect:
123-
policyController:
124-
enable: true
125-
replicas: 1
126-
image:
127-
repository: private-registry.nginx.com/nap/waf-policy-controller
128-
tag: 5.8.0
129-
imagePullPolicy: IfNotPresent
130-
wafCompiler:
131-
image:
132-
repository: private-registry.nginx.com/nap/waf-compiler
133-
tag: 5.8.0
134-
enableJobLogSaving: false
135-
resources:
136-
requests:
137-
cpu: 100m
138-
memory: 128Mi
139-
```
148+
**To disable Policy Controller:**
149+
1. Set `appprotect.policyController.enable: false` in your values.yaml
150+
2. Remove or comment out the `app_protect_default_config_source` directive from your nginx.conf
151+
3. Use traditional bundle file paths with `app_protect_policy_file`
140152

141-
### NGINX Repository Configuration
153+
## Installation Flow
142154

143-
To enable signature updates with the APSignatures CRD, configure the NGINX repository credentials:
155+
### New Installations vs. Upgrades
144156

145-
```yaml
146-
appprotect:
147-
nginxRepo:
148-
nginxCrt: <base64-encoded-cert>
149-
nginxKey: <base64-encoded-key>
150-
```
157+
**For New Installations**: Follow the complete step-by-step process below to install NGINX App Protect WAF with Policy Lifecycle Management enabled.
151158

152-
## Installation Flow
159+
**For Existing Customers**: If you have an existing NGINX App Protect WAF deployment without Policy Lifecycle Management, you need to upgrade your installation to enable PLM functionality. Use `helm upgrade` instead of `helm install` in step 5, and ensure you have the required CRDs and storage configured before upgrading.
153160

154161
### Step-by-Step Installation Process
155162

@@ -172,27 +179,42 @@ appprotect:
172179
cd nginx-app-protect
173180
```
174181

175-
3. **Apply Custom Resource Definitions**
176-
177-
Apply the required CRDs before deploying the chart:
178-
```bash
179-
kubectl apply -f crds/
180-
```
181-
182-
4. **Create Storage**
182+
3. **Create Storage**
183183

184-
Create the directory and persistent volume for policy bundles:
184+
Create the directory on the cluster:
185185
```bash
186186
mkdir -p /mnt/nap5_bundles_pv_data
187187
chown -R 101:101 /mnt/nap5_bundles_pv_data
188-
kubectl apply -f <your-pv-yaml-file>
189188
```
190189

190+
Create a YAML file `pv-hostpath.yaml` with the persistent volume file content:
191+
```
192+
apiVersion: v1
193+
kind: PersistentVolume
194+
metadata:
195+
name: nginx-app-protect-shared-bundles-pv
196+
labels:
197+
type: local
198+
spec:
199+
accessModes:
200+
- ReadWriteMany
201+
capacity:
202+
storage: "2Gi"
203+
hostPath:
204+
path: "/mnt/nap5_bundles_pv_data"
205+
persistentVolumeReclaimPolicy: Retain
206+
storageClassName: manual
207+
```
208+
Apply the `pv-hostpath.yaml` file to create the new persistent volume for policy bundles:
209+
```shell
210+
kubectl apply -f pv-hostpath.yaml
211+
```
212+
191213
{{< call-out "note" >}}
192-
The PV name defaults to `<release-name>-bundles-pv`, but can be customized using the `appprotect.storage.pv.name` setting in your values.yaml file.
214+
The PV name defaults to `<release-name>-shared-bundles-pv`, but can be customized using the `appprotect.storage.pv.name` setting in your values.yaml file. Make sure to update all corresponding values for the PV and PVC to point to the correct names.
193215
{{< /call-out >}}
194216

195-
5. **Configure Docker Registry Credentials**
217+
4. **Configure Docker Registry Credentials**
196218

197219
Create the Docker registry secret or configure in values.yaml:
198220
```bash
@@ -202,9 +224,9 @@ appprotect:
202224
--docker-password=none
203225
```
204226

205-
6. **Deploy the Helm Chart with Policy Controller**
227+
5. **Deploy the Helm Chart with Policy Controller**
206228

207-
Install the chart with Policy Controller enabled:
229+
**For new installations:**
208230
```bash
209231
helm install <release-name> . \
210232
--namespace <namespace> \
@@ -215,8 +237,19 @@ appprotect:
215237
--set appprotect.nginxRepo.nginxCert=$NGINX_CERT \
216238
--set appprotect.nginxRepo.nginxKey=$NGINX_KEY
217239
```
240+
241+
**For existing deployments (upgrade):**
242+
```bash
243+
helm upgrade <release-name> . \
244+
--namespace <namespace> \
245+
--set appprotect.policyController.enable=true \
246+
--set dockerConfigJson=$NGINX_REGISTRY_TOKEN \
247+
--set appprotect.config.nginxJWT=$JWT \
248+
--set appprotect.nginxRepo.nginxCert=$NGINX_CERT \
249+
--set appprotect.nginxRepo.nginxKey=$NGINX_KEY
250+
```
218251

219-
7. **Verify Installation**
252+
6. **Verify Installation**
220253

221254
Check that all components are deployed successfully:
222255
```bash
@@ -227,6 +260,42 @@ appprotect:
227260

228261
## Using Policy Lifecycle Management
229262

263+
### Setting up desired security update versions
264+
265+
Once PLM is deployed, you can create APSignatures resource using Kubernetes manifests and specify desired security update versions. Apply the following Custom Resource example or create your own based on the template:
266+
267+
**Sample APSignatures Resource:**
268+
269+
Create a file named `signatures.yaml` with the following content:
270+
271+
```yaml
272+
apiVersion: appprotect.f5.com/v1
273+
kind: APSignatures
274+
metadata:
275+
name: signatures
276+
spec:
277+
attack-signatures:
278+
revision: "2025.06.19" # attack signatures revision to be used
279+
bot-signatures:
280+
revision: "latest" # bot signatures revision to be used
281+
threat-campaigns:
282+
revision: "2025.06.24" # threat campaigns revision to be used
283+
```
284+
285+
{{< call-out "note" >}}
286+
The APSignatures must have name `signatures`. Only one APSignatures instance can exist
287+
{{< /call-out >}}
288+
289+
Apply the manifest:
290+
291+
```bash
292+
kubectl apply -f signatures.yaml -n <namespace>
293+
```
294+
295+
{{< call-out "note" >}}
296+
Downloading security updates may take several minutes. The version of security updates available at the time of compilation is always used to compile policies. If APSignatures is not created or the specified versions are not downloaded, the versions contained in the compiler docker image will be used.
297+
{{< /call-out >}}
298+
230299
### Creating Policy Resources
231300

232301
Once PLM is deployed, you can create policy resources using Kubernetes manifests. Apply the following Custom Resource examples or create your own based on these templates:
@@ -400,6 +469,129 @@ To verify that the policy bundles are being deployed and enforced correctly:
400469

401470
The request should be blocked, confirming that PLM has successfully compiled and deployed the policy.
402471

472+
## Upgrade the chart
473+
474+
1. **Prepare Environment Variables**
475+
476+
Set the required environment variables:
477+
```bash
478+
export JWT=<your-nginx-jwt-token>
479+
export NGINX_REGISTRY_TOKEN=<base64-encoded-docker-credentials>
480+
export NGINX_CERT=<base64-encoded-nginx-cert>
481+
export NGINX_KEY=<base64-encoded-nginx-key>
482+
```
483+
484+
2. **Pull the new Helm Chart version**
485+
486+
Login to the registry and pull the chart:
487+
```bash
488+
helm registry login private-registry.nginx.com
489+
helm pull oci://private-registry.nginx.com/nap/nginx-app-protect --version <new-release-version> --untar
490+
cd nginx-app-protect
491+
```
492+
493+
3. **Apply Custom Resource Definitions**
494+
495+
Apply the required CRDs before deploying the chart:
496+
```bash
497+
kubectl apply -f crds/
498+
```
499+
500+
4. **Create Storage**
501+
502+
Create the directory on the cluster, and persistent volume for policy bundles:
503+
```bash
504+
mkdir -p /mnt/nap5_bundles_pv_data
505+
chown -R 101:101 /mnt/nap5_bundles_pv_data
506+
```
507+
508+
Create a YAML file `pv-hostpath.yaml` with the PV file content:
509+
```
510+
apiVersion: v1
511+
kind: PersistentVolume
512+
metadata:
513+
name: nginx-app-protect-shared-bundles-pv
514+
labels:
515+
type: local
516+
spec:
517+
accessModes:
518+
- ReadWriteMany
519+
capacity:
520+
storage: "2Gi"
521+
hostPath:
522+
path: "/mnt/nap5_bundles_pv_data"
523+
persistentVolumeReclaimPolicy: Retain
524+
storageClassName: manual
525+
```
526+
Apply the `pv-hostpath.yaml` file to create the new PV:
527+
```shell
528+
kubectl apply -f pv-hostpath.yaml
529+
```
530+
531+
{{< call-out "note" >}}
532+
The PV name defaults to `<release-name>-shared-bundles-pv`, but can be customized using the `appprotect.storage.pv.name` setting in your values.yaml file.
533+
{{< /call-out >}}
534+
535+
5. **Configure Docker Registry Credentials**
536+
537+
Create the Docker registry secret or configure in values.yaml:
538+
```bash
539+
kubectl create secret docker-registry regcred -n <namespace> \
540+
--docker-server=private-registry.nginx.com \
541+
--docker-username=<JWT-Token> \
542+
--docker-password=none
543+
```
544+
545+
6. **Upgrade the Helm Chart with Policy Controller**
546+
547+
Upgrade the chart with Policy Controller enabled:
548+
```bash
549+
helm upgrade <release-name> . \
550+
--namespace <namespace> \
551+
--set appprotect.policyController.enable=true \
552+
--set dockerConfigJson=$NGINX_REGISTRY_TOKEN \
553+
--set appprotect.config.nginxJWT=$JWT \
554+
--set appprotect.nginxRepo.nginxCert=$NGINX_CERT \
555+
--set appprotect.nginxRepo.nginxKey=$NGINX_KEY
556+
```
557+
558+
7. **Verify Upgrade**
559+
560+
Check that all components are deployed successfully:
561+
```bash
562+
kubectl get pods -n <namespace>
563+
kubectl get crds | grep appprotect.f5.com
564+
kubectl get all -n <namespace>
565+
```
566+
567+
## Uninstall the chart
568+
569+
1. **Manually Delete the CRs**
570+
571+
Delete all the existing CRs created for the deployment:
572+
```bash
573+
kubectl -n <namespace> delete appolicy <policy-name>
574+
kubectl -n <namespace> delete aplogconf <logconf-name>
575+
kubectl -n <namespace> delete apusersigs <user-defined-signature-name>
576+
kubectl -n <namespace> delete apsignatures <signature-update-name>
577+
```
578+
2. **Uninstall/delete the release `<release-name>`**
579+
580+
To delete the current release, you just need to delete it using helm:
581+
```bash
582+
helm uninstall <release-name> -n <namespace>
583+
```
584+
585+
3. **Delete any possible residual resources**
586+
587+
Delete any remaining CRDs, PVC, PV, and the namespace:
588+
```bash
589+
kubectl delete pvc nginx-app-protect-shared-bundles-pvc -n <namespace>
590+
kubectl delete pv nginx-app-protect-shared-bundles-pv
591+
kubectl delete crd --all
592+
kubectl delete ns <namespace>
593+
```
594+
403595
## Troubleshooting
404596

405597
### Common Issues

0 commit comments

Comments
 (0)