Skip to content

Commit df7f6ad

Browse files
committed
Add status conditions section
1 parent 2445ab2 commit df7f6ad

File tree

1 file changed

+65
-92
lines changed

1 file changed

+65
-92
lines changed

docs/proposals/nap-waf.md

Lines changed: 65 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ NGINX App Protect WAF v5 imposes specific architectural requirements that fundam
3636
- **Multi-container deployment**: Requires separate `waf-enforcer` and `waf-config-mgr` containers alongside the main NGINX container
3737
- **Pre-compiled policies**: WAF policies must be compiled externally using NAP tooling before deployment (cannot be defined inline in Kubernetes resources)
3838
- **Shared volume architecture**: Containers communicate through shared filesystem volumes rather than direct API calls
39-
- **External storage requirement**: Compiled policy bundles must be distributed via external storage systems (S3, HTTP, MinIO)
4039

4140
### Design Philosophy
4241

@@ -205,7 +204,7 @@ The architecture demonstrates separation of concerns: external policy compilatio
205204

206205
### Network Access Requirements
207206

208-
NGF requires outbound network access to fetch WAF policies from remote locations:
207+
NGF requires outbound network access to fetch WAF policies from _remote_ locations:
209208

210209
- **HTTPS/HTTP access** to policy storage endpoints (S3, Azure Blob, HTTP servers, etc.)
211210
- **DNS resolution** for policy storage hostnames
@@ -221,6 +220,20 @@ NGF requires outbound network access to fetch WAF policies from remote locations
221220

222221
**Note**: Network access configuration is environment-specific and handled through standard Kubernetes networking patterns rather than NGF-specific configuration options.
223222

223+
#### Air-Gapped Environments
224+
225+
- **In-cluster policy storage**: Deploy MinIO or HTTP server within cluster boundaries
226+
- **Offline compilation**: Use NAP v5 tools in secure environments & upload bundles manually, or do this step within cluster boundaries
227+
- **No external dependencies**: Complete WAF functionality without internet access
228+
229+
Example air-gapped configuration:
230+
231+
```yaml
232+
spec:
233+
policySource:
234+
fileLocation: "http://policy-server.nginx-system.svc.cluster.local/policies/prod-policy.tgz"
235+
```
236+
224237
### Policy Development Workflow
225238
226239
Given NAP v5 constraints, users must follow this workflow:
@@ -241,21 +254,14 @@ Example CI/CD integration for manual updates:
241254
docker run --rm -v $(pwd):/policies nginx/nap-compiler:5.6.0 \
242255
compile --input /policies/app-policy.json --output /policies/compiled-policy.tgz
243256

244-
# Compile custom logging profile (optional - can use built-in profiles)
245-
docker run --rm -v $(pwd):/policies nginx/nap-compiler:5.6.0 \
246-
compile --input /policies/custom-log-profile.json --output /policies/log-profile.tgz
247-
248-
# Generate checksums for integrity verification
257+
# Generate checksum for integrity verification
249258
sha256sum compiled-policy.tgz > compiled-policy.tgz.sha256
250-
sha256sum log-profile.tgz > log-profile.tgz.sha256
251259

252260
# Publish to storage
253261
aws s3 cp compiled-policy.tgz s3://company-policies/prod-policy-v$(date +%Y%m%d).tgz
254262
aws s3 cp compiled-policy.tgz.sha256 s3://company-policies/prod-policy-v$(date +%Y%m%d).tgz.sha256
255-
aws s3 cp log-profile.tgz s3://company-policies/logging/custom-log-profile.tgz
256-
aws s3 cp log-profile.tgz.sha256 s3://company-policies/logging/custom-log-profile.tgz.sha256
257263

258-
# Manual update: Modify WafPolicy resource to reference new policy and logging
264+
# Manual update: Modify WafPolicy resource to reference new policy
259265
kubectl patch wafpolicy gateway-protection \
260266
--patch '{"spec":{"policySource":{"fileLocation":"s3://company-policies/prod-policy-v'$(date +%Y%m%d)'.tgz"}}}'
261267
```
@@ -360,18 +366,17 @@ metadata:
360366
namespace: nginx-gateway
361367
spec:
362368
# WAF policy configuration (extensible design)
363-
waf:
364-
policy: "Enabled" # "Enabled" | "Disabled"
365-
# configuration tweaks optional, e.g.:
369+
waf: "Enabled" # "Enabled" | "Disabled"
370+
# configuration tweaks optional, e.g.:
366371
# kubernetes:
367372
# deployment:
368-
# # NGINX container with NAP module (will set to default if waf policy is "Enabled" but these values are not configured)
373+
# # NGINX container with NAP module (will set to default if waf is "Enabled" but these values are not configured)
369374
# container:
370375
# image:
371376
# repository: private-registry.nginx.com/nginx-gateway-fabric/nginx-plus-waf
372377
# tag: "2.1.0"
373378

374-
# # NAP v5 required containers (will set to defaults if waf policy is "Enabled" but these values are not configured)
379+
# # NAP v5 required containers (will set to defaults if waf is "Enabled" but these values are not configured)
375380
# wafContainers:
376381
# enforcer:
377382
# image:
@@ -386,8 +391,6 @@ spec:
386391

387392
### WafPolicy Custom Resource with Policy Attachment
388393

389-
Due to NAP v5's pre-compilation requirement, policies must be referenced from external sources and use targetRefs for policy attachment:
390-
391394
```yaml
392395
apiVersion: gateway.nginx.org/v1alpha1
393396
kind: WafPolicy
@@ -402,7 +405,6 @@ spec:
402405
name: secure-gateway
403406
namespace: applications
404407

405-
# Policy source (required due to NAP v5 pre-compilation)
406408
policySource:
407409
fileLocation: "s3://ngf-waf-policies/production/gateway-policy-v1.2.3.tgz"
408410
authSecret:
@@ -486,10 +488,6 @@ spec:
486488
type: "Stderr"
487489

488490
---
489-
# Status examples showing WafPolicy Conditions
490-
# TODO - Need to design Conditions
491-
```
492-
493491
### Gateway and Route Resources
494492

495493
#### Gateway Configuration
@@ -653,91 +651,61 @@ data:
653651
token: <base64>
654652
```
655653

656-
## Use Cases
654+
### Status
657655

658-
### Hierarchical WAF Protection
656+
#### CRD Label
659657

660-
#### Gateway-Level Default Protection
658+
According to the [Policy and Metaresources GEP](https://gateway-api.sigs.k8s.io/geps/gep-713/), the `WafPolicy` CRD must have the `gateway.networking.k8s.io/policy: inherited` label to specify that it is an inherited policy.
659+
This label will help with discoverability and will be used by the planned Gateway API Policy [kubectl plugin](https://gateway-api.sigs.k8s.io/geps/gep-713/#kubectl-plugin-or-command-line-tool).
661660

662-
```yaml
663-
# Provides base WAF protection for all routes
664-
apiVersion: gateway.nginx.org/v1alpha1
665-
kind: WafPolicy
666-
metadata:
667-
name: gateway-base-protection
668-
namespace: applications
669-
spec:
670-
targetRefs:
671-
- group: gateway.networking.k8s.io
672-
kind: Gateway
673-
name: main-gateway
674-
policySource:
675-
fileLocation: "s3://policies/base-protection.tgz"
676-
```
661+
#### Conditions
677662

678-
**Result**: All HTTPRoutes and GRPCRoutes attached to `main-gateway` automatically inherit WAF protection.
663+
According to the [Policy and Metaresources GEP](https://gateway-api.sigs.k8s.io/geps/gep-713/), the `WafPolicy` CRD must include a `status` stanza with a slice of Conditions.
679664

680-
#### Route-Level Override
665+
The `Accepted` Condition must be populated on the `WafPolicy` CRD using the reasons defined in the [PolicyCondition API](https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/policy_types.go). If these reasons are not sufficient, we can add implementation-specific reasons.
681666

682-
```yaml
683-
# Stricter protection for sensitive endpoints
684-
apiVersion: gateway.nginx.org/v1alpha1
685-
kind: WafPolicy
686-
metadata:
687-
name: admin-strict-protection
688-
namespace: applications
689-
spec:
690-
targetRefs:
691-
- group: gateway.networking.k8s.io
692-
kind: HTTPRoute
693-
name: admin-routes
694-
policySource:
695-
fileLocation: "s3://policies/strict-admin-protection.tgz"
696-
```
667+
#### Setting Status on Objects Affected by a Policy
697668

698-
**Result**: Admin routes get stricter protection while other routes continue using base protection.
669+
In the Policy and Metaresources GEP, there's a [provisional status described here](https://gateway-api.sigs.k8s.io/geps/gep-713/#standard-status-condition-on-policy-affected-objects) that involves adding a Condition or annotation to all objects affected by a Policy.
699670

700-
### Enterprise Security Operations
671+
This solution gives the object owners some knowledge that their object is affected by a policy but minimizes status updates by limiting them to when the affected object starts or stops being affected by a policy.
672+
Even though this status is provisional, implementing it now will help with discoverability and allow us to give feedback on the solution.
701673

702-
- **SecOps teams** compile and manage WAF policies using existing NAP v5 tooling
703-
- **CI/CD pipelines** automate policy compilation, testing, and distribution
704-
- **Platform teams** deploy WAF-enabled gateways with inherited protection for all applications
705-
- **Development teams** can override Gateway policies for specific routes when needed
706-
- **Operations teams** benefit from simplified policy management with automatic inheritance
674+
Implementing this involves defining a new Condition type and reason:
707675

708-
### Multi-Environment Deployment
676+
```go
677+
package conditions
709678
710-
- **Development**: Gateway-level monitoring mode with detailed logging for policy tuning
711-
- **Staging**: WAF-enabled Gateway for comprehensive policy testing with route-specific overrides
712-
- **Production**: Full enforcement with performance-optimized policy bundles and granular route policies
679+
import (
680+
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
681+
)
713682
714-
### Selective WAF Deployment
715683
716-
- **Mixed Environment**: Some Gateways with WAF protection, others without, all managed by single NGF control plane
717-
- **Resource Optimization**: WAF containers only deployed where needed, reducing resource consumption
718-
- **Independent Scaling**: Each Gateway's NGINX Pod scales independently based on traffic requirements
719-
- **Flexible Protection**: Default Gateway protection with route-specific overrides as needed
684+
const (
685+
WafPolicyAffected gatewayv1alpha2.PolicyConditionType = "gateway.nginx.org/WafPolicyAffected"
686+
PolicyAffectedReason gatewayv1alpha2.PolicyConditionReason = "PolicyAffected"
687+
)
720688
721-
### Air-Gapped Environments
722-
723-
- **In-cluster policy storage**: Deploy MinIO or HTTP server within cluster boundaries
724-
- **Offline compilation**: Use NAP v5 tools in secure environments, upload bundles manually
725-
- **No external dependencies**: Complete WAF functionality without internet access
689+
```
726690

727-
Example air-gapped configuration:
691+
NGINX Gateway Fabric must set this Condition on all HTTPRoutes and Gateways affected by a `WafPolicy`.
692+
Below is an example of what this Condition may look like:
728693

729694
```yaml
730-
spec:
731-
policySource:
732-
fileLocation: "http://policy-server.nginx-system.svc.cluster.local/policies/prod-policy.tgz"
695+
Conditions:
696+
Type: gateway.nginx.org/WafPolicyAffected
697+
Message: Object affected by a WafPolicy.
698+
Observed Generation: 1
699+
Reason: PolicyAffected
700+
Status: True
733701
```
734702

735-
### Regulatory Compliance
703+
Some additional rules:
736704

737-
- **Audit trails**: Complete policy version history and deployment tracking
738-
- **Change control**: Formal approval processes for policy compilation and deployment
739-
- **Immutable policies**: Compiled policy bundles provide tamper-proof security configurations
740-
- **Policy inheritance tracking**: Clear visibility into which policies apply to which routes
705+
- This Condition should be added when the affected object starts being affected by a `WafPolicy`.
706+
- If an object is affected by multiple `WafPolicy`, only one Condition should exist.
707+
- When the last `WafPolicy` affecting that object is removed, the Condition should be removed.
708+
- The Observed Generation is the generation of the affected object, not the generation of the `WafPolicy`.
741709

742710
## Testing
743711

@@ -756,7 +724,6 @@ spec:
756724
- **End-to-End Workflows**: Complete policy compilation, distribution, and enforcement across multiple Gateway scenarios
757725
- **NGF Control Plane**: Single NGF Pod managing multiple WAF-enabled and standard NGINX Pods
758726
- **Policy Distribution**: Centralized policy fetching with distribution to appropriate NGINX Pods via gRPC
759-
- **Multi-Container Pod**: NAP v5 container interaction via shared volumes in Gateway-specific NGINX Pods
760727
- **Authentication**: Various credential types and failure handling for policy sources
761728
- **Network Scenarios**: Policy fetching from different source types (S3, HTTP, in-cluster)
762729
- **Selective Deployment**: Testing WAF enablement on subset of Gateways while others remain standard
@@ -770,7 +737,7 @@ spec:
770737
- **Scale Testing**: Multiple WafPolicy resources and policy updates under load
771738
- **Ephemeral Volume Performance**: Volume I/O performance and sizing validation
772739
- **Policy Inheritance Performance**: Impact of policy resolution on request processing
773-
- Note: current NFR testing likely covers all of these scenarios, but we may want to add a separate NGINX Plus WAF run
740+
- Note: current NFR testing likely covers all of these scenarios, but we may want to add a separate NGINX Plus with WAF run
774741

775742
### Conformance Testing
776743

@@ -820,6 +787,13 @@ spec:
820787
- **Source Authorization**: Operators responsible for ensuring policy sources are legitimate and approved
821788
- **Access Logging**: Standard Kubernetes audit logging captures WafPolicy resource operations; policy fetch operations logged via NGF's existing logging mechanisms
822789

790+
### Regulatory Compliance
791+
792+
- **Audit trails**: Complete policy version history and deployment tracking
793+
- **Change control**: Formal approval processes for policy compilation and deployment
794+
- **Immutable policies**: Compiled policy bundles provide tamper-proof security configurations
795+
- **Policy inheritance tracking**: Clear visibility into which policies apply to which routes
796+
823797
## Alternatives
824798

825799
### Alternative 1: Filter-Based Attachment
@@ -890,8 +864,7 @@ metadata:
890864
name: waf-enabled-proxy
891865
namespace: nginx-gateway
892866
spec:
893-
waf:
894-
policy: "Enabled"
867+
waf: "Enabled"
895868
896869
---
897870
# 3. Gateway using WAF-enabled proxy

0 commit comments

Comments
 (0)