Skip to content

Commit 24d3332

Browse files
committed
Add WafPolicy CRD
Problem: As a user of NGF with an NGINX One subscription I want a method to configure WAF protection on my Gateways and Routes So that I can enable the NAP WAF feature for the applications that need it. Solution: Define the WafPolicy CRD.
1 parent 0bbb602 commit 24d3332

12 files changed

+1117
-7
lines changed

apis/v1alpha1/clientsettingspolicy_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
66
)
77

8-
// +genclient
98
// +kubebuilder:object:root=true
109
// +kubebuilder:storageversion
1110
// +kubebuilder:subresource:status

apis/v1alpha1/nginxgateway_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package v1alpha1
22

33
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
44

5-
// +genclient
65
// +kubebuilder:object:root=true
76
// +kubebuilder:storageversion
87
// +kubebuilder:subresource:status

apis/v1alpha1/observabilitypolicy_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
66
)
77

8-
// +genclient
98
// +kubebuilder:object:root=true
109
// +kubebuilder:deprecatedversion:warning="The 'v1alpha1' version of ObservabilityPolicy API is deprecated, please migrate to 'v1alpha2'."
1110
// +kubebuilder:subresource:status

apis/v1alpha1/policy_methods.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,15 @@ func (p *UpstreamSettingsPolicy) GetPolicyStatus() v1alpha2.PolicyStatus {
4343
func (p *UpstreamSettingsPolicy) SetPolicyStatus(status v1alpha2.PolicyStatus) {
4444
p.Status = status
4545
}
46+
47+
func (p *WafPolicy) GetTargetRefs() []v1alpha2.LocalPolicyTargetReference {
48+
return []v1alpha2.LocalPolicyTargetReference{p.Spec.TargetRef}
49+
}
50+
51+
func (p *WafPolicy) GetPolicyStatus() v1alpha2.PolicyStatus {
52+
return p.Status
53+
}
54+
55+
func (p *WafPolicy) SetPolicyStatus(status v1alpha2.PolicyStatus) {
56+
p.Status = status
57+
}

apis/v1alpha1/register.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
4242
&SnippetsFilterList{},
4343
&UpstreamSettingsPolicy{},
4444
&UpstreamSettingsPolicyList{},
45+
&WafPolicy{},
46+
&WafPolicyList{},
4547
)
4648
// AddToGroupVersion allows the serialization of client types like ListOptions.
4749
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)

apis/v1alpha1/snippetsfilter_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
v1 "sigs.k8s.io/gateway-api/apis/v1"
66
)
77

8-
// +genclient
98
// +kubebuilder:object:root=true
109
// +kubebuilder:storageversion
1110
// +kubebuilder:subresource:status

apis/v1alpha1/upstreamsettingspolicy_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
66
)
77

8-
// +genclient
98
// +kubebuilder:object:root=true
109
// +kubebuilder:storageversion
1110
// +kubebuilder:subresource:status

apis/v1alpha1/wafpolicy_types.go

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package v1alpha1
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
6+
)
7+
8+
// +kubebuilder:object:root=true
9+
// +kubebuilder:storageversion
10+
// +kubebuilder:subresource:status
11+
// +kubebuilder:resource:categories=nginx-gateway-fabric
12+
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
13+
// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=inherited"
14+
15+
// WafPolicy is an Inherited Attached Policy. It provides a way to configure NGINX App Protect Web Application Firewall
16+
// for Gateways and Routes.
17+
type WafPolicy struct {
18+
metav1.TypeMeta `json:",inline"`
19+
metav1.ObjectMeta `json:"metadata,omitempty"`
20+
21+
// Spec defines the desired state of the WafPolicy.
22+
Spec WafPolicySpec `json:"spec"`
23+
24+
// Status defines the state of the WafPolicy.
25+
Status gatewayv1alpha2.PolicyStatus `json:"status,omitempty"`
26+
}
27+
28+
// +kubebuilder:object:root=true
29+
30+
// WafPolicyList contains a list of WafPolicies.
31+
type WafPolicyList struct {
32+
metav1.TypeMeta `json:",inline"`
33+
metav1.ListMeta `json:"metadata,omitempty"`
34+
Items []WafPolicy `json:"items"`
35+
}
36+
37+
// WafPolicySpec defines the desired state of a WafPolicy.
38+
type WafPolicySpec struct {
39+
PolicySource *WafPolicySource `json:"policySource,omitempty"`
40+
41+
// TargetRef identifies an API object to apply the policy to.
42+
// Object must be in the same namespace as the policy.
43+
// Support: Gateway, HTTPRoute, GRPCRoute.
44+
//
45+
// +kubebuilder:validation:XValidation:message="TargetRef Kind must be one of: Gateway, HTTPRoute, or GRPCRoute",rule="(self.kind=='Gateway' || self.kind=='HTTPRoute' || self.kind=='GRPCRoute')"
46+
// +kubebuilder:validation:XValidation:message="TargetRef Group must be gateway.networking.k8s.io.",rule="(self.group=='gateway.networking.k8s.io')"
47+
//nolint:lll
48+
TargetRef gatewayv1alpha2.LocalPolicyTargetReference `json:"targetRef"`
49+
50+
SecurityLogs []WafSecurityLog `json:"securityLogs,omitempty"`
51+
}
52+
53+
type WafPolicySource struct {
54+
// WafPolicyAuthSecret is the Secret containing authentication credentials for the WAF policy source.
55+
//
56+
// +optional
57+
AuthSecret *WafPolicyAuthSecret `json:"authSecret,omitempty"`
58+
59+
Validation *WafPolicyValidation `json:"validation,omitempty"`
60+
61+
// Polling defines the polling configuration for automatic WAF policy change detection.
62+
//
63+
// +optional
64+
Polling *WafPolicyPolling `json:"polling,omitempty"`
65+
66+
// Retry defines the retry configuration for WAF policy fetch failures.
67+
//
68+
// +optional
69+
Retry *WafPolicyRetry `json:"retry,omitempty"`
70+
71+
// Timeout for policy downloads.
72+
//
73+
// +optional
74+
Timeout *Duration `json:"timeout,omitempty"`
75+
76+
// FileLocation defines the location of the WAF policy file.
77+
//
78+
// +kubebuilder:validation:MinLength=1
79+
FileLocation string `json:"fileLocation"`
80+
}
81+
82+
// WafPolicyAuthSecret is the Secret containing authentication credentials for the WAF policy source.
83+
// It must live in the same Namespace as the policy.
84+
type WafPolicyAuthSecret struct {
85+
// Name is the name of the Secret containing authentication credentials for the WAF policy source.
86+
//
87+
// +kubebuilder:validation:MinLength=1
88+
// +kubebuilder:validation:MaxLength=253
89+
// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9_-]+$`
90+
Name string `json:"name"`
91+
}
92+
93+
type WafPolicyValidation struct {
94+
Methods []string `json:"methods,omitempty"`
95+
}
96+
97+
// WafPolicyPolling defines the polling configuration for automatic WAF policy change detection.
98+
type WafPolicyPolling struct {
99+
// Enabled indicates whether polling is enabled for automatic WAF policy change detection.
100+
//
101+
// +optional
102+
Enabled *bool `json:"enabled,omitempty"`
103+
104+
// Interval is the polling interval to check for WAF policy changes.
105+
//
106+
// +optional
107+
Interval *Duration `json:"interval,omitempty"`
108+
109+
ChecksumLocation *string `json:"checksumLocation,omitempty"`
110+
}
111+
112+
// WafPolicyRetry defines the retry configuration for WAF policy fetch failures.
113+
type WafPolicyRetry struct {
114+
// Attempts is the number of retry attempts for fetching the WAF policy.
115+
//
116+
// +optional
117+
// +kubebuilder:validation:Minimum=0
118+
Attempts *int32 `json:"attempts,omitempty"`
119+
120+
Backoff *string `json:"backoff,omitempty"`
121+
122+
MaxDelay *Duration `json:"maxDelay,omitempty"`
123+
}
124+
125+
// WafSecurityLog defines the security logging configuration for app_protect_security_log directives.
126+
// LogProfile and LogProfileBundle are mutually exclusive per security log entry.
127+
//
128+
// +kubebuilder:validation:XValidation:message="only one of logProfile or logProfileBundle may be set",rule="!(has(self.logProfile) && has(self.logProfileBundle))"
129+
//
130+
//nolint:lll
131+
type WafSecurityLog struct {
132+
Destination SecurityLogDestination `json:"destination"`
133+
134+
// LogProfile defines the built-in logging profile.
135+
//
136+
// +optional
137+
LogProfile *LogProfile `json:"logProfile,omitempty"`
138+
139+
// LogProfile defines a custom logging profile bundle, similar to policy bundle.
140+
//
141+
// +optional
142+
LogProfileBundle *WafPolicySource `json:"logProfileBundle,omitempty"`
143+
144+
// Name is the name of the security log configuration.
145+
Name string `json:"name"`
146+
}
147+
148+
// +kubebuilder:validation:XValidation:message="destination.file must be nil if the destination.type is not File",rule="!(has(self.file) && self.type != 'File')"
149+
// +kubebuilder:validation:XValidation:message="destination.file must be specified for File destination.type",rule="!(!has(self.file) && self.type == 'File')"
150+
// +kubebuilder:validation:XValidation:message="destination.syslog must be nil if the destination.type is not Syslog",rule="!(has(self.syslog) && self.type != 'Syslog')"
151+
// +kubebuilder:validation:XValidation:message="destination.syslog must be specified for Syslog destination.type",rule="!(!has(self.syslog) && self.type == 'Syslog')"
152+
//
153+
//nolint:lll
154+
type SecurityLogDestination struct {
155+
File *SecurityLogFile `json:"file,omitempty"`
156+
157+
Syslog *SecurityLogSyslog `json:"syslog,omitempty"`
158+
159+
// Type identifies the type of security log destination.
160+
//
161+
// +unionDiscriminator
162+
// +kubebuilder:default:=Stderr
163+
Type SecurityLogDestinationType `json:"type"`
164+
}
165+
166+
// +kubebuilder:validation:Enum=Stderr;File;Syslog
167+
type SecurityLogDestinationType string
168+
169+
const (
170+
SecurityLogDestinationTypeStderr SecurityLogDestinationType = "Stderr"
171+
SecurityLogDestinationTypeFile SecurityLogDestinationType = "File"
172+
SecurityLogDestinationTypeSyslog SecurityLogDestinationType = "Syslog"
173+
)
174+
175+
type SecurityLogFile struct {
176+
Path string `json:"path"`
177+
}
178+
179+
type SecurityLogSyslog struct {
180+
Server string `json:"server"`
181+
}
182+
183+
// LogProfile defines the built-in logging profile.
184+
//
185+
// +kubebuilder:validation:Enum=log_default;log_all;log_illegal;log_blocked;log_grpc_all;log_grpc_blocked;log_grpc_illegal
186+
//
187+
//nolint:lll
188+
type LogProfile string
189+
190+
const (
191+
LogProfileDefault LogProfile = "log_default"
192+
LogProfileAll LogProfile = "log_all"
193+
LogProfileIllegal LogProfile = "log_illegal"
194+
LogProfileBlocked LogProfile = "log_blocked"
195+
LogProfileGRPCAll LogProfile = "log_grpc_all"
196+
LogProfileGRPCBlocked LogProfile = "log_grpc_blocked"
197+
LogProfileGRPCIllegal LogProfile = "log_grpc_illegal"
198+
)

0 commit comments

Comments
 (0)