From 135755af39fb83647a517f3da7ff6c358542381b Mon Sep 17 00:00:00 2001 From: xosk31 Date: Tue, 3 Dec 2024 15:56:25 +0100 Subject: [PATCH] add http-request del-header to remove an HTTP header from a request before relaying it to a backend --- apis/config/v1alpha1/common_types.go | 22 +++++++++++++ apis/config/v1alpha1/listen_types_test.go | 11 +++++++ apis/config/v1alpha1/zz_generated.deepcopy.go | 21 ++++++++++++ .../crds/config.haproxy.com_backends.yaml | 32 +++++++++++++++++++ .../crds/config.haproxy.com_frontends.yaml | 32 +++++++++++++++++++ .../crds/config.haproxy.com_listens.yaml | 32 +++++++++++++++++++ 6 files changed, 150 insertions(+) diff --git a/apis/config/v1alpha1/common_types.go b/apis/config/v1alpha1/common_types.go index 1189d71..d5beb6e 100644 --- a/apis/config/v1alpha1/common_types.go +++ b/apis/config/v1alpha1/common_types.go @@ -754,6 +754,8 @@ type HTTPRequestRules struct { SetPath []HTTPPathRule `json:"setPath,omitempty"` // AddHeader appends HTTP header fields AddHeader []HTTPHeaderRule `json:"addHeader,omitempty"` + // DelHeader removes all HTTP header fields + DelHeader []HTTPDeleteHeaderRule `json:"delHeader,omitempty"` // Redirect performs an HTTP redirection based on a redirect rule. // +optional Redirect []Redirect `json:"redirect,omitempty"` @@ -804,6 +806,17 @@ func (h *HTTPRequestRules) Model() (models.HTTPRequestRules, error) { }) } + for idx, header := range h.DelHeader { + model = append(model, &models.HTTPRequestRule{ + Type: "del-header", + Index: ptr.To(int64(idx)), + HdrName: header.Name, + HdrMethod: header.Method, + Cond: header.ConditionType, + CondTest: header.Condition, + }) + } + for idx, header := range h.ReplacePath { model = append(model, &models.HTTPRequestRule{ Type: "replace-path", @@ -948,6 +961,15 @@ type HTTPHeaderRule struct { Value HTTPHeaderValue `json:"value"` } +type HTTPDeleteHeaderRule struct { + Rule `json:",inline"` + // Name specifies the header name + Name string `json:"name"` + // Method is the matching applied on the header name + // +kubebuilder:validation:Enum=str;beg;end;sub;reg + Method string `json:"method"` +} + type HTTPPathRule struct { Rule `json:",inline"` // Value specifies the path value diff --git a/apis/config/v1alpha1/listen_types_test.go b/apis/config/v1alpha1/listen_types_test.go index 3294dc2..1f075d5 100644 --- a/apis/config/v1alpha1/listen_types_test.go +++ b/apis/config/v1alpha1/listen_types_test.go @@ -122,6 +122,15 @@ var _ = Describe("Listen", Label("type"), func() { }, }, }, + DelHeader: []configv1alpha1.HTTPDeleteHeaderRule{ + { + Name: "regex", + Method: "str", + }, + { + Name: "Proxy", + }, + }, }, }, }, @@ -133,6 +142,8 @@ var _ = Describe("Listen", Label("type"), func() { Ω(p.String()).Should(ContainSubstring("http-request add-header X-Forwarded-Proto https")) Ω(p.String()).Should(ContainSubstring("http-request add-header X-Forwarded-Proto-Version \"${PROTO_VERSION}\"")) Ω(p.String()).Should(ContainSubstring("http-request set-path /metrics if !{ ssl_fc }")) + Ω(p.String()).Should(ContainSubstring("http-request del-header Proxy")) + Ω(p.String()).Should(ContainSubstring("http-request del-header regex -m str")) Ω(p.String()).Should(ContainSubstring("http-response set-header Strict-Transport-Security max-age=16000000; includeSubDomains; preload; if !{ ssl_fc }")) }) It("should create binds", func() { diff --git a/apis/config/v1alpha1/zz_generated.deepcopy.go b/apis/config/v1alpha1/zz_generated.deepcopy.go index 68b8c7e..bb0c2f3 100644 --- a/apis/config/v1alpha1/zz_generated.deepcopy.go +++ b/apis/config/v1alpha1/zz_generated.deepcopy.go @@ -670,6 +670,22 @@ func (in *HTTPChk) DeepCopy() *HTTPChk { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPDeleteHeaderRule) DeepCopyInto(out *HTTPDeleteHeaderRule) { + *out = *in + out.Rule = in.Rule +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPDeleteHeaderRule. +func (in *HTTPDeleteHeaderRule) DeepCopy() *HTTPDeleteHeaderRule { + if in == nil { + return nil + } + out := new(HTTPDeleteHeaderRule) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPHeaderRule) DeepCopyInto(out *HTTPHeaderRule) { *out = *in @@ -770,6 +786,11 @@ func (in *HTTPRequestRules) DeepCopyInto(out *HTTPRequestRules) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.DelHeader != nil { + in, out := &in.DelHeader, &out.DelHeader + *out = make([]HTTPDeleteHeaderRule, len(*in)) + copy(*out, *in) + } if in.Redirect != nil { in, out := &in.Redirect, &out.Redirect *out = make([]Redirect, len(*in)) diff --git a/helm/haproxy-operator/crds/config.haproxy.com_backends.yaml b/helm/haproxy-operator/crds/config.haproxy.com_backends.yaml index cb24af3..e66552a 100644 --- a/helm/haproxy-operator/crds/config.haproxy.com_backends.yaml +++ b/helm/haproxy-operator/crds/config.haproxy.com_backends.yaml @@ -549,6 +549,38 @@ spec: - value type: object type: array + delHeader: + description: DelHeader removes all HTTP header fields + items: + properties: + condition: + description: Condition is a condition composed of ACLs. + type: string + conditionType: + description: ConditionType specifies the type of the condition + matching ('if' or 'unless') + enum: + - if + - unless + type: string + method: + description: Method is the matching applied on the header + name + enum: + - str + - beg + - end + - sub + - reg + type: string + name: + description: Name specifies the header name + type: string + required: + - method + - name + type: object + type: array deny: description: |- Deny stops the evaluation of the rules and immediately rejects the request and emits an HTTP 403 error. diff --git a/helm/haproxy-operator/crds/config.haproxy.com_frontends.yaml b/helm/haproxy-operator/crds/config.haproxy.com_frontends.yaml index 7b539d1..8eff0d9 100644 --- a/helm/haproxy-operator/crds/config.haproxy.com_frontends.yaml +++ b/helm/haproxy-operator/crds/config.haproxy.com_frontends.yaml @@ -819,6 +819,38 @@ spec: - value type: object type: array + delHeader: + description: DelHeader removes all HTTP header fields + items: + properties: + condition: + description: Condition is a condition composed of ACLs. + type: string + conditionType: + description: ConditionType specifies the type of the condition + matching ('if' or 'unless') + enum: + - if + - unless + type: string + method: + description: Method is the matching applied on the header + name + enum: + - str + - beg + - end + - sub + - reg + type: string + name: + description: Name specifies the header name + type: string + required: + - method + - name + type: object + type: array deny: description: |- Deny stops the evaluation of the rules and immediately rejects the request and emits an HTTP 403 error. diff --git a/helm/haproxy-operator/crds/config.haproxy.com_listens.yaml b/helm/haproxy-operator/crds/config.haproxy.com_listens.yaml index d1cd24d..dd0e06c 100644 --- a/helm/haproxy-operator/crds/config.haproxy.com_listens.yaml +++ b/helm/haproxy-operator/crds/config.haproxy.com_listens.yaml @@ -961,6 +961,38 @@ spec: - value type: object type: array + delHeader: + description: DelHeader removes all HTTP header fields + items: + properties: + condition: + description: Condition is a condition composed of ACLs. + type: string + conditionType: + description: ConditionType specifies the type of the condition + matching ('if' or 'unless') + enum: + - if + - unless + type: string + method: + description: Method is the matching applied on the header + name + enum: + - str + - beg + - end + - sub + - reg + type: string + name: + description: Name specifies the header name + type: string + required: + - method + - name + type: object + type: array deny: description: |- Deny stops the evaluation of the rules and immediately rejects the request and emits an HTTP 403 error.