Skip to content

Commit fa0f095

Browse files
committed
Add polling mechanism to proposal
1 parent aebdae4 commit fa0f095

File tree

1 file changed

+85
-17
lines changed

1 file changed

+85
-17
lines changed

docs/proposals/nap-waf.md

Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55

66
## Summary
77

8-
This proposal describes the integration of NGINX App Protect (NAP) WAF v5 into NGINX Gateway Fabric (NGF) to provide comprehensive WAF protection at Gateway and Route levels while working within NAP v5's architectural constraints of multi-container deployment and pre-compiled policy requirements. The design uses Gateway API inherited policy attachment to provide flexible, hierarchical WAF protection.
8+
This proposal describes the integration of NGINX App Protect (NAP) WAF v5 into NGINX Gateway Fabric (NGF) to provide comprehensive WAF protection at Gateway and Route levels while working within NAP v5's architectural constraints of multi-container deployment and pre-compiled policy requirements. The design uses Gateway API inherited policy attachment to provide flexible, hierarchical WAF protection with GitOps-friendly static policy references through automatic polling and change detection.
99

1010
## Goals
1111

1212
- Extend NginxProxy resource to enable NAP WAF for GatewayClass/Gateway with multi-container orchestration
1313
- Design WafPolicy custom resource using inherited policy attachment for hierarchical WAF configuration
1414
- Define deployment workflows that accommodate NAP v5's external policy compilation requirements
1515
- Provide secure and automated policy distribution mechanisms from external sources
16+
- Support GitOps workflows with static policy file references and automatic change detection
1617
- Deliver enterprise-grade WAF capabilities through Kubernetes-native APIs with intuitive policy inheritance
1718
- Maintain alignment with NGF's existing security and operational patterns
1819
- Support configurable security logging for WAF events and policy violations
@@ -41,6 +42,14 @@ NGINX App Protect WAF v5 imposes specific architectural requirements that fundam
4142

4243
This proposal provides the best possible Kubernetes-native experience while respecting NAP v5 constraints, abstracting complexity from end users where possible while maintaining operational flexibility for enterprise environments. The design uses Gateway API's inherited policy attachment pattern to provide intuitive hierarchical security with the ability to override policies at more specific levels.
4344

45+
### GitOps Integration
46+
47+
A key design principle is seamless GitOps workflow support through automatic change detection:
48+
49+
- **Automatic Polling**: When polling is enabled, NGF periodically checks for policy changes using checksum validation
50+
- **Efficient Updates**: Only downloads policy bundles when content actually changes
51+
- **CI/CD Friendly**: Teams can update policies without modifying Kubernetes resources
52+
4453
### Policy Attachment Strategy
4554

4655
The design uses **inherited policy attachment** following Gateway API best practices:
@@ -132,6 +141,7 @@ graph TB
132141
NGFPod -->|Watches Resources| NginxProxy
133142
NGFPod -->|Watches Resources| GatewayWafPolicy
134143
NGFPod -->|Watches Resources| RouteWafPolicy
144+
NGFPod -->|Periodic Polling<br/>Checksum Validation| Store
135145
NGFPod -->|Fetches Policy<br/>Native Cloud Auth| Store
136146
NGFServiceAccount -.->|Cloud Provider<br/>Authentication| Store
137147
NGFPod -.->|Fallback: Uses Credentials| Secret
@@ -177,16 +187,11 @@ graph TB
177187
class PublicEndpoint endpoint
178188
class Secret optional
179189
180-
%% Notes about the architecture
181-
classDef note fill:#fffacd,stroke:#daa520,stroke-width:1px,stroke-dasharray: 5 5
182-
Note1[📝 Note: Gateway-level WafPolicy provides inherited protection<br/>Route-level WafPolicy can override for specific routes]
183-
Note2[📝 Note: Secret only required for fallback authentication<br/>Native cloud auth uses NGF Service Account annotations]
184-
class Note1,Note2 note
185190
```
186191

187192
This architecture demonstrates the hierarchical policy attachment system where Gateway-level WafPolicies provide default protection that can be overridden by Route-level policies for granular control:
188193

189-
**External Policy Management (Blue):** Security teams develop WAF policies using NAP v5 JSON schema, compile them using NAP v5 compiler tools, and publish the compiled policy bundles to accessible storage locations (S3, HTTP servers, or MinIO).
194+
**External Policy Management (Blue):** Security teams develop WAF policies using NAP v5 JSON schema, compile them using NAP v5 compiler tools, and publish the compiled policy bundles to accessible storage locations (S3, HTTP servers, MinIO etc).
190195

191196
**Control Plane (Purple):** The NGF Pod in the `nginx-gateway` namespace acts as the centralized control plane, watching for NginxProxy and WafPolicy resources across application namespaces, fetching compiled policies from external storage using appropriate authentication, and distributing policy configurations to NGINX Pods via secure gRPC connections.
192197

@@ -200,6 +205,8 @@ This architecture demonstrates the hierarchical policy attachment system where G
200205

201206
**Policy Inheritance:** Gateway-level WafPolicies automatically protect all routes attached to the Gateway. Route-level WafPolicies can override Gateway policies with more specific protection. This design supports both broad default protection and granular security controls while maintaining operational simplicity.
202207

208+
- **GitOps Integration**: Optional automatic polling detects policy changes without requiring Kubernetes resource updates
209+
203210
The architecture demonstrates separation of concerns: external policy compilation and storage, centralized policy distribution with inheritance hierarchy, and distributed policy enforcement, while maintaining security through ephemeral storage and immutable infrastructure principles.
204211

205212
### Network Access Requirements
@@ -232,6 +239,9 @@ Example air-gapped configuration:
232239
spec:
233240
policySource:
234241
fileLocation: "http://policy-server.nginx-system.svc.cluster.local/policies/prod-policy.tgz"
242+
polling:
243+
enabled: true
244+
interval: "5m"
235245
```
236246
237247
### Policy Development Workflow
@@ -243,7 +253,7 @@ Given NAP v5 constraints, users must follow this workflow:
243253
3. **Compilation**: Use NAP v5 compiler tools to create policy and logging profile bundles
244254
4. **Distribution**: Publish compiled policies and log profiles to accessible storage (S3, HTTP)
245255
5. **Configuration**: Create WafPolicy CR with targetRefs referencing Gateway or Routes and configuring security logging
246-
6. **Automatic Application**: NGF fetches and applies policies when WafPolicy is created or updated, with automatic inheritance
256+
6. **Automatic Application**: NGF fetches and applies policies when WafPolicy is created or updated, with automatic inheritance. Policies can also be updated by publishing new content to the same configured file path; when polling is enabled, NGF automatically detects and applies changes.
247257
248258
**Note**: Policy enforcement mode and behavior are defined within the compiled NAP policy itself. Security logging profiles can be either built-in names or custom compiled bundles.
249259
@@ -258,14 +268,24 @@ docker run --rm -v $(pwd):/policies nginx/nap-compiler:5.6.0 \
258268
sha256sum compiled-policy.tgz > compiled-policy.tgz.sha256
259269

260270
# Publish to storage
261-
aws s3 cp compiled-policy.tgz s3://company-policies/prod-policy-v$(date +%Y%m%d).tgz
262-
aws s3 cp compiled-policy.tgz.sha256 s3://company-policies/prod-policy-v$(date +%Y%m%d).tgz.sha256
271+
aws s3 cp compiled-policy.tgz s3://company-policies/prod-policy.tgz
272+
aws s3 cp compiled-policy.tgz.sha256 s3://company-policies/prod-policy.tgz.sha256
263273

264-
# Manual update: Modify WafPolicy resource to reference new policy
265-
kubectl patch wafpolicy gateway-protection \
266-
--patch '{"spec":{"policySource":{"fileLocation":"s3://company-policies/prod-policy-v'$(date +%Y%m%d)'.tgz"}}}'
274+
# No Kubernetes resource changes needed - NGF automatically detects the update
275+
echo "Policy updated. NGF will detect changes within polling interval."
267276
```
268277

278+
### Policy Polling and Change Detection
279+
280+
NGF supports automatic policy change detection to support GitOps workflows:
281+
282+
**Polling Mechanism:**
283+
284+
- Configurable polling interval (default: 5 minutes)
285+
- Checksum-based change detection for efficiency
286+
- Only downloads policy bundles when content changes
287+
- New policies applied immediately upon detection
288+
269289
### Security Logging Configuration
270290

271291
The securityLogs section supports multiple logging configurations, each generating an `app_protect_security_log` directive:
@@ -284,6 +304,7 @@ The securityLogs section supports multiple logging configurations, each generati
284304
- Reference compiled logging profile bundles from remote sources
285305
- Same fetch and validation mechanisms as policy bundles
286306
- Support for checksums and retry policies
307+
- Automatic polling for log profile updates
287308

288309
**Destination Types:**
289310

@@ -347,10 +368,11 @@ The design supports hierarchical policy application with clear precedence rules:
347368

348369
The integration leverages NGF's existing architecture:
349370

350-
- **Single NGF Pod**: Centralized control plane in `nginx-gateway` namespace manages all WAF operations
371+
- **Single NGF Deployment**: Centralized control plane in `nginx-gateway` namespace manages all WAF operations and policy polling
351372
- **Per-Gateway Deployment**: Each Gateway with WAF enabled gets a dedicated multi-container NGINX Pod
352373
- **Selective WAF Enablement**: Only Gateways configured with WAF-enabled NginxProxy resources deploy NAP v5 containers
353374
- **Centralized Policy Management**: NGF controllers fetch policies and distribute them to appropriate NGINX Pods via the existing Agent gRPC connection
375+
- **Automatic Change Detection**: NGF polling engine can detect policy changes and trigger updates across affected Gateways
354376

355377
## API, Customer Driven Interfaces, and User Experience
356378

@@ -414,6 +436,14 @@ spec:
414436
# Note: Policy content validation handled by NAP v5 components
415437
# We will support signature verification in the future
416438

439+
# Polling configuration for automatic change detection
440+
polling:
441+
enabled: true
442+
interval: "5m" # Check every 5 minutes
443+
# Optional: explicit checksum location
444+
# If not specified, defaults to <fileLocation>.sha256
445+
checksumLocation: "s3://ngf-waf-policies/production/gateway-policy-v1.2.3.tgz"
446+
417447
# Retry configuration for policy fetch failures
418448
retryPolicy:
419449
attempts: 3
@@ -441,6 +471,11 @@ spec:
441471
name: "policy-store-credentials"
442472
validation:
443473
methods: ["Checksum"]
474+
# Log profiles also support polling for updates
475+
polling:
476+
enabled: true
477+
interval: "10m"
478+
# ChecksumLocation defaults to <fileLocation>.sha256
444479
retryPolicy:
445480
attempts: 3
446481
backoff: "exponential"
@@ -481,6 +516,9 @@ spec:
481516
fileLocation: "s3://ngf-waf-policies/production/admin-strict-policy-v1.0.0.tgz"
482517
authSecret:
483518
name: "policy-store-credentials"
519+
polling:
520+
enabled: true
521+
interval: "2m"
484522
securityLogs:
485523
- name: "admin-logging"
486524
logProfile: "log_all" # Log everything for admin routes
@@ -716,6 +754,7 @@ Some additional rules:
716754
- **Policy Attachment Logic**: targetRefs validation and inheritance resolution
717755
- **Multi-container Orchestration**: Container startup sequences and ephemeral volume management
718756
- **Policy Validation**: Compiled policy bundle checksum integrity checking
757+
- **Polling Engine**: Change detection logic and retry mechanisms
719758

720759
### Integration Testing
721760

@@ -727,6 +766,7 @@ Some additional rules:
727766
- **Authentication**: Various credential types and failure handling for policy sources
728767
- **Network Scenarios**: Policy fetching from different source types (S3, HTTP, in-cluster)
729768
- **Selective Deployment**: Testing WAF enablement on subset of Gateways while others remain standard
769+
- **Polling and Updates**: Automatic change detection and policy application without resource modifications
730770

731771
### Performance Testing
732772

@@ -737,6 +777,7 @@ Some additional rules:
737777
- **Scale Testing**: Multiple WafPolicy resources and policy updates under load
738778
- **Ephemeral Volume Performance**: Volume I/O performance and sizing validation
739779
- **Policy Inheritance Performance**: Impact of policy resolution on request processing
780+
- **Polling Performance**: Resource impact of periodic policy checks and change detection
740781
- Note: current NFR testing likely covers all of these scenarios, but we may want to add a separate NGINX Plus with WAF run
741782

742783
### Conformance Testing
@@ -753,6 +794,7 @@ Some additional rules:
753794
- **Integrity Verification**: Checksum validation of compiled policy bundles prevents tampering
754795
- **Secure Transport**: TLS encryption for all policy downloads from external sources
755796
- **Access Control**: RBAC restrictions on WafPolicy resource creation and modification
797+
- **Polling Security**: Secure change detection mechanisms prevent unauthorized policy modifications
756798

757799
### Credential Management
758800

@@ -826,6 +868,16 @@ Some additional rules:
826868
**Approach**: Have NGINX containers fetch policies directly using njs
827869
**Rejected Reason**: Creates distributed system complexity, inconsistent state issues, and violates NGF's centralized control plane pattern
828870

871+
### Alternative 7: Manual Policy Updates Only
872+
873+
**Approach**: Require users to manually update WafPolicy resources for each policy change
874+
**Rejected Reason**: Breaks GitOps workflows and creates operational overhead; teams want to update policies without modifying Kubernetes resources
875+
876+
### Alternative 8: Webhook-Only Updates
877+
878+
**Approach**: Use only webhook notifications for policy updates, no polling
879+
**Rejected Reason**: Creates dependency on reliable webhook delivery; polling provides fallback mechanism and works in environments where webhooks are not feasible
880+
829881
## Future Enhancements
830882

831883
- **Policy signature verification**: Cryptographic validation of policy bundle authenticity using public key infrastructure
@@ -905,10 +957,19 @@ spec:
905957
namespace: applications
906958
907959
policySource:
908-
fileLocation: "s3://company-waf-policies/production/base-policy-v2.1.0.tgz"
960+
fileLocation: "s3://company-waf-policies/production/base-policy.tgz"
909961
# Secret referenced for fallback - NGF will use IRSA if available, secret if not
910962
authSecret:
911963
name: "policy-store-credentials"
964+
965+
# Automatic change detection for GitOps workflows
966+
polling:
967+
enabled: true
968+
interval: "5m"
969+
# Optional explicit checksum location
970+
# If not specified, defaults to base-policy.tgz.sha256
971+
checksumLocation: "s3://company-waf-policies/production/base-policy.tgz.sha256"
972+
912973
securityLogs:
913974
- name: "gateway-logging"
914975
logProfile: "log_blocked"
@@ -931,7 +992,10 @@ spec:
931992
namespace: applications
932993
933994
policySource:
934-
fileLocation: "s3://company-waf-policies/production/admin-strict-policy-v1.0.0.tgz"
995+
fileLocation: "s3://company-waf-policies/production/admin-strict-policy.tgz"
996+
polling:
997+
enabled: true
998+
935999
securityLogs:
9361000
- name: "admin-logging"
9371001
logProfile: "log_all" # More verbose logging for admin routes
@@ -1025,7 +1089,10 @@ spec:
10251089
namespace: applications
10261090
10271091
policySource:
1028-
fileLocation: "s3://company-waf-policies/production/api-specific-policy-v1.5.0.tgz"
1092+
fileLocation: "s3://company-waf-policies/production/api-specific-policy.tgz"
1093+
polling:
1094+
enabled: true
1095+
10291096
securityLogs:
10301097
- name: "api-logging"
10311098
logProfile: "log_blocked"
@@ -1043,3 +1110,4 @@ This complete example demonstrates:
10431110
- **HTTP and gRPC route support** with seamless policy inheritance
10441111
- **Native cloud authentication** with fallback secret support
10451112
- **Flexible logging configuration** per policy level
1113+
- **Automatic change detection** through configurable polling intervals

0 commit comments

Comments
 (0)