-
Notifications
You must be signed in to change notification settings - Fork 535
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
application-gateway-kubernetes-ingress: add patch for CVE-2022-21698, C…
…VE-2022-41273 (#9798) Signed-off-by: Thien Trung Vuong <[email protected]>
- Loading branch information
Showing
3 changed files
with
501 additions
and
5 deletions.
There are no files selected for viewing
364 changes: 364 additions & 0 deletions
364
SPECS/application-gateway-kubernetes-ingress/CVE-2022-21698.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,364 @@ | ||
From 253029f7ffbade99588df59a8b89a35d99197fe0 Mon Sep 17 00:00:00 2001 | ||
From: Tobias Brick <[email protected]> | ||
Date: Tue, 18 Jan 2022 10:19:28 +0100 | ||
Subject: [PATCH] Port upstream patch | ||
https://github.com/prometheus/client_golang/commit/9075cdf61646b5adf54d3ba77a0e4f6c65cb4fd7 | ||
|
||
Differences: | ||
- Removed tests | ||
- Removed some comments that don't merge | ||
- Line numbers and such | ||
|
||
Based on: | ||
|
||
From 9075cdf61646b5adf54d3ba77a0e4f6c65cb4fd7 Mon Sep 17 00:00:00 2001 | ||
From: Kemal Akkoyun <[email protected]> | ||
Date: Tue, 18 Jan 2022 10:19:28 +0100 | ||
Subject: [PATCH] promhttp: Check validity of method and code label values | ||
(#962) | ||
|
||
* Check validity of method and code label values | ||
|
||
Signed-off-by: Kemal Akkoyun <[email protected]> | ||
|
||
* Use more flexibly functional option pattern for configuration | ||
|
||
Signed-off-by: Kemal Akkoyun <[email protected]> | ||
|
||
* Update documentation | ||
|
||
Signed-off-by: Kemal Akkoyun <[email protected]> | ||
|
||
* Simplify | ||
|
||
Signed-off-by: Kemal Akkoyun <[email protected]> | ||
|
||
* Fix inconsistent method naming | ||
|
||
Signed-off-by: Kemal Akkoyun <[email protected]> | ||
--- | ||
prometheus/promhttp/instrument_client.go | 28 ++++++-- | ||
prometheus/promhttp/instrument_server.go | 82 ++++++++++++++++++------ | ||
prometheus/promhttp/option.go | 31 +++++++++ | ||
3 files changed, 116 insertions(+), 25 deletions(-) | ||
create mode 100644 prometheus/promhttp/option.go | ||
|
||
diff --git a/prometheus/promhttp/instrument_client.go b/prometheus/promhttp/instrument_client.go | ||
index 83c49b6..861b4d2 100644 | ||
--- a/prometheus/promhttp/instrument_client.go | ||
+++ b/prometheus/promhttp/instrument_client.go | ||
@@ -49,7 +49,10 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp | ||
// http.RoundTripper to observe the request result with the provided CounterVec. | ||
// The CounterVec must have zero, one, or two non-const non-curried labels. For | ||
// those, the only allowed label names are "code" and "method". The function | ||
-// panics otherwise. Partitioning of the CounterVec happens by HTTP status code | ||
+// panics otherwise. For the "method" label a predefined default label value set | ||
+// is used to filter given values. Values besides predefined values will count | ||
+// as `unknown` method.`WithExtraMethods` can be used to add more | ||
+// methods to the set. Partitioning of the CounterVec happens by HTTP status code | ||
// and/or HTTP method if the respective instance label names are present in the | ||
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels. | ||
// | ||
@@ -57,13 +60,18 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp | ||
// is not incremented. | ||
// | ||
// See the example for ExampleInstrumentRoundTripperDuration for example usage. | ||
-func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { | ||
+func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { | ||
+ rtOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(rtOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(counter) | ||
|
||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { | ||
resp, err := next.RoundTrip(r) | ||
if err == nil { | ||
- counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() | ||
+ counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc() | ||
} | ||
return resp, err | ||
}) | ||
@@ -73,7 +81,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou | ||
// http.RoundTripper to observe the request duration with the provided | ||
// ObserverVec. The ObserverVec must have zero, one, or two non-const | ||
// non-curried labels. For those, the only allowed label names are "code" and | ||
-// "method". The function panics otherwise. The Observe method of the Observer | ||
+// "method". The function panics otherwise. For the "method" label a predefined | ||
+// default label value set is used to filter given values. Values besides | ||
+// predefined values will count as `unknown` method. `WithExtraMethods` | ||
+// can be used to add more methods to the set. The Observe method of the Observer | ||
// in the ObserverVec is called with the request duration in | ||
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the | ||
// respective instance label names are present in the ObserverVec. For | ||
@@ -85,14 +96,19 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou | ||
// | ||
// Note that this method is only guaranteed to never observe negative durations | ||
// if used with Go1.9+. | ||
-func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { | ||
+func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { | ||
+ rtOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(rtOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(obs) | ||
|
||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { | ||
start := time.Now() | ||
resp, err := next.RoundTrip(r) | ||
if err == nil { | ||
- obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) | ||
+ obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds()) | ||
} | ||
return resp, err | ||
}) | ||
diff --git a/prometheus/promhttp/instrument_server.go b/prometheus/promhttp/instrument_server.go | ||
index 9db2438..91802f8 100644 | ||
--- a/prometheus/promhttp/instrument_server.go | ||
+++ b/prometheus/promhttp/instrument_server.go | ||
@@ -58,7 +58,12 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl | ||
// | ||
// Note that this method is only guaranteed to never observe negative durations | ||
// if used with Go1.9+. | ||
-func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { | ||
+func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { | ||
+ mwOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(mwOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(obs) | ||
|
||
if code { | ||
@@ -67,14 +72,14 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht | ||
d := newDelegator(w, nil) | ||
next.ServeHTTP(d, r) | ||
|
||
- obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds()) | ||
+ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) | ||
}) | ||
} | ||
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
now := time.Now() | ||
next.ServeHTTP(w, r) | ||
- obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds()) | ||
+ obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) | ||
}) | ||
} | ||
|
||
@@ -91,20 +96,25 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht | ||
// If the wrapped Handler panics, the Counter is not incremented. | ||
// | ||
// See the example for InstrumentHandlerDuration for example usage. | ||
-func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { | ||
+func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc { | ||
+ mwOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(mwOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(counter) | ||
|
||
if code { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
d := newDelegator(w, nil) | ||
next.ServeHTTP(d, r) | ||
- counter.With(labels(code, method, r.Method, d.Status())).Inc() | ||
+ counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc() | ||
}) | ||
} | ||
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
next.ServeHTTP(w, r) | ||
- counter.With(labels(code, method, r.Method, 0)).Inc() | ||
+ counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc() | ||
}) | ||
} | ||
|
||
@@ -126,13 +136,18 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) | ||
// if used with Go1.9+. | ||
// | ||
// See the example for InstrumentHandlerDuration for example usage. | ||
-func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { | ||
+func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { | ||
+ mwOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(mwOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(obs) | ||
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
now := time.Now() | ||
d := newDelegator(w, func(status int) { | ||
- obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds()) | ||
+ obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) | ||
}) | ||
next.ServeHTTP(d, r) | ||
}) | ||
@@ -154,7 +169,12 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha | ||
// If the wrapped Handler panics, no values are reported. | ||
// | ||
// See the example for InstrumentHandlerDuration for example usage. | ||
-func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { | ||
+func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { | ||
+ mwOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(mwOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(obs) | ||
|
||
if code { | ||
@@ -162,14 +182,14 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) | ||
d := newDelegator(w, nil) | ||
next.ServeHTTP(d, r) | ||
size := computeApproximateRequestSize(r) | ||
- obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size)) | ||
+ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size)) | ||
}) | ||
} | ||
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
next.ServeHTTP(w, r) | ||
size := computeApproximateRequestSize(r) | ||
- obs.With(labels(code, method, r.Method, 0)).Observe(float64(size)) | ||
+ obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size)) | ||
}) | ||
} | ||
|
||
@@ -189,12 +209,18 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) | ||
// If the wrapped Handler panics, no values are reported. | ||
// | ||
// See the example for InstrumentHandlerDuration for example usage. | ||
-func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler { | ||
+func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler { | ||
+ mwOpts := &option{} | ||
+ for _, o := range opts { | ||
+ o(mwOpts) | ||
+ } | ||
+ | ||
code, method := checkLabels(obs) | ||
+ | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
d := newDelegator(w, nil) | ||
next.ServeHTTP(d, r) | ||
- obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written())) | ||
+ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written())) | ||
}) | ||
} | ||
|
||
@@ -279,7 +305,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool { | ||
// unnecessary allocations on each request. | ||
var emptyLabels = prometheus.Labels{} | ||
|
||
-func labels(code, method bool, reqMethod string, status int) prometheus.Labels { | ||
+func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels { | ||
if !(code || method) { | ||
return emptyLabels | ||
} | ||
@@ -289,7 +315,7 @@ func labels(code, method bool, reqMethod string, status int) prometheus.Labels { | ||
labels["code"] = sanitizeCode(status) | ||
} | ||
if method { | ||
- labels["method"] = sanitizeMethod(reqMethod) | ||
+ labels["method"] = sanitizeMethod(reqMethod, extraMethods...) | ||
} | ||
|
||
return labels | ||
@@ -319,7 +345,12 @@ func computeApproximateRequestSize(r *http.Request) int { | ||
return s | ||
} | ||
|
||
-func sanitizeMethod(m string) string { | ||
+// If the wrapped http.Handler has a known method, it will be sanitized and returned. | ||
+// Otherwise, "unknown" will be returned. The known method list can be extended | ||
+// as needed by using extraMethods parameter. | ||
+func sanitizeMethod(m string, extraMethods ...string) string { | ||
+ // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for | ||
+ // the methods chosen as default. | ||
switch m { | ||
case "GET", "get": | ||
return "get" | ||
@@ -337,15 +368,25 @@ func sanitizeMethod(m string) string { | ||
return "options" | ||
case "NOTIFY", "notify": | ||
return "notify" | ||
+ case "TRACE", "trace": | ||
+ return "trace" | ||
+ case "PATCH", "patch": | ||
+ return "patch" | ||
default: | ||
- return strings.ToLower(m) | ||
+ for _, method := range extraMethods { | ||
+ if strings.EqualFold(m, method) { | ||
+ return strings.ToLower(m) | ||
+ } | ||
+ } | ||
+ return "unknown" | ||
} | ||
} | ||
|
||
// If the wrapped http.Handler has not set a status code, i.e. the value is | ||
-// currently 0, santizeCode will return 200, for consistency with behavior in | ||
+// currently 0, sanitizeCode will return 200, for consistency with behavior in | ||
// the stdlib. | ||
func sanitizeCode(s int) string { | ||
+ // See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml | ||
switch s { | ||
case 100: | ||
return "100" | ||
@@ -442,6 +483,9 @@ func sanitizeCode(s int) string { | ||
return "511" | ||
|
||
default: | ||
- return strconv.Itoa(s) | ||
+ if s >= 100 && s <= 599 { | ||
+ return strconv.Itoa(s) | ||
+ } | ||
+ return "unknown" | ||
} | ||
} | ||
diff --git a/prometheus/promhttp/option.go b/prometheus/promhttp/option.go | ||
new file mode 100644 | ||
index 0000000..35e41bd | ||
--- /dev/null | ||
+++ b/prometheus/promhttp/option.go | ||
@@ -0,0 +1,31 @@ | ||
+// Copyright 2022 The Prometheus Authors | ||
+// Licensed under the Apache License, Version 2.0 (the "License"); | ||
+// you may not use this file except in compliance with the License. | ||
+// You may obtain a copy of the License at | ||
+// | ||
+// http://www.apache.org/licenses/LICENSE-2.0 | ||
+// | ||
+// Unless required by applicable law or agreed to in writing, software | ||
+// distributed under the License is distributed on an "AS IS" BASIS, | ||
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
+// See the License for the specific language governing permissions and | ||
+// limitations under the License. | ||
+ | ||
+package promhttp | ||
+ | ||
+// Option are used to configure a middleware or round tripper.. | ||
+type Option func(*option) | ||
+ | ||
+type option struct { | ||
+ extraMethods []string | ||
+} | ||
+ | ||
+// WithExtraMethods adds additional HTTP methods to the list of allowed methods. | ||
+// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list. | ||
+// | ||
+// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage. | ||
+func WithExtraMethods(methods ...string) Option { | ||
+ return func(o *option) { | ||
+ o.extraMethods = methods | ||
+ } | ||
+} | ||
-- | ||
2.33.8 | ||
|
Oops, something went wrong.