Skip to content

Commit c479b82

Browse files
authored
Merge branch 'feat/nap-waf' into feat/wafpolicy-crd
2 parents b403e07 + 173fcf2 commit c479b82

File tree

22 files changed

+2497
-215
lines changed

22 files changed

+2497
-215
lines changed

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ CHART_DIR = $(SELF_DIR)charts/nginx-gateway-fabric
55
NGINX_CONF_DIR = internal/controller/nginx/conf
66
NJS_DIR = internal/controller/nginx/modules/src
77
KIND_CONFIG_FILE = $(SELF_DIR)config/cluster/kind-cluster.yaml
8+
NAP_WAF_ALPINE_VERSION = 3.19
89
NGINX_DOCKER_BUILD_PLUS_ARGS = --secret id=nginx-repo.crt,src=$(SELF_DIR)nginx-repo.crt --secret id=nginx-repo.key,src=$(SELF_DIR)nginx-repo.key
10+
NGINX_DOCKER_BUILD_NAP_WAF_ARGS = --build-arg ALPINE_VERSION=$(NAP_WAF_ALPINE_VERSION) --build-arg INCLUDE_NAP_WAF=true
911
BUILD_AGENT = local
1012

1113
PROD_TELEMETRY_ENDPOINT = oss.edge.df.f5.com:443
@@ -77,6 +79,9 @@ build-images: build-ngf-image build-nginx-image ## Build the NGF and nginx docke
7779
.PHONY: build-images-with-plus
7880
build-images-with-plus: build-ngf-image build-nginx-plus-image ## Build the NGF and NGINX Plus docker images
7981

82+
.PHONY: build-images-nap-waf
83+
build-images-with-nap-waf: build-ngf-image build-nginx-plus-image-with-nap-waf ## Build the NGF and NGINX Plus with WAF docker images
84+
8085
.PHONY: build-prod-ngf-image
8186
build-prod-ngf-image: TELEMETRY_ENDPOINT=$(PROD_TELEMETRY_ENDPOINT)
8287
build-prod-ngf-image: build-ngf-image ## Build the NGF docker image for production
@@ -99,6 +104,13 @@ build-prod-nginx-plus-image: build-nginx-plus-image ## Build the custom nginx pl
99104
build-nginx-plus-image: check-for-docker ## Build the custom nginx plus image
100105
docker build --platform linux/$(GOARCH) $(strip $(NGINX_DOCKER_BUILD_OPTIONS)) $(strip $(NGINX_DOCKER_BUILD_PLUS_ARGS)) -f $(SELF_DIR)build/Dockerfile.nginxplus -t $(strip $(NGINX_PLUS_PREFIX)):$(strip $(TAG)) $(strip $(SELF_DIR))
101106

107+
.PHONY: build-nginx-plus-image-with-nap-waf
108+
build-nginx-plus-image-with-nap-waf: check-for-docker ## Build the custom nginx plus image with NAP WAF. Note that arm is NOT supported.
109+
@if [ $(GOARCH) = "arm64" ]; then \
110+
echo "\033[0;31mIMPORTANT:\033[0m The nginx-plus-waf image cannot be built for arm64 architecture and will be built for amd64."; \
111+
fi
112+
docker build --platform linux/amd64 $(strip $(NGINX_DOCKER_BUILD_OPTIONS)) $(strip $(NGINX_DOCKER_BUILD_PLUS_ARGS)) $(strip $(NGINX_DOCKER_BUILD_NAP_WAF_ARGS)) -f $(SELF_DIR)build/Dockerfile.nginxplus -t $(strip $(NGINX_PLUS_PREFIX)):$(strip $(TAG)) $(strip $(SELF_DIR))
113+
102114
.PHONY: check-for-docker
103115
check-for-docker: ## Check if Docker is installed
104116
@docker -v || (code=$$?; printf "\033[0;31mError\033[0m: there was a problem with Docker\n"; exit $$code)

apis/v1alpha2/nginxproxy_types.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,35 @@ type NginxProxySpec struct {
7171
//
7272
// +optional
7373
DisableHTTP2 *bool `json:"disableHTTP2,omitempty"`
74+
// WAF enables NGINX App Protect WAF functionality.
75+
// When enabled, NGINX Gateway Fabric will deploy additional WAF containers
76+
// (waf-enforcer and waf-config-mgr) alongside the main NGINX container.
77+
// Default is "disabled".
78+
//
79+
// +optional
80+
// +kubebuilder:default:=disabled
81+
WAF *WAFState `json:"waf,omitempty"`
7482
// Kubernetes contains the configuration for the NGINX Deployment and Service Kubernetes objects.
7583
//
7684
// +optional
7785
Kubernetes *KubernetesSpec `json:"kubernetes,omitempty"`
7886
}
7987

88+
// WAFState defines the state of WAF functionality.
89+
//
90+
// +kubebuilder:validation:Enum=enabled;disabled
91+
type WAFState string
92+
93+
const (
94+
// WAFEnabled enables NGINX App Protect WAF functionality.
95+
// This will deploy additional containers for WAF enforcement and configuration management.
96+
WAFEnabled WAFState = "enabled"
97+
98+
// WAFDisabled disables NGINX App Protect WAF functionality.
99+
// Only the standard NGINX container will be deployed.
100+
WAFDisabled WAFState = "disabled"
101+
)
102+
80103
// Telemetry specifies the OpenTelemetry configuration.
81104
type Telemetry struct {
82105
// DisabledFeatures specifies OpenTelemetry features to be disabled.
@@ -387,6 +410,12 @@ type DeploymentSpec struct {
387410
// +optional
388411
Replicas *int32 `json:"replicas,omitempty"`
389412

413+
// WAFContainers defines container specifications for NGINX App Protect WAF v5 containers.
414+
// These containers are only deployed when WAF is enabled in the NginxProxy spec.
415+
//
416+
// +optional
417+
WAFContainers *WAFContainerSpec `json:"wafContainers,omitempty"`
418+
390419
// Pod defines Pod-specific fields.
391420
//
392421
// +optional
@@ -400,6 +429,12 @@ type DeploymentSpec struct {
400429

401430
// DaemonSet is the configuration for the NGINX DaemonSet.
402431
type DaemonSetSpec struct {
432+
// WAFContainers defines container specifications for NGINX App Protect WAF v5 containers.
433+
// These containers are only deployed when WAF is enabled in the NginxProxy spec.
434+
//
435+
// +optional
436+
WAFContainers *WAFContainerSpec `json:"wafContainers,omitempty"`
437+
403438
// Pod defines Pod-specific fields.
404439
//
405440
// +optional
@@ -484,6 +519,40 @@ type ContainerSpec struct {
484519
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
485520
}
486521

522+
// WAFContainerSpec defines the container specifications for NGINX App Protect WAF v5.
523+
// NAP v5 requires two additional containers: waf-enforcer and waf-config-mgr.
524+
type WAFContainerSpec struct {
525+
// Enforcer defines the configuration for the WAF enforcer container.
526+
// This container performs the actual WAF enforcement and policy application.
527+
//
528+
// +optional
529+
Enforcer *WAFContainerConfig `json:"enforcer,omitempty"`
530+
531+
// ConfigManager defines the configuration for the WAF configuration manager container.
532+
// This container manages policy configuration and communication with the enforcer.
533+
//
534+
// +optional
535+
ConfigManager *WAFContainerConfig `json:"configManager,omitempty"`
536+
}
537+
538+
// WAFContainerConfig defines the configuration for a single WAF container.
539+
type WAFContainerConfig struct {
540+
// Image is the container image to use for this WAF container.
541+
//
542+
// +optional
543+
Image *Image `json:"image,omitempty"`
544+
545+
// Resources describes the compute resource requirements for this WAF container.
546+
//
547+
// +optional
548+
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
549+
550+
// VolumeMounts describe the mounting of Volumes within the WAF container.
551+
//
552+
// +optional
553+
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
554+
}
555+
487556
// Image is the NGINX image to use.
488557
type Image struct {
489558
// Repository is the image path.

apis/v1alpha2/zz_generated.deepcopy.go

Lines changed: 72 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/Dockerfile.nginxplus

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# syntax=docker/dockerfile:1.16
2+
3+
# renovate: datasource=docker depName=alpine
4+
ARG ALPINE_VERSION=3.21
5+
26
FROM scratch AS nginx-files
37

48
# the following links can be replaced with local files if needed, i.e. ADD --chown=101:1001 <local_file> <container_file>
59
ADD --link --chown=101:1001 https://cs.nginx.com/static/keys/nginx_signing.rsa.pub nginx_signing.rsa.pub
610

7-
FROM alpine:3.21
11+
FROM alpine:${ALPINE_VERSION}
812

913
ARG NGINX_PLUS_VERSION=R34
1014
# renovate: datasource=github-tags depName=nginx/agent extractVersion=^v?(?<version>.*)$
1115
ARG NGINX_AGENT_VERSION=3.0.0
16+
ARG APP_PROTECT_VERSION=34.5.342
17+
ARG INCLUDE_NAP_WAF=false
1218
ARG NJS_DIR
1319
ARG NGINX_CONF_DIR
1420
ARG BUILD_AGENT
@@ -20,6 +26,10 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
2026
&& adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
2127
&& printf "%s\n" "https://pkgs.nginx.com/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
2228
&& printf "%s\n" "https://pkgs.nginx.com/nginx-agent/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
29+
&& if [ "${INCLUDE_NAP_WAF}" = "true" ]; then \
30+
printf "%s\n" "https://pkgs.nginx.com/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
31+
&& apk add --no-cache app-protect-module-plus~=${APP_PROTECT_VERSION}; \
32+
fi \
2333
&& apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-agent=${NGINX_AGENT_VERSION}
2434

2535
RUN apk add --no-cache libcap bash \
@@ -45,4 +55,5 @@ USER 101:1001
4555

4656
LABEL org.nginx.ngf.image.build.agent="${BUILD_AGENT}"
4757

58+
ENV USE_NAP_WAF=${INCLUDE_NAP_WAF}
4859
ENTRYPOINT ["/agent/entrypoint.sh"]

build/entrypoint.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ trap 'handle_quit' QUIT
2727

2828
rm -rf /var/run/nginx/*.sock
2929

30+
# Bootstrap the necessary app protect files
31+
if [ "${USE_NAP_WAF:-false}" = "true" ]; then
32+
touch /opt/app_protect/bd_config/policy_path.map
33+
fi
34+
3035
# Launch nginx
3136
echo "starting nginx ..."
3237

charts/nginx-gateway-fabric/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ The following table lists the configurable parameters of the NGINX Gateway Fabri
259259
| `certGenerator.serverTLSSecretName` | The name of the Secret containing TLS CA, certificate, and key for the NGINX Gateway Fabric control plane to securely communicate with the NGINX Agent. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `"server-tls"` |
260260
| `clusterDomain` | The DNS cluster domain of your Kubernetes cluster. | string | `"cluster.local"` |
261261
| `gateways` | A list of Gateway objects. View https://gateway-api.sigs.k8s.io/reference/spec/#gateway for full Gateway reference. | list | `[]` |
262-
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false}}` |
262+
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false},"wafContainers":{}}` |
263263
| `nginx.config` | The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways managed by this instance of NGINX Gateway Fabric. | object | `{}` |
264264
| `nginx.container` | The container configuration for the NGINX container. This is applied globally to all Gateways managed by this instance of NGINX Gateway Fabric. | object | `{}` |
265265
| `nginx.debug` | Enable debugging for NGINX. Uses the nginx-debug binary. The NGINX error log level should be set to debug in the NginxProxy resource. | bool | `false` |
@@ -283,6 +283,7 @@ The following table lists the configurable parameters of the NGINX Gateway Fabri
283283
| `nginx.usage.resolver` | The nameserver used to resolve the NGINX Plus usage reporting endpoint. Used with NGINX Instance Manager. | string | `""` |
284284
| `nginx.usage.secretName` | The name of the Secret containing the JWT for NGINX Plus usage reporting. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `"nplus-license"` |
285285
| `nginx.usage.skipVerify` | Disable client verification of the NGINX Plus usage reporting server certificate. | bool | `false` |
286+
| `nginx.wafContainers` | Configuration for NGINX App Protect WAF v5 containers. These containers are only deployed when WAF is enabled via nginx.config.waf: "Enabled". All settings are optional overrides - defaults are provided by NGF. | object | `{}` |
286287
| `nginxGateway` | The nginxGateway section contains configuration for the NGINX Gateway Fabric control plane deployment. | object | `{"affinity":{},"config":{"logging":{"level":"info"}},"configAnnotations":{},"extraVolumeMounts":[],"extraVolumes":[],"gatewayClassAnnotations":{},"gatewayClassName":"nginx","gatewayControllerName":"gateway.nginx.org/nginx-gateway-controller","gwAPIExperimentalFeatures":{"enable":false},"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric","tag":"edge"},"kind":"deployment","labels":{},"leaderElection":{"enable":true,"lockName":""},"lifecycle":{},"metrics":{"enable":true,"port":9113,"secure":false},"nodeSelector":{},"podAnnotations":{},"productTelemetry":{"enable":true},"readinessProbe":{"enable":true,"initialDelaySeconds":3,"port":8081},"replicas":1,"resources":{},"service":{"annotations":{}},"serviceAccount":{"annotations":{},"imagePullSecret":"","imagePullSecrets":[],"name":""},"snippetsFilters":{"enable":false},"terminationGracePeriodSeconds":30,"tolerations":[],"topologySpreadConstraints":[]}` |
287288
| `nginxGateway.affinity` | The affinity of the NGINX Gateway Fabric control plane pod. | object | `{}` |
288289
| `nginxGateway.config.logging.level` | Log level. | string | `"info"` |

charts/nginx-gateway-fabric/templates/nginxproxy.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ spec:
2626
{{- if .Values.nginx.debug }}
2727
debug: {{ .Values.nginx.debug }}
2828
{{- end }}
29+
{{- if and .Values.nginx.wafContainers }}
30+
wafContainers:
31+
{{- toYaml .Values.nginx.wafContainers | nindent 8 }}
32+
{{- end }}
2933
{{- end }}
3034
{{- if eq .Values.nginx.kind "daemonSet" }}
3135
daemonSet:
@@ -42,6 +46,10 @@ spec:
4246
{{- if .Values.nginx.debug }}
4347
debug: {{ .Values.nginx.debug }}
4448
{{- end }}
49+
{{- if and .Values.nginx.wafContainers }}
50+
wafContainers:
51+
{{- toYaml .Values.nginx.wafContainers | nindent 8 }}
52+
{{- end }}
4553
{{- end }}
4654
{{- if .Values.nginx.service }}
4755
service:

charts/nginx-gateway-fabric/values.schema.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,15 @@
268268
},
269269
"required": [],
270270
"type": "object"
271+
},
272+
"waf": {
273+
"description": "WAF enables NGINX App Protect WAF functionality.",
274+
"enum": [
275+
"enabled",
276+
"disabled"
277+
],
278+
"required": [],
279+
"type": "string"
271280
}
272281
},
273282
"required": [],
@@ -488,6 +497,12 @@
488497
"required": [],
489498
"title": "usage",
490499
"type": "object"
500+
},
501+
"wafContainers": {
502+
"description": "Configuration for NGINX App Protect WAF v5 containers.\nThese containers are only deployed when WAF is enabled via nginx.config.waf: \"Enabled\".\nAll settings are optional overrides - defaults are provided by NGF.",
503+
"required": [],
504+
"title": "wafContainers",
505+
"type": "object"
491506
}
492507
},
493508
"required": [],

charts/nginx-gateway-fabric/values.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,12 @@ nginx:
367367
# - IPAddress
368368
# value:
369369
# type: string
370+
# waf:
371+
# type: string
372+
# description: WAF enables NGINX App Protect WAF functionality.
373+
# enum:
374+
# - enabled
375+
# - disabled
370376
# @schema
371377
# -- The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways
372378
# managed by this instance of NGINX Gateway Fabric.
@@ -406,6 +412,33 @@ nginx:
406412
# -- extraVolumeMounts are the additional volume mounts for the NGINX container.
407413
# extraVolumeMounts: []
408414

415+
# -- Configuration for NGINX App Protect WAF v5 containers.
416+
# These containers are only deployed when WAF is enabled via nginx.config.waf: "Enabled".
417+
# All settings are optional overrides - defaults are provided by NGF.
418+
wafContainers: {}
419+
# -- WAF Enforcer container configuration.
420+
# enforcer:
421+
# image: {}
422+
423+
# -- The resource requirements of the WAF Enforcer container.
424+
# resources: {}
425+
#
426+
# # -- Additional volume mounts for the WAF enforcer container.
427+
# # NAP v5 shared volumes are automatically configured by NGF.
428+
# volumeMounts: []
429+
430+
# -- WAF Configuration Manager container configuration.
431+
# configManager:
432+
# # -- Container image configuration
433+
# image: {}
434+
#
435+
# # -- The resource requirements of the WAF config manager container.
436+
# resources: {}
437+
438+
# # -- Additional volume mounts for the WAF config manager container.
439+
# # NAP v5 shared volumes are automatically configured by NGF.
440+
# volumeMounts: []
441+
409442
# -- The service configuration for the NGINX data plane. This is applied globally to all Gateways managed by this
410443
# instance of NGINX Gateway Fabric.
411444
service:

0 commit comments

Comments
 (0)