mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-28 06:29:29 +01:00
Bump dependencies to address CVE-2023-44487
This commit is contained in:
22
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go
generated
vendored
22
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go
generated
vendored
@@ -20,6 +20,7 @@ package mutating
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -168,13 +169,12 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
|
||||
if err != nil {
|
||||
switch err := err.(type) {
|
||||
case *webhookutil.ErrCallingWebhook:
|
||||
if ctx.Err() == context.Canceled {
|
||||
klog.Warningf("Context Canceled when calling webhook %v", hook.Name)
|
||||
return err
|
||||
}
|
||||
if !ignoreClientCallFailures {
|
||||
rejected = true
|
||||
admissionmetrics.Metrics.ObserveWebhookRejection(ctx, hook.Name, "admit", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, int(err.Status.ErrStatus.Code))
|
||||
// Ignore context cancelled from webhook metrics
|
||||
if !errors.Is(err.Reason, context.Canceled) {
|
||||
admissionmetrics.Metrics.ObserveWebhookRejection(ctx, hook.Name, "admit", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, int(err.Status.ErrStatus.Code))
|
||||
}
|
||||
}
|
||||
admissionmetrics.Metrics.ObserveWebhook(ctx, hook.Name, time.Since(t), rejected, versionedAttr.Attributes, "admit", int(err.Status.ErrStatus.Code))
|
||||
case *webhookutil.ErrWebhookRejection:
|
||||
@@ -203,10 +203,14 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
|
||||
|
||||
if callErr, ok := err.(*webhookutil.ErrCallingWebhook); ok {
|
||||
if ignoreClientCallFailures {
|
||||
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
|
||||
admissionmetrics.Metrics.ObserveWebhookFailOpen(ctx, hook.Name, "admit")
|
||||
annotator.addFailedOpenAnnotation()
|
||||
|
||||
// Ignore context cancelled from webhook metrics
|
||||
if errors.Is(callErr.Reason, context.Canceled) {
|
||||
klog.Warningf("Context canceled when calling webhook %v", hook.Name)
|
||||
} else {
|
||||
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
|
||||
admissionmetrics.Metrics.ObserveWebhookFailOpen(ctx, hook.Name, "admit")
|
||||
annotator.addFailedOpenAnnotation()
|
||||
}
|
||||
utilruntime.HandleError(callErr)
|
||||
|
||||
select {
|
||||
|
||||
27
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go
generated
vendored
27
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go
generated
vendored
@@ -18,6 +18,7 @@ package validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -173,13 +174,12 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
|
||||
if err != nil {
|
||||
switch err := err.(type) {
|
||||
case *webhookutil.ErrCallingWebhook:
|
||||
if ctx.Err() == context.Canceled {
|
||||
klog.Warningf("Context Canceled when calling webhook %v", hook.Name)
|
||||
return
|
||||
}
|
||||
if !ignoreClientCallFailures {
|
||||
rejected = true
|
||||
admissionmetrics.Metrics.ObserveWebhookRejection(ctx, hook.Name, "validating", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, int(err.Status.ErrStatus.Code))
|
||||
// Ignore context cancelled from webhook metrics
|
||||
if !errors.Is(err.Reason, context.Canceled) {
|
||||
admissionmetrics.Metrics.ObserveWebhookRejection(ctx, hook.Name, "validating", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, int(err.Status.ErrStatus.Code))
|
||||
}
|
||||
}
|
||||
admissionmetrics.Metrics.ObserveWebhook(ctx, hook.Name, time.Since(t), rejected, versionedAttr.Attributes, "validating", int(err.Status.ErrStatus.Code))
|
||||
case *webhookutil.ErrWebhookRejection:
|
||||
@@ -198,12 +198,17 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
|
||||
|
||||
if callErr, ok := err.(*webhookutil.ErrCallingWebhook); ok {
|
||||
if ignoreClientCallFailures {
|
||||
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
|
||||
admissionmetrics.Metrics.ObserveWebhookFailOpen(ctx, hook.Name, "validating")
|
||||
key := fmt.Sprintf("%sround_0_index_%d", ValidatingAuditAnnotationFailedOpenKeyPrefix, idx)
|
||||
value := hook.Name
|
||||
if err := versionedAttr.Attributes.AddAnnotation(key, value); err != nil {
|
||||
klog.Warningf("Failed to set admission audit annotation %s to %s for validating webhook %s: %v", key, value, hook.Name, err)
|
||||
// Ignore context cancelled from webhook metrics
|
||||
if errors.Is(callErr.Reason, context.Canceled) {
|
||||
klog.Warningf("Context canceled when calling webhook %v", hook.Name)
|
||||
} else {
|
||||
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
|
||||
admissionmetrics.Metrics.ObserveWebhookFailOpen(ctx, hook.Name, "validating")
|
||||
key := fmt.Sprintf("%sround_0_index_%d", ValidatingAuditAnnotationFailedOpenKeyPrefix, idx)
|
||||
value := hook.Name
|
||||
if err := versionedAttr.Attributes.AddAnnotation(key, value); err != nil {
|
||||
klog.Warningf("Failed to set admission audit annotation %s to %s for validating webhook %s: %v", key, value, hook.Name, err)
|
||||
}
|
||||
}
|
||||
utilruntime.HandleError(callErr)
|
||||
return
|
||||
|
||||
48
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
48
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
@@ -126,13 +126,51 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
|
||||
sz := l.sizeEstimate(*target)
|
||||
toReplaceSz := l.sizeEstimate(args[0])
|
||||
replaceWithSz := l.sizeEstimate(args[1])
|
||||
// smallest possible result: smallest input size composed of the largest possible substrings being replaced by smallest possible replacement
|
||||
minSz := uint64(math.Ceil(float64(sz.Min)/float64(toReplaceSz.Max))) * replaceWithSz.Min
|
||||
// largest possible result: largest input size composed of the smallest possible substrings being replaced by largest possible replacement
|
||||
maxSz := uint64(math.Ceil(float64(sz.Max)/float64(toReplaceSz.Min))) * replaceWithSz.Max
|
||||
|
||||
var replaceCount, retainedSz checker.SizeEstimate
|
||||
// find the longest replacement:
|
||||
if toReplaceSz.Min == 0 {
|
||||
// if the string being replaced is empty, replace surrounds all characters in the input string with the replacement.
|
||||
if sz.Max < math.MaxUint64 {
|
||||
replaceCount.Max = sz.Max + 1
|
||||
} else {
|
||||
replaceCount.Max = sz.Max
|
||||
}
|
||||
// Include the length of the longest possible original string length.
|
||||
retainedSz.Max = sz.Max
|
||||
} else if replaceWithSz.Max <= toReplaceSz.Min {
|
||||
// If the replacement does not make the result longer, use the original string length.
|
||||
replaceCount.Max = 0
|
||||
retainedSz.Max = sz.Max
|
||||
} else {
|
||||
// Replace the smallest possible substrings with the largest possible replacement
|
||||
// as many times as possible.
|
||||
replaceCount.Max = uint64(math.Ceil(float64(sz.Max) / float64(toReplaceSz.Min)))
|
||||
}
|
||||
|
||||
// find the shortest replacement:
|
||||
if toReplaceSz.Max == 0 {
|
||||
// if the string being replaced is empty, replace surrounds all characters in the input string with the replacement.
|
||||
if sz.Min < math.MaxUint64 {
|
||||
replaceCount.Min = sz.Min + 1
|
||||
} else {
|
||||
replaceCount.Min = sz.Min
|
||||
}
|
||||
// Include the length of the shortest possible original string length.
|
||||
retainedSz.Min = sz.Min
|
||||
} else if toReplaceSz.Max <= replaceWithSz.Min {
|
||||
// If the replacement does not make the result shorter, use the original string length.
|
||||
replaceCount.Min = 0
|
||||
retainedSz.Min = sz.Min
|
||||
} else {
|
||||
// Replace the largest possible substrings being with the smallest possible replacement
|
||||
// as many times as possible.
|
||||
replaceCount.Min = uint64(math.Ceil(float64(sz.Min) / float64(toReplaceSz.Max)))
|
||||
}
|
||||
size := replaceCount.Multiply(replaceWithSz).Add(retainedSz)
|
||||
|
||||
// cost is the traversal plus the construction of the result
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(2 * common.StringTraversalCostFactor), ResultSize: &checker.SizeEstimate{Min: minSz, Max: maxSz}}
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(2 * common.StringTraversalCostFactor), ResultSize: &size}
|
||||
}
|
||||
case "split":
|
||||
if target != nil {
|
||||
|
||||
38
vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
generated
vendored
38
vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
generated
vendored
@@ -29,8 +29,11 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
|
||||
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@@ -101,6 +104,18 @@ func withAuthentication(handler http.Handler, auth authenticator.Request, failed
|
||||
)
|
||||
}
|
||||
|
||||
// http2 is an expensive protocol that is prone to abuse,
|
||||
// see CVE-2023-44487 and CVE-2023-39325 for an example.
|
||||
// Do not allow unauthenticated clients to keep these
|
||||
// connections open (i.e. basically degrade them to the
|
||||
// performance of http1 with keep-alive disabled).
|
||||
if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.UnauthenticatedHTTP2DOSMitigation) && req.ProtoMajor == 2 && isAnonymousUser(resp.User) {
|
||||
// limit this connection to just this request,
|
||||
// and then send a GOAWAY and tear down the TCP connection
|
||||
// https://github.com/golang/net/commit/97aa3a539ec716117a9d15a4659a911f50d13c3c
|
||||
w.Header().Set("Connection", "close")
|
||||
}
|
||||
|
||||
req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User))
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
@@ -108,6 +123,17 @@ func withAuthentication(handler http.Handler, auth authenticator.Request, failed
|
||||
|
||||
func Unauthorized(s runtime.NegotiatedSerializer) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
// http2 is an expensive protocol that is prone to abuse,
|
||||
// see CVE-2023-44487 and CVE-2023-39325 for an example.
|
||||
// Do not allow unauthenticated clients to keep these
|
||||
// connections open (i.e. basically degrade them to the
|
||||
// performance of http1 with keep-alive disabled).
|
||||
if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.UnauthenticatedHTTP2DOSMitigation) && req.ProtoMajor == 2 {
|
||||
// limit this connection to just this request,
|
||||
// and then send a GOAWAY and tear down the TCP connection
|
||||
// https://github.com/golang/net/commit/97aa3a539ec716117a9d15a4659a911f50d13c3c
|
||||
w.Header().Set("Connection", "close")
|
||||
}
|
||||
ctx := req.Context()
|
||||
requestInfo, found := genericapirequest.RequestInfoFrom(ctx)
|
||||
if !found {
|
||||
@@ -127,3 +153,15 @@ func audiencesAreAcceptable(apiAuds, responseAudiences authenticator.Audiences)
|
||||
|
||||
return len(apiAuds.Intersect(responseAudiences)) > 0
|
||||
}
|
||||
|
||||
func isAnonymousUser(u user.Info) bool {
|
||||
if u.GetName() == user.Anonymous {
|
||||
return true
|
||||
}
|
||||
for _, group := range u.GetGroups() {
|
||||
if group == user.AllUnauthenticated {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
20
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
20
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
@@ -182,6 +182,24 @@ const (
|
||||
// Enables server-side field validation.
|
||||
ServerSideFieldValidation featuregate.Feature = "ServerSideFieldValidation"
|
||||
|
||||
// owner: @enj
|
||||
// beta: v1.29
|
||||
//
|
||||
// Enables http2 DOS mitigations for unauthenticated clients.
|
||||
//
|
||||
// Some known reasons to disable these mitigations:
|
||||
//
|
||||
// An API server that is fronted by an L7 load balancer that is set up
|
||||
// to mitigate http2 attacks may opt to disable this protection to prevent
|
||||
// unauthenticated clients from disabling connection reuse between the load
|
||||
// balancer and the API server (many incoming connections could share the
|
||||
// same backend connection).
|
||||
//
|
||||
// An API server that is on a private network may opt to disable this
|
||||
// protection to prevent performance regressions for unauthenticated
|
||||
// clients.
|
||||
UnauthenticatedHTTP2DOSMitigation featuregate.Feature = "UnauthenticatedHTTP2DOSMitigation"
|
||||
|
||||
// owner: @caesarxuchao @roycaihw
|
||||
// alpha: v1.20
|
||||
//
|
||||
@@ -276,6 +294,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
StorageVersionHash: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
UnauthenticatedHTTP2DOSMitigation: {Default: false, PreRelease: featuregate.Beta},
|
||||
|
||||
WatchBookmark: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
|
||||
InPlacePodVerticalScaling: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
13
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
13
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
@@ -43,12 +43,13 @@ import (
|
||||
"k8s.io/apiserver/pkg/apis/config/validation"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
"k8s.io/apiserver/pkg/server/options/encryptionconfig/metrics"
|
||||
storagevalue "k8s.io/apiserver/pkg/storage/value"
|
||||
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope"
|
||||
envelopekmsv2 "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2"
|
||||
kmstypes "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2/v2"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope/metrics"
|
||||
envelopemetrics "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/metrics"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/identity"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/secretbox"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
@@ -104,6 +105,12 @@ const (
|
||||
kmsReloadHealthCheckName = "kms-providers"
|
||||
)
|
||||
|
||||
func init() {
|
||||
metrics.RegisterMetrics()
|
||||
storagevalue.RegisterMetrics()
|
||||
envelopemetrics.RegisterMetrics()
|
||||
}
|
||||
|
||||
type kmsPluginHealthzResponse struct {
|
||||
err error
|
||||
received time.Time
|
||||
@@ -445,10 +452,10 @@ func (h *kmsv2PluginProbe) isKMSv2ProviderHealthyAndMaybeRotateDEK(ctx context.C
|
||||
}
|
||||
|
||||
if errCode, err := envelopekmsv2.ValidateKeyID(response.KeyID); err != nil {
|
||||
metrics.RecordInvalidKeyIDFromStatus(h.name, string(errCode))
|
||||
envelopemetrics.RecordInvalidKeyIDFromStatus(h.name, string(errCode))
|
||||
errs = append(errs, fmt.Errorf("got invalid KMSv2 KeyID hash %q: %w", envelopekmsv2.GetHashIfNotEmpty(response.KeyID), err))
|
||||
} else {
|
||||
metrics.RecordKeyIDFromStatus(h.name, response.KeyID)
|
||||
envelopemetrics.RecordKeyIDFromStatus(h.name, response.KeyID)
|
||||
// unconditionally append as we filter out nil errors below
|
||||
errs = append(errs, h.rotateDEKOnKeyIDChange(ctx, response.KeyID, string(uuid.NewUUID())))
|
||||
}
|
||||
|
||||
5
vendor/k8s.io/apiserver/pkg/server/secure_serving.go
generated
vendored
5
vendor/k8s.io/apiserver/pkg/server/secure_serving.go
generated
vendored
@@ -189,7 +189,10 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
|
||||
if s.HTTP2MaxStreamsPerConnection > 0 {
|
||||
http2Options.MaxConcurrentStreams = uint32(s.HTTP2MaxStreamsPerConnection)
|
||||
} else {
|
||||
http2Options.MaxConcurrentStreams = 250
|
||||
// match http2.initialMaxConcurrentStreams used by clients
|
||||
// this makes it so that a malicious client can only open 400 streams before we forcibly close the connection
|
||||
// https://github.com/golang/net/commit/b225e7ca6dde1ef5a5ae5ce922861bda011cfabd
|
||||
http2Options.MaxConcurrentStreams = 100
|
||||
}
|
||||
|
||||
// increase the connection buffer size from the 1MB default to handle the specified number of concurrent streams
|
||||
|
||||
4
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
generated
vendored
@@ -157,10 +157,10 @@ func newETCD3Check(c storagebackend.Config, timeout time.Duration, stopCh <-chan
|
||||
var prober *etcd3ProberMonitor
|
||||
clientErr := fmt.Errorf("etcd client connection not yet established")
|
||||
|
||||
go wait.PollUntil(time.Second, func() (bool, error) {
|
||||
newProber, err := newETCD3ProberMonitor(c)
|
||||
go wait.PollImmediateUntil(time.Second, func() (bool, error) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
newProber, err := newETCD3ProberMonitor(c)
|
||||
// Ensure that server is already not shutting down.
|
||||
select {
|
||||
case <-stopCh:
|
||||
|
||||
Reference in New Issue
Block a user