diff --git a/internal/mode/static/policies/clientsettings/validator.go b/internal/mode/static/policies/clientsettings/validator.go index 4c9725ca26..efe8630436 100644 --- a/internal/mode/static/policies/clientsettings/validator.go +++ b/internal/mode/static/policies/clientsettings/validator.go @@ -67,6 +67,7 @@ func conflicts(a, b ngfAPI.ClientSettingsPolicySpec) bool { if a.KeepAlive.Timeout != nil && b.KeepAlive.Timeout != nil { return true } + } return false @@ -173,6 +174,22 @@ func (v *Validator) validateClientKeepAlive(keepAlive ngfAPI.ClientKeepAlive, fi ) } } + + // This is a special case. The keepalive_timeout directive takes two parameters: + // keepalive_timeout server [header], where header is optional. If header is provided and server is not, + // we can't properly configure the directive. + if keepAlive.Timeout.Header != nil && keepAlive.Timeout.Server == nil { + path := fieldPath.Child("timeout") + + allErrs = append( + allErrs, + field.Invalid( + path, + nil, + "server timeout must be set if header timeout is set", + ), + ) + } } return allErrs diff --git a/internal/mode/static/policies/clientsettings/validator_test.go b/internal/mode/static/policies/clientsettings/validator_test.go index 15ad0ed4f8..04d83ae97d 100644 --- a/internal/mode/static/policies/clientsettings/validator_test.go +++ b/internal/mode/static/policies/clientsettings/validator_test.go @@ -96,6 +96,14 @@ func TestValidator_Validate(t *testing.T) { "spec.keepAlive.timeout.header", }, }, + { + name: "invalid keepalive timeout; header provided without server", + policy: createModifiedPolicy(func(p *ngfAPI.ClientSettingsPolicy) *ngfAPI.ClientSettingsPolicy { + p.Spec.KeepAlive.Timeout.Server = nil + return p + }), + expErrSubstrings: []string{"spec.keepAlive.timeout"}, + }, { name: "valid", policy: createValidPolicy(),